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