VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmoddbghelp.cpp@ 84204

Last change on this file since 84204 was 83738, checked in by vboxsync, 5 years ago

iprt: Wrap Dbghelp.h to shut up complaints from VC++ 14.1. bugref:8489

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.2 KB
Line 
1/* $Id: dbgmoddbghelp.cpp 83738 2020-04-17 08:50:54Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader Using DbgHelp.dll if Present.
4 */
5
6/*
7 * Copyright (C) 2013-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DBG
32#include <iprt/dbg.h>
33#include "internal/iprt.h"
34
35#include <iprt/asm.h>
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/list.h>
39#include <iprt/log.h>
40#include <iprt/mem.h>
41#include <iprt/path.h>
42#include <iprt/string.h>
43#include <iprt/utf16.h>
44#include "internal/dbgmod.h"
45
46#include <iprt/win/windows.h>
47#include <iprt/win/dbghelp.h>
48#include <iprt/win/lazy-dbghelp.h>
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54/** For passing arguments to DbgHelp.dll callback. */
55typedef struct RTDBGMODBGHELPARGS
56{
57 RTDBGMOD hCnt;
58 PRTDBGMODINT pMod;
59 uint64_t uModAddr;
60 RTLDRADDR uNextRva;
61
62 /** UTF-8 version of the previous file name. */
63 char *pszPrev;
64 /** Copy of the previous file name. */
65 PRTUTF16 pwszPrev;
66 /** Number of bytes pwszPrev points to. */
67 size_t cbPrevUtf16Alloc;
68} RTDBGMODBGHELPARGS;
69
70
71/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
72static DECLCALLBACK(int) rtDbgModDbgHelp_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
73{
74 RT_NOREF(pMod, iSeg, off, pState);
75 return VERR_DBG_NO_UNWIND_INFO;
76}
77
78
79
80/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
81static DECLCALLBACK(int) rtDbgModDbgHelp_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
82 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
83{
84 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
85 return RTDbgModLineByAddr(hCnt, iSeg, off, poffDisp, pLineInfo);
86}
87
88
89/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
90static DECLCALLBACK(int) rtDbgModDbgHelp_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
91{
92 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
93 return RTDbgModLineByOrdinal(hCnt, iOrdinal, pLineInfo);
94}
95
96
97/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
98static DECLCALLBACK(uint32_t) rtDbgModDbgHelp_LineCount(PRTDBGMODINT pMod)
99{
100 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
101 return RTDbgModLineCount(hCnt);
102}
103
104
105/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
106static DECLCALLBACK(int) rtDbgModDbgHelp_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
107 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
108{
109 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
110 Assert(!pszFile[cchFile]); NOREF(cchFile);
111 return RTDbgModLineAdd(hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
112}
113
114
115/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
116static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
117 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
118{
119 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
120 return RTDbgModSymbolByAddr(hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
121}
122
123
124/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
125static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
126 PRTDBGSYMBOL pSymInfo)
127{
128 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
129 Assert(!pszSymbol[cchSymbol]); RT_NOREF_PV(cchSymbol);
130 return RTDbgModSymbolByName(hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
131}
132
133
134/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
135static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
136{
137 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
138 return RTDbgModSymbolByOrdinal(hCnt, iOrdinal, pSymInfo);
139}
140
141
142/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
143static DECLCALLBACK(uint32_t) rtDbgModDbgHelp_SymbolCount(PRTDBGMODINT pMod)
144{
145 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
146 return RTDbgModSymbolCount(hCnt);
147}
148
149
150/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
151static DECLCALLBACK(int) rtDbgModDbgHelp_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
152 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
153 uint32_t *piOrdinal)
154{
155 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
156 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
157 return RTDbgModSymbolAdd(hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
158}
159
160
161/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
162static DECLCALLBACK(int) rtDbgModDbgHelp_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
163{
164 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
165 return RTDbgModSegmentByIndex(hCnt, iSeg, pSegInfo);
166}
167
168
169/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
170static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDbgHelp_SegmentCount(PRTDBGMODINT pMod)
171{
172 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
173 return RTDbgModSegmentCount(hCnt);
174}
175
176
177/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
178static DECLCALLBACK(int) rtDbgModDbgHelp_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
179 uint32_t fFlags, PRTDBGSEGIDX piSeg)
180{
181 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
182 Assert(!pszName[cchName]); NOREF(cchName);
183 return RTDbgModSegmentAdd(hCnt, uRva, cb, pszName, fFlags, piSeg);
184}
185
186
187/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
188static DECLCALLBACK(RTUINTPTR) rtDbgModDbgHelp_ImageSize(PRTDBGMODINT pMod)
189{
190 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
191 RTUINTPTR cb1 = RTDbgModImageSize(hCnt);
192 RTUINTPTR cb2 = pMod->pImgVt->pfnImageSize(pMod);
193 return RT_MAX(cb1, cb2);
194}
195
196
197/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
198static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDbgHelp_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
199{
200 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
201 return RTDbgModRvaToSegOff(hCnt, uRva, poffSeg);
202}
203
204
205/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
206static DECLCALLBACK(int) rtDbgModDbgHelp_Close(PRTDBGMODINT pMod)
207{
208 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;;
209 RTDbgModRelease(hCnt);
210 pMod->pvDbgPriv = NULL;
211 return VINF_SUCCESS;
212}
213
214
215/**
216 * SymEnumLinesW callback that adds a line number to the container.
217 *
218 * @returns TRUE, FALSE if we're out of memory.
219 * @param pLineInfo Line number information.
220 * @param pvUser Pointer to a RTDBGMODBGHELPARGS structure.
221 */
222static BOOL CALLBACK rtDbgModDbgHelpCopyLineNumberCallback(PSRCCODEINFOW pLineInfo, PVOID pvUser)
223{
224 RTDBGMODBGHELPARGS *pArgs = (RTDBGMODBGHELPARGS *)pvUser;
225
226 if (pLineInfo->Address < pArgs->uModAddr)
227 {
228 Log((" %#018RX64 %05u %s [SKIPPED - INVALID ADDRESS!]\n", pLineInfo->Address, pLineInfo->LineNumber));
229 return TRUE;
230 }
231
232 /*
233 * To save having to call RTUtf16ToUtf8 every time, we keep a copy of the
234 * previous file name both as UTF-8 and UTF-16.
235 */
236 /** @todo we could combine RTUtf16Len and memcmp... */
237 size_t cbLen = (RTUtf16Len(pLineInfo->FileName) + 1) * sizeof(RTUTF16);
238 if ( !pArgs->pwszPrev
239 || memcmp(pArgs->pwszPrev, pLineInfo->FileName, cbLen) )
240 {
241 if (pArgs->cbPrevUtf16Alloc >= cbLen)
242 memcpy(pArgs->pwszPrev, pLineInfo->FileName, cbLen);
243 else
244 {
245 RTMemFree(pArgs->pwszPrev);
246 pArgs->cbPrevUtf16Alloc = cbLen;
247 pArgs->pwszPrev = (PRTUTF16)RTMemDupEx(pLineInfo->FileName, cbLen, pArgs->cbPrevUtf16Alloc - cbLen);
248 if (!pArgs->pwszPrev)
249 pArgs->cbPrevUtf16Alloc = 0;
250 }
251
252 RTStrFree(pArgs->pszPrev);
253 pArgs->pszPrev = NULL;
254 int rc = RTUtf16ToUtf8(pLineInfo->FileName, &pArgs->pszPrev);
255 if (RT_FAILURE(rc))
256 {
257 SetLastError(ERROR_OUTOFMEMORY);
258 Log(("rtDbgModDbgHelpCopyLineNumberCallback: Out of memory\n"));
259 return FALSE;
260 }
261 }
262
263 /*
264 * Add the line number to the container.
265 */
266 int rc = RTDbgModLineAdd(pArgs->hCnt, pArgs->pszPrev, pLineInfo->LineNumber,
267 RTDBGSEGIDX_RVA, pLineInfo->Address - pArgs->uModAddr, NULL);
268 Log((" %#018RX64 %05u %s [%Rrc]\n", pLineInfo->Address, pLineInfo->LineNumber, pArgs->pszPrev, rc));
269 NOREF(rc);
270
271 return TRUE;
272}
273
274
275/**
276 * Copies the line numbers into the container.
277 *
278 * @returns IPRT status code.
279 * @param pMod The debug module.
280 * @param hCnt The container that will keep the symbols.
281 * @param hFake The fake process handle.
282 * @param uModAddr The module load address.
283 */
284static int rtDbgModDbgHelpCopyLineNumbers(PRTDBGMODINT pMod, RTDBGMOD hCnt, HANDLE hFake, uint64_t uModAddr)
285{
286 RTDBGMODBGHELPARGS Args;
287 Args.hCnt = hCnt;
288 Args.pMod = pMod;
289 Args.uModAddr = uModAddr;
290 Args.pszPrev = NULL;
291 Args.pwszPrev = NULL;
292 Args.cbPrevUtf16Alloc = 0;
293
294 int rc;
295 if (SymEnumLinesW(hFake, uModAddr, NULL /*pszObj*/, NULL /*pszFile*/, rtDbgModDbgHelpCopyLineNumberCallback, &Args))
296 rc = VINF_SUCCESS;
297 else
298 {
299 rc = RTErrConvertFromWin32(GetLastError());
300 Log(("Line number enum: %Rrc (%u)\n", rc, GetLastError()));
301 if (rc == VERR_NOT_SUPPORTED)
302 rc = VINF_SUCCESS;
303 }
304
305 RTStrFree(Args.pszPrev);
306 RTMemFree(Args.pwszPrev);
307 return rc;
308}
309
310
311/**
312 * SymEnumSymbols callback that adds a symbol to the container.
313 *
314 * @returns TRUE
315 * @param pSymInfo The symbol information.
316 * @param cbSymbol The symbol size (estimated).
317 * @param pvUser Pointer to a RTDBGMODBGHELPARGS structure.
318 */
319static BOOL CALLBACK rtDbgModDbgHelpCopySymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG cbSymbol, PVOID pvUser)
320{
321 RTDBGMODBGHELPARGS *pArgs = (RTDBGMODBGHELPARGS *)pvUser;
322 if (pSymInfo->Address < pArgs->uModAddr) /* NT4 SP1 ntfs.dbg */
323 {
324 Log((" %#018RX64 LB %#07x %s [SKIPPED - INVALID ADDRESS!]\n", pSymInfo->Address, cbSymbol, pSymInfo->Name));
325 return TRUE;
326 }
327 if (pSymInfo->NameLen >= RTDBG_SYMBOL_NAME_LENGTH)
328 {
329 Log((" %#018RX64 LB %#07x %s [SKIPPED - TOO LONG (%u > %u)!]\n", pSymInfo->Address, cbSymbol, pSymInfo->Name,
330 pSymInfo->NameLen, RTDBG_SYMBOL_NAME_LENGTH));
331 return TRUE;
332 }
333
334 /* ASSUMES the symbol name is ASCII. */
335 int rc = RTDbgModSymbolAdd(pArgs->hCnt, pSymInfo->Name, RTDBGSEGIDX_RVA,
336 pSymInfo->Address - pArgs->uModAddr, cbSymbol, 0, NULL);
337 Log((" %#018RX64 LB %#07x %s [%Rrc]\n", pSymInfo->Address, cbSymbol, pSymInfo->Name, rc));
338 NOREF(rc);
339
340 return TRUE;
341}
342
343
344/**
345 * Copies the symbols into the container.
346 *
347 * @returns IPRT status code.
348 * @param pMod The debug module.
349 * @param hCnt The container that will keep the symbols.
350 * @param hFake The fake process handle.
351 * @param uModAddr The module load address.
352 */
353static int rtDbgModDbgHelpCopySymbols(PRTDBGMODINT pMod, RTDBGMOD hCnt, HANDLE hFake, uint64_t uModAddr)
354{
355 RTDBGMODBGHELPARGS Args;
356 Args.hCnt = hCnt;
357 Args.pMod = pMod;
358 Args.uModAddr = uModAddr;
359 int rc;
360 if (SymEnumSymbols(hFake, uModAddr, NULL, rtDbgModDbgHelpCopySymbolsCallback, &Args))
361 rc = VINF_SUCCESS;
362 else
363 {
364 rc = RTErrConvertFromWin32(GetLastError());
365 Log(("SymEnumSymbols: %Rrc (%u)\n", rc, GetLastError()));
366 }
367 return rc;
368}
369
370
371/** @callback_method_impl{FNRTLDRENUMSEGS,
372 * Copies the PE segments over into the container.} */
373static DECLCALLBACK(int) rtDbgModDbgHelpAddSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
374{
375 RTDBGMODBGHELPARGS *pArgs = (RTDBGMODBGHELPARGS *)pvUser;
376 RT_NOREF_PV(hLdrMod);
377
378 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx\n",
379 pSeg->cchName, pSeg->pszName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb));
380
381 Assert(pSeg->cchName > 0);
382 Assert(!pSeg->pszName[pSeg->cchName]);
383
384 RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
385 RTLDRADDR uRva = pSeg->RVA;
386 if (!uRva)
387 pArgs->uModAddr = pSeg->LinkAddress;
388 else if (uRva == NIL_RTLDRADDR)
389 {
390 cb = 0;
391 uRva = pArgs->uNextRva;
392 }
393 pArgs->uNextRva = uRva + cb;
394
395 return RTDbgModSegmentAdd(pArgs->hCnt, uRva, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
396}
397
398
399/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
400static DECLCALLBACK(int) rtDbgModDbgHelp_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
401{
402 NOREF(enmArch);
403
404 /*
405 * Currently only support external files with a executable already present.
406 */
407 if (!pMod->pszDbgFile)
408 return VERR_DBG_NO_MATCHING_INTERPRETER;
409 if (!pMod->pImgVt)
410 return VERR_DBG_NO_MATCHING_INTERPRETER;
411
412 /*
413 * Create a container for copying the information into. We do this early
414 * so we can determine the image base address.
415 */
416 RTDBGMOD hCnt;
417 int rc = RTDbgModCreate(&hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
418 if (RT_SUCCESS(rc))
419 {
420 RTDBGMODBGHELPARGS Args;
421 RT_ZERO(Args);
422 Args.hCnt = hCnt;
423 rc = pMod->pImgVt->pfnEnumSegments(pMod, rtDbgModDbgHelpAddSegmentsCallback, &Args);
424 if (RT_SUCCESS(rc))
425 {
426 uint32_t cbImage = pMod->pImgVt->pfnImageSize(pMod);
427 uint64_t uImageBase = Args.uModAddr ? Args.uModAddr : 0x4000000;
428
429 /*
430 * Try load the module into an empty address space.
431 */
432 static uint32_t volatile s_uFakeHandle = 0x3940000;
433 HANDLE hFake;
434 do
435 hFake = (HANDLE)(uintptr_t)ASMAtomicIncU32(&s_uFakeHandle);
436 while (hFake == NULL || hFake == INVALID_HANDLE_VALUE);
437
438 LogFlow(("rtDbgModDbgHelp_TryOpen: \n"));
439 if (SymInitialize(hFake, NULL /*SearchPath*/, FALSE /*fInvalidProcess*/))
440 {
441 SymSetOptions(SYMOPT_LOAD_LINES | SymGetOptions());
442
443 PRTUTF16 pwszDbgFile;
444 rc = RTStrToUtf16(pMod->pszDbgFile, &pwszDbgFile);
445 if (RT_SUCCESS(rc))
446 {
447 uint64_t uModAddr = SymLoadModuleExW(hFake, NULL /*hFile*/, pwszDbgFile, NULL /*pszModName*/,
448 uImageBase, cbImage, NULL /*pModData*/, 0 /*fFlags*/);
449 if (uModAddr != 0)
450 {
451 rc = rtDbgModDbgHelpCopySymbols(pMod, hCnt, hFake, uModAddr);
452 if (RT_SUCCESS(rc))
453 rc = rtDbgModDbgHelpCopyLineNumbers(pMod, hCnt, hFake, uModAddr);
454 if (RT_SUCCESS(rc))
455 {
456 pMod->pvDbgPriv = hCnt;
457 pMod->pDbgVt = &g_rtDbgModVtDbgDbgHelp;
458 hCnt = NIL_RTDBGMOD;
459 LogFlow(("rtDbgModDbgHelp_TryOpen: Successfully loaded '%s' at %#llx\n",
460 pMod->pszDbgFile, (uint64_t)uImageBase));
461 }
462
463 SymUnloadModule64(hFake, uModAddr);
464 }
465 else
466 {
467 rc = RTErrConvertFromWin32(GetLastError());
468 if (RT_SUCCESS_NP(rc))
469 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
470 LogFlow(("rtDbgModDbgHelp_TryOpen: Error loading the module '%s' at %#llx: %Rrc (%u)\n",
471 pMod->pszDbgFile, (uint64_t)uImageBase, rc, GetLastError()));
472 }
473 RTUtf16Free(pwszDbgFile);
474 }
475 else
476 LogFlow(("rtDbgModDbgHelp_TryOpen: Unicode version issue: %Rrc\n", rc));
477
478 BOOL fRc2 = SymCleanup(hFake); Assert(fRc2); NOREF(fRc2);
479 }
480 else
481 {
482 rc = RTErrConvertFromWin32(GetLastError());
483 if (RT_SUCCESS_NP(rc))
484 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
485 LogFlow(("rtDbgModDbgHelp_TryOpen: SymInitialize failed: %Rrc (%u)\n", rc, GetLastError()));
486 }
487 }
488 RTDbgModRelease(hCnt);
489 }
490 return rc;
491}
492
493
494
495/** Virtual function table for the DBGHELP debug info reader. */
496DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDbgHelp =
497{
498 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
499 /*.fSupports = */ RT_DBGTYPE_CODEVIEW,
500 /*.pszName = */ "dbghelp",
501 /*.pfnTryOpen = */ rtDbgModDbgHelp_TryOpen,
502 /*.pfnClose = */ rtDbgModDbgHelp_Close,
503
504 /*.pfnRvaToSegOff = */ rtDbgModDbgHelp_RvaToSegOff,
505 /*.pfnImageSize = */ rtDbgModDbgHelp_ImageSize,
506
507 /*.pfnSegmentAdd = */ rtDbgModDbgHelp_SegmentAdd,
508 /*.pfnSegmentCount = */ rtDbgModDbgHelp_SegmentCount,
509 /*.pfnSegmentByIndex = */ rtDbgModDbgHelp_SegmentByIndex,
510
511 /*.pfnSymbolAdd = */ rtDbgModDbgHelp_SymbolAdd,
512 /*.pfnSymbolCount = */ rtDbgModDbgHelp_SymbolCount,
513 /*.pfnSymbolByOrdinal = */ rtDbgModDbgHelp_SymbolByOrdinal,
514 /*.pfnSymbolByName = */ rtDbgModDbgHelp_SymbolByName,
515 /*.pfnSymbolByAddr = */ rtDbgModDbgHelp_SymbolByAddr,
516
517 /*.pfnLineAdd = */ rtDbgModDbgHelp_LineAdd,
518 /*.pfnLineCount = */ rtDbgModDbgHelp_LineCount,
519 /*.pfnLineByOrdinal = */ rtDbgModDbgHelp_LineByOrdinal,
520 /*.pfnLineByAddr = */ rtDbgModDbgHelp_LineByAddr,
521
522 /*.pfnUnwindFrame = */ rtDbgModDbgHelp_UnwindFrame,
523
524 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
525};
526
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette