4 * Copyright 1995 Alexandre Julliard
5 * Copyright 1996 Eric Youngdale
6 * Copyright 1999 Ove Kåven
7 * Copyright 2004 Eric Pouech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "dbghelp_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
35 static DWORD64 WINAPI
addr_to_linear(HANDLE hProcess
, HANDLE hThread
, ADDRESS64
* addr
)
42 if (GetThreadSelectorEntry(hThread
, addr
->Segment
, &le
))
43 return (le
.HighWord
.Bits
.BaseHi
<< 24) +
44 (le
.HighWord
.Bits
.BaseMid
<< 16) + le
.BaseLow
+ LOWORD(addr
->Offset
);
47 if (GetThreadSelectorEntry(hThread
, addr
->Segment
, &le
))
48 return (le
.HighWord
.Bits
.BaseHi
<< 24) +
49 (le
.HighWord
.Bits
.BaseMid
<< 16) + le
.BaseLow
+ addr
->Offset
;
52 return (DWORD
)(LOWORD(addr
->Segment
) << 4) + addr
->Offset
;
56 FIXME("Unsupported (yet) mode (%x)\n", addr
->Mode
);
59 FIXME("Failed to linearize address %04x:%s (mode %x)\n",
60 addr
->Segment
, wine_dbgstr_longlong(addr
->Offset
), addr
->Mode
);
64 static BOOL CALLBACK
read_mem(HANDLE hProcess
, DWORD addr
, void* buffer
,
65 DWORD size
, LPDWORD nread
)
68 if (!ReadProcessMemory(hProcess
, (void*)(DWORD_PTR
)addr
, buffer
, size
, &r
)) return FALSE
;
69 if (nread
) *nread
= r
;
73 static BOOL CALLBACK
read_mem64(HANDLE hProcess
, DWORD64 addr
, void* buffer
,
74 DWORD size
, LPDWORD nread
)
77 if (!ReadProcessMemory(hProcess
, (void*)(DWORD_PTR
)addr
, buffer
, size
, &r
)) return FALSE
;
78 if (nread
) *nread
= r
;
82 static inline void addr_32to64(const ADDRESS
* addr32
, ADDRESS64
* addr64
)
84 addr64
->Offset
= (ULONG64
)addr32
->Offset
;
85 addr64
->Segment
= addr32
->Segment
;
86 addr64
->Mode
= addr32
->Mode
;
89 static inline void addr_64to32(const ADDRESS64
* addr64
, ADDRESS
* addr32
)
91 addr32
->Offset
= (ULONG
)addr64
->Offset
;
92 addr32
->Segment
= addr64
->Segment
;
93 addr32
->Mode
= addr64
->Mode
;
96 BOOL
sw_read_mem(struct cpu_stack_walk
* csw
, DWORD64 addr
, void* ptr
, DWORD sz
)
99 return csw
->u
.s32
.f_read_mem(csw
->hProcess
, addr
, ptr
, sz
, NULL
);
101 return csw
->u
.s64
.f_read_mem(csw
->hProcess
, addr
, ptr
, sz
, NULL
);
104 DWORD64
sw_xlat_addr(struct cpu_stack_walk
* csw
, ADDRESS64
* addr
)
106 if (addr
->Mode
== AddrModeFlat
) return addr
->Offset
;
111 addr_64to32(addr
, &addr32
);
112 return csw
->u
.s32
.f_xlat_adr(csw
->hProcess
, csw
->hThread
, &addr32
);
114 else if (csw
->u
.s64
.f_xlat_adr
)
115 return csw
->u
.s64
.f_xlat_adr(csw
->hProcess
, csw
->hThread
, addr
);
116 return addr_to_linear(csw
->hProcess
, csw
->hThread
, addr
);
119 void* sw_table_access(struct cpu_stack_walk
* csw
, DWORD64 addr
)
122 return csw
->u
.s32
.f_tabl_acs(csw
->hProcess
, addr
);
124 return csw
->u
.s64
.f_tabl_acs(csw
->hProcess
, addr
);
127 DWORD64
sw_module_base(struct cpu_stack_walk
* csw
, DWORD64 addr
)
130 return csw
->u
.s32
.f_modl_bas(csw
->hProcess
, addr
);
132 return csw
->u
.s64
.f_modl_bas(csw
->hProcess
, addr
);
135 /***********************************************************************
136 * StackWalk (DBGHELP.@)
138 BOOL WINAPI
StackWalk(DWORD MachineType
, HANDLE hProcess
, HANDLE hThread
,
139 LPSTACKFRAME frame32
, PVOID ctx
,
140 PREAD_PROCESS_MEMORY_ROUTINE f_read_mem
,
141 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine
,
142 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine
,
143 PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr
)
145 struct cpu_stack_walk csw
;
146 STACKFRAME64 frame64
;
150 TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
151 MachineType
, hProcess
, hThread
, frame32
, ctx
,
152 f_read_mem
, FunctionTableAccessRoutine
,
153 GetModuleBaseRoutine
, f_xlat_adr
);
155 if (!(cpu
= cpu_find(MachineType
)))
157 SetLastError(ERROR_INVALID_PARAMETER
);
161 addr_32to64(&frame32
->AddrPC
, &frame64
.AddrPC
);
162 addr_32to64(&frame32
->AddrReturn
, &frame64
.AddrReturn
);
163 addr_32to64(&frame32
->AddrFrame
, &frame64
.AddrFrame
);
164 addr_32to64(&frame32
->AddrStack
, &frame64
.AddrStack
);
165 addr_32to64(&frame32
->AddrBStore
, &frame64
.AddrBStore
);
166 frame64
.FuncTableEntry
= frame32
->FuncTableEntry
; /* FIXME */
167 frame64
.Far
= frame32
->Far
;
168 frame64
.Virtual
= frame32
->Virtual
;
169 frame64
.Reserved
[0] = frame32
->Reserved
[0];
170 frame64
.Reserved
[1] = frame32
->Reserved
[1];
171 frame64
.Reserved
[2] = frame32
->Reserved
[2];
172 /* we don't handle KdHelp */
174 csw
.hProcess
= hProcess
;
175 csw
.hThread
= hThread
;
177 /* sigh... MS isn't even consistent in the func prototypes */
178 csw
.u
.s32
.f_read_mem
= (f_read_mem
) ? f_read_mem
: read_mem
;
179 csw
.u
.s32
.f_xlat_adr
= f_xlat_adr
;
180 csw
.u
.s32
.f_tabl_acs
= (FunctionTableAccessRoutine
) ? FunctionTableAccessRoutine
: SymFunctionTableAccess
;
181 csw
.u
.s32
.f_modl_bas
= (GetModuleBaseRoutine
) ? GetModuleBaseRoutine
: SymGetModuleBase
;
183 if ((ret
= cpu
->stack_walk(&csw
, &frame64
, ctx
)))
185 addr_64to32(&frame64
.AddrPC
, &frame32
->AddrPC
);
186 addr_64to32(&frame64
.AddrReturn
, &frame32
->AddrReturn
);
187 addr_64to32(&frame64
.AddrFrame
, &frame32
->AddrFrame
);
188 addr_64to32(&frame64
.AddrStack
, &frame32
->AddrStack
);
189 addr_64to32(&frame64
.AddrBStore
, &frame32
->AddrBStore
);
190 frame32
->FuncTableEntry
= frame64
.FuncTableEntry
; /* FIXME */
191 frame32
->Params
[0] = frame64
.Params
[0];
192 frame32
->Params
[1] = frame64
.Params
[1];
193 frame32
->Params
[2] = frame64
.Params
[2];
194 frame32
->Params
[3] = frame64
.Params
[3];
195 frame32
->Far
= frame64
.Far
;
196 frame32
->Virtual
= frame64
.Virtual
;
197 frame32
->Reserved
[0] = frame64
.Reserved
[0];
198 frame32
->Reserved
[1] = frame64
.Reserved
[1];
199 frame32
->Reserved
[2] = frame64
.Reserved
[2];
206 /***********************************************************************
207 * StackWalk64 (DBGHELP.@)
209 BOOL WINAPI
StackWalk64(DWORD MachineType
, HANDLE hProcess
, HANDLE hThread
,
210 LPSTACKFRAME64 frame
, PVOID ctx
,
211 PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem
,
212 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine
,
213 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine
,
214 PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr
)
216 struct cpu_stack_walk csw
;
219 TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
220 MachineType
, hProcess
, hThread
, frame
, ctx
,
221 f_read_mem
, FunctionTableAccessRoutine
,
222 GetModuleBaseRoutine
, f_xlat_adr
);
224 if (!(cpu
= cpu_find(MachineType
)))
226 SetLastError(ERROR_INVALID_PARAMETER
);
230 csw
.hProcess
= hProcess
;
231 csw
.hThread
= hThread
;
233 /* sigh... MS isn't even consistent in the func prototypes */
234 csw
.u
.s64
.f_read_mem
= (f_read_mem
) ? f_read_mem
: read_mem64
;
235 csw
.u
.s64
.f_xlat_adr
= (f_xlat_adr
) ? f_xlat_adr
: addr_to_linear
;
236 csw
.u
.s64
.f_tabl_acs
= (FunctionTableAccessRoutine
) ? FunctionTableAccessRoutine
: SymFunctionTableAccess64
;
237 csw
.u
.s64
.f_modl_bas
= (GetModuleBaseRoutine
) ? GetModuleBaseRoutine
: SymGetModuleBase64
;
239 if (!cpu
->stack_walk(&csw
, frame
, ctx
)) return FALSE
;
241 /* we don't handle KdHelp */
242 frame
->KdHelp
.Thread
= 0xC000FADE;
243 frame
->KdHelp
.ThCallbackStack
= 0x10;
244 frame
->KdHelp
.ThCallbackBStore
= 0;
245 frame
->KdHelp
.NextCallback
= 0;
246 frame
->KdHelp
.FramePointer
= 0;
247 frame
->KdHelp
.KiCallUserMode
= 0xD000DAFE;
248 frame
->KdHelp
.KeUserCallbackDispatcher
= 0xE000F000;
249 frame
->KdHelp
.SystemRangeStart
= 0xC0000000;
250 frame
->KdHelp
.Reserved
[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
255 /******************************************************************
256 * SymRegisterFunctionEntryCallback (DBGHELP.@)
260 BOOL WINAPI
SymRegisterFunctionEntryCallback(HANDLE hProc
,
261 PSYMBOL_FUNCENTRY_CALLBACK cb
, PVOID user
)
263 FIXME("(%p %p %p): stub!\n", hProc
, cb
, user
);
264 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
268 /******************************************************************
269 * SymRegisterFunctionEntryCallback64 (DBGHELP.@)
273 BOOL WINAPI
SymRegisterFunctionEntryCallback64(HANDLE hProc
,
274 PSYMBOL_FUNCENTRY_CALLBACK64 cb
,
277 FIXME("(%p %p %s): stub!\n", hProc
, cb
, wine_dbgstr_longlong(user
));
278 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);