VirtualBox

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

Last change on this file since 92112 was 92112, checked in by vboxsync, 3 years ago

IPRT/dbgmoddwarf: Don't barf on DW_TAG_label w/o any symbol name (isolinux-debug.elf). Don't assert on DW_LNE_set_descriminator appearing in v3 tables (gcc 10).

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

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