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
29 #include "dbghelp_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
34 static DWORD64 WINAPI
addr_to_linear(HANDLE hProcess
, HANDLE hThread
, ADDRESS64
* addr
)
41 if (GetThreadSelectorEntry(hThread
, addr
->Segment
, &le
))
42 return (le
.HighWord
.Bits
.BaseHi
<< 24) +
43 (le
.HighWord
.Bits
.BaseMid
<< 16) + le
.BaseLow
+ LOWORD(addr
->Offset
);
46 if (GetThreadSelectorEntry(hThread
, addr
->Segment
, &le
))
47 return (le
.HighWord
.Bits
.BaseHi
<< 24) +
48 (le
.HighWord
.Bits
.BaseMid
<< 16) + le
.BaseLow
+ addr
->Offset
;
51 return (DWORD
)(LOWORD(addr
->Segment
) << 4) + addr
->Offset
;
55 FIXME("Unsupported (yet) mode (%x)\n", addr
->Mode
);
58 FIXME("Failed to linearize address %04x:%s (mode %x)\n",
59 addr
->Segment
, wine_dbgstr_longlong(addr
->Offset
), addr
->Mode
);
63 static BOOL CALLBACK
read_mem(HANDLE hProcess
, DWORD addr
, void* buffer
,
64 DWORD size
, LPDWORD nread
)
67 if (!ReadProcessMemory(hProcess
, (void*)(DWORD_PTR
)addr
, buffer
, size
, &r
)) return FALSE
;
68 if (nread
) *nread
= r
;
72 static BOOL CALLBACK
read_mem64(HANDLE hProcess
, DWORD64 addr
, void* buffer
,
73 DWORD size
, LPDWORD nread
)
76 if (!ReadProcessMemory(hProcess
, (void*)(DWORD_PTR
)addr
, buffer
, size
, &r
)) return FALSE
;
77 if (nread
) *nread
= r
;
81 static inline void addr_32to64(const ADDRESS
* addr32
, ADDRESS64
* addr64
)
83 addr64
->Offset
= (ULONG64
)addr32
->Offset
;
84 addr64
->Segment
= addr32
->Segment
;
85 addr64
->Mode
= addr32
->Mode
;
88 static inline void addr_64to32(const ADDRESS64
* addr64
, ADDRESS
* addr32
)
90 addr32
->Offset
= (ULONG
)addr64
->Offset
;
91 addr32
->Segment
= addr64
->Segment
;
92 addr32
->Mode
= addr64
->Mode
;
95 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
, &bytes_read
);
101 return csw
->u
.s64
.f_read_mem(csw
->hProcess
, addr
, ptr
, sz
, &bytes_read
);
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
;
178 /* sigh... MS isn't even consistent in the func prototypes */
179 csw
.u
.s32
.f_read_mem
= (f_read_mem
) ? f_read_mem
: read_mem
;
180 csw
.u
.s32
.f_xlat_adr
= f_xlat_adr
;
181 csw
.u
.s32
.f_tabl_acs
= (FunctionTableAccessRoutine
) ? FunctionTableAccessRoutine
: SymFunctionTableAccess
;
182 csw
.u
.s32
.f_modl_bas
= (GetModuleBaseRoutine
) ? GetModuleBaseRoutine
: SymGetModuleBase
;
184 if ((ret
= cpu
->stack_walk(&csw
, &frame64
, ctx
)))
186 addr_64to32(&frame64
.AddrPC
, &frame32
->AddrPC
);
187 addr_64to32(&frame64
.AddrReturn
, &frame32
->AddrReturn
);
188 addr_64to32(&frame64
.AddrFrame
, &frame32
->AddrFrame
);
189 addr_64to32(&frame64
.AddrStack
, &frame32
->AddrStack
);
190 addr_64to32(&frame64
.AddrBStore
, &frame32
->AddrBStore
);
191 frame32
->FuncTableEntry
= frame64
.FuncTableEntry
; /* FIXME */
192 frame32
->Params
[0] = frame64
.Params
[0];
193 frame32
->Params
[1] = frame64
.Params
[1];
194 frame32
->Params
[2] = frame64
.Params
[2];
195 frame32
->Params
[3] = frame64
.Params
[3];
196 frame32
->Far
= frame64
.Far
;
197 frame32
->Virtual
= frame64
.Virtual
;
198 frame32
->Reserved
[0] = frame64
.Reserved
[0];
199 frame32
->Reserved
[1] = frame64
.Reserved
[1];
200 frame32
->Reserved
[2] = frame64
.Reserved
[2];
207 /***********************************************************************
208 * StackWalk64 (DBGHELP.@)
210 BOOL WINAPI
StackWalk64(DWORD MachineType
, HANDLE hProcess
, HANDLE hThread
,
211 LPSTACKFRAME64 frame
, PVOID ctx
,
212 PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem
,
213 PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine
,
214 PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine
,
215 PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr
)
217 struct cpu_stack_walk csw
;
220 TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
221 MachineType
, hProcess
, hThread
, frame
, ctx
,
222 f_read_mem
, FunctionTableAccessRoutine
,
223 GetModuleBaseRoutine
, f_xlat_adr
);
225 if (!(cpu
= cpu_find(MachineType
)))
227 SetLastError(ERROR_INVALID_PARAMETER
);
231 csw
.hProcess
= hProcess
;
232 csw
.hThread
= hThread
;
235 /* sigh... MS isn't even consistent in the func prototypes */
236 csw
.u
.s64
.f_read_mem
= (f_read_mem
) ? f_read_mem
: read_mem64
;
237 csw
.u
.s64
.f_xlat_adr
= (f_xlat_adr
) ? f_xlat_adr
: addr_to_linear
;
238 csw
.u
.s64
.f_tabl_acs
= (FunctionTableAccessRoutine
) ? FunctionTableAccessRoutine
: SymFunctionTableAccess64
;
239 csw
.u
.s64
.f_modl_bas
= (GetModuleBaseRoutine
) ? GetModuleBaseRoutine
: SymGetModuleBase64
;
241 if (!cpu
->stack_walk(&csw
, frame
, ctx
)) return FALSE
;
243 /* we don't handle KdHelp */
248 /******************************************************************
249 * SymRegisterFunctionEntryCallback (DBGHELP.@)
253 BOOL WINAPI
SymRegisterFunctionEntryCallback(HANDLE hProc
,
254 PSYMBOL_FUNCENTRY_CALLBACK cb
, PVOID user
)
256 FIXME("(%p %p %p): stub!\n", hProc
, cb
, user
);
257 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
261 /******************************************************************
262 * SymRegisterFunctionEntryCallback64 (DBGHELP.@)
266 BOOL WINAPI
SymRegisterFunctionEntryCallback64(HANDLE hProc
,
267 PSYMBOL_FUNCENTRY_CALLBACK64 cb
,
270 FIXME("(%p %p %s): stub!\n", hProc
, cb
, wine_dbgstr_longlong(user
));
271 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);