1 | /* $Id: dbgmoddwarf.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * IPRT - Debug Info Reader For DWARF.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2011-2022 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. */
|
---|
58 | typedef struct RTDWARFCURSOR *PRTDWARFCURSOR;
|
---|
59 | /** Pointer to an attribute descriptor. */
|
---|
60 | typedef struct RTDWARFATTRDESC const *PCRTDWARFATTRDESC;
|
---|
61 | /** Pointer to a DIE. */
|
---|
62 | typedef struct RTDWARFDIE *PRTDWARFDIE;
|
---|
63 | /** Pointer to a const DIE. */
|
---|
64 | typedef struct RTDWARFDIE const *PCRTDWARFDIE;
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * DWARF sections.
|
---|
68 | */
|
---|
69 | typedef 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 | */
|
---|
91 | typedef 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. */
|
---|
107 | typedef RTDWARFABBREV *PRTDWARFABBREV;
|
---|
108 | /** Pointer to a const abbreviation cache entry. */
|
---|
109 | typedef RTDWARFABBREV const *PCRTDWARFABBREV;
|
---|
110 |
|
---|
111 | /**
|
---|
112 | * Structure for gathering segment info.
|
---|
113 | */
|
---|
114 | typedef 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. */
|
---|
126 | typedef RTDBGDWARFSEG *PRTDBGDWARFSEG;
|
---|
127 |
|
---|
128 |
|
---|
129 | /**
|
---|
130 | * The instance data of the DWARF reader.
|
---|
131 | */
|
---|
132 | typedef 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. */
|
---|
199 | typedef RTDBGMODDWARF *PRTDBGMODDWARF;
|
---|
200 |
|
---|
201 | /**
|
---|
202 | * DWARF cursor for reading byte data.
|
---|
203 | */
|
---|
204 | typedef 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 | */
|
---|
235 | typedef 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. */
|
---|
287 | typedef 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 | */
|
---|
300 | typedef DECLCALLBACKTYPE(int, FNRTDWARFATTRDECODER,(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
|
---|
301 | uint32_t uForm, PRTDWARFCURSOR pCursor));
|
---|
302 | /** Pointer to an attribute decoder callback. */
|
---|
303 | typedef FNRTDWARFATTRDECODER *PFNRTDWARFATTRDECODER;
|
---|
304 |
|
---|
305 | /**
|
---|
306 | * Attribute descriptor.
|
---|
307 | */
|
---|
308 | typedef 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 | */
|
---|
344 | typedef 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;
|
---|
353 | typedef 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 | */
|
---|
361 | typedef 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 | */
|
---|
387 | typedef struct RTDWARFADDR
|
---|
388 | {
|
---|
389 | /** The address. */
|
---|
390 | uint64_t uAddress;
|
---|
391 | } RTDWARFADDR;
|
---|
392 | typedef RTDWARFADDR *PRTDWARFADDR;
|
---|
393 | typedef RTDWARFADDR const *PCRTDWARFADDR;
|
---|
394 |
|
---|
395 |
|
---|
396 | /**
|
---|
397 | * DWARF address range.
|
---|
398 | */
|
---|
399 | typedef 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;
|
---|
410 | typedef RTDWARFADDRRANGE *PRTDWARFADDRRANGE;
|
---|
411 | typedef RTDWARFADDRRANGE const *PCRTDWARFADDRRANGE;
|
---|
412 |
|
---|
413 | /** What a RTDWARFREF is relative to. */
|
---|
414 | typedef 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 | */
|
---|
428 | typedef struct RTDWARFREF
|
---|
429 | {
|
---|
430 | /** The offset. */
|
---|
431 | uint64_t off;
|
---|
432 | /** What the offset is relative to. */
|
---|
433 | krtDwarfRef enmWrt;
|
---|
434 | } RTDWARFREF;
|
---|
435 | typedef RTDWARFREF *PRTDWARFREF;
|
---|
436 | typedef RTDWARFREF const *PCRTDWARFREF;
|
---|
437 |
|
---|
438 |
|
---|
439 | /**
|
---|
440 | * DWARF Location state.
|
---|
441 | */
|
---|
442 | typedef 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. */
|
---|
452 | typedef RTDWARFLOCST *PRTDWARFLOCST;
|
---|
453 |
|
---|
454 |
|
---|
455 |
|
---|
456 | /*********************************************************************************************************************************
|
---|
457 | * Internal Functions *
|
---|
458 | *********************************************************************************************************************************/
|
---|
459 | static FNRTDWARFATTRDECODER rtDwarfDecode_Address;
|
---|
460 | static FNRTDWARFATTRDECODER rtDwarfDecode_Bool;
|
---|
461 | static FNRTDWARFATTRDECODER rtDwarfDecode_LowHighPc;
|
---|
462 | static FNRTDWARFATTRDECODER rtDwarfDecode_Ranges;
|
---|
463 | static FNRTDWARFATTRDECODER rtDwarfDecode_Reference;
|
---|
464 | static FNRTDWARFATTRDECODER rtDwarfDecode_SectOff;
|
---|
465 | static FNRTDWARFATTRDECODER rtDwarfDecode_String;
|
---|
466 | static FNRTDWARFATTRDECODER rtDwarfDecode_UnsignedInt;
|
---|
467 | static FNRTDWARFATTRDECODER rtDwarfDecode_SegmentLoc;
|
---|
468 |
|
---|
469 |
|
---|
470 | /*********************************************************************************************************************************
|
---|
471 | * Global Variables *
|
---|
472 | *********************************************************************************************************************************/
|
---|
473 | /** RTDWARFDIE description. */
|
---|
474 | static const RTDWARFDIEDESC g_CoreDieDesc = { sizeof(RTDWARFDIE), 0, NULL };
|
---|
475 |
|
---|
476 |
|
---|
477 | /**
|
---|
478 | * DW_TAG_compile_unit & DW_TAG_partial_unit.
|
---|
479 | */
|
---|
480 | typedef 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;
|
---|
522 | typedef RTDWARFDIECOMPILEUNIT *PRTDWARFDIECOMPILEUNIT;
|
---|
523 |
|
---|
524 |
|
---|
525 | /** RTDWARFDIECOMPILEUNIT attributes. */
|
---|
526 | static 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. */
|
---|
544 | static const RTDWARFDIEDESC g_CompileUnitDesc = DIE_DESC_INIT(RTDWARFDIECOMPILEUNIT, g_aCompileUnitAttrs);
|
---|
545 |
|
---|
546 |
|
---|
547 | /**
|
---|
548 | * DW_TAG_subprogram.
|
---|
549 | */
|
---|
550 | typedef 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. */
|
---|
568 | typedef RTDWARFDIESUBPROGRAM *PRTDWARFDIESUBPROGRAM;
|
---|
569 | /** Pointer to a const DW_TAG_subprogram DIE. */
|
---|
570 | typedef RTDWARFDIESUBPROGRAM const *PCRTDWARFDIESUBPROGRAM;
|
---|
571 |
|
---|
572 |
|
---|
573 | /** RTDWARFDIESUBPROGRAM attributes. */
|
---|
574 | static 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. */
|
---|
588 | static const RTDWARFDIEDESC g_SubProgramDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramAttrs);
|
---|
589 |
|
---|
590 |
|
---|
591 | /** RTDWARFDIESUBPROGRAM attributes for the specification hack. */
|
---|
592 | static 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. */
|
---|
600 | static const RTDWARFDIEDESC g_SubProgramSpecHackDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramSpecHackAttrs);
|
---|
601 |
|
---|
602 |
|
---|
603 | /**
|
---|
604 | * DW_TAG_label.
|
---|
605 | */
|
---|
606 | typedef 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. */
|
---|
620 | typedef RTDWARFDIELABEL *PRTDWARFDIELABEL;
|
---|
621 | /** Pointer to a const DW_TAG_label DIE. */
|
---|
622 | typedef RTDWARFDIELABEL const *PCRTDWARFDIELABEL;
|
---|
623 |
|
---|
624 |
|
---|
625 | /** RTDWARFDIESUBPROGRAM attributes. */
|
---|
626 | static 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. */
|
---|
635 | static const RTDWARFDIEDESC g_LabelDesc = DIE_DESC_INIT(RTDWARFDIELABEL, g_aLabelAttrs);
|
---|
636 |
|
---|
637 |
|
---|
638 | /**
|
---|
639 | * Tag names and descriptors.
|
---|
640 | */
|
---|
641 | static 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 | *********************************************************************************************************************************/
|
---|
731 | static 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 | */
|
---|
745 | static 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 | */
|
---|
767 | static 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 | */
|
---|
880 | static 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} */
|
---|
920 | static 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} */
|
---|
936 | static 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 | */
|
---|
967 | static 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 | */
|
---|
995 | static 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 | */
|
---|
1024 | static 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 | */
|
---|
1073 | static 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 | */
|
---|
1126 | static 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 | */
|
---|
1171 | static 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 | */
|
---|
1191 | static 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 | */
|
---|
1210 | static 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 | */
|
---|
1249 | static 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 | */
|
---|
1279 | static 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 | */
|
---|
1311 | static 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 | */
|
---|
1335 | static 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 | */
|
---|
1364 | static 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 | */
|
---|
1393 | static 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 | */
|
---|
1423 | static 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 | */
|
---|
1487 | static 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 | */
|
---|
1556 | static 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 | */
|
---|
1576 | static 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 | */
|
---|
1594 | static 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 | */
|
---|
1627 | static 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 | */
|
---|
1651 | static 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 | */
|
---|
1678 | static 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 | */
|
---|
1706 | static 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 | */
|
---|
1731 | static 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 | */
|
---|
1745 | static 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 | */
|
---|
1759 | static 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 | */
|
---|
1773 | static 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 | */
|
---|
1789 | static 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 | */
|
---|
1812 | static 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 | */
|
---|
1861 | static 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 | */
|
---|
1896 | static 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 | */
|
---|
1919 | static 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 | */
|
---|
1939 | static 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 | */
|
---|
1972 | static 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 | */
|
---|
1984 | static 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 | */
|
---|
2001 | static 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 | */
|
---|
2015 | static 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 | */
|
---|
2047 | static 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 | */
|
---|
2080 | static 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 | */
|
---|
2110 | static 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 | */
|
---|
2137 | static 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 | */
|
---|
2162 | typedef 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. */
|
---|
2209 | typedef RTDWARFCIEINFO *PRTDWARFCIEINFO;
|
---|
2210 | /** Pointer to const CIE info. */
|
---|
2211 | typedef 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 | */
|
---|
2223 | typedef 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;
|
---|
2249 | typedef RTDWARFCFROW *PRTDWARFCFROW;
|
---|
2250 | typedef RTDWARFCFROW const *PCRTDWARFCFROW;
|
---|
2251 |
|
---|
2252 | /** Row program execution state. */
|
---|
2253 | typedef 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;
|
---|
2271 | typedef 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 |
|
---|
2352 | static 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 | */
|
---|
2677 | static 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 | */
|
---|
2717 | static 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. */
|
---|
2741 | typedef bool FNDWARFUNWINDGEREGFROMSTATE(PCRTDBGUNWINDSTATE pState, uint16_t iReg, uint64_t *puValue);
|
---|
2742 | /** Pointer to a register getter. */
|
---|
2743 | typedef 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 | */
|
---|
2763 | static 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 |
|
---|
2871 | DECLINLINE(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 |
|
---|
2882 | DECLINLINE(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 |
|
---|
2896 | DECLINLINE(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 |
|
---|
2907 | DECLINLINE(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 | */
|
---|
2935 | static 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 | */
|
---|
3078 | static 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 | */
|
---|
3162 | static 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 | */
|
---|
3323 | DECLHIDDEN(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 | */
|
---|
3456 | static 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 | */
|
---|
3492 | DECLHIDDEN(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 | */
|
---|
3524 | static 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 | */
|
---|
3570 | static 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 | */
|
---|
3613 | static 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 | */
|
---|
3638 | static 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 | */
|
---|
3878 | static 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 | */
|
---|
3909 | static 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 | */
|
---|
3942 | static 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 | */
|
---|
4027 | static 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 | */
|
---|
4061 | static 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 | */
|
---|
4251 | static 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 | */
|
---|
4269 | static 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 | */
|
---|
4290 | static 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 | */
|
---|
4310 | static 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} */
|
---|
4339 | static 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} */
|
---|
4369 | static 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} */
|
---|
4404 | static 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} */
|
---|
4463 | static 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} */
|
---|
4516 | static 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} */
|
---|
4581 | static 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} */
|
---|
4629 | static 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} */
|
---|
4657 | static 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 | */
|
---|
4730 | static 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 | */
|
---|
4772 | static 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 |
|
---|
4782 | static 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} */
|
---|
4947 | static 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 | */
|
---|
5004 | static 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 | */
|
---|
5050 | static 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 | */
|
---|
5079 | static 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 | */
|
---|
5199 | static 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 | */
|
---|
5249 | static 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 | */
|
---|
5289 | static 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 | */
|
---|
5312 | static 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 | */
|
---|
5330 | static 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 | */
|
---|
5404 | static 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 | */
|
---|
5436 | static 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 | */
|
---|
5511 | static 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 | */
|
---|
5663 | static 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.} */
|
---|
5694 | static 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 | */
|
---|
5730 | static 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} */
|
---|
5782 | static 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} */
|
---|
5821 | static 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} */
|
---|
5830 | static 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} */
|
---|
5838 | static 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} */
|
---|
5846 | static 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} */
|
---|
5856 | static 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} */
|
---|
5865 | static 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} */
|
---|
5875 | static 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} */
|
---|
5883 | static 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} */
|
---|
5891 | static 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} */
|
---|
5902 | static 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} */
|
---|
5910 | static 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} */
|
---|
5918 | static 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} */
|
---|
5928 | static 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} */
|
---|
5938 | static 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} */
|
---|
5946 | static 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} */
|
---|
5981 | static 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 |
|
---|
6057 | static 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} */
|
---|
6102 | static 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. */
|
---|
6247 | DECL_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 |
|
---|