VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmodnm.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: 20.7 KB
Line 
1/* $Id: dbgmodnm.cpp 100931 2023-08-21 23:11:01Z vboxsync $ */
2/** @file
3 * IPRT - Debug Map Reader For NM Like Mapfiles.
4 */
5
6/*
7 * Copyright (C) 2009-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#include <iprt/dbg.h>
42#include "internal/iprt.h"
43
44#include <iprt/err.h>
45#include <iprt/ctype.h>
46#include <iprt/mem.h>
47#include <iprt/stream.h>
48#include <iprt/string.h>
49#include "internal/dbgmod.h"
50
51
52/*********************************************************************************************************************************
53* Structures and Typedefs *
54*********************************************************************************************************************************/
55/**
56 * Instance data.
57 */
58typedef struct RTDBGMODNM
59{
60 /** The debug container containing doing the real work. */
61 RTDBGMOD hCnt;
62} RTDBGMODNM;
63/** Pointer to instance data NM map reader. */
64typedef RTDBGMODNM *PRTDBGMODNM;
65
66
67
68/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
69static DECLCALLBACK(int) rtDbgModNm_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
70{
71 RT_NOREF(pMod, iSeg, off, pState);
72 return VERR_DBG_NO_UNWIND_INFO;
73}
74
75
76/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
77static DECLCALLBACK(int) rtDbgModNm_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
78 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
79{
80 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
81 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
82}
83
84
85/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
86static DECLCALLBACK(int) rtDbgModNm_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
87{
88 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
89 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
90}
91
92
93/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
94static DECLCALLBACK(uint32_t) rtDbgModNm_LineCount(PRTDBGMODINT pMod)
95{
96 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
97 return RTDbgModLineCount(pThis->hCnt);
98}
99
100
101/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
102static DECLCALLBACK(int) rtDbgModNm_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
103 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
104{
105 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
106 Assert(!pszFile[cchFile]); NOREF(cchFile);
107 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
108}
109
110
111/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
112static DECLCALLBACK(int) rtDbgModNm_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
113 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
114{
115 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
116 return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
117}
118
119
120/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
121static DECLCALLBACK(int) rtDbgModNm_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
122 PRTDBGSYMBOL pSymInfo)
123{
124 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
125 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
126 return RTDbgModSymbolByName(pThis->hCnt, pszSymbol, pSymInfo);
127}
128
129
130/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
131static DECLCALLBACK(int) rtDbgModNm_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
132{
133 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
134 return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
135}
136
137
138/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
139static DECLCALLBACK(uint32_t) rtDbgModNm_SymbolCount(PRTDBGMODINT pMod)
140{
141 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
142 return RTDbgModSymbolCount(pThis->hCnt);
143}
144
145
146/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
147static DECLCALLBACK(int) rtDbgModNm_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
148 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
149 uint32_t *piOrdinal)
150{
151 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
152 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
153 return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
154}
155
156
157/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
158static DECLCALLBACK(int) rtDbgModNm_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
159{
160 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
161 return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
162}
163
164
165/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
166static DECLCALLBACK(RTDBGSEGIDX) rtDbgModNm_SegmentCount(PRTDBGMODINT pMod)
167{
168 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
169 return RTDbgModSegmentCount(pThis->hCnt);
170}
171
172
173/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
174static DECLCALLBACK(int) rtDbgModNm_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
175 size_t cchName, uint32_t fFlags, PRTDBGSEGIDX piSeg)
176{
177 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
178 Assert(!pszName[cchName]); NOREF(cchName);
179 return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
180}
181
182
183/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
184static DECLCALLBACK(RTUINTPTR) rtDbgModNm_ImageSize(PRTDBGMODINT pMod)
185{
186 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
187 return RTDbgModImageSize(pThis->hCnt);
188}
189
190
191/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
192static DECLCALLBACK(RTDBGSEGIDX) rtDbgModNm_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
193{
194 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
195 return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
196}
197
198
199/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
200static DECLCALLBACK(int) rtDbgModNm_Close(PRTDBGMODINT pMod)
201{
202 PRTDBGMODNM pThis = (PRTDBGMODNM)pMod->pvDbgPriv;
203 RTDbgModRelease(pThis->hCnt);
204 pThis->hCnt = NIL_RTDBGMOD;
205 RTMemFree(pThis);
206 return VINF_SUCCESS;
207}
208
209
210/**
211 * Scans a NM-like map file.
212 *
213 * This implements both passes to avoid code duplication.
214 *
215 * @returns IPRT status code.
216 * @param pThis The instance data.
217 * @param pStrm The stream.
218 * @param fAddSymbols false in the first pass, true in the second.
219 */
220static int rtDbgModNmScanFile(PRTDBGMODNM pThis, PRTSTREAM pStrm, bool fAddSymbols)
221{
222 /*
223 * Try parse the stream.
224 */
225 RTUINTPTR SegZeroRva = fAddSymbols ? RTDbgModSegmentRva(pThis->hCnt, 0/*iSeg*/) : 0;
226 char szSym[RTDBG_SYMBOL_NAME_LENGTH] = "";
227 size_t cchMod = 0;
228 size_t offSym = 0;
229 unsigned cchAddr = 0;
230 uint64_t u64Low = UINT64_MAX;
231 uint64_t u64High = 0;
232 int fWithType = -1;
233 char szLine[512];
234 int rc;
235 while (RT_SUCCESS(rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine))))
236 {
237 char chType;
238 if (RT_C_IS_XDIGIT(szLine[0]))
239 {
240 /*
241 * This is really what C was made for, string parsing.
242 */
243 /* The symbol value (address). */
244 uint64_t u64Addr;
245 char *psz;
246 rc = RTStrToUInt64Ex(szLine, &psz, 16, &u64Addr);
247 if (rc != VWRN_TRAILING_CHARS)
248 return VERR_DBG_NOT_NM_MAP_FILE;
249
250 /* Check the address width. */
251 if (cchAddr == 0)
252 cchAddr = psz == &szLine[8] ? 8 : 16;
253 if (psz != &szLine[cchAddr])
254 return VERR_DBG_NOT_NM_MAP_FILE;
255
256 /* Get the type and check for single space before symbol. */
257 char *pszName;
258 if (fWithType < 0)
259 fWithType = RT_C_IS_BLANK(szLine[cchAddr + 2]) ? 1 : 0; /* have type? Linux 2.4 /proc/ksyms doesn't. */
260 if (fWithType)
261 {
262 chType = szLine[cchAddr + 1];
263 pszName = &szLine[cchAddr + 3];
264 if ( RT_C_IS_BLANK(chType)
265 || !RT_C_IS_BLANK(szLine[cchAddr + 2])
266 || RT_C_IS_BLANK(szLine[cchAddr + 3]))
267 return VERR_DBG_NOT_NM_MAP_FILE;
268 }
269 else
270 {
271 chType = 'T';
272 pszName = &szLine[cchAddr + 1];
273 }
274
275 /* Find the end of the symbol name. */
276 char *pszNameEnd = pszName;
277 char ch;
278 while ((ch = *pszNameEnd) != '\0' && !RT_C_IS_SPACE(ch))
279 pszNameEnd++;
280
281 /* Any module name (linux /proc/kallsyms) following in brackets? */
282 char *pszModName = pszNameEnd;
283 char *pszModNameEnd = pszModName;
284 if (*pszModName)
285 {
286 *pszModName++ = '\0';
287 pszModNameEnd = pszModName = RTStrStripL(pszModName);
288 if (*pszModName != '\0')
289 {
290 if (*pszModName != '[')
291 return VERR_DBG_NOT_LINUX_KALLSYMS;
292 pszModNameEnd = ++pszModName;
293 while ((ch = *pszModNameEnd) != '\0' && ch != ']')
294 pszModNameEnd++;
295 if (ch != ']')
296 return VERR_DBG_NOT_LINUX_KALLSYMS;
297 char *pszEnd = pszModNameEnd + 1;
298 if ((size_t)(pszModNameEnd - pszModName) >= 128) /* lazy bird */
299 return VERR_DBG_NOT_LINUX_KALLSYMS;
300 *pszModNameEnd = '\0';
301 if (*pszEnd)
302 pszEnd = RTStrStripL(pszEnd);
303 if (*pszEnd)
304 return VERR_DBG_NOT_LINUX_KALLSYMS;
305 }
306 }
307
308 /*
309 * Did the module change? Then update the symbol prefix.
310 */
311 if ( cchMod != (size_t)(pszModNameEnd - pszModName)
312 || memcmp(pszModName, szSym, cchMod))
313 {
314 cchMod = pszModNameEnd - pszModName;
315 if (cchMod == 0)
316 offSym = 0;
317 else
318 {
319 memcpy(szSym, pszModName, cchMod);
320 szSym[cchMod] = '.';
321 offSym = cchMod + 1;
322 }
323 szSym[offSym] = '\0';
324 }
325
326 /*
327 * Validate the type and add the symbol if it's a type we care for.
328 */
329 uint32_t fFlags = 0;
330 RTDBGSEGIDX iSegSym = 0;
331 switch (chType)
332 {
333 /* absolute */
334 case 'a':
335 case '?': /* /proc/kallsyms */
336 iSegSym = RTDBGSEGIDX_ABS;
337 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
338 break;
339 case 'A':
340 iSegSym = RTDBGSEGIDX_ABS;
341 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
342 break;
343
344 case 'b':
345 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
346 break;
347 case 'B':
348 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
349 break;
350
351 case 'c':
352 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_COMMON;
353 break;
354 case 'C':
355 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_COMMON;
356 break;
357
358 case 'd':
359 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
360 break;
361 case 'D':
362 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
363 break;
364
365 case 'g':
366 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
367 break;
368 case 'G':
369 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
370 break;
371
372 case 'i':
373 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
374 break;
375 case 'I':
376 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
377 break;
378
379 case 'r':
380 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_CONST;
381 break;
382 case 'R':
383 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_CONST;
384 break;
385
386 case 's':
387 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL;
388 break;
389 case 'S':
390 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC;
391 break;
392
393 case 't':
394 /// @todo fFlags |= RTDBG_SYM_FLAGS_LOCAL | RTDBG_SYM_FLAGS_TEXT;
395 break;
396 case 'T':
397 /// @todo fFlags |= RTDBG_SYM_FLAGS_PUBLIC | RTDBG_SYM_FLAGS_TEXT;
398 break;
399
400 case 'w':
401 /// @todo fFlags |= RTDBG_SYM_FLAGS_WEAK | RTDBG_SYM_FLAGS_LOCAL; //???
402 break;
403 case 'W':
404 /// @todo fFlags |= RTDBG_SYM_FLAGS_WEAK | RTDBG_SYM_FLAGS_PUBLIC;
405 break;
406
407 case 'N': /* debug */
408 case 'n':
409 case '-': /* stabs */
410 case 'u': /* undefined (/proc/kallsyms) */
411 case 'U':
412 case 'v': /* weakext */
413 case 'V':
414 iSegSym = NIL_RTDBGSEGIDX;
415 break;
416
417 default:
418 return VERR_DBG_NOT_NM_MAP_FILE;
419 }
420
421 if (iSegSym != NIL_RTDBGSEGIDX)
422 {
423 if (fAddSymbols)
424 {
425 size_t cchName = pszNameEnd - pszName;
426 if (cchName >= sizeof(szSym) - offSym)
427 cchName = sizeof(szSym) - offSym - 1;
428 memcpy(&szSym[offSym], pszName, cchName + 1);
429 if (iSegSym == 0)
430 rc = RTDbgModSymbolAdd(pThis->hCnt, szSym, iSegSym, u64Addr - SegZeroRva, 0/*cb*/, fFlags, NULL);
431 else
432 rc = RTDbgModSymbolAdd(pThis->hCnt, szSym, iSegSym, u64Addr, 0/*cb*/, fFlags, NULL);
433 if ( RT_FAILURE(rc)
434 && rc != VERR_DBG_DUPLICATE_SYMBOL
435 && rc != VERR_DBG_ADDRESS_CONFLICT) /* (don't be too strict) */
436 return rc;
437 }
438
439 /* Track segment span. */
440 if (iSegSym == 0)
441 {
442 if (u64Low > u64Addr)
443 u64Low = u64Addr;
444 if (u64High < u64Addr)
445 u64High = u64Addr;
446 }
447 }
448 }
449 else
450 {
451 /*
452 * This is either a blank line or a symbol without an address.
453 */
454 RTStrStripR(szLine);
455 if (szLine[0])
456 {
457 size_t cch = strlen(szLine);
458 if (cchAddr == 0)
459 cchAddr = cch < 16+3 || szLine[8+1] != ' ' ? 8 : 16;
460 if (cch < cchAddr+3+1)
461 return VERR_DBG_NOT_NM_MAP_FILE;
462 chType = szLine[cchAddr + 1];
463 if ( chType != 'U'
464 && chType != 'w')
465 return VERR_DBG_NOT_NM_MAP_FILE;
466 char *pszType = RTStrStripL(szLine);
467 if (pszType != &szLine[cchAddr + 1])
468 return VERR_DBG_NOT_NM_MAP_FILE;
469 if (!RT_C_IS_BLANK(szLine[cchAddr + 2]))
470 return VERR_DBG_NOT_NM_MAP_FILE;
471 }
472 /* else: blank - ignored */
473 }
474 }
475
476 /*
477 * The final segment.
478 */
479 if (rc == VERR_EOF)
480 {
481 if (fAddSymbols)
482 rc = VINF_SUCCESS;
483 else
484 {
485 if ( u64Low != UINT64_MAX
486 || u64High != 0)
487 rc = RTDbgModSegmentAdd(pThis->hCnt, u64Low, u64High - u64Low + 1, "main", 0, NULL);
488 else /* No sensible symbols... throw an error instead? */
489 rc = RTDbgModSegmentAdd(pThis->hCnt, 0, 0, "main", 0, NULL);
490 }
491 }
492
493 return rc;
494}
495
496
497/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
498static DECLCALLBACK(int) rtDbgModNm_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch, RTDBGCFG hDbgCfg)
499{
500 NOREF(enmArch); RT_NOREF_PV(hDbgCfg);
501
502 /*
503 * Fend off images.
504 */
505 if ( !pMod->pszDbgFile
506 || pMod->pImgVt)
507 return VERR_DBG_NO_MATCHING_INTERPRETER;
508
509 /*
510 * Try open the file and create an instance.
511 */
512 PRTSTREAM pStrm;
513 int rc = RTStrmOpen(pMod->pszDbgFile, "r", &pStrm);
514 if (RT_SUCCESS(rc))
515 {
516 PRTDBGMODNM pThis = (PRTDBGMODNM)RTMemAlloc(sizeof(*pThis));
517 if (pThis)
518 {
519 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
520 if (RT_SUCCESS(rc))
521 {
522 /*
523 * Scan the file twice, first to figure the segment
524 * sizes, then to add the symbol.
525 */
526 rc = rtDbgModNmScanFile(pThis, pStrm, false /*fAddSymbols*/);
527 if (RT_SUCCESS(rc))
528 rc = RTStrmRewind(pStrm);
529 if (RT_SUCCESS(rc))
530 rc = rtDbgModNmScanFile(pThis, pStrm, true /*fAddSymbols*/);
531 if (RT_SUCCESS(rc))
532 {
533 RTStrmClose(pStrm);
534 pMod->pvDbgPriv = pThis;
535 return rc;
536 }
537 }
538 RTDbgModRelease(pThis->hCnt);
539 RTMemFree(pThis);
540 }
541 else
542 rc = VERR_NO_MEMORY;
543 RTStrmClose(pStrm);
544 }
545 return rc;
546}
547
548
549
550/** Virtual function table for the NM-like map file reader. */
551DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgNm =
552{
553 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
554 /*.fSupports = */ RT_DBGTYPE_MAP,
555 /*.pszName = */ "nm",
556 /*.pfnTryOpen = */ rtDbgModNm_TryOpen,
557 /*.pfnClose = */ rtDbgModNm_Close,
558
559 /*.pfnRvaToSegOff = */ rtDbgModNm_RvaToSegOff,
560 /*.pfnImageSize = */ rtDbgModNm_ImageSize,
561
562 /*.pfnSegmentAdd = */ rtDbgModNm_SegmentAdd,
563 /*.pfnSegmentCount = */ rtDbgModNm_SegmentCount,
564 /*.pfnSegmentByIndex = */ rtDbgModNm_SegmentByIndex,
565
566 /*.pfnSymbolAdd = */ rtDbgModNm_SymbolAdd,
567 /*.pfnSymbolCount = */ rtDbgModNm_SymbolCount,
568 /*.pfnSymbolByOrdinal = */ rtDbgModNm_SymbolByOrdinal,
569 /*.pfnSymbolByName = */ rtDbgModNm_SymbolByName,
570 /*.pfnSymbolByAddr = */ rtDbgModNm_SymbolByAddr,
571
572 /*.pfnLineAdd = */ rtDbgModNm_LineAdd,
573 /*.pfnLineCount = */ rtDbgModNm_LineCount,
574 /*.pfnLineByOrdinal = */ rtDbgModNm_LineByOrdinal,
575 /*.pfnLineByAddr = */ rtDbgModNm_LineByAddr,
576
577 /*.pfnUnwindFrame = */ rtDbgModNm_UnwindFrame,
578
579 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
580};
581
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use