2 * PROJECT: Dr. Watson crash reporter
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Print a stacktrace
5 * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
12 void BeginStackBacktrace(DumpData
& data
)
14 DWORD symOptions
= SymGetOptions();
15 symOptions
|= SYMOPT_UNDNAME
| SYMOPT_AUTO_PUBLICS
| SYMOPT_DEFERRED_LOADS
;
16 SymSetOptions(symOptions
);
17 SymInitialize(data
.ProcessHandle
, NULL
, TRUE
);
20 void EndStackBacktrace(DumpData
& data
)
22 SymCleanup(data
.ProcessHandle
);
25 static char ToChar(UCHAR data
)
30 return 'a' + data
- 0xa;
34 void PrintStackBacktrace(FILE* output
, DumpData
& data
, ThreadData
& thread
)
37 STACKFRAME64 StackFrame
= { { 0 } };
40 MachineType
= IMAGE_FILE_MACHINE_AMD64
;
41 StackFrame
.AddrPC
.Offset
= thread
.Context
.Rip
;
42 StackFrame
.AddrPC
.Mode
= AddrModeFlat
;
43 StackFrame
.AddrStack
.Offset
= thread
.Context
.Rsp
;
44 StackFrame
.AddrStack
.Mode
= AddrModeFlat
;
45 StackFrame
.AddrFrame
.Offset
= thread
.Context
.Rbp
;
46 StackFrame
.AddrFrame
.Mode
= AddrModeFlat
;
48 MachineType
= IMAGE_FILE_MACHINE_I386
;
49 StackFrame
.AddrPC
.Offset
= thread
.Context
.Eip
;
50 StackFrame
.AddrPC
.Mode
= AddrModeFlat
;
51 StackFrame
.AddrStack
.Offset
= thread
.Context
.Esp
;
52 StackFrame
.AddrStack
.Mode
= AddrModeFlat
;
53 StackFrame
.AddrFrame
.Offset
= thread
.Context
.Ebp
;
54 StackFrame
.AddrFrame
.Mode
= AddrModeFlat
;
58 #define STACKWALK_MAX_NAMELEN 512
59 char buf
[sizeof(SYMBOL_INFO
) + STACKWALK_MAX_NAMELEN
] = {0};
60 SYMBOL_INFO
* sym
= (SYMBOL_INFO
*)buf
;
61 IMAGEHLP_MODULE64 Module
= { 0 };
62 sym
->SizeOfStruct
= sizeof(sym
);
64 /* FIXME: Disasm function! */
66 xfprintf(output
, NEWLINE
"*----> Stack Back Trace <----*" NEWLINE NEWLINE
);
68 ULONG_PTR LastFrame
= StackFrame
.AddrFrame
.Offset
- 8;
69 while(StackWalk64(MachineType
, data
.ProcessHandle
, thread
.Handle
, &StackFrame
, &thread
.Context
,
70 NULL
, SymFunctionTableAccess64
, SymGetModuleBase64
, NULL
))
72 if (!StackFrame
.AddrPC
.Offset
)
75 if (LastFrame
>= StackFrame
.AddrFrame
.Offset
)
78 LastFrame
= StackFrame
.AddrFrame
.Offset
;
82 xfprintf(output
, "FramePtr ReturnAd Param#1 Param#2 Param#3 Param#4 Function Name" NEWLINE
);
86 Module
.SizeOfStruct
= sizeof(Module
);
87 DWORD64 ModBase
= SymGetModuleBase64(data
.ProcessHandle
, StackFrame
.AddrPC
.Offset
);
88 if (!SymGetModuleInfo64(data
.ProcessHandle
, ModBase
, &Module
))
89 strcpy(Module
.ModuleName
, "<nomod>");
91 memset(sym
, '\0', sizeof(*sym
) + STACKWALK_MAX_NAMELEN
);
92 sym
->SizeOfStruct
= sizeof(*sym
);
93 sym
->MaxNameLen
= STACKWALK_MAX_NAMELEN
;
96 if (!SymFromAddr(data
.ProcessHandle
, StackFrame
.AddrPC
.Offset
, &displacement
, sym
))
97 strcpy(sym
->Name
, "<nosymbols>");
99 xfprintf(output
, "%p %p %p %p %p %p %s!%s" NEWLINE
,
100 (ULONG_PTR
)StackFrame
.AddrFrame
.Offset
, (ULONG_PTR
)StackFrame
.AddrPC
.Offset
,
101 (ULONG_PTR
)StackFrame
.Params
[0], (ULONG_PTR
)StackFrame
.Params
[1],
102 (ULONG_PTR
)StackFrame
.Params
[2], (ULONG_PTR
)StackFrame
.Params
[3],
103 Module
.ModuleName
, sym
->Name
);
106 UCHAR stackData
[0x10 * 10];
109 ULONG_PTR stackPointer
= thread
.Context
.Esp
;
110 #elif defined(_M_AMD64)
111 ULONG_PTR stackPointer
= thread
.Context
.Rsp
;
113 #error Unknown architecture
115 if (!ReadProcessMemory(data
.ProcessHandle
, (PVOID
)stackPointer
, stackData
, sizeof(stackData
), &sizeRead
))
118 xfprintf(output
, NEWLINE
"*----> Raw Stack Dump <----*" NEWLINE NEWLINE
);
119 for (size_t n
= 0; n
< sizeof(stackData
); n
+= 0x10)
121 char HexData1
[] = "?? ?? ?? ?? ?? ?? ?? ??";
122 char HexData2
[] = "?? ?? ?? ?? ?? ?? ?? ??";
123 char AsciiData1
[] = "????????";
124 char AsciiData2
[] = "????????";
126 for (size_t j
= 0; j
< 8; ++j
)
131 HexData1
[j
* 3] = ToChar(stackData
[idx
] >> 4);
132 HexData1
[j
* 3 + 1] = ToChar(stackData
[idx
] & 0xf);
133 AsciiData1
[j
] = isprint(stackData
[idx
]) ? stackData
[idx
] : '.';
138 HexData2
[j
* 3] = ToChar(stackData
[idx
] >> 4);
139 HexData2
[j
* 3 + 1] = ToChar(stackData
[idx
] & 0xf);
140 AsciiData2
[j
] = isprint(stackData
[idx
]) ? stackData
[idx
] : '.';
144 xfprintf(output
, "%p %s - %s %s%s" NEWLINE
, stackPointer
+n
, HexData1
, HexData2
, AsciiData1
, AsciiData2
);