VirtualBox

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

Last change on this file since 75244 was 75237, checked in by vboxsync, 6 years ago

IPRT: Added support for reading MAPSYM output.

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