VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmodnm.cpp@ 78365

Last change on this file since 78365 was 77907, checked in by vboxsync, 6 years ago

Runtime/dbgmodnm.cpp: Plug memory leak in error case

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