VirtualBox

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

Last change on this file since 99775 was 99775, checked in by vboxsync, 19 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

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