VirtualBox

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

Last change on this file was 100931, checked in by vboxsync, 9 months ago

IPRT/dbg: Early PDB support.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use