#c #winapi #dll #stack-trace
#c #winapi #dll #трассировка стека
Вопрос:
Вот моя проблема. Я обошел функцию «ScriptTextOut» и пытаюсь найти, откуда она была вызвана. Вот моя dll (я использую Microsoft Detour):
#pragma comment(lib, "detours.lib")
#include <Windows.h>
#include <detours.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <Usp10.h>
#include <Dbghelp.h>
HRESULT (WINAPI * Real_ScriptTextOut)(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions, const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved, int iReserved,
const WORD *pwGlyphs, int cGlyphs, const int *piAdvance, const int *piJustify, const GOFFSET *pGoffset) = ScriptTextOut;
// function used to back trace where the function was called from
void printStack()
{
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
for( i = 0; i < frames; i )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
printf( "%i: %s - 0x%0Xn", frames - i - 1, symbol->Name, symbol->Address );
}
free( symbol );
}
// My ScriptTextOut function
HRESULT WINAPI Mine_ScriptTextOut(const HDC hdc, SCRIPT_CACHE *psc, int x, int y, UINT fuOptions, const RECT *lprc, const SCRIPT_ANALYSIS *psa, const WCHAR *pwcReserved, int iReserved,
const WORD *pwGlyphs, int cGlyphs, const int *piAdvance, const int *piJustify, const GOFFSET *pGoffset)
{
printStack();
return Real_ScriptTextOut(hdc, psc, x, y, fuOptions, lprc, psa, pwcReserved, iReserved, pwGlyphs, cGlyphs, piAdvance, piJustify, pGoffset);
}
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
AllocConsole();
freopen("CONOUT$", "w", stdout);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(amp;(PVOIDamp;)Real_ScriptTextOut, Mine_ScriptTextOut);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
FreeConsole();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(amp;(PVOIDamp;)Real_ScriptTextOut, Mine_ScriptTextOut);
DetourTransactionCommit();
break;
}
return TRUE;
}
Таким образом, функция обхода работает, как ожидалось, но функция printStack() выводит некоторые странные результаты… Вот, взгляните:
Вы можете спросить, почему это странно? Ну, я ожидал найти функцию, которая вызвала ScriptTextOut, но функция перед «Mine_ScriptTextOut» — это «ScriptApplyDigitSubstitution», и хотя эти 2 явно связаны, одна не вызывает другую…
При тестировании моей функции PrintStack вне внедренной dll все работало нормально:
#include <Windows.h>
#include <Dbghelp.h>
#include <cstdio>
void printStack()
{
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
for( i = 0; i < frames; i )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
printf( "%i: %s - 0x%0Xn", frames - i - 1, symbol->Name, symbol->Address );
}
free( symbol );
}
void dontprint()
{
}
void foo()
{
printStack();
}
void test()
{
dontprint();
foo();
}
int main()
{
dontprint();
test();
return 0;
}
Вот правильный вывод:
Есть идеи, что происходит?
Комментарии:
1. Если вы компилируете с пропуском указателя фрейма, трассировка стека может быть не на 100 процентов точной.
2. Я не компилирую с пропуском указателя фрейма, поэтому я не думаю, что это проблема…
3. Более того, если программа (или библиотеки, вызываемые таким образом), в которую вы вводите, скомпилирована с пропуском указателя фрейма, у вас возникнут проблемы описанного вами типа.
4. Итак, я действительно ничего не могу сделать, чтобы получить точную трассировку стека?
5. @Noob-programmer Если у вас есть исходный код этих библиотек, вы можете перекомпилировать. В противном случае у них пропущен указатель на фрейм, и все.