2

I have created my own debugger application. It attaches to a process and creates a crash dump file. That works most of the time. The problem I have is that it will not work when the application being debugged is waiting for a mutex object (and this is the very problem that I want to debug).

Furthermore, I have created a simple test.exe application that just loops around and calls Sleep(100) but my debugger fails when it calls MiniDumpWriteDump on this application every time.

What am I doing wrong?

The error code I get returned from the code below is 2147942699 (0x8007012b)

void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
  CONTEXT c;

  memset( &c, 0, sizeof( c ) );

  GetThreadContext( hThread, &c );

  EXCEPTION_POINTERS ep;

  memset( &ep, 0, sizeof( ep ) );

  ep.ContextRecord   = &c;
  ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;

    MINIDUMP_EXCEPTION_INFORMATION minidump_exception;

  memset( &minidump_exception, 0, sizeof( minidump_exception ) );

    minidump_exception .ThreadId          = dwThreadId;
    minidump_exception.ExceptionPointers = &ep;
    minidump_exception.ClientPointers    = true;

  char txDumpPath[ MAX_PATH + 1 ];

  sprintf( txDumpPath, "%s.dmp", txProcess );

    HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

  if( hFile )
  {
    BOOL  fSuccess;


    SetLastError( 0L );

    int nDumpOptions =

    MiniDumpNormal
|    MiniDumpWithDataSegs                  
|    MiniDumpWithFullMemory                
|    MiniDumpWithHandleData                
|    MiniDumpFilterMemory                  
|    MiniDumpScanMemory                    
|    MiniDumpWithUnloadedModules           
|    MiniDumpWithIndirectlyReferencedMemory
|    MiniDumpFilterModulePaths             
|    MiniDumpWithProcessThreadData         
|    MiniDumpWithPrivateReadWriteMemory    
|    MiniDumpWithoutOptionalData           
    ;

    fSuccess = MiniDumpWriteDump( hProcess,
                                  dwProcessId,
                                  hFile,
                                  (MINIDUMP_TYPE) nDumpOptions,
                                  &minidump_exception,
                                  NULL,
                                  NULL );

    DWORD dwErr = GetLastError();

    if( ! fSuccess )
            printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );

        CloseHandle( hFile );
    }
}

I have also tried increasing the privileges with the following code snippet which I borrowed from somebody else who seemed to have a similar problem:

BOOL SetDumpPrivileges()
{
    BOOL       fSuccess  = FALSE;
    HANDLE      TokenHandle = NULL;
    TOKEN_PRIVILEGES TokenPrivileges;

    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &TokenHandle))
    {
        printf("Could not get the process token");
        goto Cleanup;
    }

    TokenPrivileges.PrivilegeCount = 1;

    if (!LookupPrivilegeValue(NULL,
        SE_DEBUG_NAME,
        &TokenPrivileges.Privileges[0].Luid))
    {
        printf("Couldn't lookup SeDebugPrivilege name");
        goto Cleanup;
    }

    TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    //Add privileges here.
    if (!AdjustTokenPrivileges(TokenHandle,
        FALSE,
        &TokenPrivileges,
        sizeof(TokenPrivileges),
        NULL,
        NULL))
    {
        printf("Could not revoke the debug privilege");
        goto Cleanup;
    }

    fSuccess = TRUE;

Cleanup:

    if (TokenHandle)
    {
        CloseHandle(TokenHandle);
    }

    return fSuccess;
}
SparkyNZ
  • 6,266
  • 7
  • 39
  • 80

2 Answers2

2

I posted a question on MSDN and somebody kindly provided me the answer to my problem. Here's the link to the discussion, and the working code snippet I've copied below.

void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
  CONTEXT c;

  memset( &c, 0, sizeof( c ) );

  HANDLE hThread;
  c.ContextFlags = CONTEXT_FULL;
  hThread = _OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadId );

  GetThreadContext( hThread, &c );

  EXCEPTION_POINTERS ep;

  memset( &ep, 0, sizeof( ep ) );

  ep.ContextRecord   = &c;
  ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;

  MINIDUMP_EXCEPTION_INFORMATION minidump_exception;

  memset( &minidump_exception, 0, sizeof( minidump_exception ) );

  minidump_exception.ThreadId          = dwThreadId;
  minidump_exception.ExceptionPointers = &ep;
  minidump_exception.ExceptionPointers->ContextRecord = &c;
  minidump_exception.ClientPointers    = false;

  char txDumpPath[ MAX_PATH + 1 ];

  time_t tNow = time( NULL );
  struct tm *pTm = localtime( &tNow );

  sprintf( txDumpPath, "%s.%02d%02d%04d_%02d%02d%02d.dmp", 
           txProcess,
           pTm->tm_mday,
           pTm->tm_mon,
           pTm->tm_year,
           pTm->tm_hour, 
           pTm->tm_min, 
           pTm->tm_sec );

    HANDLE hFile = CreateFile( txDumpPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

  if( hFile != INVALID_HANDLE_VALUE ) 
  {
    BOOL  fSuccess;

    printf( "hProcess   : %d (0x%x)\n", hProcess, hProcess );
    printf( "dwProcessId: %u (0x%lx)\n", dwProcessId, dwProcessId );
    printf( "dwThreadId : %u (0x%lx)\n", dwThreadId,  dwThreadId );

    SetLastError( 0L );

    fSuccess = MiniDumpWriteDump( hProcess, 
                                  dwProcessId, 
                                  hFile, 
                                  MiniDumpNormal,
                                  &minidump_exception, 
                                  NULL, 
                                  NULL );

    DWORD dwErr = GetLastError();

    if( ! fSuccess )
    {
      printf( "MiniDumpWriteDump -FAILED (LastError:%u)\n", dwErr );

      LPVOID lpMsgBuf;

      FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                     NULL,
                     dwErr,
                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                     (LPTSTR) &lpMsgBuf,
                     0,
                     NULL );

      // Display the string.
      printf( "%s\n", (LPCTSTR)lpMsgBuf );

      // Free the buffer.
      LocalFree( lpMsgBuf );
    }
  } 

  if( hThread )
    CloseHandle( hThread );
}
SparkyNZ
  • 6,266
  • 7
  • 39
  • 80
  • Hi , The above thing is not working for me. The thing is i have my MiniDump Written from a seperate process . Is yours a out of process crash handler ? or in-process ? Can you just clarify ? – Anantha Subramaniam Jun 11 '13 at 16:06
  • @AnanthaSubramaniam Sorry it was 6 years ago when I posted this. I honestly can't remember. I would have thought that I'd have put this on a seperate 'watchdog' thread to keep track of my main application thread - which must have been a global. – SparkyNZ Mar 28 '18 at 07:20
0

Is this problem the same one as the other question I answered with this text?

Does it not include the mutex information even with flag MiniDumpWithHandleData, also it is possibly failing because some of the flags may not be compatible with the version of DebugHlp.dll you are calling against see: here

Community
  • 1
  • 1
EdChum
  • 376,765
  • 198
  • 813
  • 562
  • Hello again. No, its a different problem. My previous question concerned the writing of handle information. The problem I describe here is that MiniDumpWriteDump fails to write anything at all for most processed. I have a tiny test application and it refuses to create a dump of any sort (creates file 0 bytes in size). If I attach the debugger app to one of our bigger apps, it does write a dump. – SparkyNZ Mar 25 '12 at 04:23