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