Join Date: Aug 2007
Posts: 8643
User-Rating:
|
Hallo,
wenn ihr bei Abstürzen eures Programms den Ablauf nachverfolgen wollt, hilft es ungemein, zu wissen, welche Funktion von wo aufgerufen wurde. Die managed Sprachen wie C# oder Java bieten dazu den CallStack an. Für C++ gibt es sowas direkt nicht, aber man kann sich ja helfen:
CPP Code: //StackWalk.h //KN4CK3R https://www.oldschoolhack.me //Credits: MSDN #ifndef __STACKWALK_H__ #define __STACKWALK_H__ #include <windows.h> #include <tchar.h> #include <list> #include <tlhelp32.h> class StackWalk { private: class Module { public: DWORD adress; DWORD size; TCHAR name[256]; bool IsIn(DWORD address) { return address >= this->adress && address <= this->adress + size; } }; //--------------------------------------------------------------------------- void *stack[63]; int stackSize; std::list<Module> moduleList; //--------------------------------------------------------------------------- void GetModuleList() { MODULEENTRY32 module32; module32.dwSize = sizeof(MODULEENTRY32); HANDLE snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); if (snapShot != INVALID_HANDLE_VALUE) { if (Module32First(snapShot, &module32)) { do { Module module; module.adress = (DWORD)module32.modBaseAddr; module.size = module32.modBaseSize; _tcscpy(module.name, module32.szModule); moduleList.push_back(module); } while (Module32Next(snapShot, &module32)); } CloseHandle(snapShot); } } //--------------------------------------------------------------------------- public: class StackFrame { private: DWORD address; DWORD offset; TCHAR moduleName[256]; public: StackFrame(DWORD address, DWORD offset, TCHAR *moduleName) { this->address = address; this->offset = offset; _tcscpy(this->moduleName, moduleName); } //--------------------------------------------------------------------------- DWORD GetAddress() { return address; } //--------------------------------------------------------------------------- DWORD GetOffset() { return offset; } //--------------------------------------------------------------------------- TCHAR* GetModuleName() { return moduleName; } //--------------------------------------------------------------------------- }; //--------------------------------------------------------------------------- std::list<StackFrame> GetCallStack() { std::list<StackFrame> frames; stackSize = RtlCaptureStackBackTrace(1, 63, stack, 0); GetModuleList(); for (int i = 0; i < stackSize; ++i) { DWORD address = (DWORD)stack[i]; for (std::list<Module>::iterator it = moduleList.begin(); it != moduleList.end(); it++) { Module module = *it; if (module.IsIn(address)) { frames.push_back(StackFrame(address - 5, address - module.adress - 5, module.name)); break; } } } return frames; } //--------------------------------------------------------------------------- }; //--------------------------------------------------------------------------- #endif
Als Beispiel, wie man die Klasse benutzen kann:
CPP Code: #include <windows.h> #include <iostream> #include "StackWalk.h" #if defined(UNICODE) || defined(_UNICODE) #define tcout wcout #else #define tcout cout #endif void stack() { StackWalk swalk; std::list<StackWalk::StackFrame> frames = swalk.GetCallStack(); for (std::list<StackWalk::StackFrame>::iterator it = frames.begin(); it != frames.end(); it++) { StackWalk::StackFrame frame = *it; std::tcout << frame.GetModuleName() << "!0x" << std::hex << frame.GetOffset() << " (0x" << frame.GetAddress() << ")" << std::endl; } } //--------------------------------------------------------------------------- void func(int c) { if (c == 5) { stack(); return; } func(++c); } //--------------------------------------------------------------------------- int _tmain(int argc, TCHAR* argv[]) { func(0); return 0; } //---------------------------------------------------------------------------
Das Programm erzeugt zB diese Ausgabe:
Quote StackTrace.exe!0x11d9f (0x1191d9f) StackTrace.exe!0x12c94 (0x1192c94) StackTrace.exe!0x12ca8 (0x1192ca8) StackTrace.exe!0x12ca8 (0x1192ca8) StackTrace.exe!0x12ca8 (0x1192ca8) StackTrace.exe!0x12ca8 (0x1192ca8) StackTrace.exe!0x12ca8 (0x1192ca8) StackTrace.exe!0x12d00 (0x1192d00) StackTrace.exe!0x1ab7a (0x119ab7a) StackTrace.exe!0x1a9aa (0x119a9aa) kernel32.dll!0x53c40 (0x772a3c40) ntdll.dll!0x637f0 (0x773937f0) ntdll.dll!0x637c3 (0x773937c3) ModuleName!Offset (Moduladresse + Offset)
Ich werde die Klasse demnächst in meine Hacks einbauen. Sollte helfen dem Problem auf die Schliche zu kommen, warum die Hacks bei manchen Leuten nicht funktionieren.
greetz KN4CK3R
|