VirtualBox

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

Last change on this file since 84204 was 83084, checked in by vboxsync, 5 years ago

IPRT,DBGPlugInDarwin: Added flags for indicating that the LINKEDIT segment should be loaded in Mach-O images and debug files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 229.7 KB
Line 
1/* $Id: dbgmoddwarf.cpp 83084 2020-02-15 15:16:11Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader For DWARF.
4 */
5
6/*
7 * Copyright (C) 2011-2020 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#define LOG_GROUP RTLOGGROUP_DBG_DWARF
32#include <iprt/dbg.h>
33#include "internal/iprt.h"
34
35#include <iprt/asm.h>
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/list.h>
39#include <iprt/log.h>
40#include <iprt/mem.h>
41#define RTDBGMODDWARF_WITH_MEM_CACHE
42#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
43# include <iprt/memcache.h>
44#endif
45#include <iprt/path.h>
46#include <iprt/string.h>
47#include <iprt/strcache.h>
48#include <iprt/x86.h>
49#include <iprt/formats/dwarf.h>
50#include "internal/dbgmod.h"
51
52
53
54/*********************************************************************************************************************************
55* Structures and Typedefs *
56*********************************************************************************************************************************/
57/** Pointer to a DWARF section reader. */
58typedef struct RTDWARFCURSOR *PRTDWARFCURSOR;
59/** Pointer to an attribute descriptor. */
60typedef struct RTDWARFATTRDESC const *PCRTDWARFATTRDESC;
61/** Pointer to a DIE. */
62typedef struct RTDWARFDIE *PRTDWARFDIE;
63/** Pointer to a const DIE. */
64typedef struct RTDWARFDIE const *PCRTDWARFDIE;
65
66/**
67 * DWARF sections.
68 */
69typedef enum krtDbgModDwarfSect
70{
71 krtDbgModDwarfSect_abbrev = 0,
72 krtDbgModDwarfSect_aranges,
73 krtDbgModDwarfSect_frame,
74 krtDbgModDwarfSect_info,
75 krtDbgModDwarfSect_inlined,
76 krtDbgModDwarfSect_line,
77 krtDbgModDwarfSect_loc,
78 krtDbgModDwarfSect_macinfo,
79 krtDbgModDwarfSect_pubnames,
80 krtDbgModDwarfSect_pubtypes,
81 krtDbgModDwarfSect_ranges,
82 krtDbgModDwarfSect_str,
83 krtDbgModDwarfSect_types,
84 /** End of valid parts (exclusive). */
85 krtDbgModDwarfSect_End
86} krtDbgModDwarfSect;
87
88/**
89 * Abbreviation cache entry.
90 */
91typedef struct RTDWARFABBREV
92{
93 /** Whether there are children or not. */
94 bool fChildren;
95#ifdef LOG_ENABLED
96 uint8_t cbHdr; /**< For calcing ABGOFF matching dwarfdump. */
97#endif
98 /** The tag. */
99 uint16_t uTag;
100 /** Offset into the abbrev section of the specification pairs. */
101 uint32_t offSpec;
102 /** The abbreviation table offset this is entry is valid for.
103 * UINT32_MAX if not valid. */
104 uint32_t offAbbrev;
105} RTDWARFABBREV;
106/** Pointer to an abbreviation cache entry. */
107typedef RTDWARFABBREV *PRTDWARFABBREV;
108/** Pointer to a const abbreviation cache entry. */
109typedef RTDWARFABBREV const *PCRTDWARFABBREV;
110
111/**
112 * Structure for gathering segment info.
113 */
114typedef struct RTDBGDWARFSEG
115{
116 /** The highest offset in the segment. */
117 uint64_t offHighest;
118 /** Calculated base address. */
119 uint64_t uBaseAddr;
120 /** Estimated The segment size. */
121 uint64_t cbSegment;
122 /** Segment number (RTLDRSEG::Sel16bit). */
123 RTSEL uSegment;
124} RTDBGDWARFSEG;
125/** Pointer to segment info. */
126typedef RTDBGDWARFSEG *PRTDBGDWARFSEG;
127
128
129/**
130 * The instance data of the DWARF reader.
131 */
132typedef struct RTDBGMODDWARF
133{
134 /** The debug container containing doing the real work. */
135 RTDBGMOD hCnt;
136 /** The image module (no reference). */
137 PRTDBGMODINT pImgMod;
138 /** The debug info module (no reference). */
139 PRTDBGMODINT pDbgInfoMod;
140 /** Nested image module (with reference ofc). */
141 PRTDBGMODINT pNestedMod;
142
143 /** DWARF debug info sections. */
144 struct
145 {
146 /** The file offset of the part. */
147 RTFOFF offFile;
148 /** The size of the part. */
149 size_t cb;
150 /** The memory mapping of the part. */
151 void const *pv;
152 /** Set if present. */
153 bool fPresent;
154 /** The debug info ordinal number in the image file. */
155 uint32_t iDbgInfo;
156 } aSections[krtDbgModDwarfSect_End];
157
158 /** The offset into the abbreviation section of the current cache. */
159 uint32_t offCachedAbbrev;
160 /** The number of cached abbreviations we've allocated space for. */
161 uint32_t cCachedAbbrevsAlloced;
162 /** Array of cached abbreviations, indexed by code. */
163 PRTDWARFABBREV paCachedAbbrevs;
164 /** Used by rtDwarfAbbrev_Lookup when the result is uncachable. */
165 RTDWARFABBREV LookupAbbrev;
166
167 /** The list of compilation units (RTDWARFDIE). */
168 RTLISTANCHOR CompileUnitList;
169
170 /** Set if we have to use link addresses because the module does not have
171 * fixups (mach_kernel). */
172 bool fUseLinkAddress;
173 /** This is set to -1 if we're doing everything in one pass.
174 * Otherwise it's 1 or 2:
175 * - In pass 1, we collect segment info.
176 * - In pass 2, we add debug info to the container.
177 * The two pass parsing is necessary for watcom generated symbol files as
178 * these contains no information about the code and data segments in the
179 * image. So we have to figure out some approximate stuff based on the
180 * segments and offsets we encounter in the debug info. */
181 int8_t iWatcomPass;
182 /** Segment index hint. */
183 uint16_t iSegHint;
184 /** The number of segments in paSegs.
185 * (During segment copying, this is abused to count useful segments.) */
186 uint32_t cSegs;
187 /** Pointer to segments if iWatcomPass isn't -1. */
188 PRTDBGDWARFSEG paSegs;
189#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
190 /** DIE allocators. */
191 struct
192 {
193 RTMEMCACHE hMemCache;
194 uint32_t cbMax;
195 } aDieAllocators[2];
196#endif
197} RTDBGMODDWARF;
198/** Pointer to instance data of the DWARF reader. */
199typedef RTDBGMODDWARF *PRTDBGMODDWARF;
200
201/**
202 * DWARF cursor for reading byte data.
203 */
204typedef struct RTDWARFCURSOR
205{
206 /** The current position. */
207 uint8_t const *pb;
208 /** The number of bytes left to read. */
209 size_t cbLeft;
210 /** The number of bytes left to read in the current unit. */
211 size_t cbUnitLeft;
212 /** The DWARF debug info reader instance. (Can be NULL for eh_frame.) */
213 PRTDBGMODDWARF pDwarfMod;
214 /** Set if this is 64-bit DWARF, clear if 32-bit. */
215 bool f64bitDwarf;
216 /** Set if the format endian is native, clear if endian needs to be
217 * inverted. */
218 bool fNativEndian;
219 /** The size of a native address. */
220 uint8_t cbNativeAddr;
221 /** The cursor status code. This is VINF_SUCCESS until some error
222 * occurs. */
223 int rc;
224 /** The start of the area covered by the cursor.
225 * Used for repositioning the cursor relative to the start of a section. */
226 uint8_t const *pbStart;
227 /** The section. */
228 krtDbgModDwarfSect enmSect;
229} RTDWARFCURSOR;
230
231
232/**
233 * DWARF line number program state.
234 */
235typedef struct RTDWARFLINESTATE
236{
237 /** Virtual Line Number Machine Registers. */
238 struct
239 {
240 uint64_t uAddress;
241 uint64_t idxOp;
242 uint32_t iFile;
243 uint32_t uLine;
244 uint32_t uColumn;
245 bool fIsStatement;
246 bool fBasicBlock;
247 bool fEndSequence;
248 bool fPrologueEnd;
249 bool fEpilogueBegin;
250 uint32_t uIsa;
251 uint32_t uDiscriminator;
252 RTSEL uSegment;
253 } Regs;
254 /** @} */
255
256 /** Header. */
257 struct
258 {
259 uint32_t uVer;
260 uint64_t offFirstOpcode;
261 uint8_t cbMinInstr;
262 uint8_t cMaxOpsPerInstr;
263 uint8_t u8DefIsStmt;
264 int8_t s8LineBase;
265 uint8_t u8LineRange;
266 uint8_t u8OpcodeBase;
267 uint8_t const *pacStdOperands;
268 } Hdr;
269
270 /** @name Include Path Table (0-based)
271 * @{ */
272 const char **papszIncPaths;
273 uint32_t cIncPaths;
274 /** @} */
275
276 /** @name File Name Table (0-based, dummy zero entry)
277 * @{ */
278 char **papszFileNames;
279 uint32_t cFileNames;
280 /** @} */
281
282 /** The DWARF debug info reader instance. */
283 PRTDBGMODDWARF pDwarfMod;
284} RTDWARFLINESTATE;
285/** Pointer to a DWARF line number program state. */
286typedef RTDWARFLINESTATE *PRTDWARFLINESTATE;
287
288
289/**
290 * Decodes an attribute and stores it in the specified DIE member field.
291 *
292 * @returns IPRT status code.
293 * @param pDie Pointer to the DIE structure.
294 * @param pbMember Pointer to the first byte in the member.
295 * @param pDesc The attribute descriptor.
296 * @param uForm The data form.
297 * @param pCursor The cursor to read data from.
298 */
299typedef DECLCALLBACK(int) FNRTDWARFATTRDECODER(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
300 uint32_t uForm, PRTDWARFCURSOR pCursor);
301/** Pointer to an attribute decoder callback. */
302typedef FNRTDWARFATTRDECODER *PFNRTDWARFATTRDECODER;
303
304/**
305 * Attribute descriptor.
306 */
307typedef struct RTDWARFATTRDESC
308{
309 /** The attribute. */
310 uint16_t uAttr;
311 /** The data member offset. */
312 uint16_t off;
313 /** The data member size and initialization method. */
314 uint8_t cbInit;
315 uint8_t bPadding[3]; /**< Alignment padding. */
316 /** The decoder function. */
317 PFNRTDWARFATTRDECODER pfnDecoder;
318} RTDWARFATTRDESC;
319
320/** Define a attribute entry. */
321#define ATTR_ENTRY(a_uAttr, a_Struct, a_Member, a_Init, a_pfnDecoder) \
322 { \
323 a_uAttr, \
324 (uint16_t)RT_OFFSETOF(a_Struct, a_Member), \
325 a_Init | ((uint8_t)RT_SIZEOFMEMB(a_Struct, a_Member) & ATTR_SIZE_MASK), \
326 { 0, 0, 0 }, \
327 a_pfnDecoder\
328 }
329
330/** @name Attribute size and init methods.
331 * @{ */
332#define ATTR_INIT_ZERO UINT8_C(0x00)
333#define ATTR_INIT_FFFS UINT8_C(0x80)
334#define ATTR_INIT_MASK UINT8_C(0x80)
335#define ATTR_SIZE_MASK UINT8_C(0x3f)
336#define ATTR_GET_SIZE(a_pAttrDesc) ((a_pAttrDesc)->cbInit & ATTR_SIZE_MASK)
337/** @} */
338
339
340/**
341 * DIE descriptor.
342 */
343typedef struct RTDWARFDIEDESC
344{
345 /** The size of the DIE. */
346 size_t cbDie;
347 /** The number of attributes. */
348 size_t cAttributes;
349 /** Pointer to the array of attributes. */
350 PCRTDWARFATTRDESC paAttributes;
351} RTDWARFDIEDESC;
352typedef struct RTDWARFDIEDESC const *PCRTDWARFDIEDESC;
353/** DIE descriptor initializer. */
354#define DIE_DESC_INIT(a_Type, a_aAttrs) { sizeof(a_Type), RT_ELEMENTS(a_aAttrs), &a_aAttrs[0] }
355
356
357/**
358 * DIE core structure, all inherits (starts with) this.
359 */
360typedef struct RTDWARFDIE
361{
362 /** Pointer to the parent node. NULL if root unit. */
363 struct RTDWARFDIE *pParent;
364 /** Our node in the sibling list. */
365 RTLISTNODE SiblingNode;
366 /** List of children. */
367 RTLISTNODE ChildList;
368 /** The number of attributes successfully decoded. */
369 uint8_t cDecodedAttrs;
370 /** The number of unknown or otherwise unhandled attributes. */
371 uint8_t cUnhandledAttrs;
372#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
373 /** The allocator index. */
374 uint8_t iAllocator;
375#endif
376 /** The die tag, indicating which union structure to use. */
377 uint16_t uTag;
378 /** Offset of the abbreviation specification (within debug_abbrev). */
379 uint32_t offSpec;
380} RTDWARFDIE;
381
382
383/**
384 * DWARF address structure.
385 */
386typedef struct RTDWARFADDR
387{
388 /** The address. */
389 uint64_t uAddress;
390} RTDWARFADDR;
391typedef RTDWARFADDR *PRTDWARFADDR;
392typedef RTDWARFADDR const *PCRTDWARFADDR;
393
394
395/**
396 * DWARF address range.
397 */
398typedef struct RTDWARFADDRRANGE
399{
400 uint64_t uLowAddress;
401 uint64_t uHighAddress;
402 uint8_t const *pbRanges; /* ?? */
403 uint8_t cAttrs : 2;
404 uint8_t fHaveLowAddress : 1;
405 uint8_t fHaveHighAddress : 1;
406 uint8_t fHaveHighIsAddress : 1;
407 uint8_t fHaveRanges : 1;
408} RTDWARFADDRRANGE;
409typedef RTDWARFADDRRANGE *PRTDWARFADDRRANGE;
410typedef RTDWARFADDRRANGE const *PCRTDWARFADDRRANGE;
411
412/** What a RTDWARFREF is relative to. */
413typedef enum krtDwarfRef
414{
415 krtDwarfRef_NotSet,
416 krtDwarfRef_LineSection,
417 krtDwarfRef_LocSection,
418 krtDwarfRef_RangesSection,
419 krtDwarfRef_InfoSection,
420 krtDwarfRef_SameUnit,
421 krtDwarfRef_TypeId64
422} krtDwarfRef;
423
424/**
425 * DWARF reference.
426 */
427typedef struct RTDWARFREF
428{
429 /** The offset. */
430 uint64_t off;
431 /** What the offset is relative to. */
432 krtDwarfRef enmWrt;
433} RTDWARFREF;
434typedef RTDWARFREF *PRTDWARFREF;
435typedef RTDWARFREF const *PCRTDWARFREF;
436
437
438/**
439 * DWARF Location state.
440 */
441typedef struct RTDWARFLOCST
442{
443 /** The input cursor. */
444 RTDWARFCURSOR Cursor;
445 /** Points to the current top of the stack. Initial value -1. */
446 int32_t iTop;
447 /** The value stack. */
448 uint64_t auStack[64];
449} RTDWARFLOCST;
450/** Pointer to location state. */
451typedef RTDWARFLOCST *PRTDWARFLOCST;
452
453
454
455/*********************************************************************************************************************************
456* Internal Functions *
457*********************************************************************************************************************************/
458static FNRTDWARFATTRDECODER rtDwarfDecode_Address;
459static FNRTDWARFATTRDECODER rtDwarfDecode_Bool;
460static FNRTDWARFATTRDECODER rtDwarfDecode_LowHighPc;
461static FNRTDWARFATTRDECODER rtDwarfDecode_Ranges;
462static FNRTDWARFATTRDECODER rtDwarfDecode_Reference;
463static FNRTDWARFATTRDECODER rtDwarfDecode_SectOff;
464static FNRTDWARFATTRDECODER rtDwarfDecode_String;
465static FNRTDWARFATTRDECODER rtDwarfDecode_UnsignedInt;
466static FNRTDWARFATTRDECODER rtDwarfDecode_SegmentLoc;
467
468
469/*********************************************************************************************************************************
470* Global Variables *
471*********************************************************************************************************************************/
472/** RTDWARFDIE description. */
473static const RTDWARFDIEDESC g_CoreDieDesc = { sizeof(RTDWARFDIE), 0, NULL };
474
475
476/**
477 * DW_TAG_compile_unit & DW_TAG_partial_unit.
478 */
479typedef struct RTDWARFDIECOMPILEUNIT
480{
481 /** The DIE core structure. */
482 RTDWARFDIE Core;
483 /** The unit name. */
484 const char *pszName;
485 /** The address range of the code belonging to this unit. */
486 RTDWARFADDRRANGE PcRange;
487 /** The language name. */
488 uint16_t uLanguage;
489 /** The identifier case. */
490 uint8_t uIdentifierCase;
491 /** String are UTF-8 encoded. If not set, the encoding is
492 * unknown. */
493 bool fUseUtf8;
494 /** The unit contains main() or equivalent. */
495 bool fMainFunction;
496 /** The line numbers for this unit. */
497 RTDWARFREF StmtListRef;
498 /** The macro information for this unit. */
499 RTDWARFREF MacroInfoRef;
500 /** Reference to the base types. */
501 RTDWARFREF BaseTypesRef;
502 /** Working directory for the unit. */
503 const char *pszCurDir;
504 /** The name of the compiler or whatever that produced this unit. */
505 const char *pszProducer;
506
507 /** @name From the unit header.
508 * @{ */
509 /** The offset into debug_info of this unit (for references). */
510 uint64_t offUnit;
511 /** The length of this unit. */
512 uint64_t cbUnit;
513 /** The offset into debug_abbrev of the abbreviation for this unit. */
514 uint64_t offAbbrev;
515 /** The native address size. */
516 uint8_t cbNativeAddr;
517 /** The DWARF version. */
518 uint8_t uDwarfVer;
519 /** @} */
520} RTDWARFDIECOMPILEUNIT;
521typedef RTDWARFDIECOMPILEUNIT *PRTDWARFDIECOMPILEUNIT;
522
523
524/** RTDWARFDIECOMPILEUNIT attributes. */
525static const RTDWARFATTRDESC g_aCompileUnitAttrs[] =
526{
527 ATTR_ENTRY(DW_AT_name, RTDWARFDIECOMPILEUNIT, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
528 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
529 ATTR_ENTRY(DW_AT_high_pc, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
530 ATTR_ENTRY(DW_AT_ranges, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_Ranges),
531 ATTR_ENTRY(DW_AT_language, RTDWARFDIECOMPILEUNIT, uLanguage, ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
532 ATTR_ENTRY(DW_AT_macro_info, RTDWARFDIECOMPILEUNIT, MacroInfoRef, ATTR_INIT_ZERO, rtDwarfDecode_SectOff),
533 ATTR_ENTRY(DW_AT_stmt_list, RTDWARFDIECOMPILEUNIT, StmtListRef, ATTR_INIT_ZERO, rtDwarfDecode_SectOff),
534 ATTR_ENTRY(DW_AT_comp_dir, RTDWARFDIECOMPILEUNIT, pszCurDir, ATTR_INIT_ZERO, rtDwarfDecode_String),
535 ATTR_ENTRY(DW_AT_producer, RTDWARFDIECOMPILEUNIT, pszProducer, ATTR_INIT_ZERO, rtDwarfDecode_String),
536 ATTR_ENTRY(DW_AT_identifier_case, RTDWARFDIECOMPILEUNIT, uIdentifierCase,ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
537 ATTR_ENTRY(DW_AT_base_types, RTDWARFDIECOMPILEUNIT, BaseTypesRef, ATTR_INIT_ZERO, rtDwarfDecode_Reference),
538 ATTR_ENTRY(DW_AT_use_UTF8, RTDWARFDIECOMPILEUNIT, fUseUtf8, ATTR_INIT_ZERO, rtDwarfDecode_Bool),
539 ATTR_ENTRY(DW_AT_main_subprogram, RTDWARFDIECOMPILEUNIT, fMainFunction, ATTR_INIT_ZERO, rtDwarfDecode_Bool)
540};
541
542/** RTDWARFDIECOMPILEUNIT description. */
543static const RTDWARFDIEDESC g_CompileUnitDesc = DIE_DESC_INIT(RTDWARFDIECOMPILEUNIT, g_aCompileUnitAttrs);
544
545
546/**
547 * DW_TAG_subprogram.
548 */
549typedef struct RTDWARFDIESUBPROGRAM
550{
551 /** The DIE core structure. */
552 RTDWARFDIE Core;
553 /** The name. */
554 const char *pszName;
555 /** The linkage name. */
556 const char *pszLinkageName;
557 /** The address range of the code belonging to this unit. */
558 RTDWARFADDRRANGE PcRange;
559 /** The first instruction in the function. */
560 RTDWARFADDR EntryPc;
561 /** Segment number (watcom). */
562 RTSEL uSegment;
563 /** Reference to the specification. */
564 RTDWARFREF SpecRef;
565} RTDWARFDIESUBPROGRAM;
566/** Pointer to a DW_TAG_subprogram DIE. */
567typedef RTDWARFDIESUBPROGRAM *PRTDWARFDIESUBPROGRAM;
568/** Pointer to a const DW_TAG_subprogram DIE. */
569typedef RTDWARFDIESUBPROGRAM const *PCRTDWARFDIESUBPROGRAM;
570
571
572/** RTDWARFDIESUBPROGRAM attributes. */
573static const RTDWARFATTRDESC g_aSubProgramAttrs[] =
574{
575 ATTR_ENTRY(DW_AT_name, RTDWARFDIESUBPROGRAM, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
576 ATTR_ENTRY(DW_AT_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
577 ATTR_ENTRY(DW_AT_MIPS_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
578 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
579 ATTR_ENTRY(DW_AT_high_pc, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
580 ATTR_ENTRY(DW_AT_ranges, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_Ranges),
581 ATTR_ENTRY(DW_AT_entry_pc, RTDWARFDIESUBPROGRAM, EntryPc, ATTR_INIT_ZERO, rtDwarfDecode_Address),
582 ATTR_ENTRY(DW_AT_segment, RTDWARFDIESUBPROGRAM, uSegment, ATTR_INIT_ZERO, rtDwarfDecode_SegmentLoc),
583 ATTR_ENTRY(DW_AT_specification, RTDWARFDIESUBPROGRAM, SpecRef, ATTR_INIT_ZERO, rtDwarfDecode_Reference)
584};
585
586/** RTDWARFDIESUBPROGRAM description. */
587static const RTDWARFDIEDESC g_SubProgramDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramAttrs);
588
589
590/** RTDWARFDIESUBPROGRAM attributes for the specification hack. */
591static const RTDWARFATTRDESC g_aSubProgramSpecHackAttrs[] =
592{
593 ATTR_ENTRY(DW_AT_name, RTDWARFDIESUBPROGRAM, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
594 ATTR_ENTRY(DW_AT_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
595 ATTR_ENTRY(DW_AT_MIPS_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
596};
597
598/** RTDWARFDIESUBPROGRAM description for the specification hack. */
599static const RTDWARFDIEDESC g_SubProgramSpecHackDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramSpecHackAttrs);
600
601
602/**
603 * DW_TAG_label.
604 */
605typedef struct RTDWARFDIELABEL
606{
607 /** The DIE core structure. */
608 RTDWARFDIE Core;
609 /** The name. */
610 const char *pszName;
611 /** The address of the first instruction. */
612 RTDWARFADDR Address;
613 /** Segment number (watcom). */
614 RTSEL uSegment;
615 /** Externally visible? */
616 bool fExternal;
617} RTDWARFDIELABEL;
618/** Pointer to a DW_TAG_label DIE. */
619typedef RTDWARFDIELABEL *PRTDWARFDIELABEL;
620/** Pointer to a const DW_TAG_label DIE. */
621typedef RTDWARFDIELABEL const *PCRTDWARFDIELABEL;
622
623
624/** RTDWARFDIESUBPROGRAM attributes. */
625static const RTDWARFATTRDESC g_aLabelAttrs[] =
626{
627 ATTR_ENTRY(DW_AT_name, RTDWARFDIELABEL, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
628 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIELABEL, Address, ATTR_INIT_ZERO, rtDwarfDecode_Address),
629 ATTR_ENTRY(DW_AT_segment, RTDWARFDIELABEL, uSegment, ATTR_INIT_ZERO, rtDwarfDecode_SegmentLoc),
630 ATTR_ENTRY(DW_AT_external, RTDWARFDIELABEL, fExternal, ATTR_INIT_ZERO, rtDwarfDecode_Bool)
631};
632
633/** RTDWARFDIESUBPROGRAM description. */
634static const RTDWARFDIEDESC g_LabelDesc = DIE_DESC_INIT(RTDWARFDIELABEL, g_aLabelAttrs);
635
636
637/**
638 * Tag names and descriptors.
639 */
640static const struct RTDWARFTAGDESC
641{
642 /** The tag value. */
643 uint16_t uTag;
644 /** The tag name as string. */
645 const char *pszName;
646 /** The DIE descriptor to use. */
647 PCRTDWARFDIEDESC pDesc;
648} g_aTagDescs[] =
649{
650#define TAGDESC(a_Name, a_pDesc) { DW_ ## a_Name, #a_Name, a_pDesc }
651#define TAGDESC_EMPTY() { 0, NULL, &g_CoreDieDesc }
652#define TAGDESC_CORE(a_Name) TAGDESC(a_Name, &g_CoreDieDesc)
653 TAGDESC_EMPTY(), /* 0x00 */
654 TAGDESC_CORE(TAG_array_type),
655 TAGDESC_CORE(TAG_class_type),
656 TAGDESC_CORE(TAG_entry_point),
657 TAGDESC_CORE(TAG_enumeration_type), /* 0x04 */
658 TAGDESC_CORE(TAG_formal_parameter),
659 TAGDESC_EMPTY(),
660 TAGDESC_EMPTY(),
661 TAGDESC_CORE(TAG_imported_declaration), /* 0x08 */
662 TAGDESC_EMPTY(),
663 TAGDESC(TAG_label, &g_LabelDesc),
664 TAGDESC_CORE(TAG_lexical_block),
665 TAGDESC_EMPTY(), /* 0x0c */
666 TAGDESC_CORE(TAG_member),
667 TAGDESC_EMPTY(),
668 TAGDESC_CORE(TAG_pointer_type),
669 TAGDESC_CORE(TAG_reference_type), /* 0x10 */
670 TAGDESC_CORE(TAG_compile_unit),
671 TAGDESC_CORE(TAG_string_type),
672 TAGDESC_CORE(TAG_structure_type),
673 TAGDESC_EMPTY(), /* 0x14 */
674 TAGDESC_CORE(TAG_subroutine_type),
675 TAGDESC_CORE(TAG_typedef),
676 TAGDESC_CORE(TAG_union_type),
677 TAGDESC_CORE(TAG_unspecified_parameters), /* 0x18 */
678 TAGDESC_CORE(TAG_variant),
679 TAGDESC_CORE(TAG_common_block),
680 TAGDESC_CORE(TAG_common_inclusion),
681 TAGDESC_CORE(TAG_inheritance), /* 0x1c */
682 TAGDESC_CORE(TAG_inlined_subroutine),
683 TAGDESC_CORE(TAG_module),
684 TAGDESC_CORE(TAG_ptr_to_member_type),
685 TAGDESC_CORE(TAG_set_type), /* 0x20 */
686 TAGDESC_CORE(TAG_subrange_type),
687 TAGDESC_CORE(TAG_with_stmt),
688 TAGDESC_CORE(TAG_access_declaration),
689 TAGDESC_CORE(TAG_base_type), /* 0x24 */
690 TAGDESC_CORE(TAG_catch_block),
691 TAGDESC_CORE(TAG_const_type),
692 TAGDESC_CORE(TAG_constant),
693 TAGDESC_CORE(TAG_enumerator), /* 0x28 */
694 TAGDESC_CORE(TAG_file_type),
695 TAGDESC_CORE(TAG_friend),
696 TAGDESC_CORE(TAG_namelist),
697 TAGDESC_CORE(TAG_namelist_item), /* 0x2c */
698 TAGDESC_CORE(TAG_packed_type),
699 TAGDESC(TAG_subprogram, &g_SubProgramDesc),
700 TAGDESC_CORE(TAG_template_type_parameter),
701 TAGDESC_CORE(TAG_template_value_parameter), /* 0x30 */
702 TAGDESC_CORE(TAG_thrown_type),
703 TAGDESC_CORE(TAG_try_block),
704 TAGDESC_CORE(TAG_variant_part),
705 TAGDESC_CORE(TAG_variable), /* 0x34 */
706 TAGDESC_CORE(TAG_volatile_type),
707 TAGDESC_CORE(TAG_dwarf_procedure),
708 TAGDESC_CORE(TAG_restrict_type),
709 TAGDESC_CORE(TAG_interface_type), /* 0x38 */
710 TAGDESC_CORE(TAG_namespace),
711 TAGDESC_CORE(TAG_imported_module),
712 TAGDESC_CORE(TAG_unspecified_type),
713 TAGDESC_CORE(TAG_partial_unit), /* 0x3c */
714 TAGDESC_CORE(TAG_imported_unit),
715 TAGDESC_EMPTY(),
716 TAGDESC_CORE(TAG_condition),
717 TAGDESC_CORE(TAG_shared_type), /* 0x40 */
718 TAGDESC_CORE(TAG_type_unit),
719 TAGDESC_CORE(TAG_rvalue_reference_type),
720 TAGDESC_CORE(TAG_template_alias)
721#undef TAGDESC
722#undef TAGDESC_EMPTY
723#undef TAGDESC_CORE
724};
725
726
727/*********************************************************************************************************************************
728* Internal Functions *
729*********************************************************************************************************************************/
730static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc,
731 PRTDWARFCURSOR pCursor, PCRTDWARFABBREV pAbbrev, bool fInitDie);
732
733
734
735#if defined(LOG_ENABLED) || defined(RT_STRICT)
736
737# if 0 /* unused */
738/**
739 * Turns a tag value into a string for logging purposes.
740 *
741 * @returns String name.
742 * @param uTag The tag.
743 */
744static const char *rtDwarfLog_GetTagName(uint32_t uTag)
745{
746 if (uTag < RT_ELEMENTS(g_aTagDescs))
747 {
748 const char *pszTag = g_aTagDescs[uTag].pszName;
749 if (pszTag)
750 return pszTag;
751 }
752
753 static char s_szStatic[32];
754 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_TAG_%#x", uTag);
755 return s_szStatic;
756}
757# endif
758
759
760/**
761 * Turns an attributevalue into a string for logging purposes.
762 *
763 * @returns String name.
764 * @param uAttr The attribute.
765 */
766static const char *rtDwarfLog_AttrName(uint32_t uAttr)
767{
768 switch (uAttr)
769 {
770 RT_CASE_RET_STR(DW_AT_sibling);
771 RT_CASE_RET_STR(DW_AT_location);
772 RT_CASE_RET_STR(DW_AT_name);
773 RT_CASE_RET_STR(DW_AT_ordering);
774 RT_CASE_RET_STR(DW_AT_byte_size);
775 RT_CASE_RET_STR(DW_AT_bit_offset);
776 RT_CASE_RET_STR(DW_AT_bit_size);
777 RT_CASE_RET_STR(DW_AT_stmt_list);
778 RT_CASE_RET_STR(DW_AT_low_pc);
779 RT_CASE_RET_STR(DW_AT_high_pc);
780 RT_CASE_RET_STR(DW_AT_language);
781 RT_CASE_RET_STR(DW_AT_discr);
782 RT_CASE_RET_STR(DW_AT_discr_value);
783 RT_CASE_RET_STR(DW_AT_visibility);
784 RT_CASE_RET_STR(DW_AT_import);
785 RT_CASE_RET_STR(DW_AT_string_length);
786 RT_CASE_RET_STR(DW_AT_common_reference);
787 RT_CASE_RET_STR(DW_AT_comp_dir);
788 RT_CASE_RET_STR(DW_AT_const_value);
789 RT_CASE_RET_STR(DW_AT_containing_type);
790 RT_CASE_RET_STR(DW_AT_default_value);
791 RT_CASE_RET_STR(DW_AT_inline);
792 RT_CASE_RET_STR(DW_AT_is_optional);
793 RT_CASE_RET_STR(DW_AT_lower_bound);
794 RT_CASE_RET_STR(DW_AT_producer);
795 RT_CASE_RET_STR(DW_AT_prototyped);
796 RT_CASE_RET_STR(DW_AT_return_addr);
797 RT_CASE_RET_STR(DW_AT_start_scope);
798 RT_CASE_RET_STR(DW_AT_bit_stride);
799 RT_CASE_RET_STR(DW_AT_upper_bound);
800 RT_CASE_RET_STR(DW_AT_abstract_origin);
801 RT_CASE_RET_STR(DW_AT_accessibility);
802 RT_CASE_RET_STR(DW_AT_address_class);
803 RT_CASE_RET_STR(DW_AT_artificial);
804 RT_CASE_RET_STR(DW_AT_base_types);
805 RT_CASE_RET_STR(DW_AT_calling_convention);
806 RT_CASE_RET_STR(DW_AT_count);
807 RT_CASE_RET_STR(DW_AT_data_member_location);
808 RT_CASE_RET_STR(DW_AT_decl_column);
809 RT_CASE_RET_STR(DW_AT_decl_file);
810 RT_CASE_RET_STR(DW_AT_decl_line);
811 RT_CASE_RET_STR(DW_AT_declaration);
812 RT_CASE_RET_STR(DW_AT_discr_list);
813 RT_CASE_RET_STR(DW_AT_encoding);
814 RT_CASE_RET_STR(DW_AT_external);
815 RT_CASE_RET_STR(DW_AT_frame_base);
816 RT_CASE_RET_STR(DW_AT_friend);
817 RT_CASE_RET_STR(DW_AT_identifier_case);
818 RT_CASE_RET_STR(DW_AT_macro_info);
819 RT_CASE_RET_STR(DW_AT_namelist_item);
820 RT_CASE_RET_STR(DW_AT_priority);
821 RT_CASE_RET_STR(DW_AT_segment);
822 RT_CASE_RET_STR(DW_AT_specification);
823 RT_CASE_RET_STR(DW_AT_static_link);
824 RT_CASE_RET_STR(DW_AT_type);
825 RT_CASE_RET_STR(DW_AT_use_location);
826 RT_CASE_RET_STR(DW_AT_variable_parameter);
827 RT_CASE_RET_STR(DW_AT_virtuality);
828 RT_CASE_RET_STR(DW_AT_vtable_elem_location);
829 RT_CASE_RET_STR(DW_AT_allocated);
830 RT_CASE_RET_STR(DW_AT_associated);
831 RT_CASE_RET_STR(DW_AT_data_location);
832 RT_CASE_RET_STR(DW_AT_byte_stride);
833 RT_CASE_RET_STR(DW_AT_entry_pc);
834 RT_CASE_RET_STR(DW_AT_use_UTF8);
835 RT_CASE_RET_STR(DW_AT_extension);
836 RT_CASE_RET_STR(DW_AT_ranges);
837 RT_CASE_RET_STR(DW_AT_trampoline);
838 RT_CASE_RET_STR(DW_AT_call_column);
839 RT_CASE_RET_STR(DW_AT_call_file);
840 RT_CASE_RET_STR(DW_AT_call_line);
841 RT_CASE_RET_STR(DW_AT_description);
842 RT_CASE_RET_STR(DW_AT_binary_scale);
843 RT_CASE_RET_STR(DW_AT_decimal_scale);
844 RT_CASE_RET_STR(DW_AT_small);
845 RT_CASE_RET_STR(DW_AT_decimal_sign);
846 RT_CASE_RET_STR(DW_AT_digit_count);
847 RT_CASE_RET_STR(DW_AT_picture_string);
848 RT_CASE_RET_STR(DW_AT_mutable);
849 RT_CASE_RET_STR(DW_AT_threads_scaled);
850 RT_CASE_RET_STR(DW_AT_explicit);
851 RT_CASE_RET_STR(DW_AT_object_pointer);
852 RT_CASE_RET_STR(DW_AT_endianity);
853 RT_CASE_RET_STR(DW_AT_elemental);
854 RT_CASE_RET_STR(DW_AT_pure);
855 RT_CASE_RET_STR(DW_AT_recursive);
856 RT_CASE_RET_STR(DW_AT_signature);
857 RT_CASE_RET_STR(DW_AT_main_subprogram);
858 RT_CASE_RET_STR(DW_AT_data_bit_offset);
859 RT_CASE_RET_STR(DW_AT_const_expr);
860 RT_CASE_RET_STR(DW_AT_enum_class);
861 RT_CASE_RET_STR(DW_AT_linkage_name);
862 RT_CASE_RET_STR(DW_AT_MIPS_linkage_name);
863 RT_CASE_RET_STR(DW_AT_WATCOM_memory_model);
864 RT_CASE_RET_STR(DW_AT_WATCOM_references_start);
865 RT_CASE_RET_STR(DW_AT_WATCOM_parm_entry);
866 }
867 static char s_szStatic[32];
868 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_AT_%#x", uAttr);
869 return s_szStatic;
870}
871
872
873/**
874 * Turns a form value into a string for logging purposes.
875 *
876 * @returns String name.
877 * @param uForm The form.
878 */
879static const char *rtDwarfLog_FormName(uint32_t uForm)
880{
881 switch (uForm)
882 {
883 RT_CASE_RET_STR(DW_FORM_addr);
884 RT_CASE_RET_STR(DW_FORM_block2);
885 RT_CASE_RET_STR(DW_FORM_block4);
886 RT_CASE_RET_STR(DW_FORM_data2);
887 RT_CASE_RET_STR(DW_FORM_data4);
888 RT_CASE_RET_STR(DW_FORM_data8);
889 RT_CASE_RET_STR(DW_FORM_string);
890 RT_CASE_RET_STR(DW_FORM_block);
891 RT_CASE_RET_STR(DW_FORM_block1);
892 RT_CASE_RET_STR(DW_FORM_data1);
893 RT_CASE_RET_STR(DW_FORM_flag);
894 RT_CASE_RET_STR(DW_FORM_sdata);
895 RT_CASE_RET_STR(DW_FORM_strp);
896 RT_CASE_RET_STR(DW_FORM_udata);
897 RT_CASE_RET_STR(DW_FORM_ref_addr);
898 RT_CASE_RET_STR(DW_FORM_ref1);
899 RT_CASE_RET_STR(DW_FORM_ref2);
900 RT_CASE_RET_STR(DW_FORM_ref4);
901 RT_CASE_RET_STR(DW_FORM_ref8);
902 RT_CASE_RET_STR(DW_FORM_ref_udata);
903 RT_CASE_RET_STR(DW_FORM_indirect);
904 RT_CASE_RET_STR(DW_FORM_sec_offset);
905 RT_CASE_RET_STR(DW_FORM_exprloc);
906 RT_CASE_RET_STR(DW_FORM_flag_present);
907 RT_CASE_RET_STR(DW_FORM_ref_sig8);
908 }
909 static char s_szStatic[32];
910 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_FORM_%#x", uForm);
911 return s_szStatic;
912}
913
914#endif /* LOG_ENABLED || RT_STRICT */
915
916
917
918/** @callback_method_impl{FNRTLDRENUMSEGS} */
919static DECLCALLBACK(int) rtDbgModDwarfScanSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
920{
921 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
922 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx\n",
923 pSeg->cchName, pSeg->pszName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb));
924 NOREF(hLdrMod);
925
926 /* Count relevant segments. */
927 if (pSeg->RVA != NIL_RTLDRADDR)
928 pThis->cSegs++;
929
930 return VINF_SUCCESS;
931}
932
933
934/** @callback_method_impl{FNRTLDRENUMSEGS} */
935static DECLCALLBACK(int) rtDbgModDwarfAddSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
936{
937 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
938 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx cbMapped=%#llx\n",
939 pSeg->cchName, pSeg->pszName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb, pSeg->cbMapped));
940 NOREF(hLdrMod);
941 Assert(pSeg->cchName > 0);
942 Assert(!pSeg->pszName[pSeg->cchName]);
943
944 /* If the segment doesn't have a mapping, just add a dummy so the indexing
945 works out correctly (same as for the image). */
946 if (pSeg->RVA == NIL_RTLDRADDR)
947 return RTDbgModSegmentAdd(pThis->hCnt, 0, 0, pSeg->pszName, 0 /*fFlags*/, NULL);
948
949 /* The link address is 0 for all segments in a relocatable ELF image. */
950 RTLDRADDR cb = pSeg->cb;
951 if ( cb < pSeg->cbMapped
952 && RTLdrGetFormat(hLdrMod) != RTLDRFMT_LX /* for debugging our drivers; 64KB section align by linker, 4KB by loader. */
953 )
954 cb = pSeg->cbMapped;
955 return RTDbgModSegmentAdd(pThis->hCnt, pSeg->RVA, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
956}
957
958
959/**
960 * Calls rtDbgModDwarfAddSegmentsCallback for each segment in the executable
961 * image.
962 *
963 * @returns IPRT status code.
964 * @param pThis The DWARF instance.
965 */
966static int rtDbgModDwarfAddSegmentsFromImage(PRTDBGMODDWARF pThis)
967{
968 AssertReturn(pThis->pImgMod && pThis->pImgMod->pImgVt, VERR_INTERNAL_ERROR_2);
969 Assert(!pThis->cSegs);
970 int rc = pThis->pImgMod->pImgVt->pfnEnumSegments(pThis->pImgMod, rtDbgModDwarfScanSegmentsCallback, pThis);
971 if (RT_SUCCESS(rc))
972 {
973 if (pThis->cSegs == 0)
974 pThis->iWatcomPass = 1;
975 else
976 {
977 pThis->cSegs = 0;
978 pThis->iWatcomPass = -1;
979 rc = pThis->pImgMod->pImgVt->pfnEnumSegments(pThis->pImgMod, rtDbgModDwarfAddSegmentsCallback, pThis);
980 }
981 }
982
983 return rc;
984}
985
986
987/**
988 * Looks up a segment.
989 *
990 * @returns Pointer to the segment on success, NULL if not found.
991 * @param pThis The DWARF instance.
992 * @param uSeg The segment number / selector.
993 */
994static PRTDBGDWARFSEG rtDbgModDwarfFindSegment(PRTDBGMODDWARF pThis, RTSEL uSeg)
995{
996 uint32_t cSegs = pThis->cSegs;
997 uint32_t iSeg = pThis->iSegHint;
998 PRTDBGDWARFSEG paSegs = pThis->paSegs;
999 if ( iSeg < cSegs
1000 && paSegs[iSeg].uSegment == uSeg)
1001 return &paSegs[iSeg];
1002
1003 for (iSeg = 0; iSeg < cSegs; iSeg++)
1004 if (uSeg == paSegs[iSeg].uSegment)
1005 {
1006 pThis->iSegHint = iSeg;
1007 return &paSegs[iSeg];
1008 }
1009
1010 AssertFailed();
1011 return NULL;
1012}
1013
1014
1015/**
1016 * Record a segment:offset during pass 1.
1017 *
1018 * @returns IPRT status code.
1019 * @param pThis The DWARF instance.
1020 * @param uSeg The segment number / selector.
1021 * @param offSeg The segment offset.
1022 */
1023static int rtDbgModDwarfRecordSegOffset(PRTDBGMODDWARF pThis, RTSEL uSeg, uint64_t offSeg)
1024{
1025 /* Look up the segment. */
1026 uint32_t cSegs = pThis->cSegs;
1027 uint32_t iSeg = pThis->iSegHint;
1028 PRTDBGDWARFSEG paSegs = pThis->paSegs;
1029 if ( iSeg >= cSegs
1030 || paSegs[iSeg].uSegment != uSeg)
1031 {
1032 for (iSeg = 0; iSeg < cSegs; iSeg++)
1033 if (uSeg <= paSegs[iSeg].uSegment)
1034 break;
1035 if ( iSeg >= cSegs
1036 || paSegs[iSeg].uSegment != uSeg)
1037 {
1038 /* Add */
1039 void *pvNew = RTMemRealloc(paSegs, (pThis->cSegs + 1) * sizeof(paSegs[0]));
1040 if (!pvNew)
1041 return VERR_NO_MEMORY;
1042 pThis->paSegs = paSegs = (PRTDBGDWARFSEG)pvNew;
1043 if (iSeg != cSegs)
1044 memmove(&paSegs[iSeg + 1], &paSegs[iSeg], (cSegs - iSeg) * sizeof(paSegs[0]));
1045 paSegs[iSeg].offHighest = offSeg;
1046 paSegs[iSeg].uBaseAddr = 0;
1047 paSegs[iSeg].cbSegment = 0;
1048 paSegs[iSeg].uSegment = uSeg;
1049 pThis->cSegs++;
1050 }
1051
1052 pThis->iSegHint = iSeg;
1053 }
1054
1055 /* Increase it's range? */
1056 if (paSegs[iSeg].offHighest < offSeg)
1057 {
1058 Log3(("rtDbgModDwarfRecordSegOffset: iSeg=%d uSeg=%#06x offSeg=%#llx\n", iSeg, uSeg, offSeg));
1059 paSegs[iSeg].offHighest = offSeg;
1060 }
1061
1062 return VINF_SUCCESS;
1063}
1064
1065
1066/**
1067 * Calls pfnSegmentAdd for each segment in the executable image.
1068 *
1069 * @returns IPRT status code.
1070 * @param pThis The DWARF instance.
1071 */
1072static int rtDbgModDwarfAddSegmentsFromPass1(PRTDBGMODDWARF pThis)
1073{
1074 AssertReturn(pThis->cSegs, VERR_DWARF_BAD_INFO);
1075 uint32_t const cSegs = pThis->cSegs;
1076 PRTDBGDWARFSEG paSegs = pThis->paSegs;
1077
1078 /*
1079 * Are the segments assigned more or less in numerical order?
1080 */
1081 if ( paSegs[0].uSegment < 16U
1082 && paSegs[cSegs - 1].uSegment - paSegs[0].uSegment + 1U <= cSegs + 16U)
1083 {
1084 /** @todo heuristics, plase. */
1085 AssertFailedReturn(VERR_DWARF_TODO);
1086
1087 }
1088 /*
1089 * Assume DOS segmentation.
1090 */
1091 else
1092 {
1093 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1094 paSegs[iSeg].uBaseAddr = (uint32_t)paSegs[iSeg].uSegment << 16;
1095 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1096 paSegs[iSeg].cbSegment = paSegs[iSeg].offHighest;
1097 }
1098
1099 /*
1100 * Add them.
1101 */
1102 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1103 {
1104 Log3(("rtDbgModDwarfAddSegmentsFromPass1: Seg#%u: %#010llx LB %#llx uSegment=%#x\n",
1105 iSeg, paSegs[iSeg].uBaseAddr, paSegs[iSeg].cbSegment, paSegs[iSeg].uSegment));
1106 char szName[32];
1107 RTStrPrintf(szName, sizeof(szName), "seg-%#04xh", paSegs[iSeg].uSegment);
1108 int rc = RTDbgModSegmentAdd(pThis->hCnt, paSegs[iSeg].uBaseAddr, paSegs[iSeg].cbSegment,
1109 szName, 0 /*fFlags*/, NULL);
1110 if (RT_FAILURE(rc))
1111 return rc;
1112 }
1113
1114 return VINF_SUCCESS;
1115}
1116
1117
1118/**
1119 * Loads a DWARF section from the image file.
1120 *
1121 * @returns IPRT status code.
1122 * @param pThis The DWARF instance.
1123 * @param enmSect The section to load.
1124 */
1125static int rtDbgModDwarfLoadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
1126{
1127 /*
1128 * Don't load stuff twice.
1129 */
1130 if (pThis->aSections[enmSect].pv)
1131 return VINF_SUCCESS;
1132
1133 /*
1134 * Sections that are not present cannot be loaded, treat them like they
1135 * are empty
1136 */
1137 if (!pThis->aSections[enmSect].fPresent)
1138 {
1139 Assert(pThis->aSections[enmSect].cb);
1140 return VINF_SUCCESS;
1141 }
1142 if (!pThis->aSections[enmSect].cb)
1143 return VINF_SUCCESS;
1144
1145 /*
1146 * Sections must be readable with the current image interface.
1147 */
1148 if (pThis->aSections[enmSect].offFile < 0)
1149 return VERR_OUT_OF_RANGE;
1150
1151 /*
1152 * Do the job.
1153 */
1154 return pThis->pDbgInfoMod->pImgVt->pfnMapPart(pThis->pDbgInfoMod,
1155 pThis->aSections[enmSect].iDbgInfo,
1156 pThis->aSections[enmSect].offFile,
1157 pThis->aSections[enmSect].cb,
1158 &pThis->aSections[enmSect].pv);
1159}
1160
1161
1162#ifdef SOME_UNUSED_FUNCTION
1163/**
1164 * Unloads a DWARF section previously mapped by rtDbgModDwarfLoadSection.
1165 *
1166 * @returns IPRT status code.
1167 * @param pThis The DWARF instance.
1168 * @param enmSect The section to unload.
1169 */
1170static int rtDbgModDwarfUnloadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
1171{
1172 if (!pThis->aSections[enmSect].pv)
1173 return VINF_SUCCESS;
1174
1175 int rc = pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[enmSect].cb, &pThis->aSections[enmSect].pv);
1176 AssertRC(rc);
1177 return rc;
1178}
1179#endif
1180
1181
1182/**
1183 * Converts to UTF-8 or otherwise makes sure it's valid UTF-8.
1184 *
1185 * @returns IPRT status code.
1186 * @param pThis The DWARF instance.
1187 * @param ppsz Pointer to the string pointer. May be
1188 * reallocated (RTStr*).
1189 */
1190static int rtDbgModDwarfStringToUtf8(PRTDBGMODDWARF pThis, char **ppsz)
1191{
1192 /** @todo DWARF & UTF-8. */
1193 NOREF(pThis);
1194 RTStrPurgeEncoding(*ppsz);
1195 return VINF_SUCCESS;
1196}
1197
1198
1199/**
1200 * Convers a link address into a segment+offset or RVA.
1201 *
1202 * @returns IPRT status code.
1203 * @param pThis The DWARF instance.
1204 * @param uSegment The segment, 0 if not applicable.
1205 * @param LinkAddress The address to convert..
1206 * @param piSeg The segment index.
1207 * @param poffSeg Where to return the segment offset.
1208 */
1209static int rtDbgModDwarfLinkAddressToSegOffset(PRTDBGMODDWARF pThis, RTSEL uSegment, uint64_t LinkAddress,
1210 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg)
1211{
1212 if (pThis->paSegs)
1213 {
1214 PRTDBGDWARFSEG pSeg = rtDbgModDwarfFindSegment(pThis, uSegment);
1215 if (pSeg)
1216 {
1217 *piSeg = pSeg - pThis->paSegs;
1218 *poffSeg = LinkAddress;
1219 return VINF_SUCCESS;
1220 }
1221 }
1222
1223 if (pThis->fUseLinkAddress)
1224 return pThis->pImgMod->pImgVt->pfnLinkAddressToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
1225
1226 /* If we have a non-zero segment number, assume it's correct for now.
1227 This helps loading watcom linked LX drivers. */
1228 if (uSegment > 0)
1229 {
1230 *piSeg = uSegment - 1;
1231 *poffSeg = LinkAddress;
1232 return VINF_SUCCESS;
1233 }
1234
1235 return pThis->pImgMod->pImgVt->pfnRvaToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
1236}
1237
1238
1239/**
1240 * Converts a segment+offset address into an RVA.
1241 *
1242 * @returns IPRT status code.
1243 * @param pThis The DWARF instance.
1244 * @param idxSegment The segment index.
1245 * @param offSegment The segment offset.
1246 * @param puRva Where to return the calculated RVA.
1247 */
1248static int rtDbgModDwarfSegOffsetToRva(PRTDBGMODDWARF pThis, RTDBGSEGIDX idxSegment, uint64_t offSegment, PRTUINTPTR puRva)
1249{
1250 if (pThis->paSegs)
1251 {
1252 PRTDBGDWARFSEG pSeg = rtDbgModDwarfFindSegment(pThis, idxSegment);
1253 if (pSeg)
1254 {
1255 *puRva = pSeg->uBaseAddr + offSegment;
1256 return VINF_SUCCESS;
1257 }
1258 }
1259
1260 RTUINTPTR uRva = RTDbgModSegmentRva(pThis->pImgMod, idxSegment);
1261 if (uRva != RTUINTPTR_MAX)
1262 {
1263 *puRva = uRva + offSegment;
1264 return VINF_SUCCESS;
1265 }
1266 return VERR_INVALID_POINTER;
1267}
1268
1269/**
1270 * Converts a segment+offset address into an RVA.
1271 *
1272 * @returns IPRT status code.
1273 * @param pThis The DWARF instance.
1274 * @param uRva The RVA to convert.
1275 * @param pidxSegment Where to return the segment index.
1276 * @param poffSegment Where to return the segment offset.
1277 */
1278static int rtDbgModDwarfRvaToSegOffset(PRTDBGMODDWARF pThis, RTUINTPTR uRva, RTDBGSEGIDX *pidxSegment, uint64_t *poffSegment)
1279{
1280 RTUINTPTR offSeg = 0;
1281 RTDBGSEGIDX idxSeg = RTDbgModRvaToSegOff(pThis->pImgMod, uRva, &offSeg);
1282 if (idxSeg != NIL_RTDBGSEGIDX)
1283 {
1284 *pidxSegment = idxSeg;
1285 *poffSegment = offSeg;
1286 return VINF_SUCCESS;
1287 }
1288 return VERR_INVALID_POINTER;
1289}
1290
1291
1292
1293/*
1294 *
1295 * DWARF Cursor.
1296 * DWARF Cursor.
1297 * DWARF Cursor.
1298 *
1299 */
1300
1301
1302/**
1303 * Reads a 8-bit unsigned integer and advances the cursor.
1304 *
1305 * @returns 8-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1306 * uErrValue is returned.
1307 * @param pCursor The cursor.
1308 * @param uErrValue What to return on read error.
1309 */
1310static uint8_t rtDwarfCursor_GetU8(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
1311{
1312 if (pCursor->cbUnitLeft < 1)
1313 {
1314 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1315 return uErrValue;
1316 }
1317
1318 uint8_t u8 = pCursor->pb[0];
1319 pCursor->pb += 1;
1320 pCursor->cbUnitLeft -= 1;
1321 pCursor->cbLeft -= 1;
1322 return u8;
1323}
1324
1325
1326/**
1327 * Reads a 16-bit unsigned integer and advances the cursor.
1328 *
1329 * @returns 16-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1330 * uErrValue is returned.
1331 * @param pCursor The cursor.
1332 * @param uErrValue What to return on read error.
1333 */
1334static uint16_t rtDwarfCursor_GetU16(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
1335{
1336 if (pCursor->cbUnitLeft < 2)
1337 {
1338 pCursor->pb += pCursor->cbUnitLeft;
1339 pCursor->cbLeft -= pCursor->cbUnitLeft;
1340 pCursor->cbUnitLeft = 0;
1341 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1342 return uErrValue;
1343 }
1344
1345 uint16_t u16 = RT_MAKE_U16(pCursor->pb[0], pCursor->pb[1]);
1346 pCursor->pb += 2;
1347 pCursor->cbUnitLeft -= 2;
1348 pCursor->cbLeft -= 2;
1349 if (!pCursor->fNativEndian)
1350 u16 = RT_BSWAP_U16(u16);
1351 return u16;
1352}
1353
1354
1355/**
1356 * Reads a 32-bit unsigned integer and advances the cursor.
1357 *
1358 * @returns 32-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1359 * uErrValue is returned.
1360 * @param pCursor The cursor.
1361 * @param uErrValue What to return on read error.
1362 */
1363static uint32_t rtDwarfCursor_GetU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
1364{
1365 if (pCursor->cbUnitLeft < 4)
1366 {
1367 pCursor->pb += pCursor->cbUnitLeft;
1368 pCursor->cbLeft -= pCursor->cbUnitLeft;
1369 pCursor->cbUnitLeft = 0;
1370 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1371 return uErrValue;
1372 }
1373
1374 uint32_t u32 = RT_MAKE_U32_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3]);
1375 pCursor->pb += 4;
1376 pCursor->cbUnitLeft -= 4;
1377 pCursor->cbLeft -= 4;
1378 if (!pCursor->fNativEndian)
1379 u32 = RT_BSWAP_U32(u32);
1380 return u32;
1381}
1382
1383
1384/**
1385 * Reads a 64-bit unsigned integer and advances the cursor.
1386 *
1387 * @returns 64-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1388 * uErrValue is returned.
1389 * @param pCursor The cursor.
1390 * @param uErrValue What to return on read error.
1391 */
1392static uint64_t rtDwarfCursor_GetU64(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1393{
1394 if (pCursor->cbUnitLeft < 8)
1395 {
1396 pCursor->pb += pCursor->cbUnitLeft;
1397 pCursor->cbLeft -= pCursor->cbUnitLeft;
1398 pCursor->cbUnitLeft = 0;
1399 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1400 return uErrValue;
1401 }
1402
1403 uint64_t u64 = RT_MAKE_U64_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3],
1404 pCursor->pb[4], pCursor->pb[5], pCursor->pb[6], pCursor->pb[7]);
1405 pCursor->pb += 8;
1406 pCursor->cbUnitLeft -= 8;
1407 pCursor->cbLeft -= 8;
1408 if (!pCursor->fNativEndian)
1409 u64 = RT_BSWAP_U64(u64);
1410 return u64;
1411}
1412
1413
1414/**
1415 * Reads an unsigned LEB128 encoded number.
1416 *
1417 * @returns unsigned 64-bit number. On error RTDWARFCURSOR::rc is set and @a
1418 * uErrValue is returned.
1419 * @param pCursor The cursor.
1420 * @param uErrValue The value to return on error.
1421 */
1422static uint64_t rtDwarfCursor_GetULeb128(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1423{
1424 if (pCursor->cbUnitLeft < 1)
1425 {
1426 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1427 return uErrValue;
1428 }
1429
1430 /*
1431 * Special case - single byte.
1432 */
1433 uint8_t b = pCursor->pb[0];
1434 if (!(b & 0x80))
1435 {
1436 pCursor->pb += 1;
1437 pCursor->cbUnitLeft -= 1;
1438 pCursor->cbLeft -= 1;
1439 return b;
1440 }
1441
1442 /*
1443 * Generic case.
1444 */
1445 /* Decode. */
1446 uint32_t off = 1;
1447 uint64_t u64Ret = b & 0x7f;
1448 do
1449 {
1450 if (off == pCursor->cbUnitLeft)
1451 {
1452 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1453 u64Ret = uErrValue;
1454 break;
1455 }
1456 b = pCursor->pb[off];
1457 u64Ret |= (b & 0x7f) << off * 7;
1458 off++;
1459 } while (b & 0x80);
1460
1461 /* Update the cursor. */
1462 pCursor->pb += off;
1463 pCursor->cbUnitLeft -= off;
1464 pCursor->cbLeft -= off;
1465
1466 /* Check the range. */
1467 uint32_t cBits = off * 7;
1468 if (cBits > 64)
1469 {
1470 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1471 u64Ret = uErrValue;
1472 }
1473
1474 return u64Ret;
1475}
1476
1477
1478/**
1479 * Reads a signed LEB128 encoded number.
1480 *
1481 * @returns signed 64-bit number. On error RTDWARFCURSOR::rc is set and @a
1482 * uErrValue is returned.
1483 * @param pCursor The cursor.
1484 * @param sErrValue The value to return on error.
1485 */
1486static int64_t rtDwarfCursor_GetSLeb128(PRTDWARFCURSOR pCursor, int64_t sErrValue)
1487{
1488 if (pCursor->cbUnitLeft < 1)
1489 {
1490 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1491 return sErrValue;
1492 }
1493
1494 /*
1495 * Special case - single byte.
1496 */
1497 uint8_t b = pCursor->pb[0];
1498 if (!(b & 0x80))
1499 {
1500 pCursor->pb += 1;
1501 pCursor->cbUnitLeft -= 1;
1502 pCursor->cbLeft -= 1;
1503 if (b & 0x40)
1504 b |= 0x80;
1505 return (int8_t)b;
1506 }
1507
1508 /*
1509 * Generic case.
1510 */
1511 /* Decode it. */
1512 uint32_t off = 1;
1513 uint64_t u64Ret = b & 0x7f;
1514 do
1515 {
1516 if (off == pCursor->cbUnitLeft)
1517 {
1518 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1519 u64Ret = (uint64_t)sErrValue;
1520 break;
1521 }
1522 b = pCursor->pb[off];
1523 u64Ret |= (b & 0x7f) << off * 7;
1524 off++;
1525 } while (b & 0x80);
1526
1527 /* Update cursor. */
1528 pCursor->pb += off;
1529 pCursor->cbUnitLeft -= off;
1530 pCursor->cbLeft -= off;
1531
1532 /* Check the range. */
1533 uint32_t cBits = off * 7;
1534 if (cBits > 64)
1535 {
1536 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1537 u64Ret = (uint64_t)sErrValue;
1538 }
1539 /* Sign extend the value. */
1540 else if (u64Ret & RT_BIT_64(cBits - 1))
1541 u64Ret |= ~(RT_BIT_64(cBits - 1) - 1);
1542
1543 return (int64_t)u64Ret;
1544}
1545
1546
1547/**
1548 * Reads an unsigned LEB128 encoded number, max 32-bit width.
1549 *
1550 * @returns unsigned 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1551 * uErrValue is returned.
1552 * @param pCursor The cursor.
1553 * @param uErrValue The value to return on error.
1554 */
1555static uint32_t rtDwarfCursor_GetULeb128AsU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
1556{
1557 uint64_t u64 = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
1558 if (u64 > UINT32_MAX)
1559 {
1560 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1561 return uErrValue;
1562 }
1563 return (uint32_t)u64;
1564}
1565
1566
1567/**
1568 * Reads a signed LEB128 encoded number, max 32-bit width.
1569 *
1570 * @returns signed 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1571 * uErrValue is returned.
1572 * @param pCursor The cursor.
1573 * @param sErrValue The value to return on error.
1574 */
1575static int32_t rtDwarfCursor_GetSLeb128AsS32(PRTDWARFCURSOR pCursor, int32_t sErrValue)
1576{
1577 int64_t s64 = rtDwarfCursor_GetSLeb128(pCursor, sErrValue);
1578 if (s64 > INT32_MAX || s64 < INT32_MIN)
1579 {
1580 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1581 return sErrValue;
1582 }
1583 return (int32_t)s64;
1584}
1585
1586
1587/**
1588 * Skips a LEB128 encoded number.
1589 *
1590 * @returns IPRT status code.
1591 * @param pCursor The cursor.
1592 */
1593static int rtDwarfCursor_SkipLeb128(PRTDWARFCURSOR pCursor)
1594{
1595 if (RT_FAILURE(pCursor->rc))
1596 return pCursor->rc;
1597
1598 if (pCursor->cbUnitLeft < 1)
1599 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1600
1601 uint32_t offSkip = 1;
1602 if (pCursor->pb[0] & 0x80)
1603 do
1604 {
1605 if (offSkip == pCursor->cbUnitLeft)
1606 {
1607 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1608 break;
1609 }
1610 } while (pCursor->pb[offSkip++] & 0x80);
1611
1612 pCursor->pb += offSkip;
1613 pCursor->cbUnitLeft -= offSkip;
1614 pCursor->cbLeft -= offSkip;
1615 return pCursor->rc;
1616}
1617
1618
1619/**
1620 * Advances the cursor a given number of bytes.
1621 *
1622 * @returns IPRT status code.
1623 * @param pCursor The cursor.
1624 * @param offSkip The number of bytes to advance.
1625 */
1626static int rtDwarfCursor_SkipBytes(PRTDWARFCURSOR pCursor, uint64_t offSkip)
1627{
1628 if (RT_FAILURE(pCursor->rc))
1629 return pCursor->rc;
1630 if (pCursor->cbUnitLeft < offSkip)
1631 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1632
1633 size_t const offSkipSizeT = (size_t)offSkip;
1634 pCursor->cbUnitLeft -= offSkipSizeT;
1635 pCursor->cbLeft -= offSkipSizeT;
1636 pCursor->pb += offSkipSizeT;
1637
1638 return VINF_SUCCESS;
1639}
1640
1641
1642/**
1643 * Reads a zero terminated string, advancing the cursor beyond the terminator.
1644 *
1645 * @returns Pointer to the string.
1646 * @param pCursor The cursor.
1647 * @param pszErrValue What to return if the string isn't terminated
1648 * before the end of the unit.
1649 */
1650static const char *rtDwarfCursor_GetSZ(PRTDWARFCURSOR pCursor, const char *pszErrValue)
1651{
1652 const char *pszRet = (const char *)pCursor->pb;
1653 for (;;)
1654 {
1655 if (!pCursor->cbUnitLeft)
1656 {
1657 pCursor->rc = VERR_DWARF_BAD_STRING;
1658 return pszErrValue;
1659 }
1660 pCursor->cbUnitLeft--;
1661 pCursor->cbLeft--;
1662 if (!*pCursor->pb++)
1663 break;
1664 }
1665 return pszRet;
1666}
1667
1668
1669/**
1670 * Reads a 1, 2, 4 or 8 byte unsigned value.
1671 *
1672 * @returns 64-bit unsigned value.
1673 * @param pCursor The cursor.
1674 * @param cbValue The value size.
1675 * @param uErrValue The error value.
1676 */
1677static uint64_t rtDwarfCursor_GetVarSizedU(PRTDWARFCURSOR pCursor, size_t cbValue, uint64_t uErrValue)
1678{
1679 uint64_t u64Ret;
1680 switch (cbValue)
1681 {
1682 case 1: u64Ret = rtDwarfCursor_GetU8( pCursor, UINT8_MAX); break;
1683 case 2: u64Ret = rtDwarfCursor_GetU16(pCursor, UINT16_MAX); break;
1684 case 4: u64Ret = rtDwarfCursor_GetU32(pCursor, UINT32_MAX); break;
1685 case 8: u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX); break;
1686 default:
1687 pCursor->rc = VERR_DWARF_BAD_INFO;
1688 return uErrValue;
1689 }
1690 if (RT_FAILURE(pCursor->rc))
1691 return uErrValue;
1692 return u64Ret;
1693}
1694
1695
1696#if 0 /* unused */
1697/**
1698 * Gets the pointer to a variable size block and advances the cursor.
1699 *
1700 * @returns Pointer to the block at the current cursor location. On error
1701 * RTDWARFCURSOR::rc is set and NULL returned.
1702 * @param pCursor The cursor.
1703 * @param cbBlock The block size.
1704 */
1705static const uint8_t *rtDwarfCursor_GetBlock(PRTDWARFCURSOR pCursor, uint32_t cbBlock)
1706{
1707 if (cbBlock > pCursor->cbUnitLeft)
1708 {
1709 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1710 return NULL;
1711 }
1712
1713 uint8_t const *pb = &pCursor->pb[0];
1714 pCursor->pb += cbBlock;
1715 pCursor->cbUnitLeft -= cbBlock;
1716 pCursor->cbLeft -= cbBlock;
1717 return pb;
1718}
1719#endif
1720
1721
1722/**
1723 * Reads an unsigned DWARF half number.
1724 *
1725 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1726 * uErrValue is returned.
1727 * @param pCursor The cursor.
1728 * @param uErrValue What to return on error.
1729 */
1730static uint16_t rtDwarfCursor_GetUHalf(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
1731{
1732 return rtDwarfCursor_GetU16(pCursor, uErrValue);
1733}
1734
1735
1736/**
1737 * Reads an unsigned DWARF byte number.
1738 *
1739 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1740 * uErrValue is returned.
1741 * @param pCursor The cursor.
1742 * @param uErrValue What to return on error.
1743 */
1744static uint8_t rtDwarfCursor_GetUByte(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
1745{
1746 return rtDwarfCursor_GetU8(pCursor, uErrValue);
1747}
1748
1749
1750/**
1751 * Reads a signed DWARF byte number.
1752 *
1753 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1754 * uErrValue is returned.
1755 * @param pCursor The cursor.
1756 * @param iErrValue What to return on error.
1757 */
1758static int8_t rtDwarfCursor_GetSByte(PRTDWARFCURSOR pCursor, int8_t iErrValue)
1759{
1760 return (int8_t)rtDwarfCursor_GetU8(pCursor, (uint8_t)iErrValue);
1761}
1762
1763
1764/**
1765 * Reads a unsigned DWARF offset value.
1766 *
1767 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1768 * uErrValue is returned.
1769 * @param pCursor The cursor.
1770 * @param uErrValue What to return on error.
1771 */
1772static uint64_t rtDwarfCursor_GetUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1773{
1774 if (pCursor->f64bitDwarf)
1775 return rtDwarfCursor_GetU64(pCursor, uErrValue);
1776 return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
1777}
1778
1779
1780/**
1781 * Reads a unsigned DWARF native offset value.
1782 *
1783 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1784 * uErrValue is returned.
1785 * @param pCursor The cursor.
1786 * @param uErrValue What to return on error.
1787 */
1788static uint64_t rtDwarfCursor_GetNativeUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1789{
1790 switch (pCursor->cbNativeAddr)
1791 {
1792 case 1: return rtDwarfCursor_GetU8(pCursor, (uint8_t )uErrValue);
1793 case 2: return rtDwarfCursor_GetU16(pCursor, (uint16_t)uErrValue);
1794 case 4: return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
1795 case 8: return rtDwarfCursor_GetU64(pCursor, uErrValue);
1796 default:
1797 pCursor->rc = VERR_INTERNAL_ERROR_2;
1798 return uErrValue;
1799 }
1800}
1801
1802
1803/**
1804 * Reads a 1, 2, 4 or 8 byte unsigned value.
1805 *
1806 * @returns 64-bit unsigned value.
1807 * @param pCursor The cursor.
1808 * @param bPtrEnc The pointer encoding.
1809 * @param uErrValue The error value.
1810 */
1811static uint64_t rtDwarfCursor_GetPtrEnc(PRTDWARFCURSOR pCursor, uint8_t bPtrEnc, uint64_t uErrValue)
1812{
1813 uint64_t u64Ret;
1814 switch (bPtrEnc & DW_EH_PE_FORMAT_MASK)
1815 {
1816 case DW_EH_PE_ptr:
1817 u64Ret = rtDwarfCursor_GetNativeUOff(pCursor, uErrValue);
1818 break;
1819 case DW_EH_PE_uleb128:
1820 u64Ret = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
1821 break;
1822 case DW_EH_PE_udata2:
1823 u64Ret = rtDwarfCursor_GetU16(pCursor, UINT16_MAX);
1824 break;
1825 case DW_EH_PE_udata4:
1826 u64Ret = rtDwarfCursor_GetU32(pCursor, UINT32_MAX);
1827 break;
1828 case DW_EH_PE_udata8:
1829 u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX);
1830 break;
1831 case DW_EH_PE_sleb128:
1832 u64Ret = rtDwarfCursor_GetSLeb128(pCursor, uErrValue);
1833 break;
1834 case DW_EH_PE_sdata2:
1835 u64Ret = (int64_t)(int16_t)rtDwarfCursor_GetU16(pCursor, UINT16_MAX);
1836 break;
1837 case DW_EH_PE_sdata4:
1838 u64Ret = (int64_t)(int32_t)rtDwarfCursor_GetU32(pCursor, UINT32_MAX);
1839 break;
1840 case DW_EH_PE_sdata8:
1841 u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX);
1842 break;
1843 default:
1844 pCursor->rc = VERR_DWARF_BAD_INFO;
1845 return uErrValue;
1846 }
1847 if (RT_FAILURE(pCursor->rc))
1848 return uErrValue;
1849 return u64Ret;
1850}
1851
1852
1853/**
1854 * Gets the unit length, updating the unit length member and DWARF bitness
1855 * members of the cursor.
1856 *
1857 * @returns The unit length.
1858 * @param pCursor The cursor.
1859 */
1860static uint64_t rtDwarfCursor_GetInitialLength(PRTDWARFCURSOR pCursor)
1861{
1862 /*
1863 * Read the initial length.
1864 */
1865 pCursor->cbUnitLeft = pCursor->cbLeft;
1866 uint64_t cbUnit = rtDwarfCursor_GetU32(pCursor, 0);
1867 if (cbUnit != UINT32_C(0xffffffff))
1868 pCursor->f64bitDwarf = false;
1869 else
1870 {
1871 pCursor->f64bitDwarf = true;
1872 cbUnit = rtDwarfCursor_GetU64(pCursor, 0);
1873 }
1874
1875
1876 /*
1877 * Set the unit length, quitely fixing bad lengths.
1878 */
1879 pCursor->cbUnitLeft = (size_t)cbUnit;
1880 if ( pCursor->cbUnitLeft > pCursor->cbLeft
1881 || pCursor->cbUnitLeft != cbUnit)
1882 pCursor->cbUnitLeft = pCursor->cbLeft;
1883
1884 return cbUnit;
1885}
1886
1887
1888/**
1889 * Calculates the section offset corresponding to the current cursor position.
1890 *
1891 * @returns 32-bit section offset. If out of range, RTDWARFCURSOR::rc will be
1892 * set and UINT32_MAX returned.
1893 * @param pCursor The cursor.
1894 */
1895static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor)
1896{
1897 size_t off = pCursor->pb - pCursor->pbStart;
1898 uint32_t offRet = (uint32_t)off;
1899 if (offRet != off)
1900 {
1901 AssertFailed();
1902 pCursor->rc = VERR_OUT_OF_RANGE;
1903 offRet = UINT32_MAX;
1904 }
1905 return offRet;
1906}
1907
1908
1909/**
1910 * Calculates an absolute cursor position from one relative to the current
1911 * cursor position.
1912 *
1913 * @returns The absolute cursor position.
1914 * @param pCursor The cursor.
1915 * @param offRelative The relative position. Must be a positive
1916 * offset.
1917 */
1918static uint8_t const *rtDwarfCursor_CalcPos(PRTDWARFCURSOR pCursor, size_t offRelative)
1919{
1920 if (offRelative > pCursor->cbUnitLeft)
1921 {
1922 Log(("rtDwarfCursor_CalcPos: bad position %#zx, cbUnitLeft=%#zu\n", offRelative, pCursor->cbUnitLeft));
1923 pCursor->rc = VERR_DWARF_BAD_POS;
1924 return NULL;
1925 }
1926 return pCursor->pb + offRelative;
1927}
1928
1929
1930/**
1931 * Advances the cursor to the given position.
1932 *
1933 * @returns IPRT status code.
1934 * @param pCursor The cursor.
1935 * @param pbNewPos The new position - returned by
1936 * rtDwarfCursor_CalcPos().
1937 */
1938static int rtDwarfCursor_AdvanceToPos(PRTDWARFCURSOR pCursor, uint8_t const *pbNewPos)
1939{
1940 if (RT_FAILURE(pCursor->rc))
1941 return pCursor->rc;
1942 AssertPtr(pbNewPos);
1943 if ((uintptr_t)pbNewPos < (uintptr_t)pCursor->pb)
1944 {
1945 Log(("rtDwarfCursor_AdvanceToPos: bad position %p, current %p\n", pbNewPos, pCursor->pb));
1946 return pCursor->rc = VERR_DWARF_BAD_POS;
1947 }
1948
1949 uintptr_t cbAdj = (uintptr_t)pbNewPos - (uintptr_t)pCursor->pb;
1950 if (RT_UNLIKELY(cbAdj > pCursor->cbUnitLeft))
1951 {
1952 AssertFailed();
1953 pCursor->rc = VERR_DWARF_BAD_POS;
1954 cbAdj = pCursor->cbUnitLeft;
1955 }
1956
1957 pCursor->cbUnitLeft -= cbAdj;
1958 pCursor->cbLeft -= cbAdj;
1959 pCursor->pb += cbAdj;
1960 return pCursor->rc;
1961}
1962
1963
1964/**
1965 * Check if the cursor is at the end of the current DWARF unit.
1966 *
1967 * @retval true if at the end or a cursor error is pending.
1968 * @retval false if not.
1969 * @param pCursor The cursor.
1970 */
1971static bool rtDwarfCursor_IsAtEndOfUnit(PRTDWARFCURSOR pCursor)
1972{
1973 return !pCursor->cbUnitLeft || RT_FAILURE(pCursor->rc);
1974}
1975
1976
1977/**
1978 * Skips to the end of the current unit.
1979 *
1980 * @returns IPRT status code.
1981 * @param pCursor The cursor.
1982 */
1983static int rtDwarfCursor_SkipUnit(PRTDWARFCURSOR pCursor)
1984{
1985 pCursor->pb += pCursor->cbUnitLeft;
1986 pCursor->cbLeft -= pCursor->cbUnitLeft;
1987 pCursor->cbUnitLeft = 0;
1988 return pCursor->rc;
1989}
1990
1991
1992/**
1993 * Check if the cursor is at the end of the section (or whatever the cursor is
1994 * processing).
1995 *
1996 * @retval true if at the end or a cursor error is pending.
1997 * @retval false if not.
1998 * @param pCursor The cursor.
1999 */
2000static bool rtDwarfCursor_IsAtEnd(PRTDWARFCURSOR pCursor)
2001{
2002 return !pCursor->cbLeft || RT_FAILURE(pCursor->rc);
2003}
2004
2005
2006/**
2007 * Initialize a section reader cursor.
2008 *
2009 * @returns IPRT status code.
2010 * @param pCursor The cursor.
2011 * @param pThis The dwarf module.
2012 * @param enmSect The name of the section to read.
2013 */
2014static int rtDwarfCursor_Init(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
2015{
2016 int rc = rtDbgModDwarfLoadSection(pThis, enmSect);
2017 if (RT_FAILURE(rc))
2018 return rc;
2019
2020 pCursor->enmSect = enmSect;
2021 pCursor->pbStart = (uint8_t const *)pThis->aSections[enmSect].pv;
2022 pCursor->pb = pCursor->pbStart;
2023 pCursor->cbLeft = pThis->aSections[enmSect].cb;
2024 pCursor->cbUnitLeft = pCursor->cbLeft;
2025 pCursor->pDwarfMod = pThis;
2026 pCursor->f64bitDwarf = false;
2027 /** @todo ask the image about the endian used as well as the address
2028 * width. */
2029 pCursor->fNativEndian = true;
2030 pCursor->cbNativeAddr = 4;
2031 pCursor->rc = VINF_SUCCESS;
2032
2033 return VINF_SUCCESS;
2034}
2035
2036
2037/**
2038 * Initialize a section reader cursor with a skip offset.
2039 *
2040 * @returns IPRT status code.
2041 * @param pCursor The cursor.
2042 * @param pThis The dwarf module.
2043 * @param enmSect The name of the section to read.
2044 * @param offSect The offset to skip into the section.
2045 */
2046static int rtDwarfCursor_InitWithOffset(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis,
2047 krtDbgModDwarfSect enmSect, uint32_t offSect)
2048{
2049 if (offSect > pThis->aSections[enmSect].cb)
2050 {
2051 Log(("rtDwarfCursor_InitWithOffset: offSect=%#x cb=%#x enmSect=%d\n", offSect, pThis->aSections[enmSect].cb, enmSect));
2052 return VERR_DWARF_BAD_POS;
2053 }
2054
2055 int rc = rtDwarfCursor_Init(pCursor, pThis, enmSect);
2056 if (RT_SUCCESS(rc))
2057 {
2058 /* pCursor->pbStart += offSect; - we're skipping, offsets are relative to start of section... */
2059 pCursor->pb += offSect;
2060 pCursor->cbLeft -= offSect;
2061 pCursor->cbUnitLeft -= offSect;
2062 }
2063
2064 return rc;
2065}
2066
2067
2068/**
2069 * Initialize a cursor for a block (subsection) retrieved from the given cursor.
2070 *
2071 * The parent cursor will be advanced past the block.
2072 *
2073 * @returns IPRT status code.
2074 * @param pCursor The cursor.
2075 * @param pParent The parent cursor. Will be moved by @a cbBlock.
2076 * @param cbBlock The size of the block the new cursor should
2077 * cover.
2078 */
2079static int rtDwarfCursor_InitForBlock(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pParent, uint32_t cbBlock)
2080{
2081 if (RT_FAILURE(pParent->rc))
2082 return pParent->rc;
2083 if (pParent->cbUnitLeft < cbBlock)
2084 {
2085 Log(("rtDwarfCursor_InitForBlock: cbUnitLeft=%#x < cbBlock=%#x \n", pParent->cbUnitLeft, cbBlock));
2086 return VERR_DWARF_BAD_POS;
2087 }
2088
2089 *pCursor = *pParent;
2090 pCursor->cbLeft = cbBlock;
2091 pCursor->cbUnitLeft = cbBlock;
2092
2093 pParent->pb += cbBlock;
2094 pParent->cbLeft -= cbBlock;
2095 pParent->cbUnitLeft -= cbBlock;
2096
2097 return VINF_SUCCESS;
2098}
2099
2100
2101/**
2102 * Initialize a reader cursor for a memory block (eh_frame).
2103 *
2104 * @returns IPRT status code.
2105 * @param pCursor The cursor.
2106 * @param pvMem The memory block.
2107 * @param cbMem The size of the memory block.
2108 */
2109static int rtDwarfCursor_InitForMem(PRTDWARFCURSOR pCursor, void const *pvMem, size_t cbMem)
2110{
2111 pCursor->enmSect = krtDbgModDwarfSect_End;
2112 pCursor->pbStart = (uint8_t const *)pvMem;
2113 pCursor->pb = (uint8_t const *)pvMem;
2114 pCursor->cbLeft = cbMem;
2115 pCursor->cbUnitLeft = cbMem;
2116 pCursor->pDwarfMod = NULL;
2117 pCursor->f64bitDwarf = false;
2118 /** @todo ask the image about the endian used as well as the address
2119 * width. */
2120 pCursor->fNativEndian = true;
2121 pCursor->cbNativeAddr = 4;
2122 pCursor->rc = VINF_SUCCESS;
2123
2124 return VINF_SUCCESS;
2125}
2126
2127
2128/**
2129 * Deletes a section reader initialized by rtDwarfCursor_Init.
2130 *
2131 * @returns @a rcOther or RTDWARCURSOR::rc.
2132 * @param pCursor The section reader.
2133 * @param rcOther Other error code to be returned if it indicates
2134 * error or if the cursor status is OK.
2135 */
2136static int rtDwarfCursor_Delete(PRTDWARFCURSOR pCursor, int rcOther)
2137{
2138 /* ... and a drop of poison. */
2139 pCursor->pb = NULL;
2140 pCursor->cbLeft = ~(size_t)0;
2141 pCursor->cbUnitLeft = ~(size_t)0;
2142 pCursor->pDwarfMod = NULL;
2143 if (RT_FAILURE(pCursor->rc) && RT_SUCCESS(rcOther))
2144 rcOther = pCursor->rc;
2145 pCursor->rc = VERR_INTERNAL_ERROR_4;
2146 return rcOther;
2147}
2148
2149
2150/*
2151 *
2152 * DWARF Frame Unwind Information.
2153 * DWARF Frame Unwind Information.
2154 * DWARF Frame Unwind Information.
2155 *
2156 */
2157
2158/**
2159 * Common information entry (CIE) information.
2160 */
2161typedef struct RTDWARFCIEINFO
2162{
2163 /** The segment location of the CIE. */
2164 uint64_t offCie;
2165 /** The DWARF version. */
2166 uint8_t uDwarfVer;
2167 /** The address pointer encoding. */
2168 uint8_t bAddressPtrEnc;
2169 /** The segment size (v4). */
2170 uint8_t cbSegment;
2171 /** The return register column. UINT8_MAX if default register. */
2172 uint8_t bRetReg;
2173 /** The LSDA pointer encoding. */
2174 uint8_t bLsdaPtrEnc;
2175
2176 /** Set if the EH data field is present ('eh'). */
2177 bool fHasEhData : 1;
2178 /** Set if there is an augmentation data size ('z'). */
2179 bool fHasAugmentationSize : 1;
2180 /** Set if the augmentation data contains a LSDA (pointer size byte in CIE,
2181 * pointer in FDA) ('L'). */
2182 bool fHasLanguageSpecificDataArea : 1;
2183 /** Set if the augmentation data contains a personality routine
2184 * (pointer size + pointer) ('P'). */
2185 bool fHasPersonalityRoutine : 1;
2186 /** Set if the augmentation data contains the address encoding . */
2187 bool fHasAddressEnc : 1;
2188 /** Set if signal frame. */
2189 bool fIsSignalFrame : 1;
2190 /** Set if we've encountered unknown augmentation data. This
2191 * means the CIE is incomplete and cannot be used. */
2192 bool fHasUnknowAugmentation : 1;
2193
2194 /** Copy of the augmentation string. */
2195 const char *pszAugmentation;
2196
2197 /** Code alignment factor for the instruction. */
2198 uint64_t uCodeAlignFactor;
2199 /** Data alignment factor for the instructions. */
2200 int64_t iDataAlignFactor;
2201
2202 /** Pointer to the instruction sequence. */
2203 uint8_t const *pbInstructions;
2204 /** The length of the instruction sequence. */
2205 size_t cbInstructions;
2206} RTDWARFCIEINFO;
2207/** Pointer to CIE info. */
2208typedef RTDWARFCIEINFO *PRTDWARFCIEINFO;
2209/** Pointer to const CIE info. */
2210typedef RTDWARFCIEINFO const *PCRTDWARFCIEINFO;
2211
2212
2213/** Number of registers we care about.
2214 * @note We're currently not expecting to be decoding ppc, arm, ia64 or such,
2215 * only x86 and x86_64. We can easily increase the column count. */
2216#define RTDWARFCF_MAX_REGISTERS 96
2217
2218
2219/**
2220 * Call frame state row.
2221 */
2222typedef struct RTDWARFCFROW
2223{
2224 /** Stack worked by DW_CFA_remember_state and DW_CFA_restore_state. */
2225 struct RTDWARFCFROW *pNextOnStack;
2226
2227 /** @name CFA - Canonical frame address expression.
2228 * Since there are partial CFA instructions, we cannot be lazy like with the
2229 * register but keep register+offset around. For DW_CFA_def_cfa_expression
2230 * we just take down the program location, though.
2231 * @{ */
2232 /** Pointer to DW_CFA_def_cfa_expression instruction, NULL if reg+offset. */
2233 uint8_t const *pbCfaExprInstr;
2234 /** The CFA register offset. */
2235 int64_t offCfaReg;
2236 /** The CFA base register number. */
2237 uint16_t uCfaBaseReg;
2238 /** Set if we've got a valid CFA definition. */
2239 bool fCfaDefined : 1;
2240 /** @} */
2241
2242 /** Set if on the heap and needs freeing. */
2243 bool fOnHeap : 1;
2244 /** Pointer to the instructions bytes defining registers.
2245 * NULL means */
2246 uint8_t const *apbRegInstrs[RTDWARFCF_MAX_REGISTERS];
2247} RTDWARFCFROW;
2248typedef RTDWARFCFROW *PRTDWARFCFROW;
2249typedef RTDWARFCFROW const *PCRTDWARFCFROW;
2250
2251/** Row program execution state. */
2252typedef struct RTDWARFCFEXEC
2253{
2254 PRTDWARFCFROW pRow;
2255 /** Number of PC bytes left to advance before we get a hit. */
2256 uint64_t cbLeftToAdvance;
2257 /** Number of pushed rows. */
2258 uint32_t cPushes;
2259 /** Set if little endian, clear if big endian. */
2260 bool fLittleEndian;
2261 /** The CIE. */
2262 PCRTDWARFCIEINFO pCie;
2263 /** The program counter value for the FDE. Subjected to segment.
2264 * Needed for DW_CFA_set_loc. */
2265 uint64_t uPcBegin;
2266 /** The offset relative to uPcBegin for which we're searching for a row.
2267 * Needed for DW_CFA_set_loc. */
2268 uint64_t offInRange;
2269} RTDWARFCFEXEC;
2270typedef RTDWARFCFEXEC *PRTDWARFCFEXEC;
2271
2272
2273/* Set of macros for getting and skipping operands. */
2274#define SKIP_ULEB128_OR_LEB128() \
2275 do \
2276 { \
2277 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2278 } while (pbInstr[offInstr++] & 0x80)
2279
2280#define GET_ULEB128_AS_U14(a_uDst) \
2281 do \
2282 { \
2283 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2284 uint8_t b = pbInstr[offInstr++]; \
2285 (a_uDst) = b & 0x7f; \
2286 if (b & 0x80) \
2287 { \
2288 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2289 b = pbInstr[offInstr++]; \
2290 AssertReturn(!(b & 0x80), VERR_DBG_MALFORMED_UNWIND_INFO); \
2291 (a_uDst) |= (uint16_t)b << 7; \
2292 } \
2293 } while (0)
2294#define GET_ULEB128_AS_U63(a_uDst) \
2295 do \
2296 { \
2297 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2298 uint8_t b = pbInstr[offInstr++]; \
2299 (a_uDst) = b & 0x7f; \
2300 if (b & 0x80) \
2301 { \
2302 unsigned cShift = 7; \
2303 do \
2304 { \
2305 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2306 AssertReturn(cShift < 63, VERR_DWARF_LEB_OVERFLOW); \
2307 b = pbInstr[offInstr++]; \
2308 (a_uDst) |= (uint16_t)(b & 0x7f) << cShift; \
2309 cShift += 7; \
2310 } while (b & 0x80); \
2311 } \
2312 } while (0)
2313#define GET_LEB128_AS_I63(a_uDst) \
2314 do \
2315 { \
2316 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2317 uint8_t b = pbInstr[offInstr++]; \
2318 if (!(b & 0x80)) \
2319 (a_uDst) = !(b & 0x40) ? b : (int64_t)(int8_t)(b | 0x80); \
2320 else \
2321 { \
2322 /* Read value into unsigned variable: */ \
2323 unsigned cShift = 7; \
2324 uint64_t uTmp = b & 0x7f; \
2325 do \
2326 { \
2327 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2328 AssertReturn(cShift < 63, VERR_DWARF_LEB_OVERFLOW); \
2329 b = pbInstr[offInstr++]; \
2330 uTmp |= (uint16_t)(b & 0x7f) << cShift; \
2331 cShift += 7; \
2332 } while (b & 0x80); \
2333 /* Sign extend before setting the destination value: */ \
2334 cShift -= 7 + 1; \
2335 if (uTmp & RT_BIT_64(cShift)) \
2336 uTmp |= ~(RT_BIT_64(cShift) - 1); \
2337 (a_uDst) = (int64_t)uTmp; \
2338 } \
2339 } while (0)
2340
2341#define SKIP_BLOCK() \
2342 do \
2343 { \
2344 uint16_t cbBlock; \
2345 GET_ULEB128_AS_U14(cbBlock); \
2346 AssertReturn(offInstr + cbBlock <= cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO); \
2347 offInstr += cbBlock; \
2348 } while (0)
2349
2350
2351static int rtDwarfUnwind_Execute(PRTDWARFCFEXEC pExecState, uint8_t const *pbInstr, uint32_t cbInstr)
2352{
2353 PRTDWARFCFROW pRow = pExecState->pRow;
2354 for (uint32_t offInstr = 0; offInstr < cbInstr;)
2355 {
2356 /*
2357 * Instruction switches.
2358 */
2359 uint8_t const bInstr = pbInstr[offInstr++];
2360 switch (bInstr & DW_CFA_high_bit_mask)
2361 {
2362 case DW_CFA_advance_loc:
2363 {
2364 uint8_t const cbAdvance = bInstr & ~DW_CFA_high_bit_mask;
2365 if (cbAdvance > pExecState->cbLeftToAdvance)
2366 return VINF_SUCCESS;
2367 pExecState->cbLeftToAdvance -= cbAdvance;
2368 break;
2369 }
2370
2371 case DW_CFA_offset:
2372 {
2373 uint8_t iReg = bInstr & ~DW_CFA_high_bit_mask;
2374 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2375 pRow->apbRegInstrs[iReg] = &pbInstr[offInstr - 1];
2376 SKIP_ULEB128_OR_LEB128();
2377 break;
2378 }
2379
2380 case 0:
2381 switch (bInstr)
2382 {
2383 case DW_CFA_nop:
2384 break;
2385
2386 /*
2387 * Register instructions.
2388 */
2389 case DW_CFA_register:
2390 case DW_CFA_offset_extended:
2391 case DW_CFA_offset_extended_sf:
2392 case DW_CFA_val_offset:
2393 case DW_CFA_val_offset_sf:
2394 {
2395 uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
2396 uint16_t iReg;
2397 GET_ULEB128_AS_U14(iReg);
2398 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2399 pRow->apbRegInstrs[iReg] = pbCurInstr;
2400 SKIP_ULEB128_OR_LEB128();
2401 break;
2402 }
2403
2404 case DW_CFA_expression:
2405 case DW_CFA_val_expression:
2406 {
2407 uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
2408 uint16_t iReg;
2409 GET_ULEB128_AS_U14(iReg);
2410 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2411 pRow->apbRegInstrs[iReg] = pbCurInstr;
2412 SKIP_BLOCK();
2413 break;
2414 }
2415
2416 case DW_CFA_restore_extended:
2417 {
2418 uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
2419 uint16_t iReg;
2420 GET_ULEB128_AS_U14(iReg);
2421 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2422 pRow->apbRegInstrs[iReg] = pbCurInstr;
2423 break;
2424 }
2425
2426 case DW_CFA_undefined:
2427 {
2428 uint16_t iReg;
2429 GET_ULEB128_AS_U14(iReg);
2430 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2431 pRow->apbRegInstrs[iReg] = NULL;
2432 break;
2433 }
2434
2435 case DW_CFA_same_value:
2436 {
2437 uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
2438 uint16_t iReg;
2439 GET_ULEB128_AS_U14(iReg);
2440 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2441 pRow->apbRegInstrs[iReg] = pbCurInstr;
2442 break;
2443 }
2444
2445
2446 /*
2447 * CFA instructions.
2448 */
2449 case DW_CFA_def_cfa:
2450 {
2451 GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
2452 uint64_t offCfaReg;
2453 GET_ULEB128_AS_U63(offCfaReg);
2454 pRow->offCfaReg = offCfaReg;
2455 pRow->pbCfaExprInstr = NULL;
2456 pRow->fCfaDefined = true;
2457 break;
2458 }
2459
2460 case DW_CFA_def_cfa_register:
2461 {
2462 GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
2463 pRow->pbCfaExprInstr = NULL;
2464 pRow->fCfaDefined = true;
2465 /* Leaves offCfaReg as is. */
2466 break;
2467 }
2468
2469 case DW_CFA_def_cfa_offset:
2470 {
2471 uint64_t offCfaReg;
2472 GET_ULEB128_AS_U63(offCfaReg);
2473 pRow->offCfaReg = offCfaReg;
2474 pRow->pbCfaExprInstr = NULL;
2475 pRow->fCfaDefined = true;
2476 /* Leaves uCfaBaseReg as is. */
2477 break;
2478 }
2479
2480 case DW_CFA_def_cfa_sf:
2481 GET_ULEB128_AS_U14(pRow->uCfaBaseReg);
2482 GET_LEB128_AS_I63(pRow->offCfaReg);
2483 pRow->pbCfaExprInstr = NULL;
2484 pRow->fCfaDefined = true;
2485 break;
2486
2487 case DW_CFA_def_cfa_offset_sf:
2488 GET_LEB128_AS_I63(pRow->offCfaReg);
2489 pRow->pbCfaExprInstr = NULL;
2490 pRow->fCfaDefined = true;
2491 /* Leaves uCfaBaseReg as is. */
2492 break;
2493
2494 case DW_CFA_def_cfa_expression:
2495 pRow->pbCfaExprInstr = &pbInstr[offInstr - 1];
2496 pRow->fCfaDefined = true;
2497 SKIP_BLOCK();
2498 break;
2499
2500 /*
2501 * Less likely instructions:
2502 */
2503 case DW_CFA_advance_loc1:
2504 {
2505 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2506 uint8_t const cbAdvance = pbInstr[offInstr++];
2507 if (cbAdvance > pExecState->cbLeftToAdvance)
2508 return VINF_SUCCESS;
2509 pExecState->cbLeftToAdvance -= cbAdvance;
2510 break;
2511 }
2512
2513 case DW_CFA_advance_loc2:
2514 {
2515 AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2516 uint16_t const cbAdvance = pExecState->fLittleEndian
2517 ? RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1])
2518 : RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
2519 if (cbAdvance > pExecState->cbLeftToAdvance)
2520 return VINF_SUCCESS;
2521 pExecState->cbLeftToAdvance -= cbAdvance;
2522 offInstr += 2;
2523 break;
2524 }
2525
2526 case DW_CFA_advance_loc4:
2527 {
2528 AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2529 uint32_t const cbAdvance = pExecState->fLittleEndian
2530 ? RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
2531 pbInstr[offInstr + 2], pbInstr[offInstr + 3])
2532 : RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
2533 pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
2534 if (cbAdvance > pExecState->cbLeftToAdvance)
2535 return VINF_SUCCESS;
2536 pExecState->cbLeftToAdvance -= cbAdvance;
2537 offInstr += 4;
2538 break;
2539 }
2540
2541 /*
2542 * This bugger is really annoying and probably never used.
2543 */
2544 case DW_CFA_set_loc:
2545 {
2546 /* Ignore the segment number. */
2547 if (pExecState->pCie->cbSegment)
2548 {
2549 offInstr += pExecState->pCie->cbSegment;
2550 AssertReturn(offInstr < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2551 }
2552
2553 /* Retrieve the address. sigh. */
2554 uint64_t uAddress;
2555 switch (pExecState->pCie->bAddressPtrEnc & (DW_EH_PE_FORMAT_MASK | DW_EH_PE_indirect))
2556 {
2557 case DW_EH_PE_udata2:
2558 AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2559 if (pExecState->fLittleEndian)
2560 uAddress = RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1]);
2561 else
2562 uAddress = RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
2563 offInstr += 2;
2564 break;
2565 case DW_EH_PE_sdata2:
2566 AssertReturn(offInstr + 1 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2567 if (pExecState->fLittleEndian)
2568 uAddress = (int64_t)(int16_t)RT_MAKE_U16(pbInstr[offInstr], pbInstr[offInstr + 1]);
2569 else
2570 uAddress = (int64_t)(int16_t)RT_MAKE_U16(pbInstr[offInstr + 1], pbInstr[offInstr]);
2571 offInstr += 2;
2572 break;
2573 case DW_EH_PE_udata4:
2574 AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2575 if (pExecState->fLittleEndian)
2576 uAddress = RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
2577 pbInstr[offInstr + 2], pbInstr[offInstr + 3]);
2578 else
2579 uAddress = RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
2580 pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
2581
2582 offInstr += 4;
2583 break;
2584 case DW_EH_PE_sdata4:
2585 AssertReturn(offInstr + 3 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2586 if (pExecState->fLittleEndian)
2587 uAddress = (int64_t)(int32_t)RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
2588 pbInstr[offInstr + 2], pbInstr[offInstr + 3]);
2589 else
2590 uAddress = (int64_t)(int32_t)RT_MAKE_U32_FROM_U8(pbInstr[offInstr + 3], pbInstr[offInstr + 2],
2591 pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
2592 offInstr += 4;
2593 break;
2594 case DW_EH_PE_udata8:
2595 case DW_EH_PE_sdata8:
2596 AssertReturn(offInstr + 7 < cbInstr, VERR_DBG_MALFORMED_UNWIND_INFO);
2597 if (pExecState->fLittleEndian)
2598 uAddress = RT_MAKE_U64_FROM_U8(pbInstr[offInstr + 0], pbInstr[offInstr + 1],
2599 pbInstr[offInstr + 2], pbInstr[offInstr + 3],
2600 pbInstr[offInstr + 4], pbInstr[offInstr + 5],
2601 pbInstr[offInstr + 6], pbInstr[offInstr + 7]);
2602 else
2603 uAddress = RT_MAKE_U64_FROM_U8(pbInstr[offInstr + 7], pbInstr[offInstr + 6],
2604 pbInstr[offInstr + 5], pbInstr[offInstr + 4],
2605 pbInstr[offInstr + 3], pbInstr[offInstr + 2],
2606 pbInstr[offInstr + 1], pbInstr[offInstr + 0]);
2607 offInstr += 8;
2608 break;
2609 case DW_EH_PE_sleb128:
2610 case DW_EH_PE_uleb128:
2611 default:
2612 AssertMsgFailedReturn(("%#x\n", pExecState->pCie->bAddressPtrEnc), VERR_DWARF_TODO);
2613 }
2614 AssertReturn(uAddress >= pExecState->uPcBegin, VERR_DBG_MALFORMED_UNWIND_INFO);
2615
2616 /* Did we advance past the desire address already? */
2617 if (uAddress > pExecState->uPcBegin + pExecState->offInRange)
2618 return VINF_SUCCESS;
2619 pExecState->cbLeftToAdvance = pExecState->uPcBegin + pExecState->offInRange - uAddress;
2620 break;
2621
2622
2623 /*
2624 * Row state push/pop instructions.
2625 */
2626
2627 case DW_CFA_remember_state:
2628 {
2629 AssertReturn(pExecState->cPushes < 10, VERR_DBG_MALFORMED_UNWIND_INFO);
2630 PRTDWARFCFROW pNewRow = (PRTDWARFCFROW)RTMemTmpAlloc(sizeof(*pNewRow));
2631 AssertReturn(pNewRow, VERR_NO_TMP_MEMORY);
2632 memcpy(pNewRow, pRow, sizeof(*pNewRow));
2633 pNewRow->pNextOnStack = pRow;
2634 pNewRow->fOnHeap = true;
2635 pExecState->pRow = pNewRow;
2636 pExecState->cPushes += 1;
2637 pRow = pNewRow;
2638 break;
2639 }
2640
2641 case DW_CFA_restore_state:
2642 AssertReturn(pRow->pNextOnStack, VERR_DBG_MALFORMED_UNWIND_INFO);
2643 Assert(pRow->fOnHeap);
2644 Assert(pExecState->cPushes > 0);
2645 pExecState->cPushes -= 1;
2646 pExecState->pRow = pRow->pNextOnStack;
2647 RTMemTmpFree(pRow);
2648 pRow = pExecState->pRow;
2649 break;
2650 }
2651 }
2652 break;
2653
2654 case DW_CFA_restore:
2655 {
2656 uint8_t const * const pbCurInstr = &pbInstr[offInstr - 1];
2657 uint8_t const iReg = bInstr & ~DW_CFA_high_bit_mask;
2658 if (iReg < RT_ELEMENTS(pRow->apbRegInstrs))
2659 pRow->apbRegInstrs[iReg] = pbCurInstr;
2660 break;
2661 }
2662 }
2663 }
2664 return VINF_TRY_AGAIN;
2665}
2666
2667
2668/**
2669 * Register getter for AMD64.
2670 *
2671 * @returns true if found, false if not.
2672 * @param pState The unwind state to get the register from.
2673 * @param iReg The dwarf register number.
2674 * @param puValue Where to store the register value.
2675 */
2676static bool rtDwarfUnwind_Amd64GetRegFromState(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue)
2677{
2678 switch (iReg)
2679 {
2680 case DWREG_AMD64_RAX: *puValue = pState->u.x86.auRegs[X86_GREG_xAX]; return true;
2681 case DWREG_AMD64_RDX: *puValue = pState->u.x86.auRegs[X86_GREG_xDX]; return true;
2682 case DWREG_AMD64_RCX: *puValue = pState->u.x86.auRegs[X86_GREG_xCX]; return true;
2683 case DWREG_AMD64_RBX: *puValue = pState->u.x86.auRegs[X86_GREG_xBX]; return true;
2684 case DWREG_AMD64_RSI: *puValue = pState->u.x86.auRegs[X86_GREG_xSI]; return true;
2685 case DWREG_AMD64_RDI: *puValue = pState->u.x86.auRegs[X86_GREG_xDI]; return true;
2686 case DWREG_AMD64_RBP: *puValue = pState->u.x86.auRegs[X86_GREG_xBP]; return true;
2687 case DWREG_AMD64_RSP: *puValue = pState->u.x86.auRegs[X86_GREG_xSP]; return true;
2688 case DWREG_AMD64_R8: *puValue = pState->u.x86.auRegs[X86_GREG_x8]; return true;
2689 case DWREG_AMD64_R9: *puValue = pState->u.x86.auRegs[X86_GREG_x9]; return true;
2690 case DWREG_AMD64_R10: *puValue = pState->u.x86.auRegs[X86_GREG_x10]; return true;
2691 case DWREG_AMD64_R11: *puValue = pState->u.x86.auRegs[X86_GREG_x11]; return true;
2692 case DWREG_AMD64_R12: *puValue = pState->u.x86.auRegs[X86_GREG_x12]; return true;
2693 case DWREG_AMD64_R13: *puValue = pState->u.x86.auRegs[X86_GREG_x13]; return true;
2694 case DWREG_AMD64_R14: *puValue = pState->u.x86.auRegs[X86_GREG_x14]; return true;
2695 case DWREG_AMD64_R15: *puValue = pState->u.x86.auRegs[X86_GREG_x15]; return true;
2696 case DWREG_AMD64_RFLAGS: *puValue = pState->u.x86.uRFlags; return true;
2697 case DWREG_AMD64_ES: *puValue = pState->u.x86.auSegs[X86_SREG_ES]; return true;
2698 case DWREG_AMD64_CS: *puValue = pState->u.x86.auSegs[X86_SREG_CS]; return true;
2699 case DWREG_AMD64_SS: *puValue = pState->u.x86.auSegs[X86_SREG_SS]; return true;
2700 case DWREG_AMD64_DS: *puValue = pState->u.x86.auSegs[X86_SREG_DS]; return true;
2701 case DWREG_AMD64_FS: *puValue = pState->u.x86.auSegs[X86_SREG_FS]; return true;
2702 case DWREG_AMD64_GS: *puValue = pState->u.x86.auSegs[X86_SREG_GS]; return true;
2703 }
2704 return false;
2705}
2706
2707
2708/**
2709 * Register getter for 386+.
2710 *
2711 * @returns true if found, false if not.
2712 * @param pState The unwind state to get the register from.
2713 * @param iReg The dwarf register number.
2714 * @param puValue Where to store the register value.
2715 */
2716static bool rtDwarfUnwind_X86GetRegFromState(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue)
2717{
2718 switch (iReg)
2719 {
2720 case DWREG_X86_EAX: *puValue = pState->u.x86.auRegs[X86_GREG_xAX]; return true;
2721 case DWREG_X86_ECX: *puValue = pState->u.x86.auRegs[X86_GREG_xCX]; return true;
2722 case DWREG_X86_EDX: *puValue = pState->u.x86.auRegs[X86_GREG_xDX]; return true;
2723 case DWREG_X86_EBX: *puValue = pState->u.x86.auRegs[X86_GREG_xBX]; return true;
2724 case DWREG_X86_ESP: *puValue = pState->u.x86.auRegs[X86_GREG_xSP]; return true;
2725 case DWREG_X86_EBP: *puValue = pState->u.x86.auRegs[X86_GREG_xBP]; return true;
2726 case DWREG_X86_ESI: *puValue = pState->u.x86.auRegs[X86_GREG_xSI]; return true;
2727 case DWREG_X86_EDI: *puValue = pState->u.x86.auRegs[X86_GREG_xDI]; return true;
2728 case DWREG_X86_EFLAGS: *puValue = pState->u.x86.uRFlags; return true;
2729 case DWREG_X86_ES: *puValue = pState->u.x86.auSegs[X86_SREG_ES]; return true;
2730 case DWREG_X86_CS: *puValue = pState->u.x86.auSegs[X86_SREG_CS]; return true;
2731 case DWREG_X86_SS: *puValue = pState->u.x86.auSegs[X86_SREG_SS]; return true;
2732 case DWREG_X86_DS: *puValue = pState->u.x86.auSegs[X86_SREG_DS]; return true;
2733 case DWREG_X86_FS: *puValue = pState->u.x86.auSegs[X86_SREG_FS]; return true;
2734 case DWREG_X86_GS: *puValue = pState->u.x86.auSegs[X86_SREG_GS]; return true;
2735 }
2736 return false;
2737}
2738
2739/** Register getter. */
2740typedef bool FNDWARFUNWINDGEREGFROMSTATE(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue);
2741/** Pointer to a register getter. */
2742typedef FNDWARFUNWINDGEREGFROMSTATE *PFNDWARFUNWINDGEREGFROMSTATE;
2743
2744
2745
2746/**
2747 * Does the heavy work for figuring out the return value of a register.
2748 *
2749 * @returns IPRT status code.
2750 * @retval VERR_NOT_FOUND if register is undefined.
2751 *
2752 * @param pRow The DWARF unwind table "row" to use.
2753 * @param uReg The DWARF register number.
2754 * @param pCie The corresponding CIE.
2755 * @param uCfa The canonical frame address to use.
2756 * @param pState The unwind to use when reading stack.
2757 * @param pOldState The unwind state to get register values from.
2758 * @param pfnGetReg The register value getter.
2759 * @param puValue Where to store the return value.
2760 * @param cbValue The size this register would have on the stack.
2761 */
2762static int rtDwarfUnwind_CalcRegisterValue(PRTDWARFCFROW pRow, unsigned uReg, PCRTDWARFCIEINFO pCie, uint64_t uCfa,
2763 PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
2764 PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint64_t *puValue, uint8_t cbValue)
2765{
2766 Assert(uReg < RT_ELEMENTS(pRow->apbRegInstrs));
2767 uint8_t const *pbInstr = pRow->apbRegInstrs[uReg];
2768 if (!pbInstr)
2769 return VERR_NOT_FOUND;
2770
2771 uint32_t cbInstr = UINT32_MAX / 2;
2772 uint32_t offInstr = 1;
2773 uint8_t const bInstr = *pbInstr;
2774 switch (bInstr)
2775 {
2776 default:
2777 if ((bInstr & DW_CFA_high_bit_mask) == DW_CFA_offset)
2778 {
2779 uint64_t offCfa;
2780 GET_ULEB128_AS_U63(offCfa);
2781 int rc = pState->pfnReadStack(pState, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, cbValue, puValue);
2782 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset %#RX64: %Rrc, %#RX64\n", uReg, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, rc, *puValue));
2783 return rc;
2784 }
2785 AssertReturn((bInstr & DW_CFA_high_bit_mask) == DW_CFA_restore, VERR_INTERNAL_ERROR);
2786 RT_FALL_THRU();
2787 case DW_CFA_restore_extended:
2788 /* Need to search the CIE for the rule. */
2789 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_restore/extended:\n", uReg));
2790 AssertFailedReturn(VERR_DWARF_TODO);
2791
2792 case DW_CFA_offset_extended:
2793 {
2794 SKIP_ULEB128_OR_LEB128();
2795 uint64_t offCfa;
2796 GET_ULEB128_AS_U63(offCfa);
2797 int rc = pState->pfnReadStack(pState, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, cbValue, puValue);
2798 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset_extended %#RX64: %Rrc, %#RX64\n", uReg, uCfa + (int64_t)offCfa * pCie->iDataAlignFactor, rc, *puValue));
2799 return rc;
2800 }
2801
2802 case DW_CFA_offset_extended_sf:
2803 {
2804 SKIP_ULEB128_OR_LEB128();
2805 int64_t offCfa;
2806 GET_LEB128_AS_I63(offCfa);
2807 int rc = pState->pfnReadStack(pState, uCfa + offCfa * pCie->iDataAlignFactor, cbValue, puValue);
2808 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_offset_extended_sf %#RX64: %Rrc, %#RX64\n", uReg, uCfa + offCfa * pCie->iDataAlignFactor, rc, *puValue));
2809 return rc;
2810 }
2811
2812 case DW_CFA_val_offset:
2813 {
2814 SKIP_ULEB128_OR_LEB128();
2815 uint64_t offCfa;
2816 GET_ULEB128_AS_U63(offCfa);
2817 *puValue = uCfa + (int64_t)offCfa * pCie->iDataAlignFactor;
2818 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_offset: %#RX64\n", uReg, *puValue));
2819 return VINF_SUCCESS;
2820 }
2821
2822 case DW_CFA_val_offset_sf:
2823 {
2824 SKIP_ULEB128_OR_LEB128();
2825 int64_t offCfa;
2826 GET_LEB128_AS_I63(offCfa);
2827 *puValue = uCfa + offCfa * pCie->iDataAlignFactor;
2828 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_offset_sf: %#RX64\n", uReg, *puValue));
2829 return VINF_SUCCESS;
2830 }
2831
2832 case DW_CFA_register:
2833 {
2834 SKIP_ULEB128_OR_LEB128();
2835 uint16_t iSrcReg;
2836 GET_ULEB128_AS_U14(iSrcReg);
2837 if (pfnGetReg(pOldState, uReg, puValue))
2838 {
2839 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_register: %#RX64\n", uReg, *puValue));
2840 return VINF_SUCCESS;
2841 }
2842 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_register: VERR_NOT_FOUND\n", uReg));
2843 return VERR_NOT_FOUND;
2844 }
2845
2846 case DW_CFA_expression:
2847 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_expression: TODO\n", uReg));
2848 AssertFailedReturn(VERR_DWARF_TODO);
2849
2850 case DW_CFA_val_expression:
2851 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_val_expression: TODO\n", uReg));
2852 AssertFailedReturn(VERR_DWARF_TODO);
2853
2854 case DW_CFA_undefined:
2855 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_undefined\n", uReg));
2856 return VERR_NOT_FOUND;
2857
2858 case DW_CFA_same_value:
2859 if (pfnGetReg(pOldState, uReg, puValue))
2860 {
2861 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_same_value: %#RX64\n", uReg, *puValue));
2862 return VINF_SUCCESS;
2863 }
2864 Log8(("rtDwarfUnwind_CalcRegisterValue(%#x): DW_CFA_same_value: VERR_NOT_FOUND\n", uReg));
2865 return VERR_NOT_FOUND;
2866 }
2867}
2868
2869
2870DECLINLINE(void) rtDwarfUnwind_UpdateX86GRegFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState, unsigned idxGReg,
2871 PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
2872 uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint8_t cbGReg)
2873{
2874 int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg,
2875 &pState->u.x86.auRegs[idxGReg], cbGReg);
2876 if (RT_SUCCESS(rc))
2877 pState->u.x86.Loaded.s.fRegs |= RT_BIT_32(idxGReg);
2878}
2879
2880
2881DECLINLINE(void) rtDwarfUnwind_UpdateX86SRegFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState, unsigned idxSReg,
2882 PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
2883 uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg)
2884{
2885 uint64_t uValue = pState->u.x86.auSegs[idxSReg];
2886 int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg, &uValue, sizeof(uint16_t));
2887 if (RT_SUCCESS(rc))
2888 {
2889 pState->u.x86.auSegs[idxSReg] = (uint16_t)uValue;
2890 pState->u.x86.Loaded.s.fSegs |= RT_BIT_32(idxSReg);
2891 }
2892}
2893
2894
2895DECLINLINE(void) rtDwarfUnwind_UpdateX86RFlagsFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
2896 PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
2897 uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg)
2898{
2899 int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg,
2900 &pState->u.x86.uRFlags, sizeof(uint32_t));
2901 if (RT_SUCCESS(rc))
2902 pState->u.x86.Loaded.s.fRFlags = 1;
2903}
2904
2905
2906DECLINLINE(void) rtDwarfUnwind_UpdatePCFromRow(PRTDBGUNWINDSTATE pState, PCRTDBGUNWINDSTATE pOldState,
2907 PRTDWARFCFROW pRow, unsigned idxDwReg, PCRTDWARFCIEINFO pCie,
2908 uint64_t uCfa, PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg, uint8_t cbPc)
2909{
2910 if (pCie->bRetReg != UINT8_MAX)
2911 idxDwReg = pCie->bRetReg;
2912 int rc = rtDwarfUnwind_CalcRegisterValue(pRow, idxDwReg, pCie, uCfa, pState, pOldState, pfnGetReg, &pState->uPc, cbPc);
2913 if (RT_SUCCESS(rc))
2914 pState->u.x86.Loaded.s.fPc = 1;
2915 else
2916 {
2917 rc = pState->pfnReadStack(pState, uCfa - cbPc, cbPc, &pState->uPc);
2918 if (RT_SUCCESS(rc))
2919 pState->u.x86.Loaded.s.fPc = 1;
2920 }
2921}
2922
2923
2924
2925/**
2926 * Updates @a pState with the rules found in @a pRow.
2927 *
2928 * @returns IPRT status code.
2929 * @param pState The unwind state to update.
2930 * @param pRow The "row" in the dwarf unwind table.
2931 * @param pCie The CIE structure for the row.
2932 * @param enmImageArch The image architecture.
2933 */
2934static int rtDwarfUnwind_UpdateStateFromRow(PRTDBGUNWINDSTATE pState, PRTDWARFCFROW pRow,
2935 PCRTDWARFCIEINFO pCie, RTLDRARCH enmImageArch)
2936{
2937 /*
2938 * We need to make a copy of the current state so we can get at the
2939 * current register values while calculating the ones of the next frame.
2940 */
2941 RTDBGUNWINDSTATE const Old = *pState;
2942
2943 /*
2944 * Get the register state getter.
2945 */
2946 PFNDWARFUNWINDGEREGFROMSTATE pfnGetReg;
2947 switch (enmImageArch)
2948 {
2949 case RTLDRARCH_AMD64:
2950 pfnGetReg = rtDwarfUnwind_Amd64GetRegFromState;
2951 break;
2952 case RTLDRARCH_X86_32:
2953 case RTLDRARCH_X86_16:
2954 pfnGetReg = rtDwarfUnwind_X86GetRegFromState;
2955 break;
2956 default:
2957 return VERR_NOT_SUPPORTED;
2958 }
2959
2960 /*
2961 * Calc the canonical frame address for the current row.
2962 */
2963 AssertReturn(pRow->fCfaDefined, VERR_DBG_MALFORMED_UNWIND_INFO);
2964 uint64_t uCfa = 0;
2965 if (!pRow->pbCfaExprInstr)
2966 {
2967 pfnGetReg(&Old, pRow->uCfaBaseReg, &uCfa);
2968 uCfa += pRow->offCfaReg;
2969 }
2970 else
2971 {
2972 AssertFailed();
2973 return VERR_DWARF_TODO;
2974 }
2975 Log8(("rtDwarfUnwind_UpdateStateFromRow: uCfa=%RX64\n", uCfa));
2976
2977 /*
2978 * Do the architecture specific register updating.
2979 */
2980 switch (enmImageArch)
2981 {
2982 case RTLDRARCH_AMD64:
2983 pState->enmRetType = RTDBGRETURNTYPE_NEAR64;
2984 pState->u.x86.FrameAddr.off = uCfa - 8*2;
2985 pState->u.x86.Loaded.fAll = 0;
2986 pState->u.x86.Loaded.s.fFrameAddr = 1;
2987 rtDwarfUnwind_UpdatePCFromRow(pState, &Old, pRow, DWREG_AMD64_RA, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2988 rtDwarfUnwind_UpdateX86RFlagsFromRow(pState, &Old, pRow, DWREG_AMD64_RFLAGS, pCie, uCfa, pfnGetReg);
2989 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xAX, pRow, DWREG_AMD64_RAX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2990 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xCX, pRow, DWREG_AMD64_RCX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2991 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDX, pRow, DWREG_AMD64_RDX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2992 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBX, pRow, DWREG_AMD64_RBX, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2993 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSP, pRow, DWREG_AMD64_RSP, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2994 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBP, pRow, DWREG_AMD64_RBP, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2995 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSI, pRow, DWREG_AMD64_RSI, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2996 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDI, pRow, DWREG_AMD64_RDI, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2997 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x8, pRow, DWREG_AMD64_R8, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2998 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x9, pRow, DWREG_AMD64_R9, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
2999 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x10, pRow, DWREG_AMD64_R10, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3000 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x11, pRow, DWREG_AMD64_R11, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3001 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x12, pRow, DWREG_AMD64_R12, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3002 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x13, pRow, DWREG_AMD64_R13, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3003 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x14, pRow, DWREG_AMD64_R14, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3004 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_x15, pRow, DWREG_AMD64_R15, pCie, uCfa, pfnGetReg, sizeof(uint64_t));
3005 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_ES, pRow, DWREG_AMD64_ES, pCie, uCfa, pfnGetReg);
3006 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_CS, pRow, DWREG_AMD64_CS, pCie, uCfa, pfnGetReg);
3007 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_SS, pRow, DWREG_AMD64_SS, pCie, uCfa, pfnGetReg);
3008 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_DS, pRow, DWREG_AMD64_DS, pCie, uCfa, pfnGetReg);
3009 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_FS, pRow, DWREG_AMD64_FS, pCie, uCfa, pfnGetReg);
3010 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_GS, pRow, DWREG_AMD64_GS, pCie, uCfa, pfnGetReg);
3011 break;
3012
3013 case RTLDRARCH_X86_32:
3014 case RTLDRARCH_X86_16:
3015 pState->enmRetType = RTDBGRETURNTYPE_NEAR32;
3016 pState->u.x86.FrameAddr.off = uCfa - 4*2;
3017 pState->u.x86.Loaded.fAll = 0;
3018 pState->u.x86.Loaded.s.fFrameAddr = 1;
3019 rtDwarfUnwind_UpdatePCFromRow(pState, &Old, pRow, DWREG_X86_RA, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3020 rtDwarfUnwind_UpdateX86RFlagsFromRow(pState, &Old, pRow, DWREG_X86_EFLAGS, pCie, uCfa, pfnGetReg);
3021 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xAX, pRow, DWREG_X86_EAX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3022 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xCX, pRow, DWREG_X86_ECX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3023 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDX, pRow, DWREG_X86_EDX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3024 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBX, pRow, DWREG_X86_EBX, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3025 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSP, pRow, DWREG_X86_ESP, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3026 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xBP, pRow, DWREG_X86_EBP, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3027 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xSI, pRow, DWREG_X86_ESI, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3028 rtDwarfUnwind_UpdateX86GRegFromRow(pState, &Old, X86_GREG_xDI, pRow, DWREG_X86_EDI, pCie, uCfa, pfnGetReg, sizeof(uint32_t));
3029 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_ES, pRow, DWREG_X86_ES, pCie, uCfa, pfnGetReg);
3030 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_CS, pRow, DWREG_X86_CS, pCie, uCfa, pfnGetReg);
3031 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_SS, pRow, DWREG_X86_SS, pCie, uCfa, pfnGetReg);
3032 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_DS, pRow, DWREG_X86_DS, pCie, uCfa, pfnGetReg);
3033 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_FS, pRow, DWREG_X86_FS, pCie, uCfa, pfnGetReg);
3034 rtDwarfUnwind_UpdateX86SRegFromRow(pState, &Old, X86_SREG_GS, pRow, DWREG_X86_GS, pCie, uCfa, pfnGetReg);
3035 if (pState->u.x86.Loaded.s.fRegs & RT_BIT_32(X86_GREG_xSP))
3036 pState->u.x86.FrameAddr.off = pState->u.x86.auRegs[X86_GREG_xSP] - 8;
3037 else
3038 pState->u.x86.FrameAddr.off = uCfa - 8;
3039 pState->u.x86.FrameAddr.sel = pState->u.x86.auSegs[X86_SREG_SS];
3040 if (pState->u.x86.Loaded.s.fSegs & RT_BIT_32(X86_SREG_CS))
3041 {
3042 if ((pState->uPc >> 16) == pState->u.x86.auSegs[X86_SREG_CS])
3043 {
3044 pState->enmRetType = RTDBGRETURNTYPE_FAR16;
3045 pState->uPc &= UINT16_MAX;
3046 Log8(("rtDwarfUnwind_UpdateStateFromRow: Detected FAR16 return to %04x:%04RX64\n", pState->u.x86.auSegs[X86_SREG_CS], pState->uPc));
3047 }
3048 else
3049 {
3050 pState->enmRetType = RTDBGRETURNTYPE_FAR32;
3051 Log8(("rtDwarfUnwind_UpdateStateFromRow: CS loaded, assume far return.\n"));
3052 }
3053 }
3054 break;
3055
3056 default:
3057 AssertFailedReturn(VERR_NOT_SUPPORTED);
3058 }
3059
3060 return VINF_SUCCESS;
3061}
3062
3063
3064/**
3065 * Processes a FDE, taking over after the PC range field.
3066 *
3067 * @returns IPRT status code.
3068 * @param pCursor The cursor.
3069 * @param pCie Information about the corresponding CIE.
3070 * @param uPcBegin The PC begin field value (sans segment).
3071 * @param cbPcRange The PC range from @a uPcBegin.
3072 * @param offInRange The offset into the range corresponding to
3073 * pState->uPc.
3074 * @param enmImageArch The image architecture.
3075 * @param pState The unwind state to work.
3076 */
3077static int rtDwarfUnwind_ProcessFde(PRTDWARFCURSOR pCursor, PCRTDWARFCIEINFO pCie, uint64_t uPcBegin,
3078 uint64_t cbPcRange, uint64_t offInRange, RTLDRARCH enmImageArch, PRTDBGUNWINDSTATE pState)
3079{
3080 /*
3081 * Deal with augmented data fields.
3082 */
3083 /* The size. */
3084 size_t cbInstr = ~(size_t)0;
3085 if (pCie->fHasAugmentationSize)
3086 {
3087 uint64_t cbAugData = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3088 if (RT_FAILURE(pCursor->rc))
3089 return pCursor->rc;
3090 if (cbAugData > pCursor->cbUnitLeft)
3091 return VERR_DBG_MALFORMED_UNWIND_INFO;
3092 cbInstr = pCursor->cbUnitLeft - cbAugData;
3093 }
3094 else if (pCie->fHasUnknowAugmentation)
3095 return VERR_DBG_MALFORMED_UNWIND_INFO;
3096
3097 /* Parse the string and fetch FDE fields. */
3098 if (!pCie->fHasEhData)
3099 for (const char *pszAug = pCie->pszAugmentation; *pszAug != '\0'; pszAug++)
3100 switch (*pszAug)
3101 {
3102 case 'L':
3103 if (pCie->bLsdaPtrEnc != DW_EH_PE_omit)
3104 rtDwarfCursor_GetPtrEnc(pCursor, pCie->bLsdaPtrEnc, 0);
3105 break;
3106 }
3107
3108 /* Skip unconsumed bytes. */
3109 if ( cbInstr != ~(size_t)0
3110 && pCursor->cbUnitLeft > cbInstr)
3111 rtDwarfCursor_SkipBytes(pCursor, pCursor->cbUnitLeft - cbInstr);
3112 if (RT_FAILURE(pCursor->rc))
3113 return pCursor->rc;
3114
3115 /*
3116 * Now "execute" the programs till we've constructed the desired row.
3117 */
3118 RTDWARFCFROW Row;
3119 RTDWARFCFEXEC ExecState = { &Row, offInRange, 0, true /** @todo byte-order*/, pCie, uPcBegin, offInRange };
3120 RT_ZERO(Row);
3121
3122 int rc = rtDwarfUnwind_Execute(&ExecState, pCie->pbInstructions, (uint32_t)pCie->cbInstructions);
3123 if (rc == VINF_TRY_AGAIN)
3124 rc = rtDwarfUnwind_Execute(&ExecState, pCursor->pb, (uint32_t)pCursor->cbUnitLeft);
3125
3126 /* On success, extract whatever state we've got. */
3127 if (RT_SUCCESS(rc))
3128 rc = rtDwarfUnwind_UpdateStateFromRow(pState, &Row, pCie, enmImageArch);
3129
3130 /*
3131 * Clean up allocations in case of pushes.
3132 */
3133 if (ExecState.pRow == &Row)
3134 Assert(!ExecState.pRow->fOnHeap);
3135 else
3136 do
3137 {
3138 PRTDWARFCFROW pPopped = ExecState.pRow;
3139 ExecState.pRow = ExecState.pRow->pNextOnStack;
3140 Assert(pPopped->fOnHeap);
3141 RTMemTmpFree(pPopped);
3142 } while (ExecState.pRow && ExecState.pRow != &Row);
3143
3144 RT_NOREF(pState, uPcBegin, cbPcRange, offInRange);
3145 return rc;
3146}
3147
3148
3149/**
3150 * Load the information we need from a CIE.
3151 *
3152 * This starts after the initial length and CIE_pointer fields has
3153 * been processed.
3154 *
3155 * @returns IPRT status code.
3156 * @param pCursor The cursor.
3157 * @param pNewCie The structure to populate with parsed CIE info.
3158 * @param offUnit The unit offset.
3159 * @param bDefaultPtrEnc The default pointer encoding.
3160 */
3161static int rtDwarfUnwind_LoadCie(PRTDWARFCURSOR pCursor, PRTDWARFCIEINFO pNewCie, uint64_t offUnit, uint8_t bDefaultPtrEnc)
3162{
3163 /*
3164 * Initialize the CIE record and get the version.
3165 */
3166 RT_ZERO(*pNewCie);
3167 pNewCie->offCie = offUnit;
3168 pNewCie->bLsdaPtrEnc = DW_EH_PE_omit;
3169 pNewCie->bAddressPtrEnc = DW_EH_PE_omit; /* set later */
3170 pNewCie->uDwarfVer = rtDwarfCursor_GetUByte(pCursor, 0);
3171 if ( pNewCie->uDwarfVer >= 1 /* Note! Some GCC versions may emit v1 here. */
3172 && pNewCie->uDwarfVer <= 5)
3173 { /* likely */ }
3174 else
3175 {
3176 Log(("rtDwarfUnwind_LoadCie(%RX64): uDwarfVer=%u: VERR_VERSION_MISMATCH\n", offUnit, pNewCie->uDwarfVer));
3177 return VERR_VERSION_MISMATCH;
3178 }
3179
3180 /*
3181 * The augmentation string.
3182 *
3183 * First deal with special "eh" string from oldish GCC (dwarf2out.c about 1997), specified in LSB:
3184 * https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
3185 */
3186 pNewCie->pszAugmentation = rtDwarfCursor_GetSZ(pCursor, "");
3187 if ( pNewCie->pszAugmentation[0] == 'e'
3188 && pNewCie->pszAugmentation[1] == 'h'
3189 && pNewCie->pszAugmentation[2] == '\0')
3190 {
3191 pNewCie->fHasEhData = true;
3192 rtDwarfCursor_GetPtrEnc(pCursor, bDefaultPtrEnc, 0);
3193 }
3194 else
3195 {
3196 /* Regular augmentation string. */
3197 for (const char *pszAug = pNewCie->pszAugmentation; *pszAug != '\0'; pszAug++)
3198 switch (*pszAug)
3199 {
3200 case 'z':
3201 pNewCie->fHasAugmentationSize = true;
3202 break;
3203 case 'L':
3204 pNewCie->fHasLanguageSpecificDataArea = true;
3205 break;
3206 case 'P':
3207 pNewCie->fHasPersonalityRoutine = true;
3208 break;
3209 case 'R':
3210 pNewCie->fHasAddressEnc = true;
3211 break;
3212 case 'S':
3213 pNewCie->fIsSignalFrame = true;
3214 break;
3215 default:
3216 pNewCie->fHasUnknowAugmentation = true;
3217 break;
3218 }
3219 }
3220
3221 /*
3222 * More standard fields
3223 */
3224 uint8_t cbAddress = 0;
3225 if (pNewCie->uDwarfVer >= 4)
3226 {
3227 cbAddress = rtDwarfCursor_GetU8(pCursor, bDefaultPtrEnc == DW_EH_PE_udata8 ? 8 : 4);
3228 pNewCie->cbSegment = rtDwarfCursor_GetU8(pCursor, 0);
3229 }
3230 pNewCie->uCodeAlignFactor = rtDwarfCursor_GetULeb128(pCursor, 1);
3231 pNewCie->iDataAlignFactor = rtDwarfCursor_GetSLeb128(pCursor, 1);
3232 pNewCie->bRetReg = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
3233
3234 /*
3235 * Augmentation data.
3236 */
3237 if (!pNewCie->fHasEhData)
3238 {
3239 /* The size. */
3240 size_t cbInstr = ~(size_t)0;
3241 if (pNewCie->fHasAugmentationSize)
3242 {
3243 uint64_t cbAugData = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3244 if (RT_FAILURE(pCursor->rc))
3245 {
3246 Log(("rtDwarfUnwind_LoadCie(%#RX64): rtDwarfCursor_GetULeb128 -> %Rrc!\n", offUnit, pCursor->rc));
3247 return pCursor->rc;
3248 }
3249 if (cbAugData > pCursor->cbUnitLeft)
3250 {
3251 Log(("rtDwarfUnwind_LoadCie(%#RX64): cbAugData=%#x pCursor->cbUnitLeft=%#x -> VERR_DBG_MALFORMED_UNWIND_INFO!\n", offUnit, cbAugData, pCursor->cbUnitLeft));
3252 return VERR_DBG_MALFORMED_UNWIND_INFO;
3253 }
3254 cbInstr = pCursor->cbUnitLeft - cbAugData;
3255 }
3256 else if (pNewCie->fHasUnknowAugmentation)
3257 {
3258 Log(("rtDwarfUnwind_LoadCie(%#RX64): fHasUnknowAugmentation=1 -> VERR_DBG_MALFORMED_UNWIND_INFO!\n", offUnit));
3259 return VERR_DBG_MALFORMED_UNWIND_INFO;
3260 }
3261
3262 /* Parse the string. */
3263 for (const char *pszAug = pNewCie->pszAugmentation; *pszAug != '\0'; pszAug++)
3264 switch (*pszAug)
3265 {
3266 case 'L':
3267 pNewCie->bLsdaPtrEnc = rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit);
3268 break;
3269 case 'P':
3270 rtDwarfCursor_GetPtrEnc(pCursor, rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit), 0);
3271 break;
3272 case 'R':
3273 pNewCie->bAddressPtrEnc = rtDwarfCursor_GetU8(pCursor, DW_EH_PE_omit);
3274 break;
3275 }
3276
3277 /* Skip unconsumed bytes. */
3278 if ( cbInstr != ~(size_t)0
3279 && pCursor->cbUnitLeft > cbInstr)
3280 rtDwarfCursor_SkipBytes(pCursor, pCursor->cbUnitLeft - cbInstr);
3281 }
3282
3283 /*
3284 * Note down where the instructions are.
3285 */
3286 pNewCie->pbInstructions = pCursor->pb;
3287 pNewCie->cbInstructions = pCursor->cbUnitLeft;
3288
3289 /*
3290 * Determine the target address encoding. Make sure we resolve DW_EH_PE_ptr.
3291 */
3292 if (pNewCie->bAddressPtrEnc == DW_EH_PE_omit)
3293 switch (cbAddress)
3294 {
3295 case 2: pNewCie->bAddressPtrEnc = DW_EH_PE_udata2; break;
3296 case 4: pNewCie->bAddressPtrEnc = DW_EH_PE_udata4; break;
3297 case 8: pNewCie->bAddressPtrEnc = DW_EH_PE_udata8; break;
3298 default: pNewCie->bAddressPtrEnc = bDefaultPtrEnc; break;
3299 }
3300 else if ((pNewCie->bAddressPtrEnc & DW_EH_PE_FORMAT_MASK) == DW_EH_PE_ptr)
3301 pNewCie->bAddressPtrEnc = bDefaultPtrEnc;
3302
3303 return VINF_SUCCESS;
3304}
3305
3306
3307/**
3308 * Does a slow unwind of a '.debug_frame' or '.eh_frame' section.
3309 *
3310 * @returns IPRT status code.
3311 * @param pCursor The cursor.
3312 * @param uRvaCursor The RVA corrsponding to the cursor start location.
3313 * @param idxSeg The segment of the PC location.
3314 * @param offSeg The segment offset of the PC location.
3315 * @param uRva The RVA of the PC location.
3316 * @param pState The unwind state to work.
3317 * @param bDefaultPtrEnc The default pointer encoding.
3318 * @param fIsEhFrame Set if this is a '.eh_frame'. GCC generate these
3319 * with different CIE_pointer values.
3320 * @param enmImageArch The image architecture.
3321 */
3322DECLHIDDEN(int) rtDwarfUnwind_Slow(PRTDWARFCURSOR pCursor, RTUINTPTR uRvaCursor,
3323 RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
3324 PRTDBGUNWINDSTATE pState, uint8_t bDefaultPtrEnc, bool fIsEhFrame, RTLDRARCH enmImageArch)
3325{
3326 Log8(("rtDwarfUnwind_Slow: idxSeg=%#x offSeg=%RTptr uRva=%RTptr enmArch=%d PC=%#RX64\n", idxSeg, offSeg, uRva, pState->enmArch, pState->uPc));
3327
3328 /*
3329 * CIE info we collect.
3330 */
3331 PRTDWARFCIEINFO paCies = NULL;
3332 uint32_t cCies = 0;
3333 PRTDWARFCIEINFO pCieHint = NULL;
3334
3335 /*
3336 * Do the scanning.
3337 */
3338 uint64_t const offCieOffset = pCursor->f64bitDwarf ? UINT64_MAX : UINT32_MAX;
3339 int rc = VERR_DBG_UNWIND_INFO_NOT_FOUND;
3340 while (!rtDwarfCursor_IsAtEnd(pCursor))
3341 {
3342 uint64_t const offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
3343 if (rtDwarfCursor_GetInitialLength(pCursor) == 0)
3344 break;
3345
3346 uint64_t const offRelCie = rtDwarfCursor_GetUOff(pCursor, offCieOffset);
3347 if (offRelCie != offCieOffset)
3348 {
3349 /*
3350 * Frame descriptor entry (FDE).
3351 */
3352 /* Locate the corresponding CIE. The CIE pointer is self relative
3353 in .eh_frame and section relative in .debug_frame. */
3354 PRTDWARFCIEINFO pCieForFde;
3355 uint64_t offCie = fIsEhFrame ? offUnit + 4 - offRelCie : offRelCie;
3356 if (pCieHint && pCieHint->offCie == offCie)
3357 pCieForFde = pCieHint;
3358 else
3359 {
3360 pCieForFde = NULL;
3361 uint32_t i = cCies;
3362 while (i-- > 0)
3363 if (paCies[i].offCie == offCie)
3364 {
3365 pCieHint = pCieForFde = &paCies[i];
3366 break;
3367 }
3368 }
3369 if (pCieForFde)
3370 {
3371 /* Read the PC range covered by this FDE (the fields are also known as initial_location). */
3372 RTDBGSEGIDX idxFdeSeg = RTDBGSEGIDX_RVA;
3373 if (pCieForFde->cbSegment)
3374 idxFdeSeg = rtDwarfCursor_GetVarSizedU(pCursor, pCieForFde->cbSegment, RTDBGSEGIDX_RVA);
3375 uint64_t uPcBegin;
3376 switch (pCieForFde->bAddressPtrEnc & DW_EH_PE_APPL_MASK)
3377 {
3378 default: AssertFailed();
3379 RT_FALL_THRU();
3380 case DW_EH_PE_absptr:
3381 uPcBegin = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
3382 break;
3383 case DW_EH_PE_pcrel:
3384 {
3385 uPcBegin = rtDwarfCursor_CalcSectOffsetU32(pCursor) + uRvaCursor;
3386 uPcBegin += rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
3387 break;
3388 }
3389 }
3390 uint64_t cbPcRange = rtDwarfCursor_GetPtrEnc(pCursor, pCieForFde->bAddressPtrEnc, 0);
3391
3392 /* Match it with what we're looking for. */
3393 bool fMatch = idxFdeSeg == RTDBGSEGIDX_RVA
3394 ? uRva - uPcBegin < cbPcRange
3395 : idxSeg == idxFdeSeg && offSeg - uPcBegin < cbPcRange;
3396 Log8(("%#08RX64: FDE pCie=%p idxFdeSeg=%#x uPcBegin=%#RX64 cbPcRange=%#x fMatch=%d\n",
3397 offUnit, pCieForFde, idxFdeSeg, uPcBegin, cbPcRange, fMatch));
3398 if (fMatch)
3399 {
3400 rc = rtDwarfUnwind_ProcessFde(pCursor, pCieForFde, uPcBegin, cbPcRange,
3401 idxFdeSeg == RTDBGSEGIDX_RVA ? uRva - uPcBegin : offSeg - uPcBegin,
3402 enmImageArch, pState);
3403 break;
3404 }
3405 }
3406 else
3407 Log8(("%#08RX64: FDE - pCie=NULL!! offCie=%#RX64 offRelCie=%#RX64 fIsEhFrame=%d\n", offUnit, offCie, offRelCie, fIsEhFrame));
3408 }
3409 else
3410 {
3411 /*
3412 * Common information entry (CIE). Record the info we need about it.
3413 */
3414 if ((cCies % 8) == 0)
3415 {
3416 void *pvNew = RTMemRealloc(paCies, sizeof(paCies[0]) * (cCies + 8));
3417 if (pvNew)
3418 {
3419 paCies = (PRTDWARFCIEINFO)pvNew;
3420 pCieHint = NULL;
3421 }
3422 else
3423 {
3424 rc = VERR_NO_MEMORY;
3425 break;
3426 }
3427 }
3428 Log8(("%#08RX64: CIE\n", offUnit));
3429 int rc2 = rtDwarfUnwind_LoadCie(pCursor, &paCies[cCies], offUnit, bDefaultPtrEnc);
3430 if (RT_SUCCESS(rc2))
3431 {
3432 Log8(("%#08RX64: CIE #%u: offCie=%#RX64\n", offUnit, cCies, paCies[cCies].offCie));
3433 cCies++;
3434 }
3435 }
3436 rtDwarfCursor_SkipUnit(pCursor);
3437 }
3438
3439 /*
3440 * Cleanup.
3441 */
3442 if (paCies)
3443 RTMemFree(paCies);
3444 Log8(("rtDwarfUnwind_Slow: returns %Rrc PC=%#RX64\n", rc, pState->uPc));
3445 return rc;
3446}
3447
3448
3449/**
3450 * Helper for translating a loader architecture value to a pointe encoding.
3451 *
3452 * @returns Pointer encoding.
3453 * @param enmLdrArch The loader architecture value to convert.
3454 */
3455static uint8_t rtDwarfUnwind_ArchToPtrEnc(RTLDRARCH enmLdrArch)
3456{
3457 switch (enmLdrArch)
3458 {
3459 case RTLDRARCH_AMD64:
3460 case RTLDRARCH_ARM64:
3461 return DW_EH_PE_udata8;
3462 case RTLDRARCH_X86_16:
3463 case RTLDRARCH_X86_32:
3464 case RTLDRARCH_ARM32:
3465 return DW_EH_PE_udata4;
3466 case RTLDRARCH_HOST:
3467 case RTLDRARCH_WHATEVER:
3468 case RTLDRARCH_INVALID:
3469 case RTLDRARCH_END:
3470 case RTLDRARCH_32BIT_HACK:
3471 break;
3472 }
3473 AssertFailed();
3474 return DW_EH_PE_udata4;
3475}
3476
3477
3478/**
3479 * Interface for the loader code.
3480 *
3481 * @returns IPRT status.
3482 * @param pvSection The '.eh_frame' section data.
3483 * @param cbSection The size of the '.eh_frame' section data.
3484 * @param uRvaSection The RVA of the '.eh_frame' section.
3485 * @param idxSeg The segment of the PC location.
3486 * @param offSeg The segment offset of the PC location.
3487 * @param uRva The RVA of the PC location.
3488 * @param pState The unwind state to work.
3489 * @param enmArch The image architecture.
3490 */
3491DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTUINTPTR uRvaSection,
3492 RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
3493 PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch)
3494{
3495 RTDWARFCURSOR Cursor;
3496 rtDwarfCursor_InitForMem(&Cursor, pvSection, cbSection);
3497 int rc = rtDwarfUnwind_Slow(&Cursor, uRvaSection, idxSeg, offSeg, uRva, pState,
3498 rtDwarfUnwind_ArchToPtrEnc(enmArch), true /*fIsEhFrame*/, enmArch);
3499 LogFlow(("rtDwarfUnwind_EhData: rtDwarfUnwind_Slow -> %Rrc\n", rc));
3500 rc = rtDwarfCursor_Delete(&Cursor, rc);
3501 LogFlow(("rtDwarfUnwind_EhData: returns %Rrc\n", rc));
3502 return rc;
3503}
3504
3505
3506/*
3507 *
3508 * DWARF Line Numbers.
3509 * DWARF Line Numbers.
3510 * DWARF Line Numbers.
3511 *
3512 */
3513
3514
3515/**
3516 * Defines a file name.
3517 *
3518 * @returns IPRT status code.
3519 * @param pLnState The line number program state.
3520 * @param pszFilename The name of the file.
3521 * @param idxInc The include path index.
3522 */
3523static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc)
3524{
3525 /*
3526 * Resize the array if necessary.
3527 */
3528 uint32_t iFileName = pLnState->cFileNames;
3529 if ((iFileName % 2) == 0)
3530 {
3531 void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2));
3532 if (!pv)
3533 return VERR_NO_MEMORY;
3534 pLnState->papszFileNames = (char **)pv;
3535 }
3536
3537 /*
3538 * Add the file name.
3539 */
3540 if ( pszFilename[0] == '/'
3541 || pszFilename[0] == '\\'
3542 || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') )
3543 pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename);
3544 else if (idxInc < pLnState->cIncPaths)
3545 pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename);
3546 else
3547 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
3548 if (!pLnState->papszFileNames[iFileName])
3549 return VERR_NO_STR_MEMORY;
3550 pLnState->cFileNames = iFileName + 1;
3551
3552 /*
3553 * Sanitize the name.
3554 */
3555 int rc = rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]);
3556 Log((" File #%02u = '%s'\n", iFileName, pLnState->papszFileNames[iFileName]));
3557 return rc;
3558}
3559
3560
3561/**
3562 * Adds a line to the table and resets parts of the state (DW_LNS_copy).
3563 *
3564 * @returns IPRT status code
3565 * @param pLnState The line number program state.
3566 * @param offOpCode The opcode offset (for logging
3567 * purposes).
3568 */
3569static int rtDwarfLine_AddLine(PRTDWARFLINESTATE pLnState, uint32_t offOpCode)
3570{
3571 PRTDBGMODDWARF pThis = pLnState->pDwarfMod;
3572 int rc;
3573 if (pThis->iWatcomPass == 1)
3574 rc = rtDbgModDwarfRecordSegOffset(pThis, pLnState->Regs.uSegment, pLnState->Regs.uAddress + 1);
3575 else
3576 {
3577 const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames
3578 ? pLnState->papszFileNames[pLnState->Regs.iFile]
3579 : "<bad file name index>";
3580 NOREF(offOpCode);
3581
3582 RTDBGSEGIDX iSeg;
3583 RTUINTPTR offSeg;
3584 rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uSegment, pLnState->Regs.uAddress,
3585 &iSeg, &offSeg); /*AssertRC(rc);*/
3586 if (RT_SUCCESS(rc))
3587 {
3588 Log2(("rtDwarfLine_AddLine: %x:%08llx (%#llx) %s(%d) [offOpCode=%08x]\n", iSeg, offSeg, pLnState->Regs.uAddress, pszFile, pLnState->Regs.uLine, offOpCode));
3589 rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL);
3590
3591 /* Ignore address conflicts for now. */
3592 if (rc == VERR_DBG_ADDRESS_CONFLICT)
3593 rc = VINF_SUCCESS;
3594 }
3595 else
3596 rc = VINF_SUCCESS; /* ignore failure */
3597 }
3598
3599 pLnState->Regs.fBasicBlock = false;
3600 pLnState->Regs.fPrologueEnd = false;
3601 pLnState->Regs.fEpilogueBegin = false;
3602 pLnState->Regs.uDiscriminator = 0;
3603 return rc;
3604}
3605
3606
3607/**
3608 * Reset the program to the start-of-sequence state.
3609 *
3610 * @param pLnState The line number program state.
3611 */
3612static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState)
3613{
3614 pLnState->Regs.uAddress = 0;
3615 pLnState->Regs.idxOp = 0;
3616 pLnState->Regs.iFile = 1;
3617 pLnState->Regs.uLine = 1;
3618 pLnState->Regs.uColumn = 0;
3619 pLnState->Regs.fIsStatement = RT_BOOL(pLnState->Hdr.u8DefIsStmt);
3620 pLnState->Regs.fBasicBlock = false;
3621 pLnState->Regs.fEndSequence = false;
3622 pLnState->Regs.fPrologueEnd = false;
3623 pLnState->Regs.fEpilogueBegin = false;
3624 pLnState->Regs.uIsa = 0;
3625 pLnState->Regs.uDiscriminator = 0;
3626 pLnState->Regs.uSegment = 0;
3627}
3628
3629
3630/**
3631 * Runs the line number program.
3632 *
3633 * @returns IPRT status code.
3634 * @param pLnState The line number program state.
3635 * @param pCursor The cursor.
3636 */
3637static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3638{
3639 LogFlow(("rtDwarfLine_RunProgram: cbUnitLeft=%zu\n", pCursor->cbUnitLeft));
3640
3641 int rc = VINF_SUCCESS;
3642 rtDwarfLine_ResetState(pLnState);
3643
3644 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
3645 {
3646#ifdef LOG_ENABLED
3647 uint32_t const offOpCode = rtDwarfCursor_CalcSectOffsetU32(pCursor);
3648#else
3649 uint32_t const offOpCode = 0;
3650#endif
3651 uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, DW_LNS_extended);
3652 if (bOpCode >= pLnState->Hdr.u8OpcodeBase)
3653 {
3654 /*
3655 * Special opcode.
3656 */
3657 uint8_t const bLogOpCode = bOpCode; NOREF(bLogOpCode);
3658 bOpCode -= pLnState->Hdr.u8OpcodeBase;
3659
3660 int32_t const cLineDelta = bOpCode % pLnState->Hdr.u8LineRange + (int32_t)pLnState->Hdr.s8LineBase;
3661 bOpCode /= pLnState->Hdr.u8LineRange;
3662
3663 uint64_t uTmp = bOpCode + pLnState->Regs.idxOp;
3664 uint64_t const cAddressDelta = uTmp / pLnState->Hdr.cMaxOpsPerInstr * pLnState->Hdr.cbMinInstr;
3665 uint64_t const cOpIndexDelta = uTmp % pLnState->Hdr.cMaxOpsPerInstr;
3666
3667 pLnState->Regs.uLine += cLineDelta;
3668 pLnState->Regs.uAddress += cAddressDelta;
3669 pLnState->Regs.idxOp += cOpIndexDelta;
3670 Log2(("%08x: DW Special Opcode %#04x: uLine + %d => %u; uAddress + %#llx => %#llx; idxOp + %#llx => %#llx\n",
3671 offOpCode, bLogOpCode, cLineDelta, pLnState->Regs.uLine, cAddressDelta, pLnState->Regs.uAddress,
3672 cOpIndexDelta, pLnState->Regs.idxOp));
3673
3674 /*
3675 * LLVM emits debug info for global constructors (_GLOBAL__I_a) which are not part of source
3676 * code but are inserted by the compiler: The resulting line number will be 0
3677 * because they are not part of the source file obviously (see https://reviews.llvm.org/rL205999),
3678 * so skip adding them when they are encountered.
3679 */
3680 if (pLnState->Regs.uLine)
3681 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3682 }
3683 else
3684 {
3685 switch (bOpCode)
3686 {
3687 /*
3688 * Standard opcode.
3689 */
3690 case DW_LNS_copy:
3691 Log2(("%08x: DW_LNS_copy\n", offOpCode));
3692 /* See the comment about LLVM above. */
3693 if (pLnState->Regs.uLine)
3694 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3695 break;
3696
3697 case DW_LNS_advance_pc:
3698 {
3699 uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0);
3700 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->Hdr.cMaxOpsPerInstr
3701 * pLnState->Hdr.cbMinInstr;
3702 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + u64Adv) % pLnState->Hdr.cMaxOpsPerInstr;
3703 Log2(("%08x: DW_LNS_advance_pc: u64Adv=%#llx (%lld) )\n", offOpCode, u64Adv, u64Adv));
3704 break;
3705 }
3706
3707 case DW_LNS_advance_line:
3708 {
3709 int32_t cLineDelta = rtDwarfCursor_GetSLeb128AsS32(pCursor, 0);
3710 pLnState->Regs.uLine += cLineDelta;
3711 Log2(("%08x: DW_LNS_advance_line: uLine + %d => %u\n", offOpCode, cLineDelta, pLnState->Regs.uLine));
3712 break;
3713 }
3714
3715 case DW_LNS_set_file:
3716 pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3717 Log2(("%08x: DW_LNS_set_file: iFile=%u\n", offOpCode, pLnState->Regs.iFile));
3718 break;
3719
3720 case DW_LNS_set_column:
3721 pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3722 Log2(("%08x: DW_LNS_set_column\n", offOpCode));
3723 break;
3724
3725 case DW_LNS_negate_stmt:
3726 pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement;
3727 Log2(("%08x: DW_LNS_negate_stmt\n", offOpCode));
3728 break;
3729
3730 case DW_LNS_set_basic_block:
3731 pLnState->Regs.fBasicBlock = true;
3732 Log2(("%08x: DW_LNS_set_basic_block\n", offOpCode));
3733 break;
3734
3735 case DW_LNS_const_add_pc:
3736 {
3737 uint8_t u8Adv = (255 - pLnState->Hdr.u8OpcodeBase) / pLnState->Hdr.u8LineRange;
3738 if (pLnState->Hdr.cMaxOpsPerInstr <= 1)
3739 pLnState->Regs.uAddress += (uint32_t)pLnState->Hdr.cbMinInstr * u8Adv;
3740 else
3741 {
3742 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u8Adv) / pLnState->Hdr.cMaxOpsPerInstr
3743 * pLnState->Hdr.cbMinInstr;
3744 pLnState->Regs.idxOp = (pLnState->Regs.idxOp + u8Adv) % pLnState->Hdr.cMaxOpsPerInstr;
3745 }
3746 Log2(("%08x: DW_LNS_const_add_pc\n", offOpCode));
3747 break;
3748 }
3749 case DW_LNS_fixed_advance_pc:
3750 pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0);
3751 pLnState->Regs.idxOp = 0;
3752 Log2(("%08x: DW_LNS_fixed_advance_pc\n", offOpCode));
3753 break;
3754
3755 case DW_LNS_set_prologue_end:
3756 pLnState->Regs.fPrologueEnd = true;
3757 Log2(("%08x: DW_LNS_set_prologue_end\n", offOpCode));
3758 break;
3759
3760 case DW_LNS_set_epilogue_begin:
3761 pLnState->Regs.fEpilogueBegin = true;
3762 Log2(("%08x: DW_LNS_set_epilogue_begin\n", offOpCode));
3763 break;
3764
3765 case DW_LNS_set_isa:
3766 pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3767 Log2(("%08x: DW_LNS_set_isa %#x\n", offOpCode, pLnState->Regs.uIsa));
3768 break;
3769
3770 default:
3771 {
3772 unsigned cOpsToSkip = pLnState->Hdr.pacStdOperands[bOpCode - 1];
3773 Log(("rtDwarfLine_RunProgram: Unknown standard opcode %#x, %#x operands, at %08x.\n", bOpCode, cOpsToSkip, offOpCode));
3774 while (cOpsToSkip-- > 0)
3775 rc = rtDwarfCursor_SkipLeb128(pCursor);
3776 break;
3777 }
3778
3779 /*
3780 * Extended opcode.
3781 */
3782 case DW_LNS_extended:
3783 {
3784 /* The instruction has a length prefix. */
3785 uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3786 if (RT_FAILURE(pCursor->rc))
3787 return pCursor->rc;
3788 if (cbInstr > pCursor->cbUnitLeft)
3789 return VERR_DWARF_BAD_LNE;
3790 uint8_t const * const pbEndOfInstr = rtDwarfCursor_CalcPos(pCursor, cbInstr);
3791
3792 /* Get the opcode and deal with it if we know it. */
3793 bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
3794 switch (bOpCode)
3795 {
3796 case DW_LNE_end_sequence:
3797#if 0 /* No need for this, I think. */
3798 pLnState->Regs.fEndSequence = true;
3799 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3800#endif
3801 rtDwarfLine_ResetState(pLnState);
3802 Log2(("%08x: DW_LNE_end_sequence\n", offOpCode));
3803 break;
3804
3805 case DW_LNE_set_address:
3806 pLnState->Regs.uAddress = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
3807 pLnState->Regs.idxOp = 0;
3808 Log2(("%08x: DW_LNE_set_address: %#llx\n", offOpCode, pLnState->Regs.uAddress));
3809 break;
3810
3811 case DW_LNE_define_file:
3812 {
3813 const char *pszFilename = rtDwarfCursor_GetSZ(pCursor, NULL);
3814 uint32_t idxInc = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
3815 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
3816 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
3817 Log2(("%08x: DW_LNE_define_file: {%d}/%s\n", offOpCode, idxInc, pszFilename));
3818
3819 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
3820 if (RT_SUCCESS(rc))
3821 rc = rtDwarfLine_DefineFileName(pLnState, pszFilename, idxInc);
3822 break;
3823 }
3824
3825 /*
3826 * Note! Was defined in DWARF 4. But... Watcom used it
3827 * for setting the segment in DWARF 2, creating
3828 * an incompatibility with the newer standard.
3829 */
3830 case DW_LNE_set_descriminator:
3831 if (pLnState->Hdr.uVer != 2)
3832 {
3833 Assert(pLnState->Hdr.uVer >= 4);
3834 pLnState->Regs.uDiscriminator = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
3835 Log2(("%08x: DW_LNE_set_descriminator: %u\n", offOpCode, pLnState->Regs.uDiscriminator));
3836 }
3837 else
3838 {
3839 uint64_t uSeg = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
3840 Log2(("%08x: DW_LNE_set_segment: %#llx, cbInstr=%#x - Watcom Extension\n", offOpCode, uSeg, cbInstr));
3841 pLnState->Regs.uSegment = (RTSEL)uSeg;
3842 AssertStmt(pLnState->Regs.uSegment == uSeg, rc = VERR_DWARF_BAD_INFO);
3843 }
3844 break;
3845
3846 default:
3847 Log(("rtDwarfLine_RunProgram: Unknown extended opcode %#x, length %#x at %08x\n", bOpCode, cbInstr, offOpCode));
3848 break;
3849 }
3850
3851 /* Advance the cursor to the end of the instruction . */
3852 rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
3853 break;
3854 }
3855 }
3856 }
3857
3858 /*
3859 * Check the status before looping.
3860 */
3861 if (RT_FAILURE(rc))
3862 return rc;
3863 if (RT_FAILURE(pCursor->rc))
3864 return pCursor->rc;
3865 }
3866 return rc;
3867}
3868
3869
3870/**
3871 * Reads the include directories for a line number unit.
3872 *
3873 * @returns IPRT status code
3874 * @param pLnState The line number program state.
3875 * @param pCursor The cursor.
3876 */
3877static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3878{
3879 int rc = rtDwarfLine_DefineFileName(pLnState, "/<bad-zero-file-name-entry>", 0);
3880 if (RT_FAILURE(rc))
3881 return rc;
3882
3883 for (;;)
3884 {
3885 const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL);
3886 if (!*psz)
3887 break;
3888
3889 uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3890 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
3891 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
3892
3893 rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc);
3894 if (RT_FAILURE(rc))
3895 return rc;
3896 }
3897 return pCursor->rc;
3898}
3899
3900
3901/**
3902 * Reads the include directories for a line number unit.
3903 *
3904 * @returns IPRT status code
3905 * @param pLnState The line number program state.
3906 * @param pCursor The cursor.
3907 */
3908static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3909{
3910 const char *psz = ""; /* The zeroth is the unit dir. */
3911 for (;;)
3912 {
3913 if ((pLnState->cIncPaths % 2) == 0)
3914 {
3915 void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2));
3916 if (!pv)
3917 return VERR_NO_MEMORY;
3918 pLnState->papszIncPaths = (const char **)pv;
3919 }
3920 Log((" Path #%02u = '%s'\n", pLnState->cIncPaths, psz));
3921 pLnState->papszIncPaths[pLnState->cIncPaths] = psz;
3922 pLnState->cIncPaths++;
3923
3924 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
3925 if (!*psz)
3926 break;
3927 }
3928
3929 return pCursor->rc;
3930}
3931
3932
3933/**
3934 * Explodes the line number table for a compilation unit.
3935 *
3936 * @returns IPRT status code
3937 * @param pThis The DWARF instance.
3938 * @param pCursor The cursor to read the line number information
3939 * via.
3940 */
3941static int rtDwarfLine_ExplodeUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
3942{
3943 RTDWARFLINESTATE LnState;
3944 RT_ZERO(LnState);
3945 LnState.pDwarfMod = pThis;
3946
3947 /*
3948 * Parse the header.
3949 */
3950 rtDwarfCursor_GetInitialLength(pCursor);
3951 LnState.Hdr.uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
3952 if ( LnState.Hdr.uVer < 2
3953 || LnState.Hdr.uVer > 4)
3954 return rtDwarfCursor_SkipUnit(pCursor);
3955
3956 LnState.Hdr.offFirstOpcode = rtDwarfCursor_GetUOff(pCursor, 0);
3957 uint8_t const * const pbFirstOpcode = rtDwarfCursor_CalcPos(pCursor, LnState.Hdr.offFirstOpcode);
3958
3959 LnState.Hdr.cbMinInstr = rtDwarfCursor_GetUByte(pCursor, 0);
3960 if (LnState.Hdr.uVer >= 4)
3961 LnState.Hdr.cMaxOpsPerInstr = rtDwarfCursor_GetUByte(pCursor, 0);
3962 else
3963 LnState.Hdr.cMaxOpsPerInstr = 1;
3964 LnState.Hdr.u8DefIsStmt = rtDwarfCursor_GetUByte(pCursor, 0);
3965 LnState.Hdr.s8LineBase = rtDwarfCursor_GetSByte(pCursor, 0);
3966 LnState.Hdr.u8LineRange = rtDwarfCursor_GetUByte(pCursor, 0);
3967 LnState.Hdr.u8OpcodeBase = rtDwarfCursor_GetUByte(pCursor, 0);
3968
3969 if ( !LnState.Hdr.u8OpcodeBase
3970 || !LnState.Hdr.cMaxOpsPerInstr
3971 || !LnState.Hdr.u8LineRange
3972 || LnState.Hdr.u8DefIsStmt > 1)
3973 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
3974 Log2(("DWARF Line number header:\n"
3975 " uVer %d\n"
3976 " offFirstOpcode %#llx\n"
3977 " cbMinInstr %u\n"
3978 " cMaxOpsPerInstr %u\n"
3979 " u8DefIsStmt %u\n"
3980 " s8LineBase %d\n"
3981 " u8LineRange %u\n"
3982 " u8OpcodeBase %u\n",
3983 LnState.Hdr.uVer, LnState.Hdr.offFirstOpcode, LnState.Hdr.cbMinInstr, LnState.Hdr.cMaxOpsPerInstr,
3984 LnState.Hdr.u8DefIsStmt, LnState.Hdr.s8LineBase, LnState.Hdr.u8LineRange, LnState.Hdr.u8OpcodeBase));
3985
3986 LnState.Hdr.pacStdOperands = pCursor->pb;
3987 for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.Hdr.u8OpcodeBase; iStdOpcode++)
3988 rtDwarfCursor_GetUByte(pCursor, 0);
3989
3990 int rc = pCursor->rc;
3991 if (RT_SUCCESS(rc))
3992 rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor);
3993 if (RT_SUCCESS(rc))
3994 rc = rtDwarfLine_ReadFileNames(&LnState, pCursor);
3995
3996 /*
3997 * Run the program....
3998 */
3999 if (RT_SUCCESS(rc))
4000 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbFirstOpcode);
4001 if (RT_SUCCESS(rc))
4002 rc = rtDwarfLine_RunProgram(&LnState, pCursor);
4003
4004 /*
4005 * Clean up.
4006 */
4007 size_t i = LnState.cFileNames;
4008 while (i-- > 0)
4009 RTStrFree(LnState.papszFileNames[i]);
4010 RTMemFree(LnState.papszFileNames);
4011 RTMemFree(LnState.papszIncPaths);
4012
4013 Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc));
4014 return rc;
4015}
4016
4017
4018/**
4019 * Explodes the line number table.
4020 *
4021 * The line numbers are insered into the debug info container.
4022 *
4023 * @returns IPRT status code
4024 * @param pThis The DWARF instance.
4025 */
4026static int rtDwarfLine_ExplodeAll(PRTDBGMODDWARF pThis)
4027{
4028 if (!pThis->aSections[krtDbgModDwarfSect_line].fPresent)
4029 return VINF_SUCCESS;
4030
4031 RTDWARFCURSOR Cursor;
4032 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line);
4033 if (RT_FAILURE(rc))
4034 return rc;
4035
4036 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
4037 && RT_SUCCESS(rc))
4038 rc = rtDwarfLine_ExplodeUnit(pThis, &Cursor);
4039
4040 return rtDwarfCursor_Delete(&Cursor, rc);
4041}
4042
4043
4044/*
4045 *
4046 * DWARF Abbreviations.
4047 * DWARF Abbreviations.
4048 * DWARF Abbreviations.
4049 *
4050 */
4051
4052/**
4053 * Deals with a cache miss in rtDwarfAbbrev_Lookup.
4054 *
4055 * @returns Pointer to abbreviation cache entry (read only). May be rendered
4056 * invalid by subsequent calls to this function.
4057 * @param pThis The DWARF instance.
4058 * @param uCode The abbreviation code to lookup.
4059 */
4060static PCRTDWARFABBREV rtDwarfAbbrev_LookupMiss(PRTDBGMODDWARF pThis, uint32_t uCode)
4061{
4062 /*
4063 * There is no entry with code zero.
4064 */
4065 if (!uCode)
4066 return NULL;
4067
4068 /*
4069 * Resize the cache array if the code is considered cachable.
4070 */
4071 bool fFillCache = true;
4072 if (pThis->cCachedAbbrevsAlloced < uCode)
4073 {
4074 if (uCode >= _64K)
4075 fFillCache = false;
4076 else
4077 {
4078 uint32_t cNew = RT_ALIGN(uCode, 64);
4079 void *pv = RTMemRealloc(pThis->paCachedAbbrevs, sizeof(pThis->paCachedAbbrevs[0]) * cNew);
4080 if (!pv)
4081 fFillCache = false;
4082 else
4083 {
4084 Log(("rtDwarfAbbrev_LookupMiss: Growing from %u to %u...\n", pThis->cCachedAbbrevsAlloced, cNew));
4085 pThis->paCachedAbbrevs = (PRTDWARFABBREV)pv;
4086 for (uint32_t i = pThis->cCachedAbbrevsAlloced; i < cNew; i++)
4087 pThis->paCachedAbbrevs[i].offAbbrev = UINT32_MAX;
4088 pThis->cCachedAbbrevsAlloced = cNew;
4089 }
4090 }
4091 }
4092
4093 /*
4094 * Walk the abbreviations till we find the desired code.
4095 */
4096 RTDWARFCURSOR Cursor;
4097 int rc = rtDwarfCursor_InitWithOffset(&Cursor, pThis, krtDbgModDwarfSect_abbrev, pThis->offCachedAbbrev);
4098 if (RT_FAILURE(rc))
4099 return NULL;
4100
4101 PRTDWARFABBREV pRet = NULL;
4102 if (fFillCache)
4103 {
4104 /*
4105 * Search for the entry and fill the cache while doing so.
4106 * We assume that abbreviation codes for a unit will stop when we see
4107 * zero code or when the code value drops.
4108 */
4109 uint32_t uPrevCode = 0;
4110 for (;;)
4111 {
4112 /* Read the 'header'. Skipping zero code bytes. */
4113#ifdef LOG_ENABLED
4114 uint32_t const offStart = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4115#endif
4116 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4117 if (pRet && (uCurCode == 0 || uCurCode < uPrevCode))
4118 break; /* probably end of unit. */
4119 if (uCurCode != 0)
4120 {
4121 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4122 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
4123 if (RT_FAILURE(Cursor.rc))
4124 break;
4125 if ( uCurTag > 0xffff
4126 || uChildren > 1)
4127 {
4128 Cursor.rc = VERR_DWARF_BAD_ABBREV;
4129 break;
4130 }
4131
4132 /* Cache it? */
4133 if (uCurCode <= pThis->cCachedAbbrevsAlloced)
4134 {
4135 PRTDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
4136 if (pEntry->offAbbrev != pThis->offCachedAbbrev)
4137 {
4138 pEntry->offAbbrev = pThis->offCachedAbbrev;
4139 pEntry->fChildren = RT_BOOL(uChildren);
4140 pEntry->uTag = uCurTag;
4141 pEntry->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4142#ifdef LOG_ENABLED
4143 pEntry->cbHdr = (uint8_t)(pEntry->offSpec - offStart);
4144 Log7(("rtDwarfAbbrev_LookupMiss(%#x): fill: %#x: uTag=%#x offAbbrev=%#x%s\n",
4145 uCode, offStart, pEntry->uTag, pEntry->offAbbrev, pEntry->fChildren ? " has-children" : ""));
4146#endif
4147 if (uCurCode == uCode)
4148 {
4149 Assert(!pRet);
4150 pRet = pEntry;
4151 if (uCurCode == pThis->cCachedAbbrevsAlloced)
4152 break;
4153 }
4154 }
4155 else if (pRet)
4156 break; /* Next unit, don't cache more. */
4157 /* else: We're growing the cache and re-reading old data. */
4158 }
4159
4160 /* Skip the specification. */
4161 uint32_t uAttr, uForm;
4162 do
4163 {
4164 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4165 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4166 } while (uAttr != 0);
4167 }
4168 if (RT_FAILURE(Cursor.rc))
4169 break;
4170
4171 /* Done? (Maximize cache filling.) */
4172 if ( pRet != NULL
4173 && uCurCode >= pThis->cCachedAbbrevsAlloced)
4174 break;
4175 uPrevCode = uCurCode;
4176 }
4177 if (pRet)
4178 Log6(("rtDwarfAbbrev_LookupMiss(%#x): uTag=%#x offSpec=%#x offAbbrev=%#x [fill]\n",
4179 uCode, pRet->uTag, pRet->offSpec, pRet->offAbbrev));
4180 else
4181 Log6(("rtDwarfAbbrev_LookupMiss(%#x): failed [fill]\n", uCode));
4182 }
4183 else
4184 {
4185 /*
4186 * Search for the entry with the desired code, no cache filling.
4187 */
4188 for (;;)
4189 {
4190 /* Read the 'header'. */
4191#ifdef LOG_ENABLED
4192 uint32_t const offStart = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4193#endif
4194 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4195 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4196 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
4197 if (RT_FAILURE(Cursor.rc))
4198 break;
4199 if ( uCurTag > 0xffff
4200 || uChildren > 1)
4201 {
4202 Cursor.rc = VERR_DWARF_BAD_ABBREV;
4203 break;
4204 }
4205
4206 /* Do we have a match? */
4207 if (uCurCode == uCode)
4208 {
4209 pRet = &pThis->LookupAbbrev;
4210 pRet->fChildren = RT_BOOL(uChildren);
4211 pRet->uTag = uCurTag;
4212 pRet->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4213 pRet->offAbbrev = pThis->offCachedAbbrev;
4214#ifdef LOG_ENABLED
4215 pRet->cbHdr = (uint8_t)(pRet->offSpec - offStart);
4216#endif
4217 break;
4218 }
4219
4220 /* Skip the specification. */
4221 uint32_t uAttr, uForm;
4222 do
4223 {
4224 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4225 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4226 } while (uAttr != 0);
4227 if (RT_FAILURE(Cursor.rc))
4228 break;
4229 }
4230 if (pRet)
4231 Log6(("rtDwarfAbbrev_LookupMiss(%#x): uTag=%#x offSpec=%#x offAbbrev=%#x [no-fill]\n",
4232 uCode, pRet->uTag, pRet->offSpec, pRet->offAbbrev));
4233 else
4234 Log6(("rtDwarfAbbrev_LookupMiss(%#x): failed [no-fill]\n", uCode));
4235 }
4236
4237 rtDwarfCursor_Delete(&Cursor, VINF_SUCCESS);
4238 return pRet;
4239}
4240
4241
4242/**
4243 * Looks up an abbreviation.
4244 *
4245 * @returns Pointer to abbreviation cache entry (read only). May be rendered
4246 * invalid by subsequent calls to this function.
4247 * @param pThis The DWARF instance.
4248 * @param uCode The abbreviation code to lookup.
4249 */
4250static PCRTDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
4251{
4252 uCode -= 1;
4253 if (uCode < pThis->cCachedAbbrevsAlloced)
4254 {
4255 if (pThis->paCachedAbbrevs[uCode].offAbbrev == pThis->offCachedAbbrev)
4256 return &pThis->paCachedAbbrevs[uCode];
4257 }
4258 return rtDwarfAbbrev_LookupMiss(pThis, uCode + 1);
4259}
4260
4261
4262/**
4263 * Sets the abbreviation offset of the current unit.
4264 *
4265 * @param pThis The DWARF instance.
4266 * @param offAbbrev The offset into the abbreviation section.
4267 */
4268static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
4269{
4270 pThis->offCachedAbbrev = offAbbrev;
4271}
4272
4273
4274
4275/*
4276 *
4277 * DIE Attribute Parsers.
4278 * DIE Attribute Parsers.
4279 * DIE Attribute Parsers.
4280 *
4281 */
4282
4283/**
4284 * Gets the compilation unit a DIE belongs to.
4285 *
4286 * @returns The compilation unit DIE.
4287 * @param pDie Some DIE in the unit.
4288 */
4289static PRTDWARFDIECOMPILEUNIT rtDwarfDie_GetCompileUnit(PRTDWARFDIE pDie)
4290{
4291 while (pDie->pParent)
4292 pDie = pDie->pParent;
4293 AssertReturn( pDie->uTag == DW_TAG_compile_unit
4294 || pDie->uTag == DW_TAG_partial_unit,
4295 NULL);
4296 return (PRTDWARFDIECOMPILEUNIT)pDie;
4297}
4298
4299
4300/**
4301 * Resolves a string section (debug_str) reference.
4302 *
4303 * @returns Pointer to the string (inside the string section).
4304 * @param pThis The DWARF instance.
4305 * @param pCursor The cursor.
4306 * @param pszErrValue What to return on failure (@a
4307 * pCursor->rc is set).
4308 */
4309static const char *rtDwarfDecodeHlp_GetStrp(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, const char *pszErrValue)
4310{
4311 uint64_t offDebugStr = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
4312 if (RT_FAILURE(pCursor->rc))
4313 return pszErrValue;
4314
4315 if (offDebugStr >= pThis->aSections[krtDbgModDwarfSect_str].cb)
4316 {
4317 /* Ugly: Exploit the cursor status field for reporting errors. */
4318 pCursor->rc = VERR_DWARF_BAD_INFO;
4319 return pszErrValue;
4320 }
4321
4322 if (!pThis->aSections[krtDbgModDwarfSect_str].pv)
4323 {
4324 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_str);
4325 if (RT_FAILURE(rc))
4326 {
4327 /* Ugly: Exploit the cursor status field for reporting errors. */
4328 pCursor->rc = rc;
4329 return pszErrValue;
4330 }
4331 }
4332
4333 return (const char *)pThis->aSections[krtDbgModDwarfSect_str].pv + (size_t)offDebugStr;
4334}
4335
4336
4337/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4338static DECLCALLBACK(int) rtDwarfDecode_Address(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4339 uint32_t uForm, PRTDWARFCURSOR pCursor)
4340{
4341 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDR), VERR_INTERNAL_ERROR_3);
4342 NOREF(pDie);
4343
4344 uint64_t uAddr;
4345 switch (uForm)
4346 {
4347 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4348 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
4349 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
4350 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
4351 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
4352 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4353 default:
4354 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
4355 }
4356 if (RT_FAILURE(pCursor->rc))
4357 return pCursor->rc;
4358
4359 PRTDWARFADDR pAddr = (PRTDWARFADDR)pbMember;
4360 pAddr->uAddress = uAddr;
4361
4362 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
4363 return VINF_SUCCESS;
4364}
4365
4366
4367/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4368static DECLCALLBACK(int) rtDwarfDecode_Bool(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4369 uint32_t uForm, PRTDWARFCURSOR pCursor)
4370{
4371 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(bool), VERR_INTERNAL_ERROR_3);
4372 NOREF(pDie);
4373
4374 bool *pfMember = (bool *)pbMember;
4375 switch (uForm)
4376 {
4377 case DW_FORM_flag:
4378 {
4379 uint8_t b = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
4380 if (b > 1)
4381 {
4382 Log(("Unexpected boolean value %#x\n", b));
4383 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pCursor->rc = VERR_DWARF_BAD_INFO;
4384 }
4385 *pfMember = RT_BOOL(b);
4386 break;
4387 }
4388
4389 case DW_FORM_flag_present:
4390 *pfMember = true;
4391 break;
4392
4393 default:
4394 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4395 }
4396
4397 Log4((" %-20s %RTbool [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), *pfMember, rtDwarfLog_FormName(uForm)));
4398 return VINF_SUCCESS;
4399}
4400
4401
4402/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4403static DECLCALLBACK(int) rtDwarfDecode_LowHighPc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4404 uint32_t uForm, PRTDWARFCURSOR pCursor)
4405{
4406 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
4407 AssertReturn(pDesc->uAttr == DW_AT_low_pc || pDesc->uAttr == DW_AT_high_pc, VERR_INTERNAL_ERROR_3);
4408 NOREF(pDie);
4409
4410 uint64_t uAddr;
4411 switch (uForm)
4412 {
4413 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4414 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
4415 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
4416 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
4417 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
4418 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4419 default:
4420 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4421 }
4422 if (RT_FAILURE(pCursor->rc))
4423 return pCursor->rc;
4424
4425 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
4426 if (pDesc->uAttr == DW_AT_low_pc)
4427 {
4428 if (pRange->fHaveLowAddress)
4429 {
4430 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_low_pc\n"));
4431 return pCursor->rc = VERR_DWARF_BAD_INFO;
4432 }
4433 pRange->fHaveLowAddress = true;
4434 pRange->uLowAddress = uAddr;
4435 }
4436 else
4437 {
4438 if (pRange->fHaveHighAddress)
4439 {
4440 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_high_pc\n"));
4441 return pCursor->rc = VERR_DWARF_BAD_INFO;
4442 }
4443 pRange->fHaveHighAddress = true;
4444 pRange->fHaveHighIsAddress = uForm == DW_FORM_addr;
4445 if (!pRange->fHaveHighIsAddress && pRange->fHaveLowAddress)
4446 {
4447 pRange->fHaveHighIsAddress = true;
4448 pRange->uHighAddress = uAddr + pRange->uLowAddress;
4449 }
4450 else
4451 pRange->uHighAddress = uAddr;
4452
4453 }
4454 pRange->cAttrs++;
4455
4456 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
4457 return VINF_SUCCESS;
4458}
4459
4460
4461/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4462static DECLCALLBACK(int) rtDwarfDecode_Ranges(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4463 uint32_t uForm, PRTDWARFCURSOR pCursor)
4464{
4465 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
4466 AssertReturn(pDesc->uAttr == DW_AT_ranges, VERR_INTERNAL_ERROR_3);
4467 NOREF(pDie);
4468
4469 /* Decode it. */
4470 uint64_t off;
4471 switch (uForm)
4472 {
4473 case DW_FORM_addr: off = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4474 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4475 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4476 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
4477 default:
4478 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4479 }
4480 if (RT_FAILURE(pCursor->rc))
4481 return pCursor->rc;
4482
4483 /* Validate the offset and load the ranges. */
4484 PRTDBGMODDWARF pThis = pCursor->pDwarfMod;
4485 if (off >= pThis->aSections[krtDbgModDwarfSect_ranges].cb)
4486 {
4487 Log(("rtDwarfDecode_Ranges: bad ranges off=%#llx\n", off));
4488 return pCursor->rc = VERR_DWARF_BAD_POS;
4489 }
4490
4491 if (!pThis->aSections[krtDbgModDwarfSect_ranges].pv)
4492 {
4493 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_ranges);
4494 if (RT_FAILURE(rc))
4495 return pCursor->rc = rc;
4496 }
4497
4498 /* Store the result. */
4499 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
4500 if (pRange->fHaveRanges)
4501 {
4502 Log(("rtDwarfDecode_Ranges: Duplicate DW_AT_ranges\n"));
4503 return pCursor->rc = VERR_DWARF_BAD_INFO;
4504 }
4505 pRange->fHaveRanges = true;
4506 pRange->cAttrs++;
4507 pRange->pbRanges = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_ranges].pv + (size_t)off;
4508
4509 Log4((" %-20s TODO [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), rtDwarfLog_FormName(uForm)));
4510 return VINF_SUCCESS;
4511}
4512
4513
4514/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4515static DECLCALLBACK(int) rtDwarfDecode_Reference(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4516 uint32_t uForm, PRTDWARFCURSOR pCursor)
4517{
4518 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
4519
4520 /* Decode it. */
4521 uint64_t off;
4522 krtDwarfRef enmWrt = krtDwarfRef_SameUnit;
4523 switch (uForm)
4524 {
4525 case DW_FORM_ref1: off = rtDwarfCursor_GetU8(pCursor, 0); break;
4526 case DW_FORM_ref2: off = rtDwarfCursor_GetU16(pCursor, 0); break;
4527 case DW_FORM_ref4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4528 case DW_FORM_ref8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4529 case DW_FORM_ref_udata: off = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4530
4531 case DW_FORM_ref_addr:
4532 enmWrt = krtDwarfRef_InfoSection;
4533 off = rtDwarfCursor_GetUOff(pCursor, 0);
4534 break;
4535
4536 case DW_FORM_ref_sig8:
4537 enmWrt = krtDwarfRef_TypeId64;
4538 off = rtDwarfCursor_GetU64(pCursor, 0);
4539 break;
4540
4541 default:
4542 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4543 }
4544 if (RT_FAILURE(pCursor->rc))
4545 return pCursor->rc;
4546
4547 /* Validate the offset and convert to debug_info relative offsets. */
4548 if (enmWrt == krtDwarfRef_InfoSection)
4549 {
4550 if (off >= pCursor->pDwarfMod->aSections[krtDbgModDwarfSect_info].cb)
4551 {
4552 Log(("rtDwarfDecode_Reference: bad info off=%#llx\n", off));
4553 return pCursor->rc = VERR_DWARF_BAD_POS;
4554 }
4555 }
4556 else if (enmWrt == krtDwarfRef_SameUnit)
4557 {
4558 PRTDWARFDIECOMPILEUNIT pUnit = rtDwarfDie_GetCompileUnit(pDie);
4559 if (off >= pUnit->cbUnit)
4560 {
4561 Log(("rtDwarfDecode_Reference: bad unit off=%#llx\n", off));
4562 return pCursor->rc = VERR_DWARF_BAD_POS;
4563 }
4564 off += pUnit->offUnit;
4565 enmWrt = krtDwarfRef_InfoSection;
4566 }
4567 /* else: not bother verifying/resolving the indirect type reference yet. */
4568
4569 /* Store it */
4570 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
4571 pRef->enmWrt = enmWrt;
4572 pRef->off = off;
4573
4574 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
4575 return VINF_SUCCESS;
4576}
4577
4578
4579/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4580static DECLCALLBACK(int) rtDwarfDecode_SectOff(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4581 uint32_t uForm, PRTDWARFCURSOR pCursor)
4582{
4583 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
4584 NOREF(pDie);
4585
4586 uint64_t off;
4587 switch (uForm)
4588 {
4589 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4590 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4591 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
4592 default:
4593 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
4594 }
4595 if (RT_FAILURE(pCursor->rc))
4596 return pCursor->rc;
4597
4598 krtDbgModDwarfSect enmSect;
4599 krtDwarfRef enmWrt;
4600 switch (pDesc->uAttr)
4601 {
4602 case DW_AT_stmt_list: enmSect = krtDbgModDwarfSect_line; enmWrt = krtDwarfRef_LineSection; break;
4603 case DW_AT_macro_info: enmSect = krtDbgModDwarfSect_loc; enmWrt = krtDwarfRef_LocSection; break;
4604 case DW_AT_ranges: enmSect = krtDbgModDwarfSect_ranges; enmWrt = krtDwarfRef_RangesSection; break;
4605 default:
4606 AssertMsgFailedReturn(("%u (%s)\n", pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr)), VERR_INTERNAL_ERROR_4);
4607 }
4608 size_t cbSect = pCursor->pDwarfMod->aSections[enmSect].cb;
4609 if (off >= cbSect)
4610 {
4611 /* Watcom generates offset past the end of the section, increasing the
4612 offset by one for each compile unit. So, just fudge it. */
4613 Log(("rtDwarfDecode_SectOff: bad off=%#llx, attr %#x (%s), enmSect=%d cb=%#llx; Assuming watcom/gcc.\n", off,
4614 pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr), enmSect, cbSect));
4615 off = cbSect;
4616 }
4617
4618 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
4619 pRef->enmWrt = enmWrt;
4620 pRef->off = off;
4621
4622 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
4623 return VINF_SUCCESS;
4624}
4625
4626
4627/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4628static DECLCALLBACK(int) rtDwarfDecode_String(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4629 uint32_t uForm, PRTDWARFCURSOR pCursor)
4630{
4631 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(const char *), VERR_INTERNAL_ERROR_3);
4632 NOREF(pDie);
4633
4634 const char *psz;
4635 switch (uForm)
4636 {
4637 case DW_FORM_string:
4638 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
4639 break;
4640
4641 case DW_FORM_strp:
4642 psz = rtDwarfDecodeHlp_GetStrp(pCursor->pDwarfMod, pCursor, NULL);
4643 break;
4644
4645 default:
4646 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4647 }
4648
4649 *(const char **)pbMember = psz;
4650 Log4((" %-20s '%s' [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), psz, rtDwarfLog_FormName(uForm)));
4651 return pCursor->rc;
4652}
4653
4654
4655/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4656static DECLCALLBACK(int) rtDwarfDecode_UnsignedInt(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4657 uint32_t uForm, PRTDWARFCURSOR pCursor)
4658{
4659 NOREF(pDie);
4660 uint64_t u64Val;
4661 switch (uForm)
4662 {
4663 case DW_FORM_udata: u64Val = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4664 case DW_FORM_data1: u64Val = rtDwarfCursor_GetU8(pCursor, 0); break;
4665 case DW_FORM_data2: u64Val = rtDwarfCursor_GetU16(pCursor, 0); break;
4666 case DW_FORM_data4: u64Val = rtDwarfCursor_GetU32(pCursor, 0); break;
4667 case DW_FORM_data8: u64Val = rtDwarfCursor_GetU64(pCursor, 0); break;
4668 default:
4669 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4670 }
4671 if (RT_FAILURE(pCursor->rc))
4672 return pCursor->rc;
4673
4674 switch (ATTR_GET_SIZE(pDesc))
4675 {
4676 case 1:
4677 *pbMember = (uint8_t)u64Val;
4678 if (*pbMember != u64Val)
4679 {
4680 AssertFailed();
4681 return VERR_OUT_OF_RANGE;
4682 }
4683 break;
4684
4685 case 2:
4686 *(uint16_t *)pbMember = (uint16_t)u64Val;
4687 if (*(uint16_t *)pbMember != u64Val)
4688 {
4689 AssertFailed();
4690 return VERR_OUT_OF_RANGE;
4691 }
4692 break;
4693
4694 case 4:
4695 *(uint32_t *)pbMember = (uint32_t)u64Val;
4696 if (*(uint32_t *)pbMember != u64Val)
4697 {
4698 AssertFailed();
4699 return VERR_OUT_OF_RANGE;
4700 }
4701 break;
4702
4703 case 8:
4704 *(uint64_t *)pbMember = (uint64_t)u64Val;
4705 if (*(uint64_t *)pbMember != u64Val)
4706 {
4707 AssertFailed();
4708 return VERR_OUT_OF_RANGE;
4709 }
4710 break;
4711
4712 default:
4713 AssertMsgFailedReturn(("%#x\n", ATTR_GET_SIZE(pDesc)), VERR_INTERNAL_ERROR_2);
4714 }
4715 return VINF_SUCCESS;
4716}
4717
4718
4719/**
4720 * Initialize location interpreter state from cursor & form.
4721 *
4722 * @returns IPRT status code.
4723 * @retval VERR_NOT_FOUND if no location information (i.e. there is source but
4724 * it resulted in no byte code).
4725 * @param pLoc The location state structure to initialize.
4726 * @param pCursor The cursor to read from.
4727 * @param uForm The attribute form.
4728 */
4729static int rtDwarfLoc_Init(PRTDWARFLOCST pLoc, PRTDWARFCURSOR pCursor, uint32_t uForm)
4730{
4731 uint32_t cbBlock;
4732 switch (uForm)
4733 {
4734 case DW_FORM_block1:
4735 cbBlock = rtDwarfCursor_GetU8(pCursor, 0);
4736 break;
4737
4738 case DW_FORM_block2:
4739 cbBlock = rtDwarfCursor_GetU16(pCursor, 0);
4740 break;
4741
4742 case DW_FORM_block4:
4743 cbBlock = rtDwarfCursor_GetU32(pCursor, 0);
4744 break;
4745
4746 case DW_FORM_block:
4747 cbBlock = rtDwarfCursor_GetULeb128(pCursor, 0);
4748 break;
4749
4750 default:
4751 AssertMsgFailedReturn(("uForm=%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4752 }
4753 if (!cbBlock)
4754 return VERR_NOT_FOUND;
4755
4756 int rc = rtDwarfCursor_InitForBlock(&pLoc->Cursor, pCursor, cbBlock);
4757 if (RT_FAILURE(rc))
4758 return rc;
4759 pLoc->iTop = -1;
4760 return VINF_SUCCESS;
4761}
4762
4763
4764/**
4765 * Pushes a value onto the stack.
4766 *
4767 * @returns VINF_SUCCESS or VERR_DWARF_STACK_OVERFLOW.
4768 * @param pLoc The state.
4769 * @param uValue The value to push.
4770 */
4771static int rtDwarfLoc_Push(PRTDWARFLOCST pLoc, uint64_t uValue)
4772{
4773 int iTop = pLoc->iTop + 1;
4774 AssertReturn((unsigned)iTop < RT_ELEMENTS(pLoc->auStack), VERR_DWARF_STACK_OVERFLOW);
4775 pLoc->auStack[iTop] = uValue;
4776 pLoc->iTop = iTop;
4777 return VINF_SUCCESS;
4778}
4779
4780
4781static int rtDwarfLoc_Evaluate(PRTDWARFLOCST pLoc, void *pvLater, void *pvUser)
4782{
4783 RT_NOREF_PV(pvLater); RT_NOREF_PV(pvUser);
4784
4785 while (!rtDwarfCursor_IsAtEndOfUnit(&pLoc->Cursor))
4786 {
4787 /* Read the next opcode.*/
4788 uint8_t const bOpcode = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4789
4790 /* Get its operands. */
4791 uint64_t uOperand1 = 0;
4792 uint64_t uOperand2 = 0;
4793 switch (bOpcode)
4794 {
4795 case DW_OP_addr:
4796 uOperand1 = rtDwarfCursor_GetNativeUOff(&pLoc->Cursor, 0);
4797 break;
4798 case DW_OP_pick:
4799 case DW_OP_const1u:
4800 case DW_OP_deref_size:
4801 case DW_OP_xderef_size:
4802 uOperand1 = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4803 break;
4804 case DW_OP_const1s:
4805 uOperand1 = (int8_t)rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4806 break;
4807 case DW_OP_const2u:
4808 uOperand1 = rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
4809 break;
4810 case DW_OP_skip:
4811 case DW_OP_bra:
4812 case DW_OP_const2s:
4813 uOperand1 = (int16_t)rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
4814 break;
4815 case DW_OP_const4u:
4816 uOperand1 = rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
4817 break;
4818 case DW_OP_const4s:
4819 uOperand1 = (int32_t)rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
4820 break;
4821 case DW_OP_const8u:
4822 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
4823 break;
4824 case DW_OP_const8s:
4825 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
4826 break;
4827 case DW_OP_regx:
4828 case DW_OP_piece:
4829 case DW_OP_plus_uconst:
4830 case DW_OP_constu:
4831 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
4832 break;
4833 case DW_OP_consts:
4834 case DW_OP_fbreg:
4835 case DW_OP_breg0+0: case DW_OP_breg0+1: case DW_OP_breg0+2: case DW_OP_breg0+3:
4836 case DW_OP_breg0+4: case DW_OP_breg0+5: case DW_OP_breg0+6: case DW_OP_breg0+7:
4837 case DW_OP_breg0+8: case DW_OP_breg0+9: case DW_OP_breg0+10: case DW_OP_breg0+11:
4838 case DW_OP_breg0+12: case DW_OP_breg0+13: case DW_OP_breg0+14: case DW_OP_breg0+15:
4839 case DW_OP_breg0+16: case DW_OP_breg0+17: case DW_OP_breg0+18: case DW_OP_breg0+19:
4840 case DW_OP_breg0+20: case DW_OP_breg0+21: case DW_OP_breg0+22: case DW_OP_breg0+23:
4841 case DW_OP_breg0+24: case DW_OP_breg0+25: case DW_OP_breg0+26: case DW_OP_breg0+27:
4842 case DW_OP_breg0+28: case DW_OP_breg0+29: case DW_OP_breg0+30: case DW_OP_breg0+31:
4843 uOperand1 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
4844 break;
4845 case DW_OP_bregx:
4846 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
4847 uOperand2 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
4848 break;
4849 }
4850 if (RT_FAILURE(pLoc->Cursor.rc))
4851 break;
4852
4853 /* Interpret the opcode. */
4854 int rc;
4855 switch (bOpcode)
4856 {
4857 case DW_OP_const1u:
4858 case DW_OP_const1s:
4859 case DW_OP_const2u:
4860 case DW_OP_const2s:
4861 case DW_OP_const4u:
4862 case DW_OP_const4s:
4863 case DW_OP_const8u:
4864 case DW_OP_const8s:
4865 case DW_OP_constu:
4866 case DW_OP_consts:
4867 case DW_OP_addr:
4868 rc = rtDwarfLoc_Push(pLoc, uOperand1);
4869 break;
4870 case DW_OP_lit0 + 0: case DW_OP_lit0 + 1: case DW_OP_lit0 + 2: case DW_OP_lit0 + 3:
4871 case DW_OP_lit0 + 4: case DW_OP_lit0 + 5: case DW_OP_lit0 + 6: case DW_OP_lit0 + 7:
4872 case DW_OP_lit0 + 8: case DW_OP_lit0 + 9: case DW_OP_lit0 + 10: case DW_OP_lit0 + 11:
4873 case DW_OP_lit0 + 12: case DW_OP_lit0 + 13: case DW_OP_lit0 + 14: case DW_OP_lit0 + 15:
4874 case DW_OP_lit0 + 16: case DW_OP_lit0 + 17: case DW_OP_lit0 + 18: case DW_OP_lit0 + 19:
4875 case DW_OP_lit0 + 20: case DW_OP_lit0 + 21: case DW_OP_lit0 + 22: case DW_OP_lit0 + 23:
4876 case DW_OP_lit0 + 24: case DW_OP_lit0 + 25: case DW_OP_lit0 + 26: case DW_OP_lit0 + 27:
4877 case DW_OP_lit0 + 28: case DW_OP_lit0 + 29: case DW_OP_lit0 + 30: case DW_OP_lit0 + 31:
4878 rc = rtDwarfLoc_Push(pLoc, bOpcode - DW_OP_lit0);
4879 break;
4880 case DW_OP_nop:
4881 break;
4882 case DW_OP_dup: /** @todo 0 operands. */
4883 case DW_OP_drop: /** @todo 0 operands. */
4884 case DW_OP_over: /** @todo 0 operands. */
4885 case DW_OP_pick: /** @todo 1 operands, a 1-byte stack index. */
4886 case DW_OP_swap: /** @todo 0 operands. */
4887 case DW_OP_rot: /** @todo 0 operands. */
4888 case DW_OP_abs: /** @todo 0 operands. */
4889 case DW_OP_and: /** @todo 0 operands. */
4890 case DW_OP_div: /** @todo 0 operands. */
4891 case DW_OP_minus: /** @todo 0 operands. */
4892 case DW_OP_mod: /** @todo 0 operands. */
4893 case DW_OP_mul: /** @todo 0 operands. */
4894 case DW_OP_neg: /** @todo 0 operands. */
4895 case DW_OP_not: /** @todo 0 operands. */
4896 case DW_OP_or: /** @todo 0 operands. */
4897 case DW_OP_plus: /** @todo 0 operands. */
4898 case DW_OP_plus_uconst: /** @todo 1 operands, a ULEB128 addend. */
4899 case DW_OP_shl: /** @todo 0 operands. */
4900 case DW_OP_shr: /** @todo 0 operands. */
4901 case DW_OP_shra: /** @todo 0 operands. */
4902 case DW_OP_xor: /** @todo 0 operands. */
4903 case DW_OP_skip: /** @todo 1 signed 2-byte constant. */
4904 case DW_OP_bra: /** @todo 1 signed 2-byte constant. */
4905 case DW_OP_eq: /** @todo 0 operands. */
4906 case DW_OP_ge: /** @todo 0 operands. */
4907 case DW_OP_gt: /** @todo 0 operands. */
4908 case DW_OP_le: /** @todo 0 operands. */
4909 case DW_OP_lt: /** @todo 0 operands. */
4910 case DW_OP_ne: /** @todo 0 operands. */
4911 case DW_OP_reg0 + 0: case DW_OP_reg0 + 1: case DW_OP_reg0 + 2: case DW_OP_reg0 + 3: /** @todo 0 operands - reg 0..31. */
4912 case DW_OP_reg0 + 4: case DW_OP_reg0 + 5: case DW_OP_reg0 + 6: case DW_OP_reg0 + 7:
4913 case DW_OP_reg0 + 8: case DW_OP_reg0 + 9: case DW_OP_reg0 + 10: case DW_OP_reg0 + 11:
4914 case DW_OP_reg0 + 12: case DW_OP_reg0 + 13: case DW_OP_reg0 + 14: case DW_OP_reg0 + 15:
4915 case DW_OP_reg0 + 16: case DW_OP_reg0 + 17: case DW_OP_reg0 + 18: case DW_OP_reg0 + 19:
4916 case DW_OP_reg0 + 20: case DW_OP_reg0 + 21: case DW_OP_reg0 + 22: case DW_OP_reg0 + 23:
4917 case DW_OP_reg0 + 24: case DW_OP_reg0 + 25: case DW_OP_reg0 + 26: case DW_OP_reg0 + 27:
4918 case DW_OP_reg0 + 28: case DW_OP_reg0 + 29: case DW_OP_reg0 + 30: case DW_OP_reg0 + 31:
4919 case DW_OP_breg0+ 0: case DW_OP_breg0+ 1: case DW_OP_breg0+ 2: case DW_OP_breg0+ 3: /** @todo 1 operand, a SLEB128 offset. */
4920 case DW_OP_breg0+ 4: case DW_OP_breg0+ 5: case DW_OP_breg0+ 6: case DW_OP_breg0+ 7:
4921 case DW_OP_breg0+ 8: case DW_OP_breg0+ 9: case DW_OP_breg0+ 10: case DW_OP_breg0+ 11:
4922 case DW_OP_breg0+ 12: case DW_OP_breg0+ 13: case DW_OP_breg0+ 14: case DW_OP_breg0+ 15:
4923 case DW_OP_breg0+ 16: case DW_OP_breg0+ 17: case DW_OP_breg0+ 18: case DW_OP_breg0+ 19:
4924 case DW_OP_breg0+ 20: case DW_OP_breg0+ 21: case DW_OP_breg0+ 22: case DW_OP_breg0+ 23:
4925 case DW_OP_breg0+ 24: case DW_OP_breg0+ 25: case DW_OP_breg0+ 26: case DW_OP_breg0+ 27:
4926 case DW_OP_breg0+ 28: case DW_OP_breg0+ 29: case DW_OP_breg0+ 30: case DW_OP_breg0+ 31:
4927 case DW_OP_piece: /** @todo 1 operand, a ULEB128 size of piece addressed. */
4928 case DW_OP_regx: /** @todo 1 operand, a ULEB128 register. */
4929 case DW_OP_fbreg: /** @todo 1 operand, a SLEB128 offset. */
4930 case DW_OP_bregx: /** @todo 2 operands, a ULEB128 register followed by a SLEB128 offset. */
4931 case DW_OP_deref: /** @todo 0 operands. */
4932 case DW_OP_deref_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
4933 case DW_OP_xderef: /** @todo 0 operands. */
4934 case DW_OP_xderef_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
4935 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_TODO);
4936 default:
4937 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_UNKNOWN_LOC_OPCODE);
4938 }
4939 }
4940
4941 return pLoc->Cursor.rc;
4942}
4943
4944
4945/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4946static DECLCALLBACK(int) rtDwarfDecode_SegmentLoc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4947 uint32_t uForm, PRTDWARFCURSOR pCursor)
4948{
4949 NOREF(pDie);
4950 AssertReturn(ATTR_GET_SIZE(pDesc) == 2, VERR_DWARF_IPE);
4951
4952 int rc;
4953 if ( uForm == DW_FORM_block
4954 || uForm == DW_FORM_block1
4955 || uForm == DW_FORM_block2
4956 || uForm == DW_FORM_block4)
4957 {
4958 RTDWARFLOCST LocSt;
4959 rc = rtDwarfLoc_Init(&LocSt, pCursor, uForm);
4960 if (RT_SUCCESS(rc))
4961 {
4962 rc = rtDwarfLoc_Evaluate(&LocSt, NULL, NULL);
4963 if (RT_SUCCESS(rc))
4964 {
4965 if (LocSt.iTop >= 0)
4966 {
4967 *(uint16_t *)pbMember = LocSt.auStack[LocSt.iTop];
4968 Log4((" %-20s %#06llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr),
4969 LocSt.auStack[LocSt.iTop], rtDwarfLog_FormName(uForm)));
4970 return VINF_SUCCESS;
4971 }
4972 rc = VERR_DWARF_STACK_UNDERFLOW;
4973 }
4974 }
4975 }
4976 else
4977 rc = rtDwarfDecode_UnsignedInt(pDie, pbMember, pDesc, uForm, pCursor);
4978 return rc;
4979}
4980
4981/*
4982 *
4983 * DWARF debug_info parser
4984 * DWARF debug_info parser
4985 * DWARF debug_info parser
4986 *
4987 */
4988
4989
4990/**
4991 * Special hack to get the name and/or linkage name for a subprogram via a
4992 * specification reference.
4993 *
4994 * Since this is a hack, we ignore failure.
4995 *
4996 * If we want to really make use of DWARF info, we'll have to create some kind
4997 * of lookup tree for handling this. But currently we don't, so a hack will
4998 * suffice.
4999 *
5000 * @param pThis The DWARF instance.
5001 * @param pSubProgram The subprogram which is short on names.
5002 */
5003static void rtDwarfInfo_TryGetSubProgramNameFromSpecRef(PRTDBGMODDWARF pThis, PRTDWARFDIESUBPROGRAM pSubProgram)
5004{
5005 /*
5006 * Must have a spec ref, and it must be in the info section.
5007 */
5008 if (pSubProgram->SpecRef.enmWrt != krtDwarfRef_InfoSection)
5009 return;
5010
5011 /*
5012 * Create a cursor for reading the info and then the abbrivation code
5013 * starting the off the DIE.
5014 */
5015 RTDWARFCURSOR InfoCursor;
5016 int rc = rtDwarfCursor_InitWithOffset(&InfoCursor, pThis, krtDbgModDwarfSect_info, pSubProgram->SpecRef.off);
5017 if (RT_FAILURE(rc))
5018 return;
5019
5020 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(&InfoCursor, UINT32_MAX);
5021 if (uAbbrCode)
5022 {
5023 /* Only references to subprogram tags are interesting here. */
5024 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5025 if ( pAbbrev
5026 && pAbbrev->uTag == DW_TAG_subprogram)
5027 {
5028 /*
5029 * Use rtDwarfInfo_ParseDie to do the parsing, but with a different
5030 * attribute spec than usual.
5031 */
5032 rtDwarfInfo_ParseDie(pThis, &pSubProgram->Core, &g_SubProgramSpecHackDesc, &InfoCursor,
5033 pAbbrev, false /*fInitDie*/);
5034 }
5035 }
5036
5037 rtDwarfCursor_Delete(&InfoCursor, VINF_SUCCESS);
5038}
5039
5040
5041/**
5042 * Select which name to use.
5043 *
5044 * @returns One of the names.
5045 * @param pszName The DWARF name, may exclude namespace and class.
5046 * Can also be NULL.
5047 * @param pszLinkageName The linkage name. Can be NULL.
5048 */
5049static const char *rtDwarfInfo_SelectName(const char *pszName, const char *pszLinkageName)
5050{
5051 if (!pszName || !pszLinkageName)
5052 return pszName ? pszName : pszLinkageName;
5053
5054 /*
5055 * Some heuristics for selecting the link name if the normal name is missing
5056 * namespace or class prefixes.
5057 */
5058 size_t cchName = strlen(pszName);
5059 size_t cchLinkageName = strlen(pszLinkageName);
5060 if (cchLinkageName <= cchName + 1)
5061 return pszName;
5062
5063 const char *psz = strstr(pszLinkageName, pszName);
5064 if (!psz || psz - pszLinkageName < 4)
5065 return pszName;
5066
5067 return pszLinkageName;
5068}
5069
5070
5071/**
5072 * Parse the attributes of a DIE.
5073 *
5074 * @returns IPRT status code.
5075 * @param pThis The DWARF instance.
5076 * @param pDie The internal DIE structure to fill.
5077 */
5078static int rtDwarfInfo_SnoopSymbols(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
5079{
5080 int rc = VINF_SUCCESS;
5081 switch (pDie->uTag)
5082 {
5083 case DW_TAG_subprogram:
5084 {
5085 PRTDWARFDIESUBPROGRAM pSubProgram = (PRTDWARFDIESUBPROGRAM)pDie;
5086
5087 /* Obtain referenced specification there is only partial info. */
5088 if ( pSubProgram->PcRange.cAttrs
5089 && !pSubProgram->pszName)
5090 rtDwarfInfo_TryGetSubProgramNameFromSpecRef(pThis, pSubProgram);
5091
5092 if (pSubProgram->PcRange.cAttrs)
5093 {
5094 if (pSubProgram->PcRange.fHaveRanges)
5095 Log5(("subprogram %s (%s) <implement ranges>\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
5096 else
5097 {
5098 Log5(("subprogram %s (%s) %#llx-%#llx%s\n", pSubProgram->pszName, pSubProgram->pszLinkageName,
5099 pSubProgram->PcRange.uLowAddress, pSubProgram->PcRange.uHighAddress,
5100 pSubProgram->PcRange.cAttrs == 2 ? "" : " !bad!"));
5101 if ( ( pSubProgram->pszName || pSubProgram->pszLinkageName)
5102 && pSubProgram->PcRange.cAttrs == 2)
5103 {
5104 if (pThis->iWatcomPass == 1)
5105 rc = rtDbgModDwarfRecordSegOffset(pThis, pSubProgram->uSegment, pSubProgram->PcRange.uHighAddress);
5106 else
5107 {
5108 RTDBGSEGIDX iSeg;
5109 RTUINTPTR offSeg;
5110 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pSubProgram->uSegment,
5111 pSubProgram->PcRange.uLowAddress,
5112 &iSeg, &offSeg);
5113 if (RT_SUCCESS(rc))
5114 {
5115 uint64_t cb;
5116 if (pSubProgram->PcRange.uHighAddress >= pSubProgram->PcRange.uLowAddress)
5117 cb = pSubProgram->PcRange.uHighAddress - pSubProgram->PcRange.uLowAddress;
5118 else
5119 cb = 1;
5120 rc = RTDbgModSymbolAdd(pThis->hCnt,
5121 rtDwarfInfo_SelectName(pSubProgram->pszName, pSubProgram->pszLinkageName),
5122 iSeg, offSeg, cb, 0 /*fFlags*/, NULL /*piOrdinal*/);
5123 if (RT_FAILURE(rc))
5124 {
5125 if ( rc == VERR_DBG_DUPLICATE_SYMBOL
5126 || rc == VERR_DBG_ADDRESS_CONFLICT /** @todo figure why this happens with 10.6.8 mach_kernel, 32-bit. */
5127 )
5128 rc = VINF_SUCCESS;
5129 else
5130 AssertMsgFailed(("%Rrc\n", rc));
5131 }
5132 }
5133 else if ( pSubProgram->PcRange.uLowAddress == 0 /* see with vmlinux */
5134 && pSubProgram->PcRange.uHighAddress == 0)
5135 {
5136 Log5(("rtDbgModDwarfLinkAddressToSegOffset: Ignoring empty range.\n"));
5137 rc = VINF_SUCCESS; /* ignore */
5138 }
5139 else
5140 {
5141 AssertRC(rc);
5142 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
5143 }
5144 }
5145 }
5146 }
5147 }
5148 else
5149 Log5(("subprogram %s (%s) external\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
5150 break;
5151 }
5152
5153 case DW_TAG_label:
5154 {
5155 PCRTDWARFDIELABEL pLabel = (PCRTDWARFDIELABEL)pDie;
5156 //if (pLabel->fExternal)
5157 {
5158 Log5(("label %s %#x:%#llx\n", pLabel->pszName, pLabel->uSegment, pLabel->Address.uAddress));
5159 if (pThis->iWatcomPass == 1)
5160 rc = rtDbgModDwarfRecordSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress);
5161 else
5162 {
5163 RTDBGSEGIDX iSeg;
5164 RTUINTPTR offSeg;
5165 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress,
5166 &iSeg, &offSeg);
5167 AssertRC(rc);
5168 if (RT_SUCCESS(rc))
5169 {
5170 rc = RTDbgModSymbolAdd(pThis->hCnt, pLabel->pszName, iSeg, offSeg, 0 /*cb*/,
5171 0 /*fFlags*/, NULL /*piOrdinal*/);
5172 AssertMsg(RT_SUCCESS(rc) || rc == VERR_DBG_ADDRESS_CONFLICT,
5173 ("%Rrc %s %x:%x\n", rc, pLabel->pszName, iSeg, offSeg));
5174 }
5175 else
5176 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
5177
5178 /* Ignore errors regarding local labels. */
5179 if (RT_FAILURE(rc) && !pLabel->fExternal)
5180 rc = -rc;
5181 }
5182
5183 }
5184 break;
5185 }
5186
5187 }
5188 return rc;
5189}
5190
5191
5192/**
5193 * Initializes the non-core fields of an internal DIE structure.
5194 *
5195 * @param pDie The DIE structure.
5196 * @param pDieDesc The DIE descriptor.
5197 */
5198static void rtDwarfInfo_InitDie(PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc)
5199{
5200 size_t i = pDieDesc->cAttributes;
5201 while (i-- > 0)
5202 {
5203 switch (pDieDesc->paAttributes[i].cbInit & ATTR_INIT_MASK)
5204 {
5205 case ATTR_INIT_ZERO:
5206 /* Nothing to do (RTMemAllocZ). */
5207 break;
5208
5209 case ATTR_INIT_FFFS:
5210 switch (pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK)
5211 {
5212 case 1:
5213 *(uint8_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT8_MAX;
5214 break;
5215 case 2:
5216 *(uint16_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT16_MAX;
5217 break;
5218 case 4:
5219 *(uint32_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT32_MAX;
5220 break;
5221 case 8:
5222 *(uint64_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT64_MAX;
5223 break;
5224 default:
5225 AssertFailed();
5226 memset((uint8_t *)pDie + pDieDesc->paAttributes[i].off, 0xff,
5227 pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK);
5228 break;
5229 }
5230 break;
5231
5232 default:
5233 AssertFailed();
5234 }
5235 }
5236}
5237
5238
5239/**
5240 * Creates a new internal DIE structure and links it up.
5241 *
5242 * @returns Pointer to the new DIE structure.
5243 * @param pThis The DWARF instance.
5244 * @param pDieDesc The DIE descriptor (for size and init).
5245 * @param pAbbrev The abbreviation cache entry.
5246 * @param pParent The parent DIE (NULL if unit).
5247 */
5248static PRTDWARFDIE rtDwarfInfo_NewDie(PRTDBGMODDWARF pThis, PCRTDWARFDIEDESC pDieDesc,
5249 PCRTDWARFABBREV pAbbrev, PRTDWARFDIE pParent)
5250{
5251 NOREF(pThis);
5252 Assert(pDieDesc->cbDie >= sizeof(RTDWARFDIE));
5253#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5254 uint32_t iAllocator = pDieDesc->cbDie > pThis->aDieAllocators[0].cbMax;
5255 Assert(pDieDesc->cbDie <= pThis->aDieAllocators[iAllocator].cbMax);
5256 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemCacheAlloc(pThis->aDieAllocators[iAllocator].hMemCache);
5257#else
5258 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemAllocZ(pDieDesc->cbDie);
5259#endif
5260 if (pDie)
5261 {
5262#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5263 RT_BZERO(pDie, pDieDesc->cbDie);
5264 pDie->iAllocator = iAllocator;
5265#endif
5266 rtDwarfInfo_InitDie(pDie, pDieDesc);
5267
5268 pDie->uTag = pAbbrev->uTag;
5269 pDie->offSpec = pAbbrev->offSpec;
5270 pDie->pParent = pParent;
5271 if (pParent)
5272 RTListAppend(&pParent->ChildList, &pDie->SiblingNode);
5273 else
5274 RTListInit(&pDie->SiblingNode);
5275 RTListInit(&pDie->ChildList);
5276
5277 }
5278 return pDie;
5279}
5280
5281
5282/**
5283 * Free all children of a DIE.
5284 *
5285 * @param pThis The DWARF instance.
5286 * @param pParentDie The parent DIE.
5287 */
5288static void rtDwarfInfo_FreeChildren(PRTDBGMODDWARF pThis, PRTDWARFDIE pParentDie)
5289{
5290 PRTDWARFDIE pChild, pNextChild;
5291 RTListForEachSafe(&pParentDie->ChildList, pChild, pNextChild, RTDWARFDIE, SiblingNode)
5292 {
5293 if (!RTListIsEmpty(&pChild->ChildList))
5294 rtDwarfInfo_FreeChildren(pThis, pChild);
5295 RTListNodeRemove(&pChild->SiblingNode);
5296#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5297 RTMemCacheFree(pThis->aDieAllocators[pChild->iAllocator].hMemCache, pChild);
5298#else
5299 RTMemFree(pChild);
5300#endif
5301 }
5302}
5303
5304
5305/**
5306 * Free a DIE an all its children.
5307 *
5308 * @param pThis The DWARF instance.
5309 * @param pDie The DIE to free.
5310 */
5311static void rtDwarfInfo_FreeDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
5312{
5313 rtDwarfInfo_FreeChildren(pThis, pDie);
5314 RTListNodeRemove(&pDie->SiblingNode);
5315#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5316 RTMemCacheFree(pThis->aDieAllocators[pDie->iAllocator].hMemCache, pDie);
5317#else
5318 RTMemFree(pChild);
5319#endif
5320}
5321
5322
5323/**
5324 * Skips a form.
5325 * @returns IPRT status code
5326 * @param pCursor The cursor.
5327 * @param uForm The form to skip.
5328 */
5329static int rtDwarfInfo_SkipForm(PRTDWARFCURSOR pCursor, uint32_t uForm)
5330{
5331 switch (uForm)
5332 {
5333 case DW_FORM_addr:
5334 return rtDwarfCursor_SkipBytes(pCursor, pCursor->cbNativeAddr);
5335
5336 case DW_FORM_block:
5337 case DW_FORM_exprloc:
5338 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetULeb128(pCursor, 0));
5339
5340 case DW_FORM_block1:
5341 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU8(pCursor, 0));
5342
5343 case DW_FORM_block2:
5344 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU16(pCursor, 0));
5345
5346 case DW_FORM_block4:
5347 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU32(pCursor, 0));
5348
5349 case DW_FORM_data1:
5350 case DW_FORM_ref1:
5351 case DW_FORM_flag:
5352 return rtDwarfCursor_SkipBytes(pCursor, 1);
5353
5354 case DW_FORM_data2:
5355 case DW_FORM_ref2:
5356 return rtDwarfCursor_SkipBytes(pCursor, 2);
5357
5358 case DW_FORM_data4:
5359 case DW_FORM_ref4:
5360 return rtDwarfCursor_SkipBytes(pCursor, 4);
5361
5362 case DW_FORM_data8:
5363 case DW_FORM_ref8:
5364 case DW_FORM_ref_sig8:
5365 return rtDwarfCursor_SkipBytes(pCursor, 8);
5366
5367 case DW_FORM_udata:
5368 case DW_FORM_sdata:
5369 case DW_FORM_ref_udata:
5370 return rtDwarfCursor_SkipLeb128(pCursor);
5371
5372 case DW_FORM_string:
5373 rtDwarfCursor_GetSZ(pCursor, NULL);
5374 return pCursor->rc;
5375
5376 case DW_FORM_indirect:
5377 return rtDwarfInfo_SkipForm(pCursor, rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX));
5378
5379 case DW_FORM_strp:
5380 case DW_FORM_ref_addr:
5381 case DW_FORM_sec_offset:
5382 return rtDwarfCursor_SkipBytes(pCursor, pCursor->f64bitDwarf ? 8 : 4);
5383
5384 case DW_FORM_flag_present:
5385 return pCursor->rc; /* no data */
5386
5387 default:
5388 Log(("rtDwarfInfo_SkipForm: Unknown form %#x\n", uForm));
5389 return VERR_DWARF_UNKNOWN_FORM;
5390 }
5391}
5392
5393
5394
5395#ifdef SOME_UNUSED_FUNCTION
5396/**
5397 * Skips a DIE.
5398 *
5399 * @returns IPRT status code.
5400 * @param pCursor The cursor.
5401 * @param pAbbrevCursor The abbreviation cursor.
5402 */
5403static int rtDwarfInfo_SkipDie(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pAbbrevCursor)
5404{
5405 for (;;)
5406 {
5407 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
5408 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
5409 if (uAttr == 0 && uForm == 0)
5410 break;
5411
5412 int rc = rtDwarfInfo_SkipForm(pCursor, uForm);
5413 if (RT_FAILURE(rc))
5414 return rc;
5415 }
5416 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pAbbrevCursor->rc;
5417}
5418#endif
5419
5420
5421/**
5422 * Parse the attributes of a DIE.
5423 *
5424 * @returns IPRT status code.
5425 * @param pThis The DWARF instance.
5426 * @param pDie The internal DIE structure to fill.
5427 * @param pDieDesc The DIE descriptor.
5428 * @param pCursor The debug_info cursor.
5429 * @param pAbbrev The abbreviation cache entry.
5430 * @param fInitDie Whether to initialize the DIE first. If not (@c
5431 * false) it's safe to assume we're following a
5432 * DW_AT_specification or DW_AT_abstract_origin,
5433 * and that we shouldn't be snooping any symbols.
5434 */
5435static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc,
5436 PRTDWARFCURSOR pCursor, PCRTDWARFABBREV pAbbrev, bool fInitDie)
5437{
5438 RTDWARFCURSOR AbbrevCursor;
5439 int rc = rtDwarfCursor_InitWithOffset(&AbbrevCursor, pThis, krtDbgModDwarfSect_abbrev, pAbbrev->offSpec);
5440 if (RT_FAILURE(rc))
5441 return rc;
5442
5443 if (fInitDie)
5444 rtDwarfInfo_InitDie(pDie, pDieDesc);
5445 for (;;)
5446 {
5447#ifdef LOG_ENABLED
5448 uint32_t const off = (uint32_t)(AbbrevCursor.pb - AbbrevCursor.pbStart);
5449#endif
5450 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
5451 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
5452 Log4((" %04x: %-23s [%s]\n", off, rtDwarfLog_AttrName(uAttr), rtDwarfLog_FormName(uForm)));
5453 if (uAttr == 0)
5454 break;
5455 if (uForm == DW_FORM_indirect)
5456 uForm = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
5457
5458 /* Look up the attribute in the descriptor and invoke the decoder. */
5459 PCRTDWARFATTRDESC pAttr = NULL;
5460 size_t i = pDieDesc->cAttributes;
5461 while (i-- > 0)
5462 if (pDieDesc->paAttributes[i].uAttr == uAttr)
5463 {
5464 pAttr = &pDieDesc->paAttributes[i];
5465 rc = pAttr->pfnDecoder(pDie, (uint8_t *)pDie + pAttr->off, pAttr, uForm, pCursor);
5466 break;
5467 }
5468
5469 /* Some house keeping. */
5470 if (pAttr)
5471 pDie->cDecodedAttrs++;
5472 else
5473 {
5474 pDie->cUnhandledAttrs++;
5475 rc = rtDwarfInfo_SkipForm(pCursor, uForm);
5476 }
5477 if (RT_FAILURE(rc))
5478 break;
5479 }
5480
5481 rc = rtDwarfCursor_Delete(&AbbrevCursor, rc);
5482 if (RT_SUCCESS(rc))
5483 rc = pCursor->rc;
5484
5485 /*
5486 * Snoop up symbols on the way out.
5487 */
5488 if (RT_SUCCESS(rc) && fInitDie)
5489 {
5490 rc = rtDwarfInfo_SnoopSymbols(pThis, pDie);
5491 /* Ignore duplicates, get work done instead. */
5492 /** @todo clean up global/static symbol mess. */
5493 if (rc == VERR_DBG_DUPLICATE_SYMBOL || rc == VERR_DBG_ADDRESS_CONFLICT)
5494 rc = VINF_SUCCESS;
5495 }
5496
5497 return rc;
5498}
5499
5500
5501/**
5502 * Load the debug information of a unit.
5503 *
5504 * @returns IPRT status code.
5505 * @param pThis The DWARF instance.
5506 * @param pCursor The debug_info cursor.
5507 * @param fKeepDies Whether to keep the DIEs or discard them as soon
5508 * as possible.
5509 */
5510static int rtDwarfInfo_LoadUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, bool fKeepDies)
5511{
5512 Log(("rtDwarfInfo_LoadUnit: %#x\n", rtDwarfCursor_CalcSectOffsetU32(pCursor)));
5513
5514 /*
5515 * Read the compilation unit header.
5516 */
5517 uint64_t offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
5518 uint64_t cbUnit = rtDwarfCursor_GetInitialLength(pCursor);
5519 cbUnit += rtDwarfCursor_CalcSectOffsetU32(pCursor) - offUnit;
5520 uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
5521 if ( uVer < 2
5522 || uVer > 4)
5523 return rtDwarfCursor_SkipUnit(pCursor);
5524 uint64_t const offAbbrev = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
5525 uint8_t const cbNativeAddr = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
5526 if (RT_FAILURE(pCursor->rc))
5527 return pCursor->rc;
5528 Log((" uVer=%d offAbbrev=%#llx cbNativeAddr=%d\n", uVer, offAbbrev, cbNativeAddr));
5529
5530 /*
5531 * Set up the abbreviation cache and store the native address size in the cursor.
5532 */
5533 if (offAbbrev > UINT32_MAX)
5534 {
5535 Log(("Unexpected abbrviation code offset of %#llx\n", offAbbrev));
5536 return VERR_DWARF_BAD_INFO;
5537 }
5538 rtDwarfAbbrev_SetUnitOffset(pThis, (uint32_t)offAbbrev);
5539 pCursor->cbNativeAddr = cbNativeAddr;
5540
5541 /*
5542 * The first DIE is a compile or partial unit, parse it here.
5543 */
5544 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
5545 if (!uAbbrCode)
5546 {
5547 Log(("Unexpected abbrviation code of zero\n"));
5548 return VERR_DWARF_BAD_INFO;
5549 }
5550 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5551 if (!pAbbrev)
5552 return VERR_DWARF_ABBREV_NOT_FOUND;
5553 if ( pAbbrev->uTag != DW_TAG_compile_unit
5554 && pAbbrev->uTag != DW_TAG_partial_unit)
5555 {
5556 Log(("Unexpected compile/partial unit tag %#x\n", pAbbrev->uTag));
5557 return VERR_DWARF_BAD_INFO;
5558 }
5559
5560 PRTDWARFDIECOMPILEUNIT pUnit;
5561 pUnit = (PRTDWARFDIECOMPILEUNIT)rtDwarfInfo_NewDie(pThis, &g_CompileUnitDesc, pAbbrev, NULL /*pParent*/);
5562 if (!pUnit)
5563 return VERR_NO_MEMORY;
5564 pUnit->offUnit = offUnit;
5565 pUnit->cbUnit = cbUnit;
5566 pUnit->offAbbrev = offAbbrev;
5567 pUnit->cbNativeAddr = cbNativeAddr;
5568 pUnit->uDwarfVer = (uint8_t)uVer;
5569 RTListAppend(&pThis->CompileUnitList, &pUnit->Core.SiblingNode);
5570
5571 int rc = rtDwarfInfo_ParseDie(pThis, &pUnit->Core, &g_CompileUnitDesc, pCursor, pAbbrev, true /*fInitDie*/);
5572 if (RT_FAILURE(rc))
5573 return rc;
5574
5575 /*
5576 * Parse DIEs.
5577 */
5578 uint32_t cDepth = 0;
5579 PRTDWARFDIE pParentDie = &pUnit->Core;
5580 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
5581 {
5582#ifdef LOG_ENABLED
5583 uint32_t offLog = rtDwarfCursor_CalcSectOffsetU32(pCursor);
5584#endif
5585 uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
5586 if (!uAbbrCode)
5587 {
5588 /* End of siblings, up one level. (Is this correct?) */
5589 if (pParentDie->pParent)
5590 {
5591 pParentDie = pParentDie->pParent;
5592 cDepth--;
5593 if (!fKeepDies && pParentDie->pParent)
5594 rtDwarfInfo_FreeChildren(pThis, pParentDie);
5595 }
5596 }
5597 else
5598 {
5599 /*
5600 * Look up the abbreviation and match the tag up with a descriptor.
5601 */
5602 pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5603 if (!pAbbrev)
5604 return VERR_DWARF_ABBREV_NOT_FOUND;
5605
5606 PCRTDWARFDIEDESC pDieDesc;
5607 const char *pszName;
5608 if (pAbbrev->uTag < RT_ELEMENTS(g_aTagDescs))
5609 {
5610 Assert(g_aTagDescs[pAbbrev->uTag].uTag == pAbbrev->uTag || g_aTagDescs[pAbbrev->uTag].uTag == 0);
5611 pszName = g_aTagDescs[pAbbrev->uTag].pszName;
5612 pDieDesc = g_aTagDescs[pAbbrev->uTag].pDesc;
5613 }
5614 else
5615 {
5616 pszName = "<unknown>";
5617 pDieDesc = &g_CoreDieDesc;
5618 }
5619 Log4(("%08x: %*stag=%s (%#x, abbrev %u @ %#x)%s\n", offLog, cDepth * 2, "", pszName,
5620 pAbbrev->uTag, uAbbrCode, pAbbrev->offSpec - pAbbrev->cbHdr, pAbbrev->fChildren ? " has children" : ""));
5621
5622 /*
5623 * Create a new internal DIE structure and parse the
5624 * attributes.
5625 */
5626 PRTDWARFDIE pNewDie = rtDwarfInfo_NewDie(pThis, pDieDesc, pAbbrev, pParentDie);
5627 if (!pNewDie)
5628 return VERR_NO_MEMORY;
5629
5630 if (pAbbrev->fChildren)
5631 {
5632 pParentDie = pNewDie;
5633 cDepth++;
5634 }
5635
5636 rc = rtDwarfInfo_ParseDie(pThis, pNewDie, pDieDesc, pCursor, pAbbrev, true /*fInitDie*/);
5637 if (RT_FAILURE(rc))
5638 return rc;
5639
5640 if (!fKeepDies && !pAbbrev->fChildren)
5641 rtDwarfInfo_FreeDie(pThis, pNewDie);
5642 }
5643 } /* while more DIEs */
5644
5645
5646 /* Unlink and free child DIEs if told to do so. */
5647 if (!fKeepDies)
5648 rtDwarfInfo_FreeChildren(pThis, &pUnit->Core);
5649
5650 return RT_SUCCESS(rc) ? pCursor->rc : rc;
5651}
5652
5653
5654/**
5655 * Extracts the symbols.
5656 *
5657 * The symbols are insered into the debug info container.
5658 *
5659 * @returns IPRT status code
5660 * @param pThis The DWARF instance.
5661 */
5662static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis)
5663{
5664 RTDWARFCURSOR Cursor;
5665 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
5666 if (RT_SUCCESS(rc))
5667 {
5668 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
5669 && RT_SUCCESS(rc))
5670 rc = rtDwarfInfo_LoadUnit(pThis, &Cursor, false /* fKeepDies */);
5671
5672 rc = rtDwarfCursor_Delete(&Cursor, rc);
5673 }
5674 return rc;
5675}
5676
5677
5678
5679/*
5680 *
5681 * Public and image level symbol handling.
5682 * Public and image level symbol handling.
5683 * Public and image level symbol handling.
5684 * Public and image level symbol handling.
5685 *
5686 *
5687 */
5688
5689#define RTDBGDWARF_SYM_ENUM_BASE_ADDRESS UINT32_C(0x200000)
5690
5691/** @callback_method_impl{FNRTLDRENUMSYMS,
5692 * Adds missing symbols from the image symbol table.} */
5693static DECLCALLBACK(int) rtDwarfSyms_EnumSymbolsCallback(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol,
5694 RTLDRADDR Value, void *pvUser)
5695{
5696 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
5697 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(uSymbol);
5698 Assert(pThis->iWatcomPass != 1);
5699
5700 RTLDRADDR uRva = Value - RTDBGDWARF_SYM_ENUM_BASE_ADDRESS;
5701 if ( Value >= RTDBGDWARF_SYM_ENUM_BASE_ADDRESS
5702 && uRva < _1G)
5703 {
5704 RTDBGSYMBOL SymInfo;
5705 RTINTPTR offDisp;
5706 int rc = RTDbgModSymbolByAddr(pThis->hCnt, RTDBGSEGIDX_RVA, uRva, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &offDisp, &SymInfo);
5707 if ( RT_FAILURE(rc)
5708 || offDisp != 0)
5709 {
5710 rc = RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, RTDBGSEGIDX_RVA, uRva, 1, 0 /*fFlags*/, NULL /*piOrdinal*/);
5711 Log(("Dwarf: Symbol #%05u %#018RTptr %s [%Rrc]\n", uSymbol, Value, pszSymbol, rc)); NOREF(rc);
5712 }
5713 }
5714 else
5715 Log(("Dwarf: Symbol #%05u %#018RTptr '%s' [SKIPPED - INVALID ADDRESS]\n", uSymbol, Value, pszSymbol));
5716 return VINF_SUCCESS;
5717}
5718
5719
5720
5721/**
5722 * Loads additional symbols from the pubnames section and the executable image.
5723 *
5724 * The symbols are insered into the debug info container.
5725 *
5726 * @returns IPRT status code
5727 * @param pThis The DWARF instance.
5728 */
5729static int rtDwarfSyms_LoadAll(PRTDBGMODDWARF pThis)
5730{
5731 /*
5732 * pubnames.
5733 */
5734 int rc = VINF_SUCCESS;
5735 if (pThis->aSections[krtDbgModDwarfSect_pubnames].fPresent)
5736 {
5737// RTDWARFCURSOR Cursor;
5738// int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
5739// if (RT_SUCCESS(rc))
5740// {
5741// while ( !rtDwarfCursor_IsAtEnd(&Cursor)
5742// && RT_SUCCESS(rc))
5743// rc = rtDwarfInfo_LoadUnit(pThis, &Cursor, false /* fKeepDies */);
5744//
5745// rc = rtDwarfCursor_Delete(&Cursor, rc);
5746// }
5747// return rc;
5748 }
5749
5750 /*
5751 * The executable image.
5752 */
5753 if ( pThis->pImgMod
5754 && pThis->pImgMod->pImgVt->pfnEnumSymbols
5755 && pThis->iWatcomPass != 1
5756 && RT_SUCCESS(rc))
5757 {
5758 rc = pThis->pImgMod->pImgVt->pfnEnumSymbols(pThis->pImgMod,
5759 RTLDR_ENUM_SYMBOL_FLAGS_ALL | RTLDR_ENUM_SYMBOL_FLAGS_NO_FWD,
5760 RTDBGDWARF_SYM_ENUM_BASE_ADDRESS,
5761 rtDwarfSyms_EnumSymbolsCallback,
5762 pThis);
5763 }
5764
5765 return rc;
5766}
5767
5768
5769
5770
5771/*
5772 *
5773 * DWARF Debug module implementation.
5774 * DWARF Debug module implementation.
5775 * DWARF Debug module implementation.
5776 *
5777 */
5778
5779
5780/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
5781static DECLCALLBACK(int) rtDbgModDwarf_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
5782{
5783 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5784
5785 /*
5786 * Unwinding info is stored in the '.debug_frame' section, or altertively
5787 * in the '.eh_frame' one in the image. In the latter case the dbgmodldr.cpp
5788 * part of the operation will take care of it. Since the sections contain the
5789 * same data, we just create a cursor and call a common function to do the job.
5790 */
5791 if (pThis->aSections[krtDbgModDwarfSect_frame].fPresent)
5792 {
5793 RTDWARFCURSOR Cursor;
5794 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_frame);
5795 if (RT_SUCCESS(rc))
5796 {
5797 /* Figure default pointer encoding from image arch. */
5798 uint8_t bPtrEnc = rtDwarfUnwind_ArchToPtrEnc(pMod->pImgVt->pfnGetArch(pMod));
5799
5800 /* Make sure we've got both seg:off and rva for the input address. */
5801 RTUINTPTR uRva = off;
5802 if (iSeg == RTDBGSEGIDX_RVA)
5803 rtDbgModDwarfRvaToSegOffset(pThis, uRva, &iSeg, &off);
5804 else
5805 rtDbgModDwarfSegOffsetToRva(pThis, iSeg, off, &uRva);
5806
5807 /* Do the work */
5808 rc = rtDwarfUnwind_Slow(&Cursor, 0 /** @todo .debug_frame RVA*/, iSeg, off, uRva,
5809 pState, bPtrEnc, false /*fIsEhFrame*/, pMod->pImgVt->pfnGetArch(pMod));
5810
5811 rc = rtDwarfCursor_Delete(&Cursor, rc);
5812 }
5813 return rc;
5814 }
5815 return VERR_DBG_NO_UNWIND_INFO;
5816}
5817
5818
5819/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
5820static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
5821 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
5822{
5823 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5824 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
5825}
5826
5827
5828/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
5829static DECLCALLBACK(int) rtDbgModDwarf_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
5830{
5831 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5832 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
5833}
5834
5835
5836/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
5837static DECLCALLBACK(uint32_t) rtDbgModDwarf_LineCount(PRTDBGMODINT pMod)
5838{
5839 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5840 return RTDbgModLineCount(pThis->hCnt);
5841}
5842
5843
5844/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
5845static DECLCALLBACK(int) rtDbgModDwarf_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
5846 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
5847{
5848 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5849 Assert(!pszFile[cchFile]); NOREF(cchFile);
5850 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
5851}
5852
5853
5854/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
5855static DECLCALLBACK(int) rtDbgModDwarf_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
5856 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
5857{
5858 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5859 return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
5860}
5861
5862
5863/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
5864static DECLCALLBACK(int) rtDbgModDwarf_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
5865 PRTDBGSYMBOL pSymInfo)
5866{
5867 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5868 Assert(!pszSymbol[cchSymbol]); RT_NOREF_PV(cchSymbol);
5869 return RTDbgModSymbolByName(pThis->hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
5870}
5871
5872
5873/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
5874static DECLCALLBACK(int) rtDbgModDwarf_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
5875{
5876 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5877 return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
5878}
5879
5880
5881/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
5882static DECLCALLBACK(uint32_t) rtDbgModDwarf_SymbolCount(PRTDBGMODINT pMod)
5883{
5884 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5885 return RTDbgModSymbolCount(pThis->hCnt);
5886}
5887
5888
5889/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
5890static DECLCALLBACK(int) rtDbgModDwarf_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
5891 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
5892 uint32_t *piOrdinal)
5893{
5894 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5895 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
5896 return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
5897}
5898
5899
5900/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
5901static DECLCALLBACK(int) rtDbgModDwarf_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
5902{
5903 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5904 return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
5905}
5906
5907
5908/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
5909static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_SegmentCount(PRTDBGMODINT pMod)
5910{
5911 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5912 return RTDbgModSegmentCount(pThis->hCnt);
5913}
5914
5915
5916/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
5917static DECLCALLBACK(int) rtDbgModDwarf_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
5918 uint32_t fFlags, PRTDBGSEGIDX piSeg)
5919{
5920 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5921 Assert(!pszName[cchName]); NOREF(cchName);
5922 return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
5923}
5924
5925
5926/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
5927static DECLCALLBACK(RTUINTPTR) rtDbgModDwarf_ImageSize(PRTDBGMODINT pMod)
5928{
5929 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5930 RTUINTPTR cb1 = RTDbgModImageSize(pThis->hCnt);
5931 RTUINTPTR cb2 = pThis->pImgMod->pImgVt->pfnImageSize(pMod);
5932 return RT_MAX(cb1, cb2);
5933}
5934
5935
5936/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
5937static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
5938{
5939 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5940 return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
5941}
5942
5943
5944/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
5945static DECLCALLBACK(int) rtDbgModDwarf_Close(PRTDBGMODINT pMod)
5946{
5947 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5948
5949 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
5950 if (pThis->aSections[iSect].pv)
5951 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb, &pThis->aSections[iSect].pv);
5952
5953 RTDbgModRelease(pThis->hCnt);
5954 RTMemFree(pThis->paCachedAbbrevs);
5955 if (pThis->pNestedMod)
5956 {
5957 pThis->pNestedMod->pImgVt->pfnClose(pThis->pNestedMod);
5958 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszName);
5959 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszDbgFile);
5960 RTMemFree(pThis->pNestedMod);
5961 pThis->pNestedMod = NULL;
5962 }
5963
5964#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5965 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
5966 while (i-- > 0)
5967 {
5968 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
5969 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
5970 }
5971#endif
5972
5973 RTMemFree(pThis);
5974
5975 return VINF_SUCCESS;
5976}
5977
5978
5979/** @callback_method_impl{FNRTLDRENUMDBG} */
5980static DECLCALLBACK(int) rtDbgModDwarfEnumCallback(RTLDRMOD hLdrMod, PCRTLDRDBGINFO pDbgInfo, void *pvUser)
5981{
5982 RT_NOREF_PV(hLdrMod);
5983
5984 /*
5985 * Skip stuff we can't handle.
5986 */
5987 if (pDbgInfo->enmType != RTLDRDBGINFOTYPE_DWARF)
5988 return VINF_SUCCESS;
5989 const char *pszSection = pDbgInfo->u.Dwarf.pszSection;
5990 if (!pszSection || !*pszSection)
5991 return VINF_SUCCESS;
5992 Assert(!pDbgInfo->pszExtFile);
5993
5994 /*
5995 * Must have a part name starting with debug_ and possibly prefixed by dots
5996 * or underscores.
5997 */
5998 if (!strncmp(pszSection, RT_STR_TUPLE(".debug_"))) /* ELF */
5999 pszSection += sizeof(".debug_") - 1;
6000 else if (!strncmp(pszSection, RT_STR_TUPLE("__debug_"))) /* Mach-O */
6001 pszSection += sizeof("__debug_") - 1;
6002 else if (!strcmp(pszSection, ".WATCOM_references"))
6003 return VINF_SUCCESS; /* Ignore special watcom section for now.*/
6004 else if ( !strcmp(pszSection, "__apple_types")
6005 || !strcmp(pszSection, "__apple_namespac")
6006 || !strcmp(pszSection, "__apple_objc")
6007 || !strcmp(pszSection, "__apple_names"))
6008 return VINF_SUCCESS; /* Ignore special apple sections for now. */
6009 else
6010 AssertMsgFailedReturn(("%s\n", pszSection), VINF_SUCCESS /*ignore*/);
6011
6012 /*
6013 * Figure out which part we're talking about.
6014 */
6015 krtDbgModDwarfSect enmSect;
6016 if (0) { /* dummy */ }
6017#define ELSE_IF_STRCMP_SET(a_Name) else if (!strcmp(pszSection, #a_Name)) enmSect = krtDbgModDwarfSect_ ## a_Name
6018 ELSE_IF_STRCMP_SET(abbrev);
6019 ELSE_IF_STRCMP_SET(aranges);
6020 ELSE_IF_STRCMP_SET(frame);
6021 ELSE_IF_STRCMP_SET(info);
6022 ELSE_IF_STRCMP_SET(inlined);
6023 ELSE_IF_STRCMP_SET(line);
6024 ELSE_IF_STRCMP_SET(loc);
6025 ELSE_IF_STRCMP_SET(macinfo);
6026 ELSE_IF_STRCMP_SET(pubnames);
6027 ELSE_IF_STRCMP_SET(pubtypes);
6028 ELSE_IF_STRCMP_SET(ranges);
6029 ELSE_IF_STRCMP_SET(str);
6030 ELSE_IF_STRCMP_SET(types);
6031#undef ELSE_IF_STRCMP_SET
6032 else
6033 {
6034 AssertMsgFailed(("%s\n", pszSection));
6035 return VINF_SUCCESS;
6036 }
6037
6038 /*
6039 * Record the section.
6040 */
6041 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
6042 AssertMsgReturn(!pThis->aSections[enmSect].fPresent, ("duplicate %s\n", pszSection), VINF_SUCCESS /*ignore*/);
6043
6044 pThis->aSections[enmSect].fPresent = true;
6045 pThis->aSections[enmSect].offFile = pDbgInfo->offFile;
6046 pThis->aSections[enmSect].pv = NULL;
6047 pThis->aSections[enmSect].cb = (size_t)pDbgInfo->cb;
6048 pThis->aSections[enmSect].iDbgInfo = pDbgInfo->iDbgInfo;
6049 if (pThis->aSections[enmSect].cb != pDbgInfo->cb)
6050 pThis->aSections[enmSect].cb = ~(size_t)0;
6051
6052 return VINF_SUCCESS;
6053}
6054
6055
6056static int rtDbgModDwarfTryOpenDbgFile(PRTDBGMODINT pDbgMod, PRTDBGMODDWARF pThis, RTLDRARCH enmArch)
6057{
6058 if ( !pDbgMod->pszDbgFile
6059 || RTPathIsSame(pDbgMod->pszDbgFile, pDbgMod->pszImgFile) == (int)true /* returns VERR too */)
6060 return VERR_DBG_NO_MATCHING_INTERPRETER;
6061
6062 /*
6063 * Only open the image.
6064 */
6065 PRTDBGMODINT pDbgInfoMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgInfoMod));
6066 if (!pDbgInfoMod)
6067 return VERR_NO_MEMORY;
6068
6069 int rc;
6070 pDbgInfoMod->u32Magic = RTDBGMOD_MAGIC;
6071 pDbgInfoMod->cRefs = 1;
6072 if (RTStrCacheRetain(pDbgMod->pszDbgFile) != UINT32_MAX)
6073 {
6074 pDbgInfoMod->pszImgFile = pDbgMod->pszDbgFile;
6075 if (RTStrCacheRetain(pDbgMod->pszName) != UINT32_MAX)
6076 {
6077 pDbgInfoMod->pszName = pDbgMod->pszName;
6078 pDbgInfoMod->pImgVt = &g_rtDbgModVtImgLdr;
6079 rc = pDbgInfoMod->pImgVt->pfnTryOpen(pDbgInfoMod, enmArch, 0 /*fLdrFlags*/);
6080 if (RT_SUCCESS(rc))
6081 {
6082 pThis->pDbgInfoMod = pDbgInfoMod;
6083 pThis->pNestedMod = pDbgInfoMod;
6084 return VINF_SUCCESS;
6085 }
6086
6087 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszName);
6088 }
6089 else
6090 rc = VERR_NO_STR_MEMORY;
6091 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszImgFile);
6092 }
6093 else
6094 rc = VERR_NO_STR_MEMORY;
6095 RTMemFree(pDbgInfoMod);
6096 return rc;
6097}
6098
6099
6100/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
6101static DECLCALLBACK(int) rtDbgModDwarf_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
6102{
6103 /*
6104 * DWARF is only supported when part of an image.
6105 */
6106 if (!pMod->pImgVt)
6107 return VERR_DBG_NO_MATCHING_INTERPRETER;
6108
6109 /*
6110 * Create the module instance data.
6111 */
6112 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)RTMemAllocZ(sizeof(*pThis));
6113 if (!pThis)
6114 return VERR_NO_MEMORY;
6115 pThis->pDbgInfoMod = pMod;
6116 pThis->pImgMod = pMod;
6117 RTListInit(&pThis->CompileUnitList);
6118
6119 /** @todo better fUseLinkAddress heuristics! */
6120 /* mach_kernel: */
6121 if ( (pMod->pszDbgFile && strstr(pMod->pszDbgFile, "mach_kernel"))
6122 || (pMod->pszImgFile && strstr(pMod->pszImgFile, "mach_kernel"))
6123 || (pMod->pszImgFileSpecified && strstr(pMod->pszImgFileSpecified, "mach_kernel")) )
6124 pThis->fUseLinkAddress = true;
6125
6126#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
6127 AssertCompile(RT_ELEMENTS(pThis->aDieAllocators) == 2);
6128 pThis->aDieAllocators[0].cbMax = sizeof(RTDWARFDIE);
6129 pThis->aDieAllocators[1].cbMax = sizeof(RTDWARFDIECOMPILEUNIT);
6130 for (uint32_t i = 0; i < RT_ELEMENTS(g_aTagDescs); i++)
6131 if (g_aTagDescs[i].pDesc && g_aTagDescs[i].pDesc->cbDie > pThis->aDieAllocators[1].cbMax)
6132 pThis->aDieAllocators[1].cbMax = (uint32_t)g_aTagDescs[i].pDesc->cbDie;
6133 pThis->aDieAllocators[1].cbMax = RT_ALIGN_32(pThis->aDieAllocators[1].cbMax, sizeof(uint64_t));
6134
6135 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDieAllocators); i++)
6136 {
6137 int rc = RTMemCacheCreate(&pThis->aDieAllocators[i].hMemCache, pThis->aDieAllocators[i].cbMax, sizeof(uint64_t),
6138 UINT32_MAX, NULL /*pfnCtor*/, NULL /*pfnDtor*/, NULL /*pvUser*/, 0 /*fFlags*/);
6139 if (RT_FAILURE(rc))
6140 {
6141 while (i-- > 0)
6142 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
6143 RTMemFree(pThis);
6144 return rc;
6145 }
6146 }
6147#endif
6148
6149 /*
6150 * If the debug file name is set, let's see if it's an ELF image with DWARF
6151 * inside it. In that case we'll have to deal with two image modules, one
6152 * for segments and address translation and one for the debug information.
6153 */
6154 if (pMod->pszDbgFile != NULL)
6155 rtDbgModDwarfTryOpenDbgFile(pMod, pThis, enmArch);
6156
6157 /*
6158 * Enumerate the debug info in the module, looking for DWARF bits.
6159 */
6160 int rc = pThis->pDbgInfoMod->pImgVt->pfnEnumDbgInfo(pThis->pDbgInfoMod, rtDbgModDwarfEnumCallback, pThis);
6161 if (RT_SUCCESS(rc))
6162 {
6163 if (pThis->aSections[krtDbgModDwarfSect_info].fPresent)
6164 {
6165 /*
6166 * Extract / explode the data we want (symbols and line numbers)
6167 * storing them in a container module.
6168 */
6169 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
6170 if (RT_SUCCESS(rc))
6171 {
6172 pMod->pvDbgPriv = pThis;
6173
6174 rc = rtDbgModDwarfAddSegmentsFromImage(pThis);
6175 if (RT_SUCCESS(rc))
6176 rc = rtDwarfInfo_LoadAll(pThis);
6177 if (RT_SUCCESS(rc))
6178 rc = rtDwarfSyms_LoadAll(pThis);
6179 if (RT_SUCCESS(rc))
6180 rc = rtDwarfLine_ExplodeAll(pThis);
6181 if (RT_SUCCESS(rc) && pThis->iWatcomPass == 1)
6182 {
6183 rc = rtDbgModDwarfAddSegmentsFromPass1(pThis);
6184 pThis->iWatcomPass = 2;
6185 if (RT_SUCCESS(rc))
6186 rc = rtDwarfInfo_LoadAll(pThis);
6187 if (RT_SUCCESS(rc))
6188 rc = rtDwarfSyms_LoadAll(pThis);
6189 if (RT_SUCCESS(rc))
6190 rc = rtDwarfLine_ExplodeAll(pThis);
6191 }
6192
6193 /*
6194 * Free the cached abbreviations and unload all sections.
6195 */
6196 pThis->cCachedAbbrevsAlloced = 0;
6197 RTMemFree(pThis->paCachedAbbrevs);
6198 pThis->paCachedAbbrevs = NULL;
6199
6200 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
6201 if (pThis->aSections[iSect].pv)
6202 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb,
6203 &pThis->aSections[iSect].pv);
6204
6205 if (RT_SUCCESS(rc))
6206 {
6207 /** @todo Kill pThis->CompileUnitList and the alloc caches. */
6208 return VINF_SUCCESS;
6209 }
6210
6211 /* bail out. */
6212 RTDbgModRelease(pThis->hCnt);
6213 pMod->pvDbgPriv = NULL;
6214 }
6215 }
6216 else
6217 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
6218 }
6219
6220 if (pThis->paCachedAbbrevs)
6221 RTMemFree(pThis->paCachedAbbrevs);
6222 pThis->paCachedAbbrevs = NULL;
6223
6224 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
6225 if (pThis->aSections[iSect].pv)
6226 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb,
6227 &pThis->aSections[iSect].pv);
6228
6229#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
6230 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
6231 while (i-- > 0)
6232 {
6233 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
6234 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
6235 }
6236#endif
6237
6238 RTMemFree(pThis);
6239
6240 return rc;
6241}
6242
6243
6244
6245/** Virtual function table for the DWARF debug info reader. */
6246DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDwarf =
6247{
6248 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
6249 /*.fSupports = */ RT_DBGTYPE_DWARF,
6250 /*.pszName = */ "dwarf",
6251 /*.pfnTryOpen = */ rtDbgModDwarf_TryOpen,
6252 /*.pfnClose = */ rtDbgModDwarf_Close,
6253
6254 /*.pfnRvaToSegOff = */ rtDbgModDwarf_RvaToSegOff,
6255 /*.pfnImageSize = */ rtDbgModDwarf_ImageSize,
6256
6257 /*.pfnSegmentAdd = */ rtDbgModDwarf_SegmentAdd,
6258 /*.pfnSegmentCount = */ rtDbgModDwarf_SegmentCount,
6259 /*.pfnSegmentByIndex = */ rtDbgModDwarf_SegmentByIndex,
6260
6261 /*.pfnSymbolAdd = */ rtDbgModDwarf_SymbolAdd,
6262 /*.pfnSymbolCount = */ rtDbgModDwarf_SymbolCount,
6263 /*.pfnSymbolByOrdinal = */ rtDbgModDwarf_SymbolByOrdinal,
6264 /*.pfnSymbolByName = */ rtDbgModDwarf_SymbolByName,
6265 /*.pfnSymbolByAddr = */ rtDbgModDwarf_SymbolByAddr,
6266
6267 /*.pfnLineAdd = */ rtDbgModDwarf_LineAdd,
6268 /*.pfnLineCount = */ rtDbgModDwarf_LineCount,
6269 /*.pfnLineByOrdinal = */ rtDbgModDwarf_LineByOrdinal,
6270 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr,
6271
6272 /*.pfnUnwindFrame = */ rtDbgModDwarf_UnwindFrame,
6273
6274 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
6275};
6276
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