VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmodmapsym.cpp@ 93138

Last change on this file since 93138 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.1 KB
Line 
1/* $Id: dbgmodmapsym.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT - Debug Map Reader for MAPSYM files (used by SYMDBG from old MASM).
4 *
5 * MAPSYM is was the tool producing these files from linker map files for
6 * use with SYMDBG (which shipped with MASM 3.0 (possibly earlier)), the OS/2
7 * kernel debugger, and other tools. The format is very limited and they had
8 * to strip down the os2krnl.map file in later years to keep MAPSYM happy.
9 */
10
11/*
12 * Copyright (C) 2009-2022 Oracle Corporation
13 *
14 * This file is part of VirtualBox Open Source Edition (OSE), as
15 * available from http://www.virtualbox.org. This file is free software;
16 * you can redistribute it and/or modify it under the terms of the GNU
17 * General Public License (GPL) as published by the Free Software
18 * Foundation, in version 2 as it comes in the "COPYING" file of the
19 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
20 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
21 *
22 * The contents of this file may alternatively be used under the terms
23 * of the Common Development and Distribution License Version 1.0
24 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
25 * VirtualBox OSE distribution, in which case the provisions of the
26 * CDDL are applicable instead of those of the GPL.
27 *
28 * You may elect to license modified versions of this file under the
29 * terms and conditions of either the GPL or the CDDL or both.
30 */
31
32
33/*********************************************************************************************************************************
34* Header Files *
35*********************************************************************************************************************************/
36#define LOG_GROUP RTLOGGROUP_DBG
37#include <iprt/dbg.h>
38#include "internal/iprt.h"
39
40#include <iprt/err.h>
41#include <iprt/ctype.h>
42#include <iprt/file.h>
43#include <iprt/log.h>
44#include <iprt/mem.h>
45#include <iprt/stream.h>
46#include <iprt/string.h>
47#include "internal/dbgmod.h"
48
49
50/*********************************************************************************************************************************
51* Structures and Typedefs *
52*********************************************************************************************************************************/
53/** @name MAPSYM structures and constants.
54 * @{ */
55
56/** MAPSYM: Header structure. */
57typedef struct MAPSYMHDR
58{
59 uint16_t off16NextMap; /**< 0x00: Offset of the next map divided by 16. */
60 uint8_t bFlags; /**< 0x02: Who really knows... */
61 uint8_t bReserved; /**< 0x03: Reserved / unknown. */
62 uint16_t uSegEntry; /**< 0x04: Some entrypoint/segment thing we don't care about. */
63 uint16_t cConsts; /**< 0x06: Constants referenced by offConstDef. */
64 uint16_t offConstDef; /**< 0x08: Offset to head of constant chain. Not div 16? */
65 uint16_t cSegs; /**< 0x0a: Number of segments in the map. */
66 uint16_t off16SegDef; /**< 0x0c: Offset of the segment defintions divided by 16. */
67 uint8_t cchMaxSym; /**< 0x0e: Maximum symbol-name length. */
68 uint8_t cchModule; /**< 0x0f: Length of the module name. */
69 RT_FLEXIBLE_ARRAY_EXTENSION
70 char achModule[RT_FLEXIBLE_ARRAY]; /**< 0x10: Module name, length given by cchModule. */
71} MAPSYMHDR;
72
73/** MAPSYM: Tail structure. */
74typedef struct MAPSYMTAIL
75{
76 uint16_t offNextMap; /**< 0x00: Always zero (it's the tail, see). */
77 uint8_t bRelease; /**< 0x02: Minor version number. */
78 uint8_t bVersion; /**< 0x03: Major version number. */
79} MAPSYMTAIL;
80
81/** MAPSYM: Segment defintion. */
82typedef struct MAPSYMSEGDEF
83{
84 uint16_t off16NextSeg; /**< 0x00: Offset of the next segment divided by 16. */
85 uint16_t cSymbols; /**< 0x02: Number of symbol offsets . */
86 uint16_t offSymbolOffsets; /**< 0x04: Offset of the symbol offset table. Each entry is a 16-bit value giving
87 * the offset symbol relative to this structure. */
88 uint16_t au16Reserved0[4]; /**< 0x06: Reserved / unknown.
89 * First byte/word seems to be 1-based segment number. */
90 uint8_t bFlags; /**< 0x0e: MAPSYMSEGDEF_F_32BIT or zero. */
91 uint8_t bReserved1; /**< 0x0f: Reserved / unknown. */
92 uint16_t offLineDef; /**< 0x10: Offset to the line defintions. */
93 uint16_t u16Reserved2; /**< 0x12: Reserved / unknown. Often seen holding 0xff00. */
94 uint8_t cchSegName; /**< 0x14: Segment name length. */
95 RT_FLEXIBLE_ARRAY_EXTENSION
96 char achSegName[RT_FLEXIBLE_ARRAY]; /**< 0x15: Segment name, length given by cchSegName. */
97} MAPSYMSEGDEF;
98
99#define MAPSYMSEGDEF_F_32BIT UINT8_C(0x01) /**< Indicates 32-bit segment rather than 16-bit, relevant for symbols. */
100#define MAPSYMSEGDEF_F_UNKNOWN UINT8_C(0x02) /**< Set on all segments in os2krnlr.sym from ACP2. */
101
102/** MAPSYM: 16-bit symbol */
103typedef struct MAPSYMSYMDEF16
104{
105 uint16_t uValue; /**< 0x00: The symbol value (address). */
106 uint8_t cchName; /**< 0x02: Symbol name length. */
107 char achName[1]; /**< 0x03: The symbol name, length give by cchName. */
108} MAPSYMSYMDEF16;
109
110/** MAPSYM: 16-bit symbol */
111typedef struct MAPSYMSYMDEF32
112{
113 uint32_t uValue; /**< 0x00: The symbol value (address). */
114 uint8_t cchName; /**< 0x04: Symbol name length. */
115 char achName[1]; /**< 0x05: The symbol name, length give by cchName. */
116} MAPSYMSYMDEF32;
117
118/** MAPSYM: Line number defintions. */
119typedef struct MAPSYMLINEDEF
120{
121 uint16_t off16NextLine; /**< 0x00: Offset to the next line defintion divided by 16. */
122 uint16_t uSegment; /**< 0x02: Guessing this must be segment number. */
123 uint16_t offLines; /**< 0x04: Offset to the line number array, relative to this structure. */
124 uint16_t cLines; /**< 0x08: Number of line numbers in the array. */
125 uint8_t cchSrcFile; /**< 0x0a: Length of source filename. */
126 RT_FLEXIBLE_ARRAY_EXTENSION
127 char achSrcFile[RT_FLEXIBLE_ARRAY]; /**< 0x0b: Source filename, length given by cchSrcFile. */
128} MAPSYMLINEDEF;
129
130/** MAPSYM: 16-bit line numbers. */
131typedef struct MAPSYMLINENO16
132{
133 uint16_t offSeg;
134 uint16_t uLineNo;
135} MAPSYMLINENO16;
136
137/** @} */
138
139
140/*********************************************************************************************************************************
141* Defined Constants And Macros *
142*********************************************************************************************************************************/
143/** Maximum number of segments we expect in a MAPSYM file. */
144#define RTDBGMODMAPSYM_MAX_SEGMENTS 256
145
146
147
148/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
149static DECLCALLBACK(int) rtDbgModMapSym_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
150{
151 RT_NOREF(pMod, iSeg, off, pState);
152 return VERR_DBG_NO_UNWIND_INFO;
153}
154
155
156/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
157static DECLCALLBACK(int) rtDbgModMapSym_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
158 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
159{
160 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
161 return RTDbgModLineByAddr(hCnt, iSeg, off, poffDisp, pLineInfo);
162}
163
164
165/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
166static DECLCALLBACK(int) rtDbgModMapSym_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
167{
168 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
169 return RTDbgModLineByOrdinal(hCnt, iOrdinal, pLineInfo);
170}
171
172
173/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
174static DECLCALLBACK(uint32_t) rtDbgModMapSym_LineCount(PRTDBGMODINT pMod)
175{
176 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
177 return RTDbgModLineCount(hCnt);
178}
179
180
181/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
182static DECLCALLBACK(int) rtDbgModMapSym_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
183 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
184{
185 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
186 Assert(!pszFile[cchFile]); NOREF(cchFile);
187 return RTDbgModLineAdd(hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
188}
189
190
191/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
192static DECLCALLBACK(int) rtDbgModMapSym_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
193 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
194{
195 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
196 return RTDbgModSymbolByAddr(hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
197}
198
199
200/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
201static DECLCALLBACK(int) rtDbgModMapSym_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
202 PRTDBGSYMBOL pSymInfo)
203{
204 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
205 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
206 return RTDbgModSymbolByName(hCnt, pszSymbol, pSymInfo);
207}
208
209
210/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
211static DECLCALLBACK(int) rtDbgModMapSym_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
212{
213 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
214 return RTDbgModSymbolByOrdinal(hCnt, iOrdinal, pSymInfo);
215}
216
217
218/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
219static DECLCALLBACK(uint32_t) rtDbgModMapSym_SymbolCount(PRTDBGMODINT pMod)
220{
221 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
222 return RTDbgModSymbolCount(hCnt);
223}
224
225
226/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
227static DECLCALLBACK(int) rtDbgModMapSym_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
228 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
229 uint32_t *piOrdinal)
230{
231 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
232 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
233 return RTDbgModSymbolAdd(hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
234}
235
236
237/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
238static DECLCALLBACK(int) rtDbgModMapSym_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
239{
240 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
241 return RTDbgModSegmentByIndex(hCnt, iSeg, pSegInfo);
242}
243
244
245/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
246static DECLCALLBACK(RTDBGSEGIDX) rtDbgModMapSym_SegmentCount(PRTDBGMODINT pMod)
247{
248 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
249 return RTDbgModSegmentCount(hCnt);
250}
251
252
253/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
254static DECLCALLBACK(int) rtDbgModMapSym_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
255 size_t cchName, uint32_t fFlags, PRTDBGSEGIDX piSeg)
256{
257 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
258 Assert(!pszName[cchName]); NOREF(cchName);
259 return RTDbgModSegmentAdd(hCnt, uRva, cb, pszName, fFlags, piSeg);
260}
261
262
263/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
264static DECLCALLBACK(RTUINTPTR) rtDbgModMapSym_ImageSize(PRTDBGMODINT pMod)
265{
266 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
267 return RTDbgModImageSize(hCnt);
268}
269
270
271/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
272static DECLCALLBACK(RTDBGSEGIDX) rtDbgModMapSym_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
273{
274 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
275 return RTDbgModRvaToSegOff(hCnt, uRva, poffSeg);
276}
277
278
279/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
280static DECLCALLBACK(int) rtDbgModMapSym_Close(PRTDBGMODINT pMod)
281{
282 RTDBGMOD hCnt = (RTDBGMOD)pMod->pvDbgPriv;
283 RTDbgModRelease(hCnt);
284 pMod->pvDbgPriv = NULL;
285 return VINF_SUCCESS;
286}
287
288
289/**
290 * Validate the module header.
291 *
292 * @returns true if valid, false if not.
293 * @param pHdr The header.
294 * @param cbAvail How much we've actually read.
295 * @param cbFile The file size (relative to module header).
296 */
297static bool rtDbgModMapSymIsValidHeader(MAPSYMHDR const *pHdr, size_t cbAvail, uint64_t cbFile)
298{
299 if (cbAvail <= RT_UOFFSETOF(MAPSYMHDR, achModule))
300 return false;
301
302 if (pHdr->cSegs == 0)
303 return false;
304 if (pHdr->cSegs > RTDBGMODMAPSYM_MAX_SEGMENTS)
305 return false;
306
307 if (pHdr->off16SegDef == 0)
308 return false;
309 if (pHdr->off16SegDef * (uint32_t)16 >= cbFile)
310 return false;
311
312 if (pHdr->cchModule == 0)
313 return false;
314 if (pHdr->cchModule > 128) /* Note must be smaller than abPadding below in caller */
315 return false;
316
317 size_t cchMaxName = cbAvail - RT_UOFFSETOF(MAPSYMHDR, achModule);
318 if (pHdr->cchModule > cchMaxName)
319 return false;
320
321 for (uint32_t i = 0; i < pHdr->cchModule; i++)
322 {
323 unsigned char const uch = pHdr->achModule[i];
324 if ( uch < 0x20
325 || uch >= 0x7f)
326 return false;
327 }
328
329 return true;
330}
331
332
333/**
334 * Validate the given segment definition.
335 *
336 * @returns true if valid, false if not.
337 * @param pSegDef The segment definition structure.
338 * @param cbMax Host many bytes are available starting with pSegDef.
339 */
340static bool rtDbgModMapSymIsValidSegDef(MAPSYMSEGDEF const *pSegDef, size_t cbMax)
341{
342 if (RT_UOFFSETOF(MAPSYMSEGDEF, achSegName) > cbMax)
343 return false;
344 if (pSegDef->cSymbols)
345 {
346 if (pSegDef->cSymbols > _32K)
347 {
348 Log(("rtDbgModMapSymIsValidSegDef: Too many symbols: %#x\n", pSegDef->cSymbols));
349 return false;
350 }
351
352 if (pSegDef->offSymbolOffsets + (uint32_t)2 * pSegDef->cSymbols > cbMax)
353 {
354 Log(("rtDbgModMapSymIsValidSegDef: Bad symbol offset/count: %#x/%#x\n", pSegDef->offSymbolOffsets, pSegDef->cSymbols));
355 return false;
356 }
357 }
358
359 size_t cchMaxName = cbMax - RT_UOFFSETOF(MAPSYMHDR, achModule);
360 if (pSegDef->cchSegName > cchMaxName)
361 {
362 Log(("rtDbgModMapSymIsValidSegDef: Bad segment name length\n"));
363 return false;
364 }
365
366 for (uint32_t i = 0; i < pSegDef->cchSegName; i++)
367 {
368 unsigned char uch = pSegDef->achSegName[i];
369 if ( uch < 0x20
370 || uch >= 0x7f)
371 {
372 Log(("rtDbgModMapSymIsValidSegDef: Bad segment name: %.*Rhxs\n", pSegDef->cchSegName, pSegDef->achSegName));
373 return false;
374 }
375 }
376
377 return true;
378}
379
380
381/**
382 * Fills @a hCnt with segments and symbols from the MAPSYM file.
383 *
384 * @note We only support reading the first module, right now.
385 */
386static int rtDbgModMapSymReadIt(RTDBGMOD hCnt, uint8_t const *pbFile, size_t cbFile)
387{
388 /*
389 * Revalidate the header.
390 */
391 MAPSYMHDR const *pHdr = (MAPSYMHDR const *)pbFile;
392 if (!rtDbgModMapSymIsValidHeader(pHdr, cbFile, cbFile))
393 return VERR_DBG_NO_MATCHING_INTERPRETER;
394 Log(("rtDbgModMapSymReadIt: szModule='%.*s' cSegs=%u off16NextMap=%#x\n",
395 pHdr->cchModule, pHdr->achModule, pHdr->cSegs, pHdr->off16NextMap));
396
397 /*
398 * Load each segment.
399 */
400 uint32_t uRva = 0;
401 uint32_t const cSegs = pHdr->cSegs;
402 uint32_t offSegment = pHdr->off16SegDef * (uint32_t)16;
403 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
404 {
405 if (offSegment >= cbFile)
406 return VERR_DBG_NO_MATCHING_INTERPRETER;
407
408 size_t const cbMax = cbFile - offSegment;
409 MAPSYMSEGDEF const *pSegDef = (MAPSYMSEGDEF const *)&pbFile[offSegment];
410 if (!rtDbgModMapSymIsValidSegDef(pSegDef, cbMax))
411 return VERR_DBG_NO_MATCHING_INTERPRETER;
412
413 Log(("rtDbgModMapSymReadIt: Segment #%u: flags=%#x name='%.*s' symbols=%#x @ %#x next=%#x lines=@%#x (reserved: %#x %#x %#x %#x %#x %#x)\n",
414 iSeg, pSegDef->bFlags, pSegDef->cchSegName, pSegDef->achSegName, pSegDef->cSymbols, pSegDef->offSymbolOffsets,
415 pSegDef->off16NextSeg, pSegDef->offLineDef, pSegDef->au16Reserved0[0], pSegDef->au16Reserved0[1],
416 pSegDef->au16Reserved0[2], pSegDef->au16Reserved0[3], pSegDef->bReserved1, pSegDef->u16Reserved2));
417
418 /*
419 * First symbol pass finds the largest symbol and uses that as the segment size.
420 */
421 uint32_t cbSegmentEst = 0;
422 uint32_t const cSymbols = pSegDef->cSymbols;
423 uint16_t const * const paoffSymbols = (uint16_t const *)&pbFile[offSegment + pSegDef->offSymbolOffsets];
424 bool const fIs32Bit = RT_BOOL(pSegDef->bFlags & MAPSYMSEGDEF_F_32BIT);
425 uint32_t const cbSymDef = fIs32Bit ? 4 + 1 : 2 + 1;
426 for (uint32_t iSymbol = 0; iSymbol < cSymbols; iSymbol++)
427 {
428 uint32_t off = paoffSymbols[iSymbol] + offSegment;
429 if (off + cbSymDef <= cbFile)
430 {
431 uint32_t uValue = fIs32Bit ? *(uint32_t const *)&pbFile[off] : (uint32_t)*(uint16_t const *)&pbFile[off];
432 if (uValue > cbSegmentEst)
433 cbSegmentEst = uValue;
434 }
435 else
436 Log(("rtDbgModMapSymReadIt: Bad symbol offset %#x\n", off));
437 }
438
439 /*
440 * Add the segment.
441 */
442 char szName[256];
443 memcpy(szName, pSegDef->achSegName, pSegDef->cchSegName);
444 szName[pSegDef->cchSegName] = '\0';
445 if (!pSegDef->cchSegName)
446 RTStrPrintf(szName, sizeof(szName), "seg%02u", iSeg);
447
448 RTDBGSEGIDX idxDbgSeg = iSeg;
449 int rc = RTDbgModSegmentAdd(hCnt, uRva, cbSegmentEst, szName, 0 /*fFlags*/, &idxDbgSeg);
450 if (RT_FAILURE(rc))
451 return rc;
452
453 uRva += cbSegmentEst;
454
455 /*
456 * The second symbol pass loads the symbol values and names.
457 */
458 for (uint32_t iSymbol = 0; iSymbol < cSymbols; iSymbol++)
459 {
460 uint32_t off = paoffSymbols[iSymbol] + offSegment;
461 if (off + cbSymDef <= cbFile)
462 {
463 /* Get value: */
464 uint32_t uValue = RT_MAKE_U16(pbFile[off], pbFile[off + 1]);
465 off += 2;
466 if (fIs32Bit)
467 {
468 uValue |= RT_MAKE_U32_FROM_U8(0, 0, pbFile[off], pbFile[off + 1]);
469 off += 2;
470 }
471
472 /* Get name: */
473 uint8_t cchName = pbFile[off++];
474 if (off + cchName <= cbFile)
475 {
476 memcpy(szName, &pbFile[off], cchName);
477 szName[cchName] = '\0';
478 RTStrPurgeEncoding(szName);
479 }
480 else
481 cchName = 0;
482 if (cchName == 0)
483 RTStrPrintf(szName, sizeof(szName), "unknown_%u_%u", iSeg, iSymbol);
484
485 /* Try add it: */
486 rc = RTDbgModSymbolAdd(hCnt, szName, idxDbgSeg, uValue, 0 /*cb*/, 0 /*fFlags*/, NULL /*piOrdinal*/);
487 if (RT_SUCCESS(rc))
488 Log7(("rtDbgModMapSymReadIt: %02x:%06x %s\n", idxDbgSeg, uValue, szName));
489 else if ( rc == VERR_DBG_DUPLICATE_SYMBOL
490 || rc == VERR_DBG_ADDRESS_CONFLICT
491 || rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE)
492 Log(("rtDbgModMapSymReadIt: %02x:%06x %s\n", idxDbgSeg, uValue, szName));
493 else
494 {
495 Log(("rtDbgModMapSymReadIt: Unexpected RTDbgModSymbolAdd failure: %Rrc - %02x:%06x %s\n",
496 rc, idxDbgSeg, uValue, szName));
497 return rc;
498 }
499 }
500 }
501
502 /* Next segment */
503 offSegment = pSegDef->off16NextSeg * (uint32_t)16;
504 }
505 return VINF_SUCCESS;
506}
507
508
509/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
510static DECLCALLBACK(int) rtDbgModMapSym_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
511{
512 NOREF(enmArch);
513
514 /*
515 * Fend off images.
516 */
517 if ( !pMod->pszDbgFile
518 || pMod->pImgVt)
519 return VERR_DBG_NO_MATCHING_INTERPRETER;
520 pMod->pvDbgPriv = NULL;
521
522 /*
523 * Try open the file and check out the first header.
524 */
525 RTFILE hFile;
526 int rc = RTFileOpen(&hFile, pMod->pszDbgFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
527 if (RT_SUCCESS(rc))
528 {
529 uint64_t cbFile = 0;
530 rc = RTFileQuerySize(hFile, &cbFile);
531 if ( RT_SUCCESS(rc)
532 && cbFile < _2M)
533 {
534 union
535 {
536 MAPSYMHDR Hdr;
537 char abPadding[sizeof(MAPSYMHDR) + 257]; /* rtDbgModMapSymIsValidHeader makes size assumptions. */
538 } uBuf;
539 size_t cbToRead = (size_t)RT_MIN(cbFile, sizeof(uBuf));
540 rc = RTFileReadAt(hFile, 0, &uBuf, RT_MIN(cbFile, sizeof(uBuf)), NULL);
541 if (RT_SUCCESS(rc))
542 {
543 if (rtDbgModMapSymIsValidHeader(&uBuf.Hdr, cbToRead, cbFile))
544 {
545 uBuf.Hdr.achModule[uBuf.Hdr.cchModule] = '\0';
546
547 /*
548 * Read the whole thing into memory, create an
549 * instance/container and load it with symbols.
550 */
551 void *pvFile = NULL;
552 size_t cbFile2 = 0;
553 rc = RTFileReadAllByHandle(hFile, &pvFile, &cbFile2);
554 if (RT_SUCCESS(rc))
555 {
556 RTDBGMOD hCnt;
557 rc = RTDbgModCreate(&hCnt, uBuf.Hdr.achModule, 0 /*cbSeg*/, 0 /*fFlags*/);
558 if (RT_SUCCESS(rc))
559 {
560 rc = rtDbgModMapSymReadIt(hCnt, (uint8_t const *)pvFile, cbFile2);
561 if (RT_SUCCESS(rc))
562 pMod->pvDbgPriv = hCnt;
563 else
564 RTDbgModRelease(hCnt);
565 }
566 RTFileReadAllFree(pvFile, cbFile2);
567 }
568 }
569 else
570 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
571 }
572 }
573 RTFileClose(hFile);
574 }
575 Log(("rtDbgModMapSym_TryOpen: %s -> %Rrc, %p\n", pMod->pszDbgFile, rc, pMod->pvDbgPriv));
576 return rc;
577}
578
579
580
581/** Virtual function table for the MAPSYM file reader. */
582DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgMapSym =
583{
584 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
585 /*.fSupports = */ RT_DBGTYPE_SYM,
586 /*.pszName = */ "mapsym",
587 /*.pfnTryOpen = */ rtDbgModMapSym_TryOpen,
588 /*.pfnClose = */ rtDbgModMapSym_Close,
589
590 /*.pfnRvaToSegOff = */ rtDbgModMapSym_RvaToSegOff,
591 /*.pfnImageSize = */ rtDbgModMapSym_ImageSize,
592
593 /*.pfnSegmentAdd = */ rtDbgModMapSym_SegmentAdd,
594 /*.pfnSegmentCount = */ rtDbgModMapSym_SegmentCount,
595 /*.pfnSegmentByIndex = */ rtDbgModMapSym_SegmentByIndex,
596
597 /*.pfnSymbolAdd = */ rtDbgModMapSym_SymbolAdd,
598 /*.pfnSymbolCount = */ rtDbgModMapSym_SymbolCount,
599 /*.pfnSymbolByOrdinal = */ rtDbgModMapSym_SymbolByOrdinal,
600 /*.pfnSymbolByName = */ rtDbgModMapSym_SymbolByName,
601 /*.pfnSymbolByAddr = */ rtDbgModMapSym_SymbolByAddr,
602
603 /*.pfnLineAdd = */ rtDbgModMapSym_LineAdd,
604 /*.pfnLineCount = */ rtDbgModMapSym_LineCount,
605 /*.pfnLineByOrdinal = */ rtDbgModMapSym_LineByOrdinal,
606 /*.pfnLineByAddr = */ rtDbgModMapSym_LineByAddr,
607
608 /*.pfnUnwindFrame = */ rtDbgModMapSym_UnwindFrame,
609
610 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
611};
612
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