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
)
100 return csw
->u
.s32
.f_read_mem(csw
->hProcess
, addr
, ptr
, sz
, &bytes_read
);
102 return csw
->u
.s64
.f_read_mem(csw
->hProcess
, addr
, ptr
, sz
, &bytes_read
);
105 DWORD64
sw_xlat_addr(struct cpu_stack_walk
* csw
, ADDRESS64
* addr
)
107 if (addr
->Mode
== AddrModeFlat
) return addr
->Offset
;
112 addr_64to32(addr
, &addr32
);
113 return csw
->u
.s32
.f_xlat_adr(csw
->hProcess
, csw
->hThread
, &addr32
);
115 else if (csw
->u
.s64
.f_xlat_adr
)
116 return csw
->u
.s64
.f_xlat_adr(csw
->hProcess
, csw
->hThread
, addr
);
117 return addr_to_linear(csw
->hProcess
, csw
->hThread
, addr
);
120 void* sw_table_access(struct cpu_stack_walk
* csw
, DWORD64 addr
)
123 return csw
->u
.s32
.f_tabl_acs(csw
->hProcess
, addr
);
125 return csw
->u
.s64
.f_tabl_acs(csw
->hProcess
, addr
);
128 DWORD64
sw_module_base(struct cpu_stack_walk
* csw
, DWORD64 addr
)
131 return csw
->u
.s32
.f_modl_bas(csw
->hProcess
, addr
);
133 return csw
->u
.s64
.f_modl_bas(csw
->hProcess
, addr
);
136 /***********************************************************************
137 * StackWalk (DBGHELP.@)
139 BOOL WINAPI
StackWalk(DWORD MachineType
, HANDLE hProcess
, HANDLE hThread
,
140 LPSTACKFRAME frame32
, PVOID ctx
,
141 PREAD_PROCESS_MEMORY_ROUTINE f_read_mem
,
142 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine
,
143 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine
,
144 PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr
)
146 struct cpu_stack_walk csw
;
147 STACKFRAME64 frame64
;
151 TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
152 MachineType
, hProcess
, hThread
, frame32
, ctx
,
153 f_read_mem
, FunctionTableAccessRoutine
,
154 GetModuleBaseRoutine
, f_xlat_adr
);
156 if (!(cpu
= cpu_find(MachineType
)))
158 SetLastError(ERROR_INVALID_PARAMETER
);
162 addr_32to64(&frame32
->AddrPC
, &frame64
.AddrPC
);
163 addr_32to64(&frame32
->AddrReturn
, &frame64
.AddrReturn
);
164 addr_32to64(&frame32
->AddrFrame
, &frame64
.AddrFrame
);
165 addr_32to64(&frame32
->AddrStack
, &frame64
.AddrStack
);
166 addr_32to64(&frame32
->AddrBStore
, &frame64
.AddrBStore
);
167 frame64
.FuncTableEntry
= frame32
->FuncTableEntry
; /* FIXME */
168 frame64
.Far
= frame32
->Far
;
169 frame64
.Virtual
= frame32
->Virtual
;
170 frame64
.Reserved
[0] = frame32
->Reserved
[0];
171 frame64
.Reserved
[1] = frame32
->Reserved
[1];
172 frame64
.Reserved
[2] = frame32
->Reserved
[2];
173 /* we don't handle KdHelp */
175 csw
.hProcess
= hProcess
;
176 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
;
234 /* sigh... MS isn't even consistent in the func prototypes */
235 csw
.u
.s64
.f_read_mem
= (f_read_mem
) ? f_read_mem
: read_mem64
;
236 csw
.u
.s64
.f_xlat_adr
= (f_xlat_adr
) ? f_xlat_adr
: addr_to_linear
;
237 csw
.u
.s64
.f_tabl_acs
= (FunctionTableAccessRoutine
) ? FunctionTableAccessRoutine
: SymFunctionTableAccess64
;
238 csw
.u
.s64
.f_modl_bas
= (GetModuleBaseRoutine
) ? GetModuleBaseRoutine
: SymGetModuleBase64
;
240 if (!cpu
->stack_walk(&csw
, frame
, ctx
)) return FALSE
;
242 /* we don't handle KdHelp */
247 /******************************************************************
248 * SymRegisterFunctionEntryCallback (DBGHELP.@)
252 BOOL WINAPI
SymRegisterFunctionEntryCallback(HANDLE hProc
,
253 PSYMBOL_FUNCENTRY_CALLBACK cb
, PVOID user
)
255 FIXME("(%p %p %p): stub!\n", hProc
, cb
, user
);
256 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
260 /******************************************************************
261 * SymRegisterFunctionEntryCallback64 (DBGHELP.@)
265 BOOL WINAPI
SymRegisterFunctionEntryCallback64(HANDLE hProc
,
266 PSYMBOL_FUNCENTRY_CALLBACK64 cb
,
269 FIXME("(%p %p %s): stub!\n", hProc
, cb
, wine_dbgstr_longlong(user
));
270 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);