VirtualBox

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

© 2023 Oracle
ContactPrivacy policyTerms of Use