VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp@ 38531

Last change on this file since 38531 was 38531, checked in by vboxsync, 14 years ago

iprt: debug info coding...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/* $Id: dbgmoddwarf.cpp 38531 2011-08-25 14:30:23Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader For DWARF.
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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 * DWARF sections.
47 */
48typedef enum krtDbgModDwarfSect
49{
50 krtDbgModDwarfSect_abbrev = 0,
51 krtDbgModDwarfSect_aranges,
52 krtDbgModDwarfSect_frame,
53 krtDbgModDwarfSect_info,
54 krtDbgModDwarfSect_inlined,
55 krtDbgModDwarfSect_line,
56 krtDbgModDwarfSect_loc,
57 krtDbgModDwarfSect_macinfo,
58 krtDbgModDwarfSect_pubnames,
59 krtDbgModDwarfSect_pubtypes,
60 krtDbgModDwarfSect_ranges,
61 krtDbgModDwarfSect_str,
62 krtDbgModDwarfSect_types,
63 /** End of valid parts (exclusive). */
64 krtDbgModDwarfSect_End
65} krtDbgModDwarfSect;
66
67/**
68 * The instance data of the DWARF reader.
69 */
70typedef struct RTDBGMODDWARF
71{
72 /** The debug container containing doing the real work. */
73 RTDBGMOD hCnt;
74 /** Pointer to back to the debug info module (no reference ofc). */
75 PRTDBGMODINT pMod;
76
77 /** Total line number count. */
78 uint32_t cLines;
79 /** Total symbol count. */
80 uint32_t cSymbols;
81
82 /** DWARF debug info sections. */
83 struct
84 {
85 /** The file offset of the part. */
86 RTFOFF offFile;
87 /** The size of the part. */
88 size_t cb;
89 /** The memory mapping of the part. */
90 void const *pv;
91 /** Set if present. */
92 bool fPresent;
93 } aSections[krtDbgModDwarfSect_End];
94} RTDBGMODDWARF;
95/** Pointer to instance data of the DWARF reader. */
96typedef RTDBGMODDWARF *PRTDBGMODDWARF;
97
98
99
100/**
101 * Loads a DWARF section from the image file.
102 *
103 * @returns IPRT status code.
104 * @param pThis The DWARF instance.
105 * @param enmSect The section to load.
106 */
107static int rtDbgModDwarfLoadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
108{
109 /*
110 * Don't load stuff twice.
111 */
112 if (pThis->aSections[enmSect].pv)
113 return VINF_SUCCESS;
114
115 /*
116 * Sections that are not present cannot be loaded, treat them like they
117 * are empty
118 */
119 if (!pThis->aSections[enmSect].fPresent)
120 {
121 Assert(pThis->aSections[enmSect].cb);
122 return VINF_SUCCESS;
123 }
124 if (!pThis->aSections[enmSect].cb)
125 return VINF_SUCCESS;
126
127 /*
128 * Sections must be readable with the current image interface.
129 */
130 if (pThis->aSections[enmSect].offFile < 0)
131 return VERR_OUT_OF_RANGE;
132
133 /*
134 * Do the job.
135 */
136 return pThis->pMod->pImgVt->pfnMapPart(pThis->pMod, pThis->aSections[enmSect].offFile, pThis->aSections[enmSect].cb,
137 &pThis->aSections[enmSect].pv);
138}
139
140
141/**
142 * Unloads a DWARF section previously mapped by rtDbgModDwarfLoadSection.
143 *
144 * @returns IPRT status code.
145 * @param pThis The DWARF instance.
146 * @param enmSect The section to unload.
147 */
148static int rtDbgModDwarfUnloadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
149{
150 if (!pThis->aSections[enmSect].pv)
151 return VINF_SUCCESS;
152
153 return pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[enmSect].cb, &pThis->aSections[enmSect].pv);
154}
155
156
157
158/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
159static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
160 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
161{
162 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
163 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
164}
165
166
167/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
168static DECLCALLBACK(int) rtDbgModDwarf_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
169{
170 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
171 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
172}
173
174
175/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
176static DECLCALLBACK(uint32_t) rtDbgModDwarf_LineCount(PRTDBGMODINT pMod)
177{
178 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
179 return RTDbgModLineCount(pThis->hCnt);
180}
181
182
183/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
184static DECLCALLBACK(int) rtDbgModDwarf_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
185 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
186{
187 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
188 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
189}
190
191
192/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
193static DECLCALLBACK(int) rtDbgModDwarf_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
194 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
195{
196 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
197 return VERR_DBG_NO_SYMBOLS;
198}
199
200
201/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
202static DECLCALLBACK(int) rtDbgModDwarf_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
203 PRTDBGSYMBOL pSymInfo)
204{
205 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
206 return VERR_DBG_NO_SYMBOLS;
207}
208
209
210/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
211static DECLCALLBACK(int) rtDbgModDwarf_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
212{
213 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
214 return VERR_DBG_NO_SYMBOLS;
215}
216
217
218/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
219static DECLCALLBACK(uint32_t) rtDbgModDwarf_SymbolCount(PRTDBGMODINT pMod)
220{
221 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
222 return pThis->cSymbols;
223}
224
225
226/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
227static DECLCALLBACK(int) rtDbgModDwarf_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 return VERR_NOT_SUPPORTED;
232}
233
234
235/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
236static DECLCALLBACK(int) rtDbgModDwarf_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
237{
238 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
239 return VERR_DBG_INVALID_SEGMENT_INDEX;
240}
241
242
243/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
244static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_SegmentCount(PRTDBGMODINT pMod)
245{
246 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
247 return 0; /** @todo defer to image reader if present? */
248}
249
250
251/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
252static DECLCALLBACK(int) rtDbgModDwarf_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
253 uint32_t fFlags, PRTDBGSEGIDX piSeg)
254{
255 return VERR_NOT_SUPPORTED;
256}
257
258
259/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
260static DECLCALLBACK(RTUINTPTR) rtDbgModDwarf_ImageSize(PRTDBGMODINT pMod)
261{
262 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
263 return 0; /** @todo defer to image reader if present? */
264}
265
266
267/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
268static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
269{
270 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
271 /** @todo defer to image reader if present? */
272 *poffSeg = uRva;
273 return 0;
274}
275
276
277/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
278static DECLCALLBACK(int) rtDbgModDwarf_Close(PRTDBGMODINT pMod)
279{
280 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
281
282 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
283 if (pThis->aSections[iSect].pv)
284 pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[iSect].cb, &pThis->aSections[iSect].pv);
285
286 RTDbgModRelease(pThis->hCnt);
287 RTMemFree(pThis);
288
289 return VINF_SUCCESS;
290}
291
292
293static int rtDbgModDwarfExplodeLineNumbers(PRTDBGMODDWARF pThis)
294{
295 if (!pThis->aSections[krtDbgModDwarfSect_line].fPresent)
296 return VINF_SUCCESS;
297 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_line);
298 if (RT_FAILURE(rc))
299 return rc;
300
301
302 int rc2 = rtDbgModDwarfUnloadSection(pThis, krtDbgModDwarfSect_line);
303 return RT_SUCCESS(rc2) || RT_FAILURE(rc) ? rc : rc2;
304}
305
306
307static int rtDbgModDwarfExtractSymbols(PRTDBGMODDWARF pThis)
308{
309 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_info);
310 if (RT_FAILURE(rc))
311 return rc;
312
313
314 return VERR_NOT_IMPLEMENTED;
315}
316
317
318/** @callback_method_impl{FNRTLDRENUMDBG} */
319static DECLCALLBACK(int) rtDbgModDwarfEnumCallback(RTLDRMOD hLdrMod, uint32_t iDbgInfo, RTLDRDBGINFOTYPE enmType,
320 uint16_t iMajorVer, uint16_t iMinorVer, const char *pszPartNm,
321 RTFOFF offFile, RTUINTPTR LinkAddress, RTUINTPTR cb,
322 const char *pszExtFile, void *pvUser)
323{
324 /*
325 * Skip stuff we can't handle.
326 */
327 if ( enmType != RTLDRDBGINFOTYPE_DWARF
328 || !pszPartNm
329 || pszExtFile)
330 return VINF_SUCCESS;
331
332 /*
333 * Must have a part name starting with debug_ and possibly prefixed by dots
334 * or underscores.
335 */
336 if (!strncmp(pszPartNm, ".debug_", sizeof(".debug_") - 1))
337 pszPartNm += sizeof(".debug_") - 1;
338 else if (!strncmp(pszPartNm, "__debug_", sizeof("__debug_") - 1))
339 pszPartNm += sizeof("__debug_") - 1;
340 else
341 AssertMsgFailedReturn(("%s\n", pszPartNm), VINF_SUCCESS /*ignore*/);
342
343 /*
344 * Figure out which part we're talking about.
345 */
346 krtDbgModDwarfSect enmSect;
347 if (0) { /* dummy */ }
348#define ELSE_IF_STRCMP_SET(a_Name) else if (!strcmp(pszPartNm, #a_Name)) enmSect = krtDbgModDwarfSect_ ## a_Name
349 ELSE_IF_STRCMP_SET(abbrev);
350 ELSE_IF_STRCMP_SET(aranges);
351 ELSE_IF_STRCMP_SET(frame);
352 ELSE_IF_STRCMP_SET(info);
353 ELSE_IF_STRCMP_SET(inlined);
354 ELSE_IF_STRCMP_SET(line);
355 ELSE_IF_STRCMP_SET(loc);
356 ELSE_IF_STRCMP_SET(macinfo);
357 ELSE_IF_STRCMP_SET(pubnames);
358 ELSE_IF_STRCMP_SET(pubtypes);
359 ELSE_IF_STRCMP_SET(ranges);
360 ELSE_IF_STRCMP_SET(str);
361 ELSE_IF_STRCMP_SET(types);
362#undef ELSE_IF_STRCMP_SET
363 else
364 {
365 AssertMsgFailed(("%s\n", pszPartNm));
366 return VINF_SUCCESS;
367 }
368
369 /*
370 * Record the section.
371 */
372 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
373 AssertMsgReturn(!pThis->aSections[enmSect].fPresent, ("duplicate %s\n", pszPartNm), VINF_SUCCESS /*ignore*/);
374
375 pThis->aSections[enmSect].fPresent = true;
376 pThis->aSections[enmSect].offFile = offFile;
377 pThis->aSections[enmSect].pv = NULL;
378 pThis->aSections[enmSect].cb = (size_t)cb;
379 if (pThis->aSections[enmSect].cb != cb)
380 pThis->aSections[enmSect].cb = ~(size_t)0;
381
382 return VINF_SUCCESS;
383}
384
385
386/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
387static DECLCALLBACK(int) rtDbgModDwarf_TryOpen(PRTDBGMODINT pMod)
388{
389 /*
390 * DWARF is only supported when part of an image.
391 */
392 if (!pMod->pImgVt)
393 return VERR_DBG_NO_MATCHING_INTERPRETER;
394
395 /*
396 * Enumerate the debug info in the module, looking for DWARF bits.
397 */
398 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)RTMemAllocZ(sizeof(*pThis));
399 if (!pThis)
400 return VERR_NO_MEMORY;
401 pThis->pMod = pMod;
402
403 int rc = pMod->pImgVt->pfnEnumDbgInfo(pMod, rtDbgModDwarfEnumCallback, pThis);
404 if (RT_SUCCESS(rc))
405 {
406 if (pThis->aSections[krtDbgModDwarfSect_info].fPresent)
407 {
408 /*
409 * Extract / explode the data we want (symbols and line numbers)
410 * storing them in a container module.
411 */
412 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
413 if (RT_SUCCESS(rc))
414 {
415 rc = rtDbgModDwarfExtractSymbols(pThis);
416 if (RT_SUCCESS(rc))
417 rc = rtDbgModDwarfExplodeLineNumbers(pThis);
418 if (RT_SUCCESS(rc))
419 {
420 pMod->pvDbgPriv = pThis;
421 return VINF_SUCCESS;
422 }
423
424 /* bail out. */
425 RTDbgModRelease(pThis->hCnt);
426 }
427 }
428 else
429 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
430 }
431 RTMemFree(pThis);
432
433 return rc;
434}
435
436
437
438/** Virtual function table for the DWARF debug info reader. */
439DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDwarf =
440{
441 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
442 /*.fSupports = */ RT_DBGTYPE_DWARF,
443 /*.pszName = */ "dwarf",
444 /*.pfnTryOpen = */ rtDbgModDwarf_TryOpen,
445 /*.pfnClose = */ rtDbgModDwarf_Close,
446
447 /*.pfnRvaToSegOff = */ rtDbgModDwarf_RvaToSegOff,
448 /*.pfnImageSize = */ rtDbgModDwarf_ImageSize,
449
450 /*.pfnSegmentAdd = */ rtDbgModDwarf_SegmentAdd,
451 /*.pfnSegmentCount = */ rtDbgModDwarf_SegmentCount,
452 /*.pfnSegmentByIndex = */ rtDbgModDwarf_SegmentByIndex,
453
454 /*.pfnSymbolAdd = */ rtDbgModDwarf_SymbolAdd,
455 /*.pfnSymbolCount = */ rtDbgModDwarf_SymbolCount,
456 /*.pfnSymbolByOrdinal = */ rtDbgModDwarf_SymbolByOrdinal,
457 /*.pfnSymbolByName = */ rtDbgModDwarf_SymbolByName,
458 /*.pfnSymbolByAddr = */ rtDbgModDwarf_SymbolByAddr,
459
460 /*.pfnLineAdd = */ rtDbgModDwarf_LineAdd,
461 /*.pfnLineCount = */ rtDbgModDwarf_LineCount,
462 /*.pfnLineByOrdinal = */ rtDbgModDwarf_LineByOrdinal,
463 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr,
464
465 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
466};
467
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette