Ловильный выход (1); - PullRequest
5 голосов
/ 08 марта 2009

У меня есть приложение MFC SDI, которое при запуске загружает DLL. Я могу только просматривать исходный код и использовать DLL, но не могу изменить и перекомпилировать его.

Ситуация теперь такова, что всякий раз, когда DLL сталкивается с ошибкой, она вызывает функцию exit (), как показано ниже.

bool Func()
{
  // .. do something here

  if (error) { exit(999); }
}

В моем приложении MFC я установил SetUnhandledExceptionFilter для обработки всех исключений, а также создал MiniDump для целей отладки.

Так что теперь проблема в том, что всякий раз, когда DLL сталкивается с какой-либо ошибкой, она просто вызывает exit () с кодом состояния 999, и мой ExceptionFilter не будет ее перехватывать, и, следовательно, MiniDump не создается для отладки PostMortem.

Мне было интересно, если:
1. Есть ли другой способ, чтобы мой глобальный обработчик исключений мог это уловить?
2. Могу ли я переопределить функцию exit (), чтобы при ее вызове я вызывал метод «throw (« error error! »)» И мой глобальный обработчик исключений мог его перехватить.
3. Я попытался использовать atexit () в своем приложении MFC, в результате чего я зарегистрировал другую функцию, чтобы выдавать ошибку всякий раз, когда DLL вызывает exit (). Но, похоже, это не работает.

Что я действительно хотел сделать, так это чтобы всякий раз, когда DLL сталкивался с ошибкой, я хотел, чтобы был создан MiniDump, чтобы я мог выполнять отладку PostMortem. Есть ли что-нибудь еще, что может работать в этой ситуации?

Спасибо.

Ответы [ 4 ]

1 голос
/ 20 сентября 2009

Проверьте таблицу импорта символов DLL.

Вы просто можете переназначить его на функцию по вашему выбору во время выполнения.

Как это сделать (если есть выход):

Большинство DLL используют импорт символов через таблицу переходов. Если вы установите точку останова на вызывающем абоненте, вы увидите, что он вызывает инструкцию для прыжка в длину. Таблица переходов является страницей PAGE_EXECUTE_READWRITE, поэтому вы можете просто перезаписать этот слот таблицы переходов своим собственным адресом.

Местоположение таблицы переходов будет различным, но оно всегда будет постоянным смещением от адреса загрузки и, следовательно, постоянным смещением любого указателя функции в DLL, найденную GetProcAddress.

Конечно, все это предполагает, что DLL никогда не меняется. Вероятно, есть способ найти все эти вещи во время выполнения, но я не знаю, как вы поступите с этим.

О, вы не можете вернуться с выхода (). Тебе придется долго прыгать.

0 голосов
/ 06 ноября 2009

Когда процесс завершается нормально, каждая DLL получает DLL_PROCESS_DETACH уведомление . Как насчет написания вашей собственной DLL с единственной целью - перехватить это уведомление?

0 голосов
/ 20 сентября 2009

Я еще не нашел решения для этого, но вот одна из возможных причин, почему ваш обработчик atexit не помогает: dll может статически связываться с CRT. Это будет означать, что код для exit () встроен непосредственно в dll, что даст ему собственный закрытый список обработчиков выхода, поэтому обработчик atexit, зарегистрированный внутри вашего хост-процесса, никогда не будет виден. Если бы вы смогли вызвать atexit() изнутри dll (что было бы довольно сложно организовать), это, вероятно, сработало бы.

Просто предположение - надеюсь, это поможет.

0 голосов
/ 29 июля 2009

Вот макрос, который я написал для размещения точек останова в функциях exit ():

Imports System.IO

' Sets breakpoints on all exit functions.  useful for catching library code that 
' calls exit in the debugger.
Sub AddBreakpointsToExit()
    Dim bp As EnvDTE.Breakpoint
    Dim bps As EnvDTE.Breakpoints

    Dim envVar As String = "VS90COMNTOOLS"
    Dim comnTools As String = System.Environment.GetEnvironmentVariable(envVar)
    If (String.IsNullOrEmpty(comnTools)) Then
        Throw New System.Exception("Environment variable '" + envVar + "' doesn't exist.")
    End If
    Dim filePath As String = System.IO.Path.Combine(comnTools, "..\..\VC\crt\src\crt0dat.c")

    ' set exit function names and line #s:
    Dim exitFunctions(0 To 4) As String
    exitFunctions(0) = "exit"
    exitFunctions(1) = "_exit"
    exitFunctions(2) = "_cexit"
    exitFunctions(3) = "_c_exit"

    ' line numbers are based on the Visual Studio 2008 definition.
    ' TODO: check and add options if 2005 or 2010 are differen.t
    Dim exitLines(0 To 4) As Integer
    exitLines(0) = 412
    exitLines(1) = 420
    exitLines(2) = 427
    exitLines(3) = 434

    ' set breakpoints:
    For i = 0 To 3 Step 1
        bps = DTE.Debugger.Breakpoints.Add(File:=filePath, Line:=exitLines(i))
    Next i

End Sub
...