VirtualBox

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

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

IPRT: Moved the dwarf defines into iprt/formats/dwarf.h. Did some unwind tweaking & fixing. Show local labels. bugref:3897

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 229.2 KB
Line 
1/* $Id: dbgmoddwarf.cpp 75238 2018-11-03 02:53:46Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader For DWARF.
4 */
5
6/*
7 * Copyright (C) 2011-2017 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, NULL }
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 paCies = (PRTDWARFCIEINFO)pvNew;
3419 else
3420 {
3421 rc = VERR_NO_MEMORY;
3422 break;
3423 }
3424 }
3425 Log8(("%#08RX64: CIE\n", offUnit));
3426 int rc2 = rtDwarfUnwind_LoadCie(pCursor, &paCies[cCies], offUnit, bDefaultPtrEnc);
3427 if (RT_SUCCESS(rc2))
3428 {
3429 Log8(("%#08RX64: CIE #%u: offCie=%#RX64\n", offUnit, cCies, paCies[cCies].offCie));
3430 cCies++;
3431 }
3432 }
3433 rtDwarfCursor_SkipUnit(pCursor);
3434 }
3435
3436 /*
3437 * Cleanup.
3438 */
3439 if (paCies)
3440 RTMemFree(paCies);
3441 Log8(("rtDwarfUnwind_Slow: returns %Rrc PC=%#RX64\n", rc, pState->uPc));
3442 return rc;
3443}
3444
3445
3446/**
3447 * Helper for translating a loader architecture value to a pointe encoding.
3448 *
3449 * @returns Pointer encoding.
3450 * @param enmLdrArch The loader architecture value to convert.
3451 */
3452static uint8_t rtDwarfUnwind_ArchToPtrEnc(RTLDRARCH enmLdrArch)
3453{
3454 switch (enmLdrArch)
3455 {
3456 case RTLDRARCH_AMD64:
3457 case RTLDRARCH_ARM64:
3458 return DW_EH_PE_udata8;
3459 case RTLDRARCH_X86_16:
3460 case RTLDRARCH_X86_32:
3461 case RTLDRARCH_ARM32:
3462 return DW_EH_PE_udata4;
3463 case RTLDRARCH_HOST:
3464 case RTLDRARCH_WHATEVER:
3465 case RTLDRARCH_INVALID:
3466 case RTLDRARCH_END:
3467 case RTLDRARCH_32BIT_HACK:
3468 break;
3469 }
3470 AssertFailed();
3471 return DW_EH_PE_udata4;
3472}
3473
3474
3475/**
3476 * Interface for the loader code.
3477 *
3478 * @returns IPRT status.
3479 * @param pvSection The '.eh_frame' section data.
3480 * @param cbSection The size of the '.eh_frame' section data.
3481 * @param uRvaSection The RVA of the '.eh_frame' section.
3482 * @param idxSeg The segment of the PC location.
3483 * @param offSeg The segment offset of the PC location.
3484 * @param uRva The RVA of the PC location.
3485 * @param pState The unwind state to work.
3486 * @param enmArch The image architecture.
3487 */
3488DECLHIDDEN(int) rtDwarfUnwind_EhData(void const *pvSection, size_t cbSection, RTUINTPTR uRvaSection,
3489 RTDBGSEGIDX idxSeg, RTUINTPTR offSeg, RTUINTPTR uRva,
3490 PRTDBGUNWINDSTATE pState, RTLDRARCH enmArch)
3491{
3492 RTDWARFCURSOR Cursor;
3493 rtDwarfCursor_InitForMem(&Cursor, pvSection, cbSection);
3494 int rc = rtDwarfUnwind_Slow(&Cursor, uRvaSection, idxSeg, offSeg, uRva, pState,
3495 rtDwarfUnwind_ArchToPtrEnc(enmArch), true /*fIsEhFrame*/, enmArch);
3496 LogFlow(("rtDwarfUnwind_EhData: rtDwarfUnwind_Slow -> %Rrc\n", rc));
3497 rc = rtDwarfCursor_Delete(&Cursor, rc);
3498 LogFlow(("rtDwarfUnwind_EhData: returns %Rrc\n", rc));
3499 return rc;
3500}
3501
3502
3503/*
3504 *
3505 * DWARF Line Numbers.
3506 * DWARF Line Numbers.
3507 * DWARF Line Numbers.
3508 *
3509 */
3510
3511
3512/**
3513 * Defines a file name.
3514 *
3515 * @returns IPRT status code.
3516 * @param pLnState The line number program state.
3517 * @param pszFilename The name of the file.
3518 * @param idxInc The include path index.
3519 */
3520static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc)
3521{
3522 /*
3523 * Resize the array if necessary.
3524 */
3525 uint32_t iFileName = pLnState->cFileNames;
3526 if ((iFileName % 2) == 0)
3527 {
3528 void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2));
3529 if (!pv)
3530 return VERR_NO_MEMORY;
3531 pLnState->papszFileNames = (char **)pv;
3532 }
3533
3534 /*
3535 * Add the file name.
3536 */
3537 if ( pszFilename[0] == '/'
3538 || pszFilename[0] == '\\'
3539 || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') )
3540 pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename);
3541 else if (idxInc < pLnState->cIncPaths)
3542 pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename);
3543 else
3544 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
3545 if (!pLnState->papszFileNames[iFileName])
3546 return VERR_NO_STR_MEMORY;
3547 pLnState->cFileNames = iFileName + 1;
3548
3549 /*
3550 * Sanitize the name.
3551 */
3552 int rc = rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]);
3553 Log((" File #%02u = '%s'\n", iFileName, pLnState->papszFileNames[iFileName]));
3554 return rc;
3555}
3556
3557
3558/**
3559 * Adds a line to the table and resets parts of the state (DW_LNS_copy).
3560 *
3561 * @returns IPRT status code
3562 * @param pLnState The line number program state.
3563 * @param offOpCode The opcode offset (for logging
3564 * purposes).
3565 */
3566static int rtDwarfLine_AddLine(PRTDWARFLINESTATE pLnState, uint32_t offOpCode)
3567{
3568 PRTDBGMODDWARF pThis = pLnState->pDwarfMod;
3569 int rc;
3570 if (pThis->iWatcomPass == 1)
3571 rc = rtDbgModDwarfRecordSegOffset(pThis, pLnState->Regs.uSegment, pLnState->Regs.uAddress + 1);
3572 else
3573 {
3574 const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames
3575 ? pLnState->papszFileNames[pLnState->Regs.iFile]
3576 : "<bad file name index>";
3577 NOREF(offOpCode);
3578
3579 RTDBGSEGIDX iSeg;
3580 RTUINTPTR offSeg;
3581 rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uSegment, pLnState->Regs.uAddress,
3582 &iSeg, &offSeg); /*AssertRC(rc);*/
3583 if (RT_SUCCESS(rc))
3584 {
3585 Log2(("rtDwarfLine_AddLine: %x:%08llx (%#llx) %s(%d) [offOpCode=%08x]\n", iSeg, offSeg, pLnState->Regs.uAddress, pszFile, pLnState->Regs.uLine, offOpCode));
3586 rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL);
3587
3588 /* Ignore address conflicts for now. */
3589 if (rc == VERR_DBG_ADDRESS_CONFLICT)
3590 rc = VINF_SUCCESS;
3591 }
3592 else
3593 rc = VINF_SUCCESS; /* ignore failure */
3594 }
3595
3596 pLnState->Regs.fBasicBlock = false;
3597 pLnState->Regs.fPrologueEnd = false;
3598 pLnState->Regs.fEpilogueBegin = false;
3599 pLnState->Regs.uDiscriminator = 0;
3600 return rc;
3601}
3602
3603
3604/**
3605 * Reset the program to the start-of-sequence state.
3606 *
3607 * @param pLnState The line number program state.
3608 */
3609static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState)
3610{
3611 pLnState->Regs.uAddress = 0;
3612 pLnState->Regs.idxOp = 0;
3613 pLnState->Regs.iFile = 1;
3614 pLnState->Regs.uLine = 1;
3615 pLnState->Regs.uColumn = 0;
3616 pLnState->Regs.fIsStatement = RT_BOOL(pLnState->Hdr.u8DefIsStmt);
3617 pLnState->Regs.fBasicBlock = false;
3618 pLnState->Regs.fEndSequence = false;
3619 pLnState->Regs.fPrologueEnd = false;
3620 pLnState->Regs.fEpilogueBegin = false;
3621 pLnState->Regs.uIsa = 0;
3622 pLnState->Regs.uDiscriminator = 0;
3623 pLnState->Regs.uSegment = 0;
3624}
3625
3626
3627/**
3628 * Runs the line number program.
3629 *
3630 * @returns IPRT status code.
3631 * @param pLnState The line number program state.
3632 * @param pCursor The cursor.
3633 */
3634static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3635{
3636 LogFlow(("rtDwarfLine_RunProgram: cbUnitLeft=%zu\n", pCursor->cbUnitLeft));
3637
3638 int rc = VINF_SUCCESS;
3639 rtDwarfLine_ResetState(pLnState);
3640
3641 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
3642 {
3643#ifdef LOG_ENABLED
3644 uint32_t const offOpCode = rtDwarfCursor_CalcSectOffsetU32(pCursor);
3645#else
3646 uint32_t const offOpCode = 0;
3647#endif
3648 uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, DW_LNS_extended);
3649 if (bOpCode >= pLnState->Hdr.u8OpcodeBase)
3650 {
3651 /*
3652 * Special opcode.
3653 */
3654 uint8_t const bLogOpCode = bOpCode; NOREF(bLogOpCode);
3655 bOpCode -= pLnState->Hdr.u8OpcodeBase;
3656
3657 int32_t const cLineDelta = bOpCode % pLnState->Hdr.u8LineRange + (int32_t)pLnState->Hdr.s8LineBase;
3658 bOpCode /= pLnState->Hdr.u8LineRange;
3659
3660 uint64_t uTmp = bOpCode + pLnState->Regs.idxOp;
3661 uint64_t const cAddressDelta = uTmp / pLnState->Hdr.cMaxOpsPerInstr * pLnState->Hdr.cbMinInstr;
3662 uint64_t const cOpIndexDelta = uTmp % pLnState->Hdr.cMaxOpsPerInstr;
3663
3664 pLnState->Regs.uLine += cLineDelta;
3665 pLnState->Regs.uAddress += cAddressDelta;
3666 pLnState->Regs.idxOp += cOpIndexDelta;
3667 Log2(("%08x: DW Special Opcode %#04x: uLine + %d => %u; uAddress + %#llx => %#llx; idxOp + %#llx => %#llx\n",
3668 offOpCode, bLogOpCode, cLineDelta, pLnState->Regs.uLine, cAddressDelta, pLnState->Regs.uAddress,
3669 cOpIndexDelta, pLnState->Regs.idxOp));
3670
3671 /*
3672 * LLVM emits debug info for global constructors (_GLOBAL__I_a) which are not part of source
3673 * code but are inserted by the compiler: The resulting line number will be 0
3674 * because they are not part of the source file obviously (see https://reviews.llvm.org/rL205999),
3675 * so skip adding them when they are encountered.
3676 */
3677 if (pLnState->Regs.uLine)
3678 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3679 }
3680 else
3681 {
3682 switch (bOpCode)
3683 {
3684 /*
3685 * Standard opcode.
3686 */
3687 case DW_LNS_copy:
3688 Log2(("%08x: DW_LNS_copy\n", offOpCode));
3689 /* See the comment about LLVM above. */
3690 if (pLnState->Regs.uLine)
3691 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3692 break;
3693
3694 case DW_LNS_advance_pc:
3695 {
3696 uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0);
3697 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->Hdr.cMaxOpsPerInstr
3698 * pLnState->Hdr.cbMinInstr;
3699 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + u64Adv) % pLnState->Hdr.cMaxOpsPerInstr;
3700 Log2(("%08x: DW_LNS_advance_pc: u64Adv=%#llx (%lld) )\n", offOpCode, u64Adv, u64Adv));
3701 break;
3702 }
3703
3704 case DW_LNS_advance_line:
3705 {
3706 int32_t cLineDelta = rtDwarfCursor_GetSLeb128AsS32(pCursor, 0);
3707 pLnState->Regs.uLine += cLineDelta;
3708 Log2(("%08x: DW_LNS_advance_line: uLine + %d => %u\n", offOpCode, cLineDelta, pLnState->Regs.uLine));
3709 break;
3710 }
3711
3712 case DW_LNS_set_file:
3713 pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3714 Log2(("%08x: DW_LNS_set_file: iFile=%u\n", offOpCode, pLnState->Regs.iFile));
3715 break;
3716
3717 case DW_LNS_set_column:
3718 pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3719 Log2(("%08x: DW_LNS_set_column\n", offOpCode));
3720 break;
3721
3722 case DW_LNS_negate_stmt:
3723 pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement;
3724 Log2(("%08x: DW_LNS_negate_stmt\n", offOpCode));
3725 break;
3726
3727 case DW_LNS_set_basic_block:
3728 pLnState->Regs.fBasicBlock = true;
3729 Log2(("%08x: DW_LNS_set_basic_block\n", offOpCode));
3730 break;
3731
3732 case DW_LNS_const_add_pc:
3733 {
3734 uint8_t u8Adv = (255 - pLnState->Hdr.u8OpcodeBase) / pLnState->Hdr.u8LineRange;
3735 if (pLnState->Hdr.cMaxOpsPerInstr <= 1)
3736 pLnState->Regs.uAddress += (uint32_t)pLnState->Hdr.cbMinInstr * u8Adv;
3737 else
3738 {
3739 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u8Adv) / pLnState->Hdr.cMaxOpsPerInstr
3740 * pLnState->Hdr.cbMinInstr;
3741 pLnState->Regs.idxOp = (pLnState->Regs.idxOp + u8Adv) % pLnState->Hdr.cMaxOpsPerInstr;
3742 }
3743 Log2(("%08x: DW_LNS_const_add_pc\n", offOpCode));
3744 break;
3745 }
3746 case DW_LNS_fixed_advance_pc:
3747 pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0);
3748 pLnState->Regs.idxOp = 0;
3749 Log2(("%08x: DW_LNS_fixed_advance_pc\n", offOpCode));
3750 break;
3751
3752 case DW_LNS_set_prologue_end:
3753 pLnState->Regs.fPrologueEnd = true;
3754 Log2(("%08x: DW_LNS_set_prologue_end\n", offOpCode));
3755 break;
3756
3757 case DW_LNS_set_epilogue_begin:
3758 pLnState->Regs.fEpilogueBegin = true;
3759 Log2(("%08x: DW_LNS_set_epilogue_begin\n", offOpCode));
3760 break;
3761
3762 case DW_LNS_set_isa:
3763 pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
3764 Log2(("%08x: DW_LNS_set_isa %#x\n", offOpCode, pLnState->Regs.uIsa));
3765 break;
3766
3767 default:
3768 {
3769 unsigned cOpsToSkip = pLnState->Hdr.pacStdOperands[bOpCode - 1];
3770 Log(("rtDwarfLine_RunProgram: Unknown standard opcode %#x, %#x operands, at %08x.\n", bOpCode, cOpsToSkip, offOpCode));
3771 while (cOpsToSkip-- > 0)
3772 rc = rtDwarfCursor_SkipLeb128(pCursor);
3773 break;
3774 }
3775
3776 /*
3777 * Extended opcode.
3778 */
3779 case DW_LNS_extended:
3780 {
3781 /* The instruction has a length prefix. */
3782 uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3783 if (RT_FAILURE(pCursor->rc))
3784 return pCursor->rc;
3785 if (cbInstr > pCursor->cbUnitLeft)
3786 return VERR_DWARF_BAD_LNE;
3787 uint8_t const * const pbEndOfInstr = rtDwarfCursor_CalcPos(pCursor, cbInstr);
3788
3789 /* Get the opcode and deal with it if we know it. */
3790 bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
3791 switch (bOpCode)
3792 {
3793 case DW_LNE_end_sequence:
3794#if 0 /* No need for this, I think. */
3795 pLnState->Regs.fEndSequence = true;
3796 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
3797#endif
3798 rtDwarfLine_ResetState(pLnState);
3799 Log2(("%08x: DW_LNE_end_sequence\n", offOpCode));
3800 break;
3801
3802 case DW_LNE_set_address:
3803 pLnState->Regs.uAddress = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
3804 pLnState->Regs.idxOp = 0;
3805 Log2(("%08x: DW_LNE_set_address: %#llx\n", offOpCode, pLnState->Regs.uAddress));
3806 break;
3807
3808 case DW_LNE_define_file:
3809 {
3810 const char *pszFilename = rtDwarfCursor_GetSZ(pCursor, NULL);
3811 uint32_t idxInc = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
3812 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
3813 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
3814 Log2(("%08x: DW_LNE_define_file: {%d}/%s\n", offOpCode, idxInc, pszFilename));
3815
3816 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
3817 if (RT_SUCCESS(rc))
3818 rc = rtDwarfLine_DefineFileName(pLnState, pszFilename, idxInc);
3819 break;
3820 }
3821
3822 /*
3823 * Note! Was defined in DWARF 4. But... Watcom used it
3824 * for setting the segment in DWARF 2, creating
3825 * an incompatibility with the newer standard.
3826 */
3827 case DW_LNE_set_descriminator:
3828 if (pLnState->Hdr.uVer != 2)
3829 {
3830 Assert(pLnState->Hdr.uVer >= 4);
3831 pLnState->Regs.uDiscriminator = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
3832 Log2(("%08x: DW_LNE_set_descriminator: %u\n", offOpCode, pLnState->Regs.uDiscriminator));
3833 }
3834 else
3835 {
3836 uint64_t uSeg = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
3837 Log2(("%08x: DW_LNE_set_segment: %#llx, cbInstr=%#x - Watcom Extension\n", offOpCode, uSeg, cbInstr));
3838 pLnState->Regs.uSegment = (RTSEL)uSeg;
3839 AssertStmt(pLnState->Regs.uSegment == uSeg, rc = VERR_DWARF_BAD_INFO);
3840 }
3841 break;
3842
3843 default:
3844 Log(("rtDwarfLine_RunProgram: Unknown extended opcode %#x, length %#x at %08x\n", bOpCode, cbInstr, offOpCode));
3845 break;
3846 }
3847
3848 /* Advance the cursor to the end of the instruction . */
3849 rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
3850 break;
3851 }
3852 }
3853 }
3854
3855 /*
3856 * Check the status before looping.
3857 */
3858 if (RT_FAILURE(rc))
3859 return rc;
3860 if (RT_FAILURE(pCursor->rc))
3861 return pCursor->rc;
3862 }
3863 return rc;
3864}
3865
3866
3867/**
3868 * Reads the include directories for a line number unit.
3869 *
3870 * @returns IPRT status code
3871 * @param pLnState The line number program state.
3872 * @param pCursor The cursor.
3873 */
3874static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3875{
3876 int rc = rtDwarfLine_DefineFileName(pLnState, "/<bad-zero-file-name-entry>", 0);
3877 if (RT_FAILURE(rc))
3878 return rc;
3879
3880 for (;;)
3881 {
3882 const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL);
3883 if (!*psz)
3884 break;
3885
3886 uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
3887 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
3888 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
3889
3890 rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc);
3891 if (RT_FAILURE(rc))
3892 return rc;
3893 }
3894 return pCursor->rc;
3895}
3896
3897
3898/**
3899 * Reads the include directories for a line number unit.
3900 *
3901 * @returns IPRT status code
3902 * @param pLnState The line number program state.
3903 * @param pCursor The cursor.
3904 */
3905static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
3906{
3907 const char *psz = ""; /* The zeroth is the unit dir. */
3908 for (;;)
3909 {
3910 if ((pLnState->cIncPaths % 2) == 0)
3911 {
3912 void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2));
3913 if (!pv)
3914 return VERR_NO_MEMORY;
3915 pLnState->papszIncPaths = (const char **)pv;
3916 }
3917 Log((" Path #%02u = '%s'\n", pLnState->cIncPaths, psz));
3918 pLnState->papszIncPaths[pLnState->cIncPaths] = psz;
3919 pLnState->cIncPaths++;
3920
3921 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
3922 if (!*psz)
3923 break;
3924 }
3925
3926 return pCursor->rc;
3927}
3928
3929
3930/**
3931 * Explodes the line number table for a compilation unit.
3932 *
3933 * @returns IPRT status code
3934 * @param pThis The DWARF instance.
3935 * @param pCursor The cursor to read the line number information
3936 * via.
3937 */
3938static int rtDwarfLine_ExplodeUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
3939{
3940 RTDWARFLINESTATE LnState;
3941 RT_ZERO(LnState);
3942 LnState.pDwarfMod = pThis;
3943
3944 /*
3945 * Parse the header.
3946 */
3947 rtDwarfCursor_GetInitialLength(pCursor);
3948 LnState.Hdr.uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
3949 if ( LnState.Hdr.uVer < 2
3950 || LnState.Hdr.uVer > 4)
3951 return rtDwarfCursor_SkipUnit(pCursor);
3952
3953 LnState.Hdr.offFirstOpcode = rtDwarfCursor_GetUOff(pCursor, 0);
3954 uint8_t const * const pbFirstOpcode = rtDwarfCursor_CalcPos(pCursor, LnState.Hdr.offFirstOpcode);
3955
3956 LnState.Hdr.cbMinInstr = rtDwarfCursor_GetUByte(pCursor, 0);
3957 if (LnState.Hdr.uVer >= 4)
3958 LnState.Hdr.cMaxOpsPerInstr = rtDwarfCursor_GetUByte(pCursor, 0);
3959 else
3960 LnState.Hdr.cMaxOpsPerInstr = 1;
3961 LnState.Hdr.u8DefIsStmt = rtDwarfCursor_GetUByte(pCursor, 0);
3962 LnState.Hdr.s8LineBase = rtDwarfCursor_GetSByte(pCursor, 0);
3963 LnState.Hdr.u8LineRange = rtDwarfCursor_GetUByte(pCursor, 0);
3964 LnState.Hdr.u8OpcodeBase = rtDwarfCursor_GetUByte(pCursor, 0);
3965
3966 if ( !LnState.Hdr.u8OpcodeBase
3967 || !LnState.Hdr.cMaxOpsPerInstr
3968 || !LnState.Hdr.u8LineRange
3969 || LnState.Hdr.u8DefIsStmt > 1)
3970 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
3971 Log2(("DWARF Line number header:\n"
3972 " uVer %d\n"
3973 " offFirstOpcode %#llx\n"
3974 " cbMinInstr %u\n"
3975 " cMaxOpsPerInstr %u\n"
3976 " u8DefIsStmt %u\n"
3977 " s8LineBase %d\n"
3978 " u8LineRange %u\n"
3979 " u8OpcodeBase %u\n",
3980 LnState.Hdr.uVer, LnState.Hdr.offFirstOpcode, LnState.Hdr.cbMinInstr, LnState.Hdr.cMaxOpsPerInstr,
3981 LnState.Hdr.u8DefIsStmt, LnState.Hdr.s8LineBase, LnState.Hdr.u8LineRange, LnState.Hdr.u8OpcodeBase));
3982
3983 LnState.Hdr.pacStdOperands = pCursor->pb;
3984 for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.Hdr.u8OpcodeBase; iStdOpcode++)
3985 rtDwarfCursor_GetUByte(pCursor, 0);
3986
3987 int rc = pCursor->rc;
3988 if (RT_SUCCESS(rc))
3989 rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor);
3990 if (RT_SUCCESS(rc))
3991 rc = rtDwarfLine_ReadFileNames(&LnState, pCursor);
3992
3993 /*
3994 * Run the program....
3995 */
3996 if (RT_SUCCESS(rc))
3997 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbFirstOpcode);
3998 if (RT_SUCCESS(rc))
3999 rc = rtDwarfLine_RunProgram(&LnState, pCursor);
4000
4001 /*
4002 * Clean up.
4003 */
4004 size_t i = LnState.cFileNames;
4005 while (i-- > 0)
4006 RTStrFree(LnState.papszFileNames[i]);
4007 RTMemFree(LnState.papszFileNames);
4008 RTMemFree(LnState.papszIncPaths);
4009
4010 Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc));
4011 return rc;
4012}
4013
4014
4015/**
4016 * Explodes the line number table.
4017 *
4018 * The line numbers are insered into the debug info container.
4019 *
4020 * @returns IPRT status code
4021 * @param pThis The DWARF instance.
4022 */
4023static int rtDwarfLine_ExplodeAll(PRTDBGMODDWARF pThis)
4024{
4025 if (!pThis->aSections[krtDbgModDwarfSect_line].fPresent)
4026 return VINF_SUCCESS;
4027
4028 RTDWARFCURSOR Cursor;
4029 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line);
4030 if (RT_FAILURE(rc))
4031 return rc;
4032
4033 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
4034 && RT_SUCCESS(rc))
4035 rc = rtDwarfLine_ExplodeUnit(pThis, &Cursor);
4036
4037 return rtDwarfCursor_Delete(&Cursor, rc);
4038}
4039
4040
4041/*
4042 *
4043 * DWARF Abbreviations.
4044 * DWARF Abbreviations.
4045 * DWARF Abbreviations.
4046 *
4047 */
4048
4049/**
4050 * Deals with a cache miss in rtDwarfAbbrev_Lookup.
4051 *
4052 * @returns Pointer to abbreviation cache entry (read only). May be rendered
4053 * invalid by subsequent calls to this function.
4054 * @param pThis The DWARF instance.
4055 * @param uCode The abbreviation code to lookup.
4056 */
4057static PCRTDWARFABBREV rtDwarfAbbrev_LookupMiss(PRTDBGMODDWARF pThis, uint32_t uCode)
4058{
4059 /*
4060 * There is no entry with code zero.
4061 */
4062 if (!uCode)
4063 return NULL;
4064
4065 /*
4066 * Resize the cache array if the code is considered cachable.
4067 */
4068 bool fFillCache = true;
4069 if (pThis->cCachedAbbrevsAlloced < uCode)
4070 {
4071 if (uCode >= _64K)
4072 fFillCache = false;
4073 else
4074 {
4075 uint32_t cNew = RT_ALIGN(uCode, 64);
4076 void *pv = RTMemRealloc(pThis->paCachedAbbrevs, sizeof(pThis->paCachedAbbrevs[0]) * cNew);
4077 if (!pv)
4078 fFillCache = false;
4079 else
4080 {
4081 Log(("rtDwarfAbbrev_LookupMiss: Growing from %u to %u...\n", pThis->cCachedAbbrevsAlloced, cNew));
4082 pThis->paCachedAbbrevs = (PRTDWARFABBREV)pv;
4083 for (uint32_t i = pThis->cCachedAbbrevsAlloced; i < cNew; i++)
4084 pThis->paCachedAbbrevs[i].offAbbrev = UINT32_MAX;
4085 pThis->cCachedAbbrevsAlloced = cNew;
4086 }
4087 }
4088 }
4089
4090 /*
4091 * Walk the abbreviations till we find the desired code.
4092 */
4093 RTDWARFCURSOR Cursor;
4094 int rc = rtDwarfCursor_InitWithOffset(&Cursor, pThis, krtDbgModDwarfSect_abbrev, pThis->offCachedAbbrev);
4095 if (RT_FAILURE(rc))
4096 return NULL;
4097
4098 PRTDWARFABBREV pRet = NULL;
4099 if (fFillCache)
4100 {
4101 /*
4102 * Search for the entry and fill the cache while doing so.
4103 * We assume that abbreviation codes for a unit will stop when we see
4104 * zero code or when the code value drops.
4105 */
4106 uint32_t uPrevCode = 0;
4107 for (;;)
4108 {
4109 /* Read the 'header'. Skipping zero code bytes. */
4110#ifdef LOG_ENABLED
4111 uint32_t const offStart = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4112#endif
4113 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4114 if (pRet && (uCurCode == 0 || uCurCode < uPrevCode))
4115 break; /* probably end of unit. */
4116 if (uCurCode != 0)
4117 {
4118 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4119 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
4120 if (RT_FAILURE(Cursor.rc))
4121 break;
4122 if ( uCurTag > 0xffff
4123 || uChildren > 1)
4124 {
4125 Cursor.rc = VERR_DWARF_BAD_ABBREV;
4126 break;
4127 }
4128
4129 /* Cache it? */
4130 if (uCurCode <= pThis->cCachedAbbrevsAlloced)
4131 {
4132 PRTDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
4133 if (pEntry->offAbbrev != pThis->offCachedAbbrev)
4134 {
4135 pEntry->offAbbrev = pThis->offCachedAbbrev;
4136 pEntry->fChildren = RT_BOOL(uChildren);
4137 pEntry->uTag = uCurTag;
4138 pEntry->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4139#ifdef LOG_ENABLED
4140 pEntry->cbHdr = (uint8_t)(pEntry->offSpec - offStart);
4141 Log7(("rtDwarfAbbrev_LookupMiss(%#x): fill: %#x: uTag=%#x offAbbrev=%#x%s\n",
4142 uCode, offStart, pEntry->uTag, pEntry->offAbbrev, pEntry->fChildren ? " has-children" : ""));
4143#endif
4144 if (uCurCode == uCode)
4145 {
4146 Assert(!pRet);
4147 pRet = pEntry;
4148 if (uCurCode == pThis->cCachedAbbrevsAlloced)
4149 break;
4150 }
4151 }
4152 else if (pRet)
4153 break; /* Next unit, don't cache more. */
4154 /* else: We're growing the cache and re-reading old data. */
4155 }
4156
4157 /* Skip the specification. */
4158 uint32_t uAttr, uForm;
4159 do
4160 {
4161 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4162 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4163 } while (uAttr != 0);
4164 }
4165 if (RT_FAILURE(Cursor.rc))
4166 break;
4167
4168 /* Done? (Maximize cache filling.) */
4169 if ( pRet != NULL
4170 && uCurCode >= pThis->cCachedAbbrevsAlloced)
4171 break;
4172 uPrevCode = uCurCode;
4173 }
4174 if (pRet)
4175 Log6(("rtDwarfAbbrev_LookupMiss(%#x): uTag=%#x offSpec=%#x offAbbrev=%#x [fill]\n",
4176 uCode, pRet->uTag, pRet->offSpec, pRet->offAbbrev));
4177 else
4178 Log6(("rtDwarfAbbrev_LookupMiss(%#x): failed [fill]\n", uCode));
4179 }
4180 else
4181 {
4182 /*
4183 * Search for the entry with the desired code, no cache filling.
4184 */
4185 for (;;)
4186 {
4187 /* Read the 'header'. */
4188#ifdef LOG_ENABLED
4189 uint32_t const offStart = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4190#endif
4191 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4192 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4193 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
4194 if (RT_FAILURE(Cursor.rc))
4195 break;
4196 if ( uCurTag > 0xffff
4197 || uChildren > 1)
4198 {
4199 Cursor.rc = VERR_DWARF_BAD_ABBREV;
4200 break;
4201 }
4202
4203 /* Do we have a match? */
4204 if (uCurCode == uCode)
4205 {
4206 pRet = &pThis->LookupAbbrev;
4207 pRet->fChildren = RT_BOOL(uChildren);
4208 pRet->uTag = uCurTag;
4209 pRet->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
4210 pRet->offAbbrev = pThis->offCachedAbbrev;
4211#ifdef LOG_ENABLED
4212 pRet->cbHdr = (uint8_t)(pRet->offSpec - offStart);
4213#endif
4214 break;
4215 }
4216
4217 /* Skip the specification. */
4218 uint32_t uAttr, uForm;
4219 do
4220 {
4221 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4222 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
4223 } while (uAttr != 0);
4224 if (RT_FAILURE(Cursor.rc))
4225 break;
4226 }
4227 if (pRet)
4228 Log6(("rtDwarfAbbrev_LookupMiss(%#x): uTag=%#x offSpec=%#x offAbbrev=%#x [no-fill]\n",
4229 uCode, pRet->uTag, pRet->offSpec, pRet->offAbbrev));
4230 else
4231 Log6(("rtDwarfAbbrev_LookupMiss(%#x): failed [no-fill]\n", uCode));
4232 }
4233
4234 rtDwarfCursor_Delete(&Cursor, VINF_SUCCESS);
4235 return pRet;
4236}
4237
4238
4239/**
4240 * Looks up an abbreviation.
4241 *
4242 * @returns Pointer to abbreviation cache entry (read only). May be rendered
4243 * invalid by subsequent calls to this function.
4244 * @param pThis The DWARF instance.
4245 * @param uCode The abbreviation code to lookup.
4246 */
4247static PCRTDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
4248{
4249 uCode -= 1;
4250 if (uCode < pThis->cCachedAbbrevsAlloced)
4251 {
4252 if (pThis->paCachedAbbrevs[uCode].offAbbrev == pThis->offCachedAbbrev)
4253 return &pThis->paCachedAbbrevs[uCode];
4254 }
4255 return rtDwarfAbbrev_LookupMiss(pThis, uCode + 1);
4256}
4257
4258
4259/**
4260 * Sets the abbreviation offset of the current unit.
4261 *
4262 * @param pThis The DWARF instance.
4263 * @param offAbbrev The offset into the abbreviation section.
4264 */
4265static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
4266{
4267 pThis->offCachedAbbrev = offAbbrev;
4268}
4269
4270
4271
4272/*
4273 *
4274 * DIE Attribute Parsers.
4275 * DIE Attribute Parsers.
4276 * DIE Attribute Parsers.
4277 *
4278 */
4279
4280/**
4281 * Gets the compilation unit a DIE belongs to.
4282 *
4283 * @returns The compilation unit DIE.
4284 * @param pDie Some DIE in the unit.
4285 */
4286static PRTDWARFDIECOMPILEUNIT rtDwarfDie_GetCompileUnit(PRTDWARFDIE pDie)
4287{
4288 while (pDie->pParent)
4289 pDie = pDie->pParent;
4290 AssertReturn( pDie->uTag == DW_TAG_compile_unit
4291 || pDie->uTag == DW_TAG_partial_unit,
4292 NULL);
4293 return (PRTDWARFDIECOMPILEUNIT)pDie;
4294}
4295
4296
4297/**
4298 * Resolves a string section (debug_str) reference.
4299 *
4300 * @returns Pointer to the string (inside the string section).
4301 * @param pThis The DWARF instance.
4302 * @param pCursor The cursor.
4303 * @param pszErrValue What to return on failure (@a
4304 * pCursor->rc is set).
4305 */
4306static const char *rtDwarfDecodeHlp_GetStrp(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, const char *pszErrValue)
4307{
4308 uint64_t offDebugStr = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
4309 if (RT_FAILURE(pCursor->rc))
4310 return pszErrValue;
4311
4312 if (offDebugStr >= pThis->aSections[krtDbgModDwarfSect_str].cb)
4313 {
4314 /* Ugly: Exploit the cursor status field for reporting errors. */
4315 pCursor->rc = VERR_DWARF_BAD_INFO;
4316 return pszErrValue;
4317 }
4318
4319 if (!pThis->aSections[krtDbgModDwarfSect_str].pv)
4320 {
4321 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_str);
4322 if (RT_FAILURE(rc))
4323 {
4324 /* Ugly: Exploit the cursor status field for reporting errors. */
4325 pCursor->rc = rc;
4326 return pszErrValue;
4327 }
4328 }
4329
4330 return (const char *)pThis->aSections[krtDbgModDwarfSect_str].pv + (size_t)offDebugStr;
4331}
4332
4333
4334/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4335static DECLCALLBACK(int) rtDwarfDecode_Address(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4336 uint32_t uForm, PRTDWARFCURSOR pCursor)
4337{
4338 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDR), VERR_INTERNAL_ERROR_3);
4339 NOREF(pDie);
4340
4341 uint64_t uAddr;
4342 switch (uForm)
4343 {
4344 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4345 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
4346 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
4347 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
4348 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
4349 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4350 default:
4351 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
4352 }
4353 if (RT_FAILURE(pCursor->rc))
4354 return pCursor->rc;
4355
4356 PRTDWARFADDR pAddr = (PRTDWARFADDR)pbMember;
4357 pAddr->uAddress = uAddr;
4358
4359 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
4360 return VINF_SUCCESS;
4361}
4362
4363
4364/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4365static DECLCALLBACK(int) rtDwarfDecode_Bool(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4366 uint32_t uForm, PRTDWARFCURSOR pCursor)
4367{
4368 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(bool), VERR_INTERNAL_ERROR_3);
4369 NOREF(pDie);
4370
4371 bool *pfMember = (bool *)pbMember;
4372 switch (uForm)
4373 {
4374 case DW_FORM_flag:
4375 {
4376 uint8_t b = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
4377 if (b > 1)
4378 {
4379 Log(("Unexpected boolean value %#x\n", b));
4380 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pCursor->rc = VERR_DWARF_BAD_INFO;
4381 }
4382 *pfMember = RT_BOOL(b);
4383 break;
4384 }
4385
4386 case DW_FORM_flag_present:
4387 *pfMember = true;
4388 break;
4389
4390 default:
4391 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4392 }
4393
4394 Log4((" %-20s %RTbool [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), *pfMember, rtDwarfLog_FormName(uForm)));
4395 return VINF_SUCCESS;
4396}
4397
4398
4399/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4400static DECLCALLBACK(int) rtDwarfDecode_LowHighPc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4401 uint32_t uForm, PRTDWARFCURSOR pCursor)
4402{
4403 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
4404 AssertReturn(pDesc->uAttr == DW_AT_low_pc || pDesc->uAttr == DW_AT_high_pc, VERR_INTERNAL_ERROR_3);
4405 NOREF(pDie);
4406
4407 uint64_t uAddr;
4408 switch (uForm)
4409 {
4410 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4411 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
4412 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
4413 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
4414 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
4415 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4416 default:
4417 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4418 }
4419 if (RT_FAILURE(pCursor->rc))
4420 return pCursor->rc;
4421
4422 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
4423 if (pDesc->uAttr == DW_AT_low_pc)
4424 {
4425 if (pRange->fHaveLowAddress)
4426 {
4427 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_low_pc\n"));
4428 return pCursor->rc = VERR_DWARF_BAD_INFO;
4429 }
4430 pRange->fHaveLowAddress = true;
4431 pRange->uLowAddress = uAddr;
4432 }
4433 else
4434 {
4435 if (pRange->fHaveHighAddress)
4436 {
4437 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_high_pc\n"));
4438 return pCursor->rc = VERR_DWARF_BAD_INFO;
4439 }
4440 pRange->fHaveHighAddress = true;
4441 pRange->fHaveHighIsAddress = uForm == DW_FORM_addr;
4442 if (!pRange->fHaveHighIsAddress && pRange->fHaveLowAddress)
4443 {
4444 pRange->fHaveHighIsAddress = true;
4445 pRange->uHighAddress = uAddr + pRange->uLowAddress;
4446 }
4447 else
4448 pRange->uHighAddress = uAddr;
4449
4450 }
4451 pRange->cAttrs++;
4452
4453 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
4454 return VINF_SUCCESS;
4455}
4456
4457
4458/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4459static DECLCALLBACK(int) rtDwarfDecode_Ranges(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4460 uint32_t uForm, PRTDWARFCURSOR pCursor)
4461{
4462 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
4463 AssertReturn(pDesc->uAttr == DW_AT_ranges, VERR_INTERNAL_ERROR_3);
4464 NOREF(pDie);
4465
4466 /* Decode it. */
4467 uint64_t off;
4468 switch (uForm)
4469 {
4470 case DW_FORM_addr: off = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
4471 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4472 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4473 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
4474 default:
4475 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4476 }
4477 if (RT_FAILURE(pCursor->rc))
4478 return pCursor->rc;
4479
4480 /* Validate the offset and load the ranges. */
4481 PRTDBGMODDWARF pThis = pCursor->pDwarfMod;
4482 if (off >= pThis->aSections[krtDbgModDwarfSect_ranges].cb)
4483 {
4484 Log(("rtDwarfDecode_Ranges: bad ranges off=%#llx\n", off));
4485 return pCursor->rc = VERR_DWARF_BAD_POS;
4486 }
4487
4488 if (!pThis->aSections[krtDbgModDwarfSect_ranges].pv)
4489 {
4490 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_ranges);
4491 if (RT_FAILURE(rc))
4492 return pCursor->rc = rc;
4493 }
4494
4495 /* Store the result. */
4496 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
4497 if (pRange->fHaveRanges)
4498 {
4499 Log(("rtDwarfDecode_Ranges: Duplicate DW_AT_ranges\n"));
4500 return pCursor->rc = VERR_DWARF_BAD_INFO;
4501 }
4502 pRange->fHaveRanges = true;
4503 pRange->cAttrs++;
4504 pRange->pbRanges = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_ranges].pv + (size_t)off;
4505
4506 Log4((" %-20s TODO [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), rtDwarfLog_FormName(uForm)));
4507 return VINF_SUCCESS;
4508}
4509
4510
4511/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4512static DECLCALLBACK(int) rtDwarfDecode_Reference(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4513 uint32_t uForm, PRTDWARFCURSOR pCursor)
4514{
4515 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
4516
4517 /* Decode it. */
4518 uint64_t off;
4519 krtDwarfRef enmWrt = krtDwarfRef_SameUnit;
4520 switch (uForm)
4521 {
4522 case DW_FORM_ref1: off = rtDwarfCursor_GetU8(pCursor, 0); break;
4523 case DW_FORM_ref2: off = rtDwarfCursor_GetU16(pCursor, 0); break;
4524 case DW_FORM_ref4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4525 case DW_FORM_ref8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4526 case DW_FORM_ref_udata: off = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4527
4528 case DW_FORM_ref_addr:
4529 enmWrt = krtDwarfRef_InfoSection;
4530 off = rtDwarfCursor_GetUOff(pCursor, 0);
4531 break;
4532
4533 case DW_FORM_ref_sig8:
4534 enmWrt = krtDwarfRef_TypeId64;
4535 off = rtDwarfCursor_GetU64(pCursor, 0);
4536 break;
4537
4538 default:
4539 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4540 }
4541 if (RT_FAILURE(pCursor->rc))
4542 return pCursor->rc;
4543
4544 /* Validate the offset and convert to debug_info relative offsets. */
4545 if (enmWrt == krtDwarfRef_InfoSection)
4546 {
4547 if (off >= pCursor->pDwarfMod->aSections[krtDbgModDwarfSect_info].cb)
4548 {
4549 Log(("rtDwarfDecode_Reference: bad info off=%#llx\n", off));
4550 return pCursor->rc = VERR_DWARF_BAD_POS;
4551 }
4552 }
4553 else if (enmWrt == krtDwarfRef_SameUnit)
4554 {
4555 PRTDWARFDIECOMPILEUNIT pUnit = rtDwarfDie_GetCompileUnit(pDie);
4556 if (off >= pUnit->cbUnit)
4557 {
4558 Log(("rtDwarfDecode_Reference: bad unit off=%#llx\n", off));
4559 return pCursor->rc = VERR_DWARF_BAD_POS;
4560 }
4561 off += pUnit->offUnit;
4562 enmWrt = krtDwarfRef_InfoSection;
4563 }
4564 /* else: not bother verifying/resolving the indirect type reference yet. */
4565
4566 /* Store it */
4567 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
4568 pRef->enmWrt = enmWrt;
4569 pRef->off = off;
4570
4571 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
4572 return VINF_SUCCESS;
4573}
4574
4575
4576/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4577static DECLCALLBACK(int) rtDwarfDecode_SectOff(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4578 uint32_t uForm, PRTDWARFCURSOR pCursor)
4579{
4580 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
4581 NOREF(pDie);
4582
4583 uint64_t off;
4584 switch (uForm)
4585 {
4586 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
4587 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
4588 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
4589 default:
4590 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
4591 }
4592 if (RT_FAILURE(pCursor->rc))
4593 return pCursor->rc;
4594
4595 krtDbgModDwarfSect enmSect;
4596 krtDwarfRef enmWrt;
4597 switch (pDesc->uAttr)
4598 {
4599 case DW_AT_stmt_list: enmSect = krtDbgModDwarfSect_line; enmWrt = krtDwarfRef_LineSection; break;
4600 case DW_AT_macro_info: enmSect = krtDbgModDwarfSect_loc; enmWrt = krtDwarfRef_LocSection; break;
4601 case DW_AT_ranges: enmSect = krtDbgModDwarfSect_ranges; enmWrt = krtDwarfRef_RangesSection; break;
4602 default:
4603 AssertMsgFailedReturn(("%u (%s)\n", pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr)), VERR_INTERNAL_ERROR_4);
4604 }
4605 size_t cbSect = pCursor->pDwarfMod->aSections[enmSect].cb;
4606 if (off >= cbSect)
4607 {
4608 /* Watcom generates offset past the end of the section, increasing the
4609 offset by one for each compile unit. So, just fudge it. */
4610 Log(("rtDwarfDecode_SectOff: bad off=%#llx, attr %#x (%s), enmSect=%d cb=%#llx; Assuming watcom/gcc.\n", off,
4611 pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr), enmSect, cbSect));
4612 off = cbSect;
4613 }
4614
4615 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
4616 pRef->enmWrt = enmWrt;
4617 pRef->off = off;
4618
4619 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
4620 return VINF_SUCCESS;
4621}
4622
4623
4624/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4625static DECLCALLBACK(int) rtDwarfDecode_String(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4626 uint32_t uForm, PRTDWARFCURSOR pCursor)
4627{
4628 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(const char *), VERR_INTERNAL_ERROR_3);
4629 NOREF(pDie);
4630
4631 const char *psz;
4632 switch (uForm)
4633 {
4634 case DW_FORM_string:
4635 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
4636 break;
4637
4638 case DW_FORM_strp:
4639 psz = rtDwarfDecodeHlp_GetStrp(pCursor->pDwarfMod, pCursor, NULL);
4640 break;
4641
4642 default:
4643 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4644 }
4645
4646 *(const char **)pbMember = psz;
4647 Log4((" %-20s '%s' [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), psz, rtDwarfLog_FormName(uForm)));
4648 return pCursor->rc;
4649}
4650
4651
4652/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4653static DECLCALLBACK(int) rtDwarfDecode_UnsignedInt(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4654 uint32_t uForm, PRTDWARFCURSOR pCursor)
4655{
4656 NOREF(pDie);
4657 uint64_t u64Val;
4658 switch (uForm)
4659 {
4660 case DW_FORM_udata: u64Val = rtDwarfCursor_GetULeb128(pCursor, 0); break;
4661 case DW_FORM_data1: u64Val = rtDwarfCursor_GetU8(pCursor, 0); break;
4662 case DW_FORM_data2: u64Val = rtDwarfCursor_GetU16(pCursor, 0); break;
4663 case DW_FORM_data4: u64Val = rtDwarfCursor_GetU32(pCursor, 0); break;
4664 case DW_FORM_data8: u64Val = rtDwarfCursor_GetU64(pCursor, 0); break;
4665 default:
4666 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4667 }
4668 if (RT_FAILURE(pCursor->rc))
4669 return pCursor->rc;
4670
4671 switch (ATTR_GET_SIZE(pDesc))
4672 {
4673 case 1:
4674 *pbMember = (uint8_t)u64Val;
4675 if (*pbMember != u64Val)
4676 {
4677 AssertFailed();
4678 return VERR_OUT_OF_RANGE;
4679 }
4680 break;
4681
4682 case 2:
4683 *(uint16_t *)pbMember = (uint16_t)u64Val;
4684 if (*(uint16_t *)pbMember != u64Val)
4685 {
4686 AssertFailed();
4687 return VERR_OUT_OF_RANGE;
4688 }
4689 break;
4690
4691 case 4:
4692 *(uint32_t *)pbMember = (uint32_t)u64Val;
4693 if (*(uint32_t *)pbMember != u64Val)
4694 {
4695 AssertFailed();
4696 return VERR_OUT_OF_RANGE;
4697 }
4698 break;
4699
4700 case 8:
4701 *(uint64_t *)pbMember = (uint64_t)u64Val;
4702 if (*(uint64_t *)pbMember != u64Val)
4703 {
4704 AssertFailed();
4705 return VERR_OUT_OF_RANGE;
4706 }
4707 break;
4708
4709 default:
4710 AssertMsgFailedReturn(("%#x\n", ATTR_GET_SIZE(pDesc)), VERR_INTERNAL_ERROR_2);
4711 }
4712 return VINF_SUCCESS;
4713}
4714
4715
4716/**
4717 * Initialize location interpreter state from cursor & form.
4718 *
4719 * @returns IPRT status code.
4720 * @retval VERR_NOT_FOUND if no location information (i.e. there is source but
4721 * it resulted in no byte code).
4722 * @param pLoc The location state structure to initialize.
4723 * @param pCursor The cursor to read from.
4724 * @param uForm The attribute form.
4725 */
4726static int rtDwarfLoc_Init(PRTDWARFLOCST pLoc, PRTDWARFCURSOR pCursor, uint32_t uForm)
4727{
4728 uint32_t cbBlock;
4729 switch (uForm)
4730 {
4731 case DW_FORM_block1:
4732 cbBlock = rtDwarfCursor_GetU8(pCursor, 0);
4733 break;
4734
4735 case DW_FORM_block2:
4736 cbBlock = rtDwarfCursor_GetU16(pCursor, 0);
4737 break;
4738
4739 case DW_FORM_block4:
4740 cbBlock = rtDwarfCursor_GetU32(pCursor, 0);
4741 break;
4742
4743 case DW_FORM_block:
4744 cbBlock = rtDwarfCursor_GetULeb128(pCursor, 0);
4745 break;
4746
4747 default:
4748 AssertMsgFailedReturn(("uForm=%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
4749 }
4750 if (!cbBlock)
4751 return VERR_NOT_FOUND;
4752
4753 int rc = rtDwarfCursor_InitForBlock(&pLoc->Cursor, pCursor, cbBlock);
4754 if (RT_FAILURE(rc))
4755 return rc;
4756 pLoc->iTop = -1;
4757 return VINF_SUCCESS;
4758}
4759
4760
4761/**
4762 * Pushes a value onto the stack.
4763 *
4764 * @returns VINF_SUCCESS or VERR_DWARF_STACK_OVERFLOW.
4765 * @param pLoc The state.
4766 * @param uValue The value to push.
4767 */
4768static int rtDwarfLoc_Push(PRTDWARFLOCST pLoc, uint64_t uValue)
4769{
4770 int iTop = pLoc->iTop + 1;
4771 AssertReturn((unsigned)iTop < RT_ELEMENTS(pLoc->auStack), VERR_DWARF_STACK_OVERFLOW);
4772 pLoc->auStack[iTop] = uValue;
4773 pLoc->iTop = iTop;
4774 return VINF_SUCCESS;
4775}
4776
4777
4778static int rtDwarfLoc_Evaluate(PRTDWARFLOCST pLoc, void *pvLater, void *pvUser)
4779{
4780 RT_NOREF_PV(pvLater); RT_NOREF_PV(pvUser);
4781
4782 while (!rtDwarfCursor_IsAtEndOfUnit(&pLoc->Cursor))
4783 {
4784 /* Read the next opcode.*/
4785 uint8_t const bOpcode = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4786
4787 /* Get its operands. */
4788 uint64_t uOperand1 = 0;
4789 uint64_t uOperand2 = 0;
4790 switch (bOpcode)
4791 {
4792 case DW_OP_addr:
4793 uOperand1 = rtDwarfCursor_GetNativeUOff(&pLoc->Cursor, 0);
4794 break;
4795 case DW_OP_pick:
4796 case DW_OP_const1u:
4797 case DW_OP_deref_size:
4798 case DW_OP_xderef_size:
4799 uOperand1 = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4800 break;
4801 case DW_OP_const1s:
4802 uOperand1 = (int8_t)rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
4803 break;
4804 case DW_OP_const2u:
4805 uOperand1 = rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
4806 break;
4807 case DW_OP_skip:
4808 case DW_OP_bra:
4809 case DW_OP_const2s:
4810 uOperand1 = (int16_t)rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
4811 break;
4812 case DW_OP_const4u:
4813 uOperand1 = rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
4814 break;
4815 case DW_OP_const4s:
4816 uOperand1 = (int32_t)rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
4817 break;
4818 case DW_OP_const8u:
4819 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
4820 break;
4821 case DW_OP_const8s:
4822 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
4823 break;
4824 case DW_OP_regx:
4825 case DW_OP_piece:
4826 case DW_OP_plus_uconst:
4827 case DW_OP_constu:
4828 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
4829 break;
4830 case DW_OP_consts:
4831 case DW_OP_fbreg:
4832 case DW_OP_breg0+0: case DW_OP_breg0+1: case DW_OP_breg0+2: case DW_OP_breg0+3:
4833 case DW_OP_breg0+4: case DW_OP_breg0+5: case DW_OP_breg0+6: case DW_OP_breg0+7:
4834 case DW_OP_breg0+8: case DW_OP_breg0+9: case DW_OP_breg0+10: case DW_OP_breg0+11:
4835 case DW_OP_breg0+12: case DW_OP_breg0+13: case DW_OP_breg0+14: case DW_OP_breg0+15:
4836 case DW_OP_breg0+16: case DW_OP_breg0+17: case DW_OP_breg0+18: case DW_OP_breg0+19:
4837 case DW_OP_breg0+20: case DW_OP_breg0+21: case DW_OP_breg0+22: case DW_OP_breg0+23:
4838 case DW_OP_breg0+24: case DW_OP_breg0+25: case DW_OP_breg0+26: case DW_OP_breg0+27:
4839 case DW_OP_breg0+28: case DW_OP_breg0+29: case DW_OP_breg0+30: case DW_OP_breg0+31:
4840 uOperand1 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
4841 break;
4842 case DW_OP_bregx:
4843 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
4844 uOperand2 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
4845 break;
4846 }
4847 if (RT_FAILURE(pLoc->Cursor.rc))
4848 break;
4849
4850 /* Interpret the opcode. */
4851 int rc;
4852 switch (bOpcode)
4853 {
4854 case DW_OP_const1u:
4855 case DW_OP_const1s:
4856 case DW_OP_const2u:
4857 case DW_OP_const2s:
4858 case DW_OP_const4u:
4859 case DW_OP_const4s:
4860 case DW_OP_const8u:
4861 case DW_OP_const8s:
4862 case DW_OP_constu:
4863 case DW_OP_consts:
4864 case DW_OP_addr:
4865 rc = rtDwarfLoc_Push(pLoc, uOperand1);
4866 break;
4867 case DW_OP_lit0 + 0: case DW_OP_lit0 + 1: case DW_OP_lit0 + 2: case DW_OP_lit0 + 3:
4868 case DW_OP_lit0 + 4: case DW_OP_lit0 + 5: case DW_OP_lit0 + 6: case DW_OP_lit0 + 7:
4869 case DW_OP_lit0 + 8: case DW_OP_lit0 + 9: case DW_OP_lit0 + 10: case DW_OP_lit0 + 11:
4870 case DW_OP_lit0 + 12: case DW_OP_lit0 + 13: case DW_OP_lit0 + 14: case DW_OP_lit0 + 15:
4871 case DW_OP_lit0 + 16: case DW_OP_lit0 + 17: case DW_OP_lit0 + 18: case DW_OP_lit0 + 19:
4872 case DW_OP_lit0 + 20: case DW_OP_lit0 + 21: case DW_OP_lit0 + 22: case DW_OP_lit0 + 23:
4873 case DW_OP_lit0 + 24: case DW_OP_lit0 + 25: case DW_OP_lit0 + 26: case DW_OP_lit0 + 27:
4874 case DW_OP_lit0 + 28: case DW_OP_lit0 + 29: case DW_OP_lit0 + 30: case DW_OP_lit0 + 31:
4875 rc = rtDwarfLoc_Push(pLoc, bOpcode - DW_OP_lit0);
4876 break;
4877 case DW_OP_nop:
4878 break;
4879 case DW_OP_dup: /** @todo 0 operands. */
4880 case DW_OP_drop: /** @todo 0 operands. */
4881 case DW_OP_over: /** @todo 0 operands. */
4882 case DW_OP_pick: /** @todo 1 operands, a 1-byte stack index. */
4883 case DW_OP_swap: /** @todo 0 operands. */
4884 case DW_OP_rot: /** @todo 0 operands. */
4885 case DW_OP_abs: /** @todo 0 operands. */
4886 case DW_OP_and: /** @todo 0 operands. */
4887 case DW_OP_div: /** @todo 0 operands. */
4888 case DW_OP_minus: /** @todo 0 operands. */
4889 case DW_OP_mod: /** @todo 0 operands. */
4890 case DW_OP_mul: /** @todo 0 operands. */
4891 case DW_OP_neg: /** @todo 0 operands. */
4892 case DW_OP_not: /** @todo 0 operands. */
4893 case DW_OP_or: /** @todo 0 operands. */
4894 case DW_OP_plus: /** @todo 0 operands. */
4895 case DW_OP_plus_uconst: /** @todo 1 operands, a ULEB128 addend. */
4896 case DW_OP_shl: /** @todo 0 operands. */
4897 case DW_OP_shr: /** @todo 0 operands. */
4898 case DW_OP_shra: /** @todo 0 operands. */
4899 case DW_OP_xor: /** @todo 0 operands. */
4900 case DW_OP_skip: /** @todo 1 signed 2-byte constant. */
4901 case DW_OP_bra: /** @todo 1 signed 2-byte constant. */
4902 case DW_OP_eq: /** @todo 0 operands. */
4903 case DW_OP_ge: /** @todo 0 operands. */
4904 case DW_OP_gt: /** @todo 0 operands. */
4905 case DW_OP_le: /** @todo 0 operands. */
4906 case DW_OP_lt: /** @todo 0 operands. */
4907 case DW_OP_ne: /** @todo 0 operands. */
4908 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. */
4909 case DW_OP_reg0 + 4: case DW_OP_reg0 + 5: case DW_OP_reg0 + 6: case DW_OP_reg0 + 7:
4910 case DW_OP_reg0 + 8: case DW_OP_reg0 + 9: case DW_OP_reg0 + 10: case DW_OP_reg0 + 11:
4911 case DW_OP_reg0 + 12: case DW_OP_reg0 + 13: case DW_OP_reg0 + 14: case DW_OP_reg0 + 15:
4912 case DW_OP_reg0 + 16: case DW_OP_reg0 + 17: case DW_OP_reg0 + 18: case DW_OP_reg0 + 19:
4913 case DW_OP_reg0 + 20: case DW_OP_reg0 + 21: case DW_OP_reg0 + 22: case DW_OP_reg0 + 23:
4914 case DW_OP_reg0 + 24: case DW_OP_reg0 + 25: case DW_OP_reg0 + 26: case DW_OP_reg0 + 27:
4915 case DW_OP_reg0 + 28: case DW_OP_reg0 + 29: case DW_OP_reg0 + 30: case DW_OP_reg0 + 31:
4916 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. */
4917 case DW_OP_breg0+ 4: case DW_OP_breg0+ 5: case DW_OP_breg0+ 6: case DW_OP_breg0+ 7:
4918 case DW_OP_breg0+ 8: case DW_OP_breg0+ 9: case DW_OP_breg0+ 10: case DW_OP_breg0+ 11:
4919 case DW_OP_breg0+ 12: case DW_OP_breg0+ 13: case DW_OP_breg0+ 14: case DW_OP_breg0+ 15:
4920 case DW_OP_breg0+ 16: case DW_OP_breg0+ 17: case DW_OP_breg0+ 18: case DW_OP_breg0+ 19:
4921 case DW_OP_breg0+ 20: case DW_OP_breg0+ 21: case DW_OP_breg0+ 22: case DW_OP_breg0+ 23:
4922 case DW_OP_breg0+ 24: case DW_OP_breg0+ 25: case DW_OP_breg0+ 26: case DW_OP_breg0+ 27:
4923 case DW_OP_breg0+ 28: case DW_OP_breg0+ 29: case DW_OP_breg0+ 30: case DW_OP_breg0+ 31:
4924 case DW_OP_piece: /** @todo 1 operand, a ULEB128 size of piece addressed. */
4925 case DW_OP_regx: /** @todo 1 operand, a ULEB128 register. */
4926 case DW_OP_fbreg: /** @todo 1 operand, a SLEB128 offset. */
4927 case DW_OP_bregx: /** @todo 2 operands, a ULEB128 register followed by a SLEB128 offset. */
4928 case DW_OP_deref: /** @todo 0 operands. */
4929 case DW_OP_deref_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
4930 case DW_OP_xderef: /** @todo 0 operands. */
4931 case DW_OP_xderef_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
4932 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_TODO);
4933 default:
4934 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_UNKNOWN_LOC_OPCODE);
4935 }
4936 }
4937
4938 return pLoc->Cursor.rc;
4939}
4940
4941
4942/** @callback_method_impl{FNRTDWARFATTRDECODER} */
4943static DECLCALLBACK(int) rtDwarfDecode_SegmentLoc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
4944 uint32_t uForm, PRTDWARFCURSOR pCursor)
4945{
4946 NOREF(pDie);
4947 AssertReturn(ATTR_GET_SIZE(pDesc) == 2, VERR_DWARF_IPE);
4948
4949 int rc;
4950 if ( uForm == DW_FORM_block
4951 || uForm == DW_FORM_block1
4952 || uForm == DW_FORM_block2
4953 || uForm == DW_FORM_block4)
4954 {
4955 RTDWARFLOCST LocSt;
4956 rc = rtDwarfLoc_Init(&LocSt, pCursor, uForm);
4957 if (RT_SUCCESS(rc))
4958 {
4959 rc = rtDwarfLoc_Evaluate(&LocSt, NULL, NULL);
4960 if (RT_SUCCESS(rc))
4961 {
4962 if (LocSt.iTop >= 0)
4963 {
4964 *(uint16_t *)pbMember = LocSt.auStack[LocSt.iTop];
4965 Log4((" %-20s %#06llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr),
4966 LocSt.auStack[LocSt.iTop], rtDwarfLog_FormName(uForm)));
4967 return VINF_SUCCESS;
4968 }
4969 rc = VERR_DWARF_STACK_UNDERFLOW;
4970 }
4971 }
4972 }
4973 else
4974 rc = rtDwarfDecode_UnsignedInt(pDie, pbMember, pDesc, uForm, pCursor);
4975 return rc;
4976}
4977
4978/*
4979 *
4980 * DWARF debug_info parser
4981 * DWARF debug_info parser
4982 * DWARF debug_info parser
4983 *
4984 */
4985
4986
4987/**
4988 * Special hack to get the name and/or linkage name for a subprogram via a
4989 * specification reference.
4990 *
4991 * Since this is a hack, we ignore failure.
4992 *
4993 * If we want to really make use of DWARF info, we'll have to create some kind
4994 * of lookup tree for handling this. But currently we don't, so a hack will
4995 * suffice.
4996 *
4997 * @param pThis The DWARF instance.
4998 * @param pSubProgram The subprogram which is short on names.
4999 */
5000static void rtDwarfInfo_TryGetSubProgramNameFromSpecRef(PRTDBGMODDWARF pThis, PRTDWARFDIESUBPROGRAM pSubProgram)
5001{
5002 /*
5003 * Must have a spec ref, and it must be in the info section.
5004 */
5005 if (pSubProgram->SpecRef.enmWrt != krtDwarfRef_InfoSection)
5006 return;
5007
5008 /*
5009 * Create a cursor for reading the info and then the abbrivation code
5010 * starting the off the DIE.
5011 */
5012 RTDWARFCURSOR InfoCursor;
5013 int rc = rtDwarfCursor_InitWithOffset(&InfoCursor, pThis, krtDbgModDwarfSect_info, pSubProgram->SpecRef.off);
5014 if (RT_FAILURE(rc))
5015 return;
5016
5017 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(&InfoCursor, UINT32_MAX);
5018 if (uAbbrCode)
5019 {
5020 /* Only references to subprogram tags are interesting here. */
5021 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5022 if ( pAbbrev
5023 && pAbbrev->uTag == DW_TAG_subprogram)
5024 {
5025 /*
5026 * Use rtDwarfInfo_ParseDie to do the parsing, but with a different
5027 * attribute spec than usual.
5028 */
5029 rtDwarfInfo_ParseDie(pThis, &pSubProgram->Core, &g_SubProgramSpecHackDesc, &InfoCursor,
5030 pAbbrev, false /*fInitDie*/);
5031 }
5032 }
5033
5034 rtDwarfCursor_Delete(&InfoCursor, VINF_SUCCESS);
5035}
5036
5037
5038/**
5039 * Select which name to use.
5040 *
5041 * @returns One of the names.
5042 * @param pszName The DWARF name, may exclude namespace and class.
5043 * Can also be NULL.
5044 * @param pszLinkageName The linkage name. Can be NULL.
5045 */
5046static const char *rtDwarfInfo_SelectName(const char *pszName, const char *pszLinkageName)
5047{
5048 if (!pszName || !pszLinkageName)
5049 return pszName ? pszName : pszLinkageName;
5050
5051 /*
5052 * Some heuristics for selecting the link name if the normal name is missing
5053 * namespace or class prefixes.
5054 */
5055 size_t cchName = strlen(pszName);
5056 size_t cchLinkageName = strlen(pszLinkageName);
5057 if (cchLinkageName <= cchName + 1)
5058 return pszName;
5059
5060 const char *psz = strstr(pszLinkageName, pszName);
5061 if (!psz || psz - pszLinkageName < 4)
5062 return pszName;
5063
5064 return pszLinkageName;
5065}
5066
5067
5068/**
5069 * Parse the attributes of a DIE.
5070 *
5071 * @returns IPRT status code.
5072 * @param pThis The DWARF instance.
5073 * @param pDie The internal DIE structure to fill.
5074 */
5075static int rtDwarfInfo_SnoopSymbols(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
5076{
5077 int rc = VINF_SUCCESS;
5078 switch (pDie->uTag)
5079 {
5080 case DW_TAG_subprogram:
5081 {
5082 PRTDWARFDIESUBPROGRAM pSubProgram = (PRTDWARFDIESUBPROGRAM)pDie;
5083
5084 /* Obtain referenced specification there is only partial info. */
5085 if ( pSubProgram->PcRange.cAttrs
5086 && !pSubProgram->pszName)
5087 rtDwarfInfo_TryGetSubProgramNameFromSpecRef(pThis, pSubProgram);
5088
5089 if (pSubProgram->PcRange.cAttrs)
5090 {
5091 if (pSubProgram->PcRange.fHaveRanges)
5092 Log5(("subprogram %s (%s) <implement ranges>\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
5093 else
5094 {
5095 Log5(("subprogram %s (%s) %#llx-%#llx%s\n", pSubProgram->pszName, pSubProgram->pszLinkageName,
5096 pSubProgram->PcRange.uLowAddress, pSubProgram->PcRange.uHighAddress,
5097 pSubProgram->PcRange.cAttrs == 2 ? "" : " !bad!"));
5098 if ( ( pSubProgram->pszName || pSubProgram->pszLinkageName)
5099 && pSubProgram->PcRange.cAttrs == 2)
5100 {
5101 if (pThis->iWatcomPass == 1)
5102 rc = rtDbgModDwarfRecordSegOffset(pThis, pSubProgram->uSegment, pSubProgram->PcRange.uHighAddress);
5103 else
5104 {
5105 RTDBGSEGIDX iSeg;
5106 RTUINTPTR offSeg;
5107 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pSubProgram->uSegment,
5108 pSubProgram->PcRange.uLowAddress,
5109 &iSeg, &offSeg);
5110 if (RT_SUCCESS(rc))
5111 {
5112 uint64_t cb;
5113 if (pSubProgram->PcRange.uHighAddress >= pSubProgram->PcRange.uLowAddress)
5114 cb = pSubProgram->PcRange.uHighAddress - pSubProgram->PcRange.uLowAddress;
5115 else
5116 cb = 1;
5117 rc = RTDbgModSymbolAdd(pThis->hCnt,
5118 rtDwarfInfo_SelectName(pSubProgram->pszName, pSubProgram->pszLinkageName),
5119 iSeg, offSeg, cb, 0 /*fFlags*/, NULL /*piOrdinal*/);
5120 if (RT_FAILURE(rc))
5121 {
5122 if ( rc == VERR_DBG_DUPLICATE_SYMBOL
5123 || rc == VERR_DBG_ADDRESS_CONFLICT /** @todo figure why this happens with 10.6.8 mach_kernel, 32-bit. */
5124 )
5125 rc = VINF_SUCCESS;
5126 else
5127 AssertMsgFailed(("%Rrc\n", rc));
5128 }
5129 }
5130 else if ( pSubProgram->PcRange.uLowAddress == 0 /* see with vmlinux */
5131 && pSubProgram->PcRange.uHighAddress == 0)
5132 {
5133 Log5(("rtDbgModDwarfLinkAddressToSegOffset: Ignoring empty range.\n"));
5134 rc = VINF_SUCCESS; /* ignore */
5135 }
5136 else
5137 {
5138 AssertRC(rc);
5139 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
5140 }
5141 }
5142 }
5143 }
5144 }
5145 else
5146 Log5(("subprogram %s (%s) external\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
5147 break;
5148 }
5149
5150 case DW_TAG_label:
5151 {
5152 PCRTDWARFDIELABEL pLabel = (PCRTDWARFDIELABEL)pDie;
5153 //if (pLabel->fExternal)
5154 {
5155 Log5(("label %s %#x:%#llx\n", pLabel->pszName, pLabel->uSegment, pLabel->Address.uAddress));
5156 if (pThis->iWatcomPass == 1)
5157 rc = rtDbgModDwarfRecordSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress);
5158 else
5159 {
5160 RTDBGSEGIDX iSeg;
5161 RTUINTPTR offSeg;
5162 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress,
5163 &iSeg, &offSeg);
5164 AssertRC(rc);
5165 if (RT_SUCCESS(rc))
5166 {
5167 rc = RTDbgModSymbolAdd(pThis->hCnt, pLabel->pszName, iSeg, offSeg, 0 /*cb*/,
5168 0 /*fFlags*/, NULL /*piOrdinal*/);
5169 AssertMsg(RT_SUCCESS(rc) || rc == VERR_DBG_ADDRESS_CONFLICT,
5170 ("%Rrc %s %x:%x\n", rc, pLabel->pszName, iSeg, offSeg));
5171 }
5172 else
5173 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
5174
5175 /* Ignore errors regarding local labels. */
5176 if (RT_FAILURE(rc) && !pLabel->fExternal)
5177 rc = -rc;
5178 }
5179
5180 }
5181 break;
5182 }
5183
5184 }
5185 return rc;
5186}
5187
5188
5189/**
5190 * Initializes the non-core fields of an internal DIE structure.
5191 *
5192 * @param pDie The DIE structure.
5193 * @param pDieDesc The DIE descriptor.
5194 */
5195static void rtDwarfInfo_InitDie(PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc)
5196{
5197 size_t i = pDieDesc->cAttributes;
5198 while (i-- > 0)
5199 {
5200 switch (pDieDesc->paAttributes[i].cbInit & ATTR_INIT_MASK)
5201 {
5202 case ATTR_INIT_ZERO:
5203 /* Nothing to do (RTMemAllocZ). */
5204 break;
5205
5206 case ATTR_INIT_FFFS:
5207 switch (pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK)
5208 {
5209 case 1:
5210 *(uint8_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT8_MAX;
5211 break;
5212 case 2:
5213 *(uint16_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT16_MAX;
5214 break;
5215 case 4:
5216 *(uint32_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT32_MAX;
5217 break;
5218 case 8:
5219 *(uint64_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT64_MAX;
5220 break;
5221 default:
5222 AssertFailed();
5223 memset((uint8_t *)pDie + pDieDesc->paAttributes[i].off, 0xff,
5224 pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK);
5225 break;
5226 }
5227 break;
5228
5229 default:
5230 AssertFailed();
5231 }
5232 }
5233}
5234
5235
5236/**
5237 * Creates a new internal DIE structure and links it up.
5238 *
5239 * @returns Pointer to the new DIE structure.
5240 * @param pThis The DWARF instance.
5241 * @param pDieDesc The DIE descriptor (for size and init).
5242 * @param pAbbrev The abbreviation cache entry.
5243 * @param pParent The parent DIE (NULL if unit).
5244 */
5245static PRTDWARFDIE rtDwarfInfo_NewDie(PRTDBGMODDWARF pThis, PCRTDWARFDIEDESC pDieDesc,
5246 PCRTDWARFABBREV pAbbrev, PRTDWARFDIE pParent)
5247{
5248 NOREF(pThis);
5249 Assert(pDieDesc->cbDie >= sizeof(RTDWARFDIE));
5250#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5251 uint32_t iAllocator = pDieDesc->cbDie > pThis->aDieAllocators[0].cbMax;
5252 Assert(pDieDesc->cbDie <= pThis->aDieAllocators[iAllocator].cbMax);
5253 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemCacheAlloc(pThis->aDieAllocators[iAllocator].hMemCache);
5254#else
5255 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemAllocZ(pDieDesc->cbDie);
5256#endif
5257 if (pDie)
5258 {
5259#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5260 RT_BZERO(pDie, pDieDesc->cbDie);
5261 pDie->iAllocator = iAllocator;
5262#endif
5263 rtDwarfInfo_InitDie(pDie, pDieDesc);
5264
5265 pDie->uTag = pAbbrev->uTag;
5266 pDie->offSpec = pAbbrev->offSpec;
5267 pDie->pParent = pParent;
5268 if (pParent)
5269 RTListAppend(&pParent->ChildList, &pDie->SiblingNode);
5270 else
5271 RTListInit(&pDie->SiblingNode);
5272 RTListInit(&pDie->ChildList);
5273
5274 }
5275 return pDie;
5276}
5277
5278
5279/**
5280 * Free all children of a DIE.
5281 *
5282 * @param pThis The DWARF instance.
5283 * @param pParentDie The parent DIE.
5284 */
5285static void rtDwarfInfo_FreeChildren(PRTDBGMODDWARF pThis, PRTDWARFDIE pParentDie)
5286{
5287 PRTDWARFDIE pChild, pNextChild;
5288 RTListForEachSafe(&pParentDie->ChildList, pChild, pNextChild, RTDWARFDIE, SiblingNode)
5289 {
5290 if (!RTListIsEmpty(&pChild->ChildList))
5291 rtDwarfInfo_FreeChildren(pThis, pChild);
5292 RTListNodeRemove(&pChild->SiblingNode);
5293#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5294 RTMemCacheFree(pThis->aDieAllocators[pChild->iAllocator].hMemCache, pChild);
5295#else
5296 RTMemFree(pChild);
5297#endif
5298 }
5299}
5300
5301
5302/**
5303 * Free a DIE an all its children.
5304 *
5305 * @param pThis The DWARF instance.
5306 * @param pDie The DIE to free.
5307 */
5308static void rtDwarfInfo_FreeDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
5309{
5310 rtDwarfInfo_FreeChildren(pThis, pDie);
5311 RTListNodeRemove(&pDie->SiblingNode);
5312#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5313 RTMemCacheFree(pThis->aDieAllocators[pDie->iAllocator].hMemCache, pDie);
5314#else
5315 RTMemFree(pChild);
5316#endif
5317}
5318
5319
5320/**
5321 * Skips a form.
5322 * @returns IPRT status code
5323 * @param pCursor The cursor.
5324 * @param uForm The form to skip.
5325 */
5326static int rtDwarfInfo_SkipForm(PRTDWARFCURSOR pCursor, uint32_t uForm)
5327{
5328 switch (uForm)
5329 {
5330 case DW_FORM_addr:
5331 return rtDwarfCursor_SkipBytes(pCursor, pCursor->cbNativeAddr);
5332
5333 case DW_FORM_block:
5334 case DW_FORM_exprloc:
5335 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetULeb128(pCursor, 0));
5336
5337 case DW_FORM_block1:
5338 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU8(pCursor, 0));
5339
5340 case DW_FORM_block2:
5341 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU16(pCursor, 0));
5342
5343 case DW_FORM_block4:
5344 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU32(pCursor, 0));
5345
5346 case DW_FORM_data1:
5347 case DW_FORM_ref1:
5348 case DW_FORM_flag:
5349 return rtDwarfCursor_SkipBytes(pCursor, 1);
5350
5351 case DW_FORM_data2:
5352 case DW_FORM_ref2:
5353 return rtDwarfCursor_SkipBytes(pCursor, 2);
5354
5355 case DW_FORM_data4:
5356 case DW_FORM_ref4:
5357 return rtDwarfCursor_SkipBytes(pCursor, 4);
5358
5359 case DW_FORM_data8:
5360 case DW_FORM_ref8:
5361 case DW_FORM_ref_sig8:
5362 return rtDwarfCursor_SkipBytes(pCursor, 8);
5363
5364 case DW_FORM_udata:
5365 case DW_FORM_sdata:
5366 case DW_FORM_ref_udata:
5367 return rtDwarfCursor_SkipLeb128(pCursor);
5368
5369 case DW_FORM_string:
5370 rtDwarfCursor_GetSZ(pCursor, NULL);
5371 return pCursor->rc;
5372
5373 case DW_FORM_indirect:
5374 return rtDwarfInfo_SkipForm(pCursor, rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX));
5375
5376 case DW_FORM_strp:
5377 case DW_FORM_ref_addr:
5378 case DW_FORM_sec_offset:
5379 return rtDwarfCursor_SkipBytes(pCursor, pCursor->f64bitDwarf ? 8 : 4);
5380
5381 case DW_FORM_flag_present:
5382 return pCursor->rc; /* no data */
5383
5384 default:
5385 Log(("rtDwarfInfo_SkipForm: Unknown form %#x\n", uForm));
5386 return VERR_DWARF_UNKNOWN_FORM;
5387 }
5388}
5389
5390
5391
5392#ifdef SOME_UNUSED_FUNCTION
5393/**
5394 * Skips a DIE.
5395 *
5396 * @returns IPRT status code.
5397 * @param pCursor The cursor.
5398 * @param pAbbrevCursor The abbreviation cursor.
5399 */
5400static int rtDwarfInfo_SkipDie(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pAbbrevCursor)
5401{
5402 for (;;)
5403 {
5404 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
5405 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
5406 if (uAttr == 0 && uForm == 0)
5407 break;
5408
5409 int rc = rtDwarfInfo_SkipForm(pCursor, uForm);
5410 if (RT_FAILURE(rc))
5411 return rc;
5412 }
5413 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pAbbrevCursor->rc;
5414}
5415#endif
5416
5417
5418/**
5419 * Parse the attributes of a DIE.
5420 *
5421 * @returns IPRT status code.
5422 * @param pThis The DWARF instance.
5423 * @param pDie The internal DIE structure to fill.
5424 * @param pDieDesc The DIE descriptor.
5425 * @param pCursor The debug_info cursor.
5426 * @param pAbbrev The abbreviation cache entry.
5427 * @param fInitDie Whether to initialize the DIE first. If not (@c
5428 * false) it's safe to assume we're following a
5429 * DW_AT_specification or DW_AT_abstract_origin,
5430 * and that we shouldn't be snooping any symbols.
5431 */
5432static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc,
5433 PRTDWARFCURSOR pCursor, PCRTDWARFABBREV pAbbrev, bool fInitDie)
5434{
5435 RTDWARFCURSOR AbbrevCursor;
5436 int rc = rtDwarfCursor_InitWithOffset(&AbbrevCursor, pThis, krtDbgModDwarfSect_abbrev, pAbbrev->offSpec);
5437 if (RT_FAILURE(rc))
5438 return rc;
5439
5440 if (fInitDie)
5441 rtDwarfInfo_InitDie(pDie, pDieDesc);
5442 for (;;)
5443 {
5444#ifdef LOG_ENABLED
5445 uint32_t const off = (uint32_t)(AbbrevCursor.pb - AbbrevCursor.pbStart);
5446#endif
5447 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
5448 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
5449 Log4((" %04x: %-23s [%s]\n", off, rtDwarfLog_AttrName(uAttr), rtDwarfLog_FormName(uForm)));
5450 if (uAttr == 0)
5451 break;
5452 if (uForm == DW_FORM_indirect)
5453 uForm = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
5454
5455 /* Look up the attribute in the descriptor and invoke the decoder. */
5456 PCRTDWARFATTRDESC pAttr = NULL;
5457 size_t i = pDieDesc->cAttributes;
5458 while (i-- > 0)
5459 if (pDieDesc->paAttributes[i].uAttr == uAttr)
5460 {
5461 pAttr = &pDieDesc->paAttributes[i];
5462 rc = pAttr->pfnDecoder(pDie, (uint8_t *)pDie + pAttr->off, pAttr, uForm, pCursor);
5463 break;
5464 }
5465
5466 /* Some house keeping. */
5467 if (pAttr)
5468 pDie->cDecodedAttrs++;
5469 else
5470 {
5471 pDie->cUnhandledAttrs++;
5472 rc = rtDwarfInfo_SkipForm(pCursor, uForm);
5473 }
5474 if (RT_FAILURE(rc))
5475 break;
5476 }
5477
5478 rc = rtDwarfCursor_Delete(&AbbrevCursor, rc);
5479 if (RT_SUCCESS(rc))
5480 rc = pCursor->rc;
5481
5482 /*
5483 * Snoop up symbols on the way out.
5484 */
5485 if (RT_SUCCESS(rc) && fInitDie)
5486 {
5487 rc = rtDwarfInfo_SnoopSymbols(pThis, pDie);
5488 /* Ignore duplicates, get work done instead. */
5489 /** @todo clean up global/static symbol mess. */
5490 if (rc == VERR_DBG_DUPLICATE_SYMBOL || rc == VERR_DBG_ADDRESS_CONFLICT)
5491 rc = VINF_SUCCESS;
5492 }
5493
5494 return rc;
5495}
5496
5497
5498/**
5499 * Load the debug information of a unit.
5500 *
5501 * @returns IPRT status code.
5502 * @param pThis The DWARF instance.
5503 * @param pCursor The debug_info cursor.
5504 * @param fKeepDies Whether to keep the DIEs or discard them as soon
5505 * as possible.
5506 */
5507static int rtDwarfInfo_LoadUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, bool fKeepDies)
5508{
5509 Log(("rtDwarfInfo_LoadUnit: %#x\n", rtDwarfCursor_CalcSectOffsetU32(pCursor)));
5510
5511 /*
5512 * Read the compilation unit header.
5513 */
5514 uint64_t offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
5515 uint64_t cbUnit = rtDwarfCursor_GetInitialLength(pCursor);
5516 cbUnit += rtDwarfCursor_CalcSectOffsetU32(pCursor) - offUnit;
5517 uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
5518 if ( uVer < 2
5519 || uVer > 4)
5520 return rtDwarfCursor_SkipUnit(pCursor);
5521 uint64_t const offAbbrev = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
5522 uint8_t const cbNativeAddr = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
5523 if (RT_FAILURE(pCursor->rc))
5524 return pCursor->rc;
5525 Log((" uVer=%d offAbbrev=%#llx cbNativeAddr=%d\n", uVer, offAbbrev, cbNativeAddr));
5526
5527 /*
5528 * Set up the abbreviation cache and store the native address size in the cursor.
5529 */
5530 if (offAbbrev > UINT32_MAX)
5531 {
5532 Log(("Unexpected abbrviation code offset of %#llx\n", offAbbrev));
5533 return VERR_DWARF_BAD_INFO;
5534 }
5535 rtDwarfAbbrev_SetUnitOffset(pThis, (uint32_t)offAbbrev);
5536 pCursor->cbNativeAddr = cbNativeAddr;
5537
5538 /*
5539 * The first DIE is a compile or partial unit, parse it here.
5540 */
5541 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
5542 if (!uAbbrCode)
5543 {
5544 Log(("Unexpected abbrviation code of zero\n"));
5545 return VERR_DWARF_BAD_INFO;
5546 }
5547 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5548 if (!pAbbrev)
5549 return VERR_DWARF_ABBREV_NOT_FOUND;
5550 if ( pAbbrev->uTag != DW_TAG_compile_unit
5551 && pAbbrev->uTag != DW_TAG_partial_unit)
5552 {
5553 Log(("Unexpected compile/partial unit tag %#x\n", pAbbrev->uTag));
5554 return VERR_DWARF_BAD_INFO;
5555 }
5556
5557 PRTDWARFDIECOMPILEUNIT pUnit;
5558 pUnit = (PRTDWARFDIECOMPILEUNIT)rtDwarfInfo_NewDie(pThis, &g_CompileUnitDesc, pAbbrev, NULL /*pParent*/);
5559 if (!pUnit)
5560 return VERR_NO_MEMORY;
5561 pUnit->offUnit = offUnit;
5562 pUnit->cbUnit = cbUnit;
5563 pUnit->offAbbrev = offAbbrev;
5564 pUnit->cbNativeAddr = cbNativeAddr;
5565 pUnit->uDwarfVer = (uint8_t)uVer;
5566 RTListAppend(&pThis->CompileUnitList, &pUnit->Core.SiblingNode);
5567
5568 int rc = rtDwarfInfo_ParseDie(pThis, &pUnit->Core, &g_CompileUnitDesc, pCursor, pAbbrev, true /*fInitDie*/);
5569 if (RT_FAILURE(rc))
5570 return rc;
5571
5572 /*
5573 * Parse DIEs.
5574 */
5575 uint32_t cDepth = 0;
5576 PRTDWARFDIE pParentDie = &pUnit->Core;
5577 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
5578 {
5579#ifdef LOG_ENABLED
5580 uint32_t offLog = rtDwarfCursor_CalcSectOffsetU32(pCursor);
5581#endif
5582 uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
5583 if (!uAbbrCode)
5584 {
5585 /* End of siblings, up one level. (Is this correct?) */
5586 if (pParentDie->pParent)
5587 {
5588 pParentDie = pParentDie->pParent;
5589 cDepth--;
5590 if (!fKeepDies && pParentDie->pParent)
5591 rtDwarfInfo_FreeChildren(pThis, pParentDie);
5592 }
5593 }
5594 else
5595 {
5596 /*
5597 * Look up the abbreviation and match the tag up with a descriptor.
5598 */
5599 pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
5600 if (!pAbbrev)
5601 return VERR_DWARF_ABBREV_NOT_FOUND;
5602
5603 PCRTDWARFDIEDESC pDieDesc;
5604 const char *pszName;
5605 if (pAbbrev->uTag < RT_ELEMENTS(g_aTagDescs))
5606 {
5607 Assert(g_aTagDescs[pAbbrev->uTag].uTag == pAbbrev->uTag || g_aTagDescs[pAbbrev->uTag].uTag == 0);
5608 pszName = g_aTagDescs[pAbbrev->uTag].pszName;
5609 pDieDesc = g_aTagDescs[pAbbrev->uTag].pDesc;
5610 }
5611 else
5612 {
5613 pszName = "<unknown>";
5614 pDieDesc = &g_CoreDieDesc;
5615 }
5616 Log4(("%08x: %*stag=%s (%#x, abbrev %u @ %#x)%s\n", offLog, cDepth * 2, "", pszName,
5617 pAbbrev->uTag, uAbbrCode, pAbbrev->offSpec - pAbbrev->cbHdr, pAbbrev->fChildren ? " has children" : ""));
5618
5619 /*
5620 * Create a new internal DIE structure and parse the
5621 * attributes.
5622 */
5623 PRTDWARFDIE pNewDie = rtDwarfInfo_NewDie(pThis, pDieDesc, pAbbrev, pParentDie);
5624 if (!pNewDie)
5625 return VERR_NO_MEMORY;
5626
5627 if (pAbbrev->fChildren)
5628 {
5629 pParentDie = pNewDie;
5630 cDepth++;
5631 }
5632
5633 rc = rtDwarfInfo_ParseDie(pThis, pNewDie, pDieDesc, pCursor, pAbbrev, true /*fInitDie*/);
5634 if (RT_FAILURE(rc))
5635 return rc;
5636
5637 if (!fKeepDies && !pAbbrev->fChildren)
5638 rtDwarfInfo_FreeDie(pThis, pNewDie);
5639 }
5640 } /* while more DIEs */
5641
5642
5643 /* Unlink and free child DIEs if told to do so. */
5644 if (!fKeepDies)
5645 rtDwarfInfo_FreeChildren(pThis, &pUnit->Core);
5646
5647 return RT_SUCCESS(rc) ? pCursor->rc : rc;
5648}
5649
5650
5651/**
5652 * Extracts the symbols.
5653 *
5654 * The symbols are insered into the debug info container.
5655 *
5656 * @returns IPRT status code
5657 * @param pThis The DWARF instance.
5658 */
5659static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis)
5660{
5661 RTDWARFCURSOR Cursor;
5662 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
5663 if (RT_SUCCESS(rc))
5664 {
5665 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
5666 && RT_SUCCESS(rc))
5667 rc = rtDwarfInfo_LoadUnit(pThis, &Cursor, false /* fKeepDies */);
5668
5669 rc = rtDwarfCursor_Delete(&Cursor, rc);
5670 }
5671 return rc;
5672}
5673
5674
5675
5676/*
5677 *
5678 * Public and image level symbol handling.
5679 * Public and image level symbol handling.
5680 * Public and image level symbol handling.
5681 * Public and image level symbol handling.
5682 *
5683 *
5684 */
5685
5686#define RTDBGDWARF_SYM_ENUM_BASE_ADDRESS UINT32_C(0x200000)
5687
5688/** @callback_method_impl{FNRTLDRENUMSYMS,
5689 * Adds missing symbols from the image symbol table.} */
5690static DECLCALLBACK(int) rtDwarfSyms_EnumSymbolsCallback(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol,
5691 RTLDRADDR Value, void *pvUser)
5692{
5693 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
5694 RT_NOREF_PV(hLdrMod); RT_NOREF_PV(uSymbol);
5695 Assert(pThis->iWatcomPass != 1);
5696
5697 RTLDRADDR uRva = Value - RTDBGDWARF_SYM_ENUM_BASE_ADDRESS;
5698 if ( Value >= RTDBGDWARF_SYM_ENUM_BASE_ADDRESS
5699 && uRva < _1G)
5700 {
5701 RTDBGSYMBOL SymInfo;
5702 RTINTPTR offDisp;
5703 int rc = RTDbgModSymbolByAddr(pThis->hCnt, RTDBGSEGIDX_RVA, uRva, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &offDisp, &SymInfo);
5704 if ( RT_FAILURE(rc)
5705 || offDisp != 0)
5706 {
5707 rc = RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, RTDBGSEGIDX_RVA, uRva, 1, 0 /*fFlags*/, NULL /*piOrdinal*/);
5708 Log(("Dwarf: Symbol #%05u %#018RTptr %s [%Rrc]\n", uSymbol, Value, pszSymbol, rc)); NOREF(rc);
5709 }
5710 }
5711 else
5712 Log(("Dwarf: Symbol #%05u %#018RTptr '%s' [SKIPPED - INVALID ADDRESS]\n", uSymbol, Value, pszSymbol));
5713 return VINF_SUCCESS;
5714}
5715
5716
5717
5718/**
5719 * Loads additional symbols from the pubnames section and the executable image.
5720 *
5721 * The symbols are insered into the debug info container.
5722 *
5723 * @returns IPRT status code
5724 * @param pThis The DWARF instance.
5725 */
5726static int rtDwarfSyms_LoadAll(PRTDBGMODDWARF pThis)
5727{
5728 /*
5729 * pubnames.
5730 */
5731 int rc = VINF_SUCCESS;
5732 if (pThis->aSections[krtDbgModDwarfSect_pubnames].fPresent)
5733 {
5734// RTDWARFCURSOR Cursor;
5735// int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
5736// if (RT_SUCCESS(rc))
5737// {
5738// while ( !rtDwarfCursor_IsAtEnd(&Cursor)
5739// && RT_SUCCESS(rc))
5740// rc = rtDwarfInfo_LoadUnit(pThis, &Cursor, false /* fKeepDies */);
5741//
5742// rc = rtDwarfCursor_Delete(&Cursor, rc);
5743// }
5744// return rc;
5745 }
5746
5747 /*
5748 * The executable image.
5749 */
5750 if ( pThis->pImgMod
5751 && pThis->pImgMod->pImgVt->pfnEnumSymbols
5752 && pThis->iWatcomPass != 1
5753 && RT_SUCCESS(rc))
5754 {
5755 rc = pThis->pImgMod->pImgVt->pfnEnumSymbols(pThis->pImgMod,
5756 RTLDR_ENUM_SYMBOL_FLAGS_ALL | RTLDR_ENUM_SYMBOL_FLAGS_NO_FWD,
5757 RTDBGDWARF_SYM_ENUM_BASE_ADDRESS,
5758 rtDwarfSyms_EnumSymbolsCallback,
5759 pThis);
5760 }
5761
5762 return rc;
5763}
5764
5765
5766
5767
5768/*
5769 *
5770 * DWARF Debug module implementation.
5771 * DWARF Debug module implementation.
5772 * DWARF Debug module implementation.
5773 *
5774 */
5775
5776
5777/** @interface_method_impl{RTDBGMODVTDBG,pfnUnwindFrame} */
5778static DECLCALLBACK(int) rtDbgModDwarf_UnwindFrame(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState)
5779{
5780 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5781
5782 /*
5783 * Unwinding info is stored in the '.debug_frame' section, or altertively
5784 * in the '.eh_frame' one in the image. In the latter case the dbgmodldr.cpp
5785 * part of the operation will take care of it. Since the sections contain the
5786 * same data, we just create a cursor and call a common function to do the job.
5787 */
5788 if (pThis->aSections[krtDbgModDwarfSect_frame].fPresent)
5789 {
5790 RTDWARFCURSOR Cursor;
5791 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_frame);
5792 if (RT_SUCCESS(rc))
5793 {
5794 /* Figure default pointer encoding from image arch. */
5795 uint8_t bPtrEnc = rtDwarfUnwind_ArchToPtrEnc(pMod->pImgVt->pfnGetArch(pMod));
5796
5797 /* Make sure we've got both seg:off and rva for the input address. */
5798 RTUINTPTR uRva = off;
5799 if (iSeg == RTDBGSEGIDX_RVA)
5800 rtDbgModDwarfRvaToSegOffset(pThis, uRva, &iSeg, &off);
5801 else
5802 rtDbgModDwarfSegOffsetToRva(pThis, iSeg, off, &uRva);
5803
5804 /* Do the work */
5805 rc = rtDwarfUnwind_Slow(&Cursor, 0 /** @todo .debug_frame RVA*/, iSeg, off, uRva,
5806 pState, bPtrEnc, false /*fIsEhFrame*/, pMod->pImgVt->pfnGetArch(pMod));
5807
5808 rc = rtDwarfCursor_Delete(&Cursor, rc);
5809 }
5810 return rc;
5811 }
5812 return VERR_DBG_NO_UNWIND_INFO;
5813}
5814
5815
5816/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
5817static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
5818 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
5819{
5820 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5821 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
5822}
5823
5824
5825/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
5826static DECLCALLBACK(int) rtDbgModDwarf_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
5827{
5828 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5829 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
5830}
5831
5832
5833/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
5834static DECLCALLBACK(uint32_t) rtDbgModDwarf_LineCount(PRTDBGMODINT pMod)
5835{
5836 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5837 return RTDbgModLineCount(pThis->hCnt);
5838}
5839
5840
5841/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
5842static DECLCALLBACK(int) rtDbgModDwarf_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
5843 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
5844{
5845 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5846 Assert(!pszFile[cchFile]); NOREF(cchFile);
5847 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
5848}
5849
5850
5851/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
5852static DECLCALLBACK(int) rtDbgModDwarf_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
5853 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
5854{
5855 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5856 return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
5857}
5858
5859
5860/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
5861static DECLCALLBACK(int) rtDbgModDwarf_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
5862 PRTDBGSYMBOL pSymInfo)
5863{
5864 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5865 Assert(!pszSymbol[cchSymbol]); RT_NOREF_PV(cchSymbol);
5866 return RTDbgModSymbolByName(pThis->hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
5867}
5868
5869
5870/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
5871static DECLCALLBACK(int) rtDbgModDwarf_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
5872{
5873 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5874 return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
5875}
5876
5877
5878/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
5879static DECLCALLBACK(uint32_t) rtDbgModDwarf_SymbolCount(PRTDBGMODINT pMod)
5880{
5881 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5882 return RTDbgModSymbolCount(pThis->hCnt);
5883}
5884
5885
5886/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
5887static DECLCALLBACK(int) rtDbgModDwarf_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
5888 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
5889 uint32_t *piOrdinal)
5890{
5891 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5892 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
5893 return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
5894}
5895
5896
5897/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
5898static DECLCALLBACK(int) rtDbgModDwarf_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
5899{
5900 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5901 return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
5902}
5903
5904
5905/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
5906static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_SegmentCount(PRTDBGMODINT pMod)
5907{
5908 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5909 return RTDbgModSegmentCount(pThis->hCnt);
5910}
5911
5912
5913/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
5914static DECLCALLBACK(int) rtDbgModDwarf_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
5915 uint32_t fFlags, PRTDBGSEGIDX piSeg)
5916{
5917 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5918 Assert(!pszName[cchName]); NOREF(cchName);
5919 return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
5920}
5921
5922
5923/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
5924static DECLCALLBACK(RTUINTPTR) rtDbgModDwarf_ImageSize(PRTDBGMODINT pMod)
5925{
5926 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5927 RTUINTPTR cb1 = RTDbgModImageSize(pThis->hCnt);
5928 RTUINTPTR cb2 = pThis->pImgMod->pImgVt->pfnImageSize(pMod);
5929 return RT_MAX(cb1, cb2);
5930}
5931
5932
5933/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
5934static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
5935{
5936 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5937 return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
5938}
5939
5940
5941/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
5942static DECLCALLBACK(int) rtDbgModDwarf_Close(PRTDBGMODINT pMod)
5943{
5944 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
5945
5946 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
5947 if (pThis->aSections[iSect].pv)
5948 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb, &pThis->aSections[iSect].pv);
5949
5950 RTDbgModRelease(pThis->hCnt);
5951 RTMemFree(pThis->paCachedAbbrevs);
5952 if (pThis->pNestedMod)
5953 {
5954 pThis->pNestedMod->pImgVt->pfnClose(pThis->pNestedMod);
5955 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszName);
5956 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszDbgFile);
5957 RTMemFree(pThis->pNestedMod);
5958 pThis->pNestedMod = NULL;
5959 }
5960
5961#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
5962 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
5963 while (i-- > 0)
5964 {
5965 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
5966 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
5967 }
5968#endif
5969
5970 RTMemFree(pThis);
5971
5972 return VINF_SUCCESS;
5973}
5974
5975
5976/** @callback_method_impl{FNRTLDRENUMDBG} */
5977static DECLCALLBACK(int) rtDbgModDwarfEnumCallback(RTLDRMOD hLdrMod, PCRTLDRDBGINFO pDbgInfo, void *pvUser)
5978{
5979 RT_NOREF_PV(hLdrMod);
5980
5981 /*
5982 * Skip stuff we can't handle.
5983 */
5984 if (pDbgInfo->enmType != RTLDRDBGINFOTYPE_DWARF)
5985 return VINF_SUCCESS;
5986 const char *pszSection = pDbgInfo->u.Dwarf.pszSection;
5987 if (!pszSection || !*pszSection)
5988 return VINF_SUCCESS;
5989 Assert(!pDbgInfo->pszExtFile);
5990
5991 /*
5992 * Must have a part name starting with debug_ and possibly prefixed by dots
5993 * or underscores.
5994 */
5995 if (!strncmp(pszSection, RT_STR_TUPLE(".debug_"))) /* ELF */
5996 pszSection += sizeof(".debug_") - 1;
5997 else if (!strncmp(pszSection, RT_STR_TUPLE("__debug_"))) /* Mach-O */
5998 pszSection += sizeof("__debug_") - 1;
5999 else if (!strcmp(pszSection, ".WATCOM_references"))
6000 return VINF_SUCCESS; /* Ignore special watcom section for now.*/
6001 else if ( !strcmp(pszSection, "__apple_types")
6002 || !strcmp(pszSection, "__apple_namespac")
6003 || !strcmp(pszSection, "__apple_objc")
6004 || !strcmp(pszSection, "__apple_names"))
6005 return VINF_SUCCESS; /* Ignore special apple sections for now. */
6006 else
6007 AssertMsgFailedReturn(("%s\n", pszSection), VINF_SUCCESS /*ignore*/);
6008
6009 /*
6010 * Figure out which part we're talking about.
6011 */
6012 krtDbgModDwarfSect enmSect;
6013 if (0) { /* dummy */ }
6014#define ELSE_IF_STRCMP_SET(a_Name) else if (!strcmp(pszSection, #a_Name)) enmSect = krtDbgModDwarfSect_ ## a_Name
6015 ELSE_IF_STRCMP_SET(abbrev);
6016 ELSE_IF_STRCMP_SET(aranges);
6017 ELSE_IF_STRCMP_SET(frame);
6018 ELSE_IF_STRCMP_SET(info);
6019 ELSE_IF_STRCMP_SET(inlined);
6020 ELSE_IF_STRCMP_SET(line);
6021 ELSE_IF_STRCMP_SET(loc);
6022 ELSE_IF_STRCMP_SET(macinfo);
6023 ELSE_IF_STRCMP_SET(pubnames);
6024 ELSE_IF_STRCMP_SET(pubtypes);
6025 ELSE_IF_STRCMP_SET(ranges);
6026 ELSE_IF_STRCMP_SET(str);
6027 ELSE_IF_STRCMP_SET(types);
6028#undef ELSE_IF_STRCMP_SET
6029 else
6030 {
6031 AssertMsgFailed(("%s\n", pszSection));
6032 return VINF_SUCCESS;
6033 }
6034
6035 /*
6036 * Record the section.
6037 */
6038 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
6039 AssertMsgReturn(!pThis->aSections[enmSect].fPresent, ("duplicate %s\n", pszSection), VINF_SUCCESS /*ignore*/);
6040
6041 pThis->aSections[enmSect].fPresent = true;
6042 pThis->aSections[enmSect].offFile = pDbgInfo->offFile;
6043 pThis->aSections[enmSect].pv = NULL;
6044 pThis->aSections[enmSect].cb = (size_t)pDbgInfo->cb;
6045 pThis->aSections[enmSect].iDbgInfo = pDbgInfo->iDbgInfo;
6046 if (pThis->aSections[enmSect].cb != pDbgInfo->cb)
6047 pThis->aSections[enmSect].cb = ~(size_t)0;
6048
6049 return VINF_SUCCESS;
6050}
6051
6052
6053static int rtDbgModDwarfTryOpenDbgFile(PRTDBGMODINT pDbgMod, PRTDBGMODDWARF pThis, RTLDRARCH enmArch)
6054{
6055 if ( !pDbgMod->pszDbgFile
6056 || RTPathIsSame(pDbgMod->pszDbgFile, pDbgMod->pszImgFile) == (int)true /* returns VERR too */)
6057 return VERR_DBG_NO_MATCHING_INTERPRETER;
6058
6059 /*
6060 * Only open the image.
6061 */
6062 PRTDBGMODINT pDbgInfoMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgInfoMod));
6063 if (!pDbgInfoMod)
6064 return VERR_NO_MEMORY;
6065
6066 int rc;
6067 pDbgInfoMod->u32Magic = RTDBGMOD_MAGIC;
6068 pDbgInfoMod->cRefs = 1;
6069 if (RTStrCacheRetain(pDbgMod->pszDbgFile) != UINT32_MAX)
6070 {
6071 pDbgInfoMod->pszImgFile = pDbgMod->pszDbgFile;
6072 if (RTStrCacheRetain(pDbgMod->pszName) != UINT32_MAX)
6073 {
6074 pDbgInfoMod->pszName = pDbgMod->pszName;
6075 pDbgInfoMod->pImgVt = &g_rtDbgModVtImgLdr;
6076 rc = pDbgInfoMod->pImgVt->pfnTryOpen(pDbgInfoMod, enmArch);
6077 if (RT_SUCCESS(rc))
6078 {
6079 pThis->pDbgInfoMod = pDbgInfoMod;
6080 pThis->pNestedMod = pDbgInfoMod;
6081 return VINF_SUCCESS;
6082 }
6083
6084 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszName);
6085 }
6086 else
6087 rc = VERR_NO_STR_MEMORY;
6088 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszImgFile);
6089 }
6090 else
6091 rc = VERR_NO_STR_MEMORY;
6092 RTMemFree(pDbgInfoMod);
6093 return rc;
6094}
6095
6096
6097/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
6098static DECLCALLBACK(int) rtDbgModDwarf_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
6099{
6100 /*
6101 * DWARF is only supported when part of an image.
6102 */
6103 if (!pMod->pImgVt)
6104 return VERR_DBG_NO_MATCHING_INTERPRETER;
6105
6106 /*
6107 * Create the module instance data.
6108 */
6109 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)RTMemAllocZ(sizeof(*pThis));
6110 if (!pThis)
6111 return VERR_NO_MEMORY;
6112 pThis->pDbgInfoMod = pMod;
6113 pThis->pImgMod = pMod;
6114 RTListInit(&pThis->CompileUnitList);
6115
6116 /** @todo better fUseLinkAddress heuristics! */
6117 /* mach_kernel: */
6118 if ( (pMod->pszDbgFile && strstr(pMod->pszDbgFile, "mach_kernel"))
6119 || (pMod->pszImgFile && strstr(pMod->pszImgFile, "mach_kernel"))
6120 || (pMod->pszImgFileSpecified && strstr(pMod->pszImgFileSpecified, "mach_kernel")) )
6121 pThis->fUseLinkAddress = true;
6122
6123#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
6124 AssertCompile(RT_ELEMENTS(pThis->aDieAllocators) == 2);
6125 pThis->aDieAllocators[0].cbMax = sizeof(RTDWARFDIE);
6126 pThis->aDieAllocators[1].cbMax = sizeof(RTDWARFDIECOMPILEUNIT);
6127 for (uint32_t i = 0; i < RT_ELEMENTS(g_aTagDescs); i++)
6128 if (g_aTagDescs[i].pDesc && g_aTagDescs[i].pDesc->cbDie > pThis->aDieAllocators[1].cbMax)
6129 pThis->aDieAllocators[1].cbMax = (uint32_t)g_aTagDescs[i].pDesc->cbDie;
6130 pThis->aDieAllocators[1].cbMax = RT_ALIGN_32(pThis->aDieAllocators[1].cbMax, sizeof(uint64_t));
6131
6132 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDieAllocators); i++)
6133 {
6134 int rc = RTMemCacheCreate(&pThis->aDieAllocators[i].hMemCache, pThis->aDieAllocators[i].cbMax, sizeof(uint64_t),
6135 UINT32_MAX, NULL /*pfnCtor*/, NULL /*pfnDtor*/, NULL /*pvUser*/, 0 /*fFlags*/);
6136 if (RT_FAILURE(rc))
6137 {
6138 while (i-- > 0)
6139 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
6140 RTMemFree(pThis);
6141 return rc;
6142 }
6143 }
6144#endif
6145
6146 /*
6147 * If the debug file name is set, let's see if it's an ELF image with DWARF
6148 * inside it. In that case we'll have to deal with two image modules, one
6149 * for segments and address translation and one for the debug information.
6150 */
6151 if (pMod->pszDbgFile != NULL)
6152 rtDbgModDwarfTryOpenDbgFile(pMod, pThis, enmArch);
6153
6154 /*
6155 * Enumerate the debug info in the module, looking for DWARF bits.
6156 */
6157 int rc = pThis->pDbgInfoMod->pImgVt->pfnEnumDbgInfo(pThis->pDbgInfoMod, rtDbgModDwarfEnumCallback, pThis);
6158 if (RT_SUCCESS(rc))
6159 {
6160 if (pThis->aSections[krtDbgModDwarfSect_info].fPresent)
6161 {
6162 /*
6163 * Extract / explode the data we want (symbols and line numbers)
6164 * storing them in a container module.
6165 */
6166 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
6167 if (RT_SUCCESS(rc))
6168 {
6169 pMod->pvDbgPriv = pThis;
6170
6171 rc = rtDbgModDwarfAddSegmentsFromImage(pThis);
6172 if (RT_SUCCESS(rc))
6173 rc = rtDwarfInfo_LoadAll(pThis);
6174 if (RT_SUCCESS(rc))
6175 rc = rtDwarfSyms_LoadAll(pThis);
6176 if (RT_SUCCESS(rc))
6177 rc = rtDwarfLine_ExplodeAll(pThis);
6178 if (RT_SUCCESS(rc) && pThis->iWatcomPass == 1)
6179 {
6180 rc = rtDbgModDwarfAddSegmentsFromPass1(pThis);
6181 pThis->iWatcomPass = 2;
6182 if (RT_SUCCESS(rc))
6183 rc = rtDwarfInfo_LoadAll(pThis);
6184 if (RT_SUCCESS(rc))
6185 rc = rtDwarfSyms_LoadAll(pThis);
6186 if (RT_SUCCESS(rc))
6187 rc = rtDwarfLine_ExplodeAll(pThis);
6188 }
6189 if (RT_SUCCESS(rc))
6190 {
6191 /*
6192 * Free the cached abbreviations and unload all sections.
6193 */
6194 pThis->cCachedAbbrevsAlloced = 0;
6195 RTMemFree(pThis->paCachedAbbrevs);
6196 pThis->paCachedAbbrevs = NULL;
6197
6198 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
6199 if (pThis->aSections[iSect].pv)
6200 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb,
6201 &pThis->aSections[iSect].pv);
6202
6203 /** @todo Kill pThis->CompileUnitList and the alloc caches. */
6204 return VINF_SUCCESS;
6205 }
6206
6207 /* bail out. */
6208 RTDbgModRelease(pThis->hCnt);
6209 pMod->pvDbgPriv = NULL;
6210 }
6211 }
6212 else
6213 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
6214 }
6215
6216 RTMemFree(pThis->paCachedAbbrevs);
6217
6218#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
6219 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
6220 while (i-- > 0)
6221 {
6222 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
6223 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
6224 }
6225#endif
6226
6227 RTMemFree(pThis);
6228
6229 return rc;
6230}
6231
6232
6233
6234/** Virtual function table for the DWARF debug info reader. */
6235DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDwarf =
6236{
6237 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
6238 /*.fSupports = */ RT_DBGTYPE_DWARF,
6239 /*.pszName = */ "dwarf",
6240 /*.pfnTryOpen = */ rtDbgModDwarf_TryOpen,
6241 /*.pfnClose = */ rtDbgModDwarf_Close,
6242
6243 /*.pfnRvaToSegOff = */ rtDbgModDwarf_RvaToSegOff,
6244 /*.pfnImageSize = */ rtDbgModDwarf_ImageSize,
6245
6246 /*.pfnSegmentAdd = */ rtDbgModDwarf_SegmentAdd,
6247 /*.pfnSegmentCount = */ rtDbgModDwarf_SegmentCount,
6248 /*.pfnSegmentByIndex = */ rtDbgModDwarf_SegmentByIndex,
6249
6250 /*.pfnSymbolAdd = */ rtDbgModDwarf_SymbolAdd,
6251 /*.pfnSymbolCount = */ rtDbgModDwarf_SymbolCount,
6252 /*.pfnSymbolByOrdinal = */ rtDbgModDwarf_SymbolByOrdinal,
6253 /*.pfnSymbolByName = */ rtDbgModDwarf_SymbolByName,
6254 /*.pfnSymbolByAddr = */ rtDbgModDwarf_SymbolByAddr,
6255
6256 /*.pfnLineAdd = */ rtDbgModDwarf_LineAdd,
6257 /*.pfnLineCount = */ rtDbgModDwarf_LineCount,
6258 /*.pfnLineByOrdinal = */ rtDbgModDwarf_LineByOrdinal,
6259 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr,
6260
6261 /*.pfnUnwindFrame = */ rtDbgModDwarf_UnwindFrame,
6262
6263 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
6264};
6265
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