VirtualBox

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

Last change on this file since 38617 was 38617, checked in by vboxsync, 14 years ago

More DWARF parsing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 114.2 KB
Line 
1/* $Id: dbgmoddwarf.cpp 38617 2011-09-02 20:22:26Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader For DWARF.
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DBG_DWARF
32#include <iprt/dbg.h>
33#include "internal/iprt.h"
34
35#include <iprt/asm.h>
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/list.h>
39#include <iprt/log.h>
40#include <iprt/mem.h>
41#include <iprt/path.h>
42#include <iprt/string.h>
43#include "internal/dbgmod.h"
44
45
46/*******************************************************************************
47* Defined Constants And Macros *
48*******************************************************************************/
49/** @name Standard DWARF Line Number Opcodes
50 * @{ */
51#define DW_LNS_extended UINT8_C(0x00)
52#define DW_LNS_copy UINT8_C(0x01)
53#define DW_LNS_advance_pc UINT8_C(0x02)
54#define DW_LNS_advance_line UINT8_C(0x03)
55#define DW_LNS_set_file UINT8_C(0x04)
56#define DW_LNS_set_column UINT8_C(0x05)
57#define DW_LNS_negate_stmt UINT8_C(0x06)
58#define DW_LNS_set_basic_block UINT8_C(0x07)
59#define DW_LNS_const_add_pc UINT8_C(0x08)
60#define DW_LNS_fixed_advance_pc UINT8_C(0x09)
61#define DW_LNS_set_prologue_end UINT8_C(0x0a)
62#define DW_LNS_set_epilogue_begin UINT8_C(0x0b)
63#define DW_LNS_set_isa UINT8_C(0x0c)
64#define DW_LNS_what_question_mark UINT8_C(0x0d)
65/** @} */
66
67
68/** @name Extended DWARF Line Number Opcodes
69 * @{ */
70#define DW_LNE_end_sequence UINT8_C(1)
71#define DW_LNE_set_address UINT8_C(2)
72#define DW_LNE_define_file UINT8_C(3)
73#define DW_LNE_set_descriminator UINT8_C(4)
74/** @} */
75
76/** @name DIE Tags.
77 * @{ */
78#define DW_TAG_array_type UINT16_C(0x0001)
79#define DW_TAG_class_type UINT16_C(0x0002)
80#define DW_TAG_entry_point UINT16_C(0x0003)
81#define DW_TAG_enumeration_type UINT16_C(0x0004)
82#define DW_TAG_formal_parameter UINT16_C(0x0005)
83#define DW_TAG_imported_declaration UINT16_C(0x0008)
84#define DW_TAG_label UINT16_C(0x000a)
85#define DW_TAG_lexical_block UINT16_C(0x000b)
86#define DW_TAG_member UINT16_C(0x000d)
87#define DW_TAG_pointer_type UINT16_C(0x000f)
88#define DW_TAG_reference_type UINT16_C(0x0010)
89#define DW_TAG_compile_unit UINT16_C(0x0011)
90#define DW_TAG_string_type UINT16_C(0x0012)
91#define DW_TAG_structure_type UINT16_C(0x0013)
92#define DW_TAG_subroutine_type UINT16_C(0x0015)
93#define DW_TAG_typedef UINT16_C(0x0016)
94#define DW_TAG_union_type UINT16_C(0x0017)
95#define DW_TAG_unspecified_parameters UINT16_C(0x0018)
96#define DW_TAG_variant UINT16_C(0x0019)
97#define DW_TAG_common_block UINT16_C(0x001a)
98#define DW_TAG_common_inclusion UINT16_C(0x001b)
99#define DW_TAG_inheritance UINT16_C(0x001c)
100#define DW_TAG_inlined_subroutine UINT16_C(0x001d)
101#define DW_TAG_module UINT16_C(0x001e)
102#define DW_TAG_ptr_to_member_type UINT16_C(0x001f)
103#define DW_TAG_set_type UINT16_C(0x0020)
104#define DW_TAG_subrange_type UINT16_C(0x0021)
105#define DW_TAG_with_stmt UINT16_C(0x0022)
106#define DW_TAG_access_declaration UINT16_C(0x0023)
107#define DW_TAG_base_type UINT16_C(0x0024)
108#define DW_TAG_catch_block UINT16_C(0x0025)
109#define DW_TAG_const_type UINT16_C(0x0026)
110#define DW_TAG_constant UINT16_C(0x0027)
111#define DW_TAG_enumerator UINT16_C(0x0028)
112#define DW_TAG_file_type UINT16_C(0x0029)
113#define DW_TAG_friend UINT16_C(0x002a)
114#define DW_TAG_namelist UINT16_C(0x002b)
115#define DW_TAG_namelist_item UINT16_C(0x002c)
116#define DW_TAG_packed_type UINT16_C(0x002d)
117#define DW_TAG_subprogram UINT16_C(0x002e)
118#define DW_TAG_template_type_parameter UINT16_C(0x002f)
119#define DW_TAG_template_value_parameter UINT16_C(0x0030)
120#define DW_TAG_thrown_type UINT16_C(0x0031)
121#define DW_TAG_try_block UINT16_C(0x0032)
122#define DW_TAG_variant_part UINT16_C(0x0033)
123#define DW_TAG_variable UINT16_C(0x0034)
124#define DW_TAG_volatile_type UINT16_C(0x0035)
125#define DW_TAG_dwarf_procedure UINT16_C(0x0036)
126#define DW_TAG_restrict_type UINT16_C(0x0037)
127#define DW_TAG_interface_type UINT16_C(0x0038)
128#define DW_TAG_namespace UINT16_C(0x0039)
129#define DW_TAG_imported_module UINT16_C(0x003a)
130#define DW_TAG_unspecified_type UINT16_C(0x003b)
131#define DW_TAG_partial_unit UINT16_C(0x003c)
132#define DW_TAG_imported_unit UINT16_C(0x003d)
133#define DW_TAG_condition UINT16_C(0x003f)
134#define DW_TAG_shared_type UINT16_C(0x0040)
135#define DW_TAG_type_unit UINT16_C(0x0041)
136#define DW_TAG_rvalue_reference_type UINT16_C(0x0042)
137#define DW_TAG_template_alias UINT16_C(0x0043)
138#define DW_TAG_lo_user UINT16_C(0x4080)
139#define DW_TAG_hi_user UINT16_C(0xffff)
140/** @} */
141
142
143/** @name DIE Attributes.
144 * @{ */
145#define DW_AT_sibling UINT16_C(0x0001)
146#define DW_AT_location UINT16_C(0x0002)
147#define DW_AT_name UINT16_C(0x0003)
148#define DW_AT_ordering UINT16_C(0x0009)
149#define DW_AT_byte_size UINT16_C(0x000b)
150#define DW_AT_bit_offset UINT16_C(0x000c)
151#define DW_AT_bit_size UINT16_C(0x000d)
152#define DW_AT_stmt_list UINT16_C(0x0010)
153#define DW_AT_low_pc UINT16_C(0x0011)
154#define DW_AT_high_pc UINT16_C(0x0012)
155#define DW_AT_language UINT16_C(0x0013)
156#define DW_AT_discr UINT16_C(0x0015)
157#define DW_AT_discr_value UINT16_C(0x0016)
158#define DW_AT_visibility UINT16_C(0x0017)
159#define DW_AT_import UINT16_C(0x0018)
160#define DW_AT_string_length UINT16_C(0x0019)
161#define DW_AT_common_reference UINT16_C(0x001a)
162#define DW_AT_comp_dir UINT16_C(0x001b)
163#define DW_AT_const_value UINT16_C(0x001c)
164#define DW_AT_containing_type UINT16_C(0x001d)
165#define DW_AT_default_value UINT16_C(0x001e)
166#define DW_AT_inline UINT16_C(0x0020)
167#define DW_AT_is_optional UINT16_C(0x0021)
168#define DW_AT_lower_bound UINT16_C(0x0022)
169#define DW_AT_producer UINT16_C(0x0025)
170#define DW_AT_prototyped UINT16_C(0x0027)
171#define DW_AT_return_addr UINT16_C(0x002a)
172#define DW_AT_start_scope UINT16_C(0x002c)
173#define DW_AT_bit_stride UINT16_C(0x002e)
174#define DW_AT_upper_bound UINT16_C(0x002f)
175#define DW_AT_abstract_origin UINT16_C(0x0031)
176#define DW_AT_accessibility UINT16_C(0x0032)
177#define DW_AT_address_class UINT16_C(0x0033)
178#define DW_AT_artificial UINT16_C(0x0034)
179#define DW_AT_base_types UINT16_C(0x0035)
180#define DW_AT_calling_convention UINT16_C(0x0036)
181#define DW_AT_count UINT16_C(0x0037)
182#define DW_AT_data_member_location UINT16_C(0x0038)
183#define DW_AT_decl_column UINT16_C(0x0039)
184#define DW_AT_decl_file UINT16_C(0x003a)
185#define DW_AT_decl_line UINT16_C(0x003b)
186#define DW_AT_declaration UINT16_C(0x003c)
187#define DW_AT_discr_list UINT16_C(0x003d)
188#define DW_AT_encoding UINT16_C(0x003e)
189#define DW_AT_external UINT16_C(0x003f)
190#define DW_AT_frame_base UINT16_C(0x0040)
191#define DW_AT_friend UINT16_C(0x0041)
192#define DW_AT_identifier_case UINT16_C(0x0042)
193#define DW_AT_macro_info UINT16_C(0x0043)
194#define DW_AT_namelist_item UINT16_C(0x0044)
195#define DW_AT_priority UINT16_C(0x0045)
196#define DW_AT_segment UINT16_C(0x0046)
197#define DW_AT_specification UINT16_C(0x0047)
198#define DW_AT_static_link UINT16_C(0x0048)
199#define DW_AT_type UINT16_C(0x0049)
200#define DW_AT_use_location UINT16_C(0x004a)
201#define DW_AT_variable_parameter UINT16_C(0x004b)
202#define DW_AT_virtuality UINT16_C(0x004c)
203#define DW_AT_vtable_elem_location UINT16_C(0x004d)
204#define DW_AT_allocated UINT16_C(0x004e)
205#define DW_AT_associated UINT16_C(0x004f)
206#define DW_AT_data_location UINT16_C(0x0050)
207#define DW_AT_byte_stride UINT16_C(0x0051)
208#define DW_AT_entry_pc UINT16_C(0x0052)
209#define DW_AT_use_UTF8 UINT16_C(0x0053)
210#define DW_AT_extension UINT16_C(0x0054)
211#define DW_AT_ranges UINT16_C(0x0055)
212#define DW_AT_trampoline UINT16_C(0x0056)
213#define DW_AT_call_column UINT16_C(0x0057)
214#define DW_AT_call_file UINT16_C(0x0058)
215#define DW_AT_call_line UINT16_C(0x0059)
216#define DW_AT_description UINT16_C(0x005a)
217#define DW_AT_binary_scale UINT16_C(0x005b)
218#define DW_AT_decimal_scale UINT16_C(0x005c)
219#define DW_AT_small UINT16_C(0x005d)
220#define DW_AT_decimal_sign UINT16_C(0x005e)
221#define DW_AT_digit_count UINT16_C(0x005f)
222#define DW_AT_picture_string UINT16_C(0x0060)
223#define DW_AT_mutable UINT16_C(0x0061)
224#define DW_AT_threads_scaled UINT16_C(0x0062)
225#define DW_AT_explicit UINT16_C(0x0063)
226#define DW_AT_object_pointer UINT16_C(0x0064)
227#define DW_AT_endianity UINT16_C(0x0065)
228#define DW_AT_elemental UINT16_C(0x0066)
229#define DW_AT_pure UINT16_C(0x0067)
230#define DW_AT_recursive UINT16_C(0x0068)
231#define DW_AT_signature UINT16_C(0x0069)
232#define DW_AT_main_subprogram UINT16_C(0x006a)
233#define DW_AT_data_bit_offset UINT16_C(0x006b)
234#define DW_AT_const_expr UINT16_C(0x006c)
235#define DW_AT_enum_class UINT16_C(0x006d)
236#define DW_AT_linkage_name UINT16_C(0x006e)
237#define DW_AT_lo_user UINT16_C(0x2000)
238#define DW_AT_hi_user UINT16_C(0x3fff)
239/** @} */
240
241/** @name DIE Forms.
242 * @{ */
243#define DW_FORM_addr UINT16_C(0x01)
244/* What was 0x02? */
245#define DW_FORM_block2 UINT16_C(0x03)
246#define DW_FORM_block4 UINT16_C(0x04)
247#define DW_FORM_data2 UINT16_C(0x05)
248#define DW_FORM_data4 UINT16_C(0x06)
249#define DW_FORM_data8 UINT16_C(0x07)
250#define DW_FORM_string UINT16_C(0x08)
251#define DW_FORM_block UINT16_C(0x09)
252#define DW_FORM_block1 UINT16_C(0x0a)
253#define DW_FORM_data1 UINT16_C(0x0b)
254#define DW_FORM_flag UINT16_C(0x0c)
255#define DW_FORM_sdata UINT16_C(0x0d)
256#define DW_FORM_strp UINT16_C(0x0e)
257#define DW_FORM_udata UINT16_C(0x0f)
258#define DW_FORM_ref_addr UINT16_C(0x10)
259#define DW_FORM_ref1 UINT16_C(0x11)
260#define DW_FORM_ref2 UINT16_C(0x12)
261#define DW_FORM_ref4 UINT16_C(0x13)
262#define DW_FORM_ref8 UINT16_C(0x14)
263#define DW_FORM_ref_udata UINT16_C(0x15)
264#define DW_FORM_indirect UINT16_C(0x16)
265#define DW_FORM_sec_offset UINT16_C(0x17)
266#define DW_FORM_exprloc UINT16_C(0x18)
267#define DW_FORM_flag_present UINT16_C(0x19)
268#define DW_FORM_ref_sig8 UINT16_C(0x20)
269/** @} */
270
271/** @name Address classes.
272 * @{ */
273#define DW_ADDR_none UINT8_C(0)
274#define DW_ADDR_i386_near16 UINT8_C(1)
275#define DW_ADDR_i386_far16 UINT8_C(2)
276#define DW_ADDR_i386_huge16 UINT8_C(3)
277#define DW_ADDR_i386_near32 UINT8_C(4)
278#define DW_ADDR_i386_far32 UINT8_C(5)
279/** @} */
280
281
282/*******************************************************************************
283* Structures and Typedefs *
284*******************************************************************************/
285/** Pointer to a DWARF section reader. */
286typedef struct RTDWARFCURSOR *PRTDWARFCURSOR;
287/** Pointer to an attribute descriptor. */
288typedef struct RTDWARFATTRDESC const *PCRTDWARFATTRDESC;
289/** Pointer to a DIE. */
290typedef struct RTDWARFDIE *PRTDWARFDIE;
291/** Pointer to a const DIE. */
292typedef struct RTDWARFDIE const *PCRTDWARFDIE;
293
294/**
295 * DWARF sections.
296 */
297typedef enum krtDbgModDwarfSect
298{
299 krtDbgModDwarfSect_abbrev = 0,
300 krtDbgModDwarfSect_aranges,
301 krtDbgModDwarfSect_frame,
302 krtDbgModDwarfSect_info,
303 krtDbgModDwarfSect_inlined,
304 krtDbgModDwarfSect_line,
305 krtDbgModDwarfSect_loc,
306 krtDbgModDwarfSect_macinfo,
307 krtDbgModDwarfSect_pubnames,
308 krtDbgModDwarfSect_pubtypes,
309 krtDbgModDwarfSect_ranges,
310 krtDbgModDwarfSect_str,
311 krtDbgModDwarfSect_types,
312 /** End of valid parts (exclusive). */
313 krtDbgModDwarfSect_End
314} krtDbgModDwarfSect;
315
316/**
317 * Abbreviation cache entry.
318 */
319typedef struct RTDWARFABBREV
320{
321 /** Whether this entry is filled in or not. */
322 bool fFilled;
323 /** Whether there are children or not. */
324 bool fChildren;
325 /** The tag. */
326 uint16_t uTag;
327 /** Offset into the abbrev section of the specification pairs. */
328 uint32_t offSpec;
329} RTDWARFABBREV;
330/** Pointer to an abbreviation cache entry. */
331typedef RTDWARFABBREV *PRTDWARFABBREV;
332/** Pointer to a const abbreviation cache entry. */
333typedef RTDWARFABBREV const *PCRTDWARFABBREV;
334
335
336/**
337 * The instance data of the DWARF reader.
338 */
339typedef struct RTDBGMODDWARF
340{
341 /** The debug container containing doing the real work. */
342 RTDBGMOD hCnt;
343 /** Pointer to back to the debug info module (no reference ofc). */
344 PRTDBGMODINT pMod;
345
346 /** DWARF debug info sections. */
347 struct
348 {
349 /** The file offset of the part. */
350 RTFOFF offFile;
351 /** The size of the part. */
352 size_t cb;
353 /** The memory mapping of the part. */
354 void const *pv;
355 /** Set if present. */
356 bool fPresent;
357 } aSections[krtDbgModDwarfSect_End];
358
359 /** The offset into the abbreviation section of the current cache. */
360 uint32_t offCachedAbbrev;
361 /** The number of cached abbreviations we've allocated space for. */
362 uint32_t cCachedAbbrevsAlloced;
363 /** Used for range checking cache lookups. */
364 uint32_t cCachedAbbrevs;
365 /** Array of cached abbreviations, indexed by code. */
366 PRTDWARFABBREV paCachedAbbrevs;
367 /** Used by rtDwarfAbbrev_Lookup when the result is uncachable. */
368 RTDWARFABBREV LookupAbbrev;
369
370 /** The list of compilation units (RTDWARFDIE). */
371 RTLISTNODE CompileUnitList;
372} RTDBGMODDWARF;
373/** Pointer to instance data of the DWARF reader. */
374typedef RTDBGMODDWARF *PRTDBGMODDWARF;
375
376/**
377 * DWARF cursor for reading byte data.
378 */
379typedef struct RTDWARFCURSOR
380{
381 /** The current position. */
382 uint8_t const *pb;
383 /** The number of bytes left to read. */
384 size_t cbLeft;
385 /** The number of bytes left to read in the current unit. */
386 size_t cbUnitLeft;
387 /** The DWARF debug info reader instance. */
388 PRTDBGMODDWARF pDwarfMod;
389 /** Set if this is 64-bit DWARF, clear if 32-bit. */
390 bool f64bitDwarf;
391 /** Set if the format endian is native, clear if endian needs to be
392 * inverted. */
393 bool fNativEndian;
394 /** The size of a native address. */
395 uint8_t cbNativeAddr;
396 /** The cursor status code. This is VINF_SUCCESS until some error
397 * occurs. */
398 int rc;
399 /** The start of the area covered by the cursor.
400 * Used for repositioning the cursor relative to the start of a section. */
401 uint8_t const *pbStart;
402 /** The section. */
403 krtDbgModDwarfSect enmSect;
404} RTDWARFCURSOR;
405
406
407/**
408 * DWARF line number program state.
409 */
410typedef struct RTDWARFLINESTATE
411{
412 /** Virtual Line Number Machine Registers. */
413 struct
414 {
415 uint64_t uAddress;
416 uint64_t idxOp;
417 uint32_t iFile;
418 uint32_t uLine;
419 uint32_t uColumn;
420 bool fIsStatement;
421 bool fBasicBlock;
422 bool fEndSequence;
423 bool fPrologueEnd;
424 bool fEpilogueBegin;
425 uint32_t uIsa;
426 uint32_t uDiscriminator;
427 } Regs;
428 /** @} */
429
430 /** Header. */
431 struct
432 {
433 uint32_t uVer;
434 uint64_t offFirstOpcode;
435 uint8_t cbMinInstr;
436 uint8_t cMaxOpsPerInstr;
437 uint8_t u8DefIsStmt;
438 int8_t s8LineBase;
439 uint8_t u8LineRange;
440 uint8_t u8OpcodeBase;
441 uint8_t const *pacStdOperands;
442 } Hdr;
443
444 /** @name Include Path Table (0-based)
445 * @{ */
446 const char **papszIncPaths;
447 uint32_t cIncPaths;
448 /** @} */
449
450 /** @name File Name Table (0-based, dummy zero entry)
451 * @{ */
452 char **papszFileNames;
453 uint32_t cFileNames;
454 /** @} */
455
456 /** The DWARF debug info reader instance. */
457 PRTDBGMODDWARF pDwarfMod;
458} RTDWARFLINESTATE;
459/** Pointer to a DWARF line number program state. */
460typedef RTDWARFLINESTATE *PRTDWARFLINESTATE;
461
462
463/**
464 * Decodes an attribute and stores it in the specified DIE member field.
465 *
466 * @returns IPRT status code.
467 * @param pDie Pointer to the DIE structure.
468 * @param pbMember Pointer to the first byte in the member.
469 * @param pDesc The attribute descriptor.
470 * @param uForm The data form.
471 * @param pDataCursor The cursor to read data from.
472 */
473typedef DECLCALLBACK(int) FNRTDWARFATTRDECODER(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
474 uint32_t uForm, PRTDWARFCURSOR pCursor);
475/** Pointer to an attribute decoder callback. */
476typedef FNRTDWARFATTRDECODER *PFNRTDWARFATTRDECODER;
477
478/**
479 * Attribute descriptor.
480 */
481typedef struct RTDWARFATTRDESC
482{
483 /** The attribute. */
484 uint8_t uAttr;
485 /** The data member size and initialization method. */
486 uint8_t cbInit;
487 /** The data member offset. */
488 uint16_t off;
489 /** The decoder function. */
490 PFNRTDWARFATTRDECODER pfnDecoder;
491} RTDWARFATTRDESC;
492
493/** Define a attribute entry. */
494#define ATTR_ENTRY(a_uAttr, a_Struct, a_Member, a_Init, a_pfnDecoder) \
495 { \
496 a_uAttr, \
497 a_Init | ((uint8_t)RT_SIZEOFMEMB(a_Struct, a_Member) & ATTR_SIZE_MASK), \
498 (uint16_t)RT_OFFSETOF(a_Struct, a_Member), \
499 a_pfnDecoder\
500 }
501
502/** @name Attribute size and init methods.
503 * @{ */
504#define ATTR_INIT_ZERO UINT8_C(0x00)
505#define ATTR_INIT_FFFS UINT8_C(0x40)
506#define ATTR_INIT_ADDRINFO UINT8_C(0x80)
507#define ATTR_INIT_RESERVED UINT8_C(0xc0)
508#define ATTR_INIT_MASK UINT8_C(0xc0)
509#define ATTR_SIZE_MASK UINT8_C(0x3f)
510#define ATTR_GET_SIZE(a_pAttrDesc) ((a_pAttrDesc)->cbInit & ATTR_SIZE_MASK)
511/** @} */
512
513
514/**
515 * DIE descriptor.
516 */
517typedef struct RTDWARFDIEDESC
518{
519 /** The number of attributes. */
520 size_t cAttributes;
521 /** The */
522 PCRTDWARFATTRDESC paAttributes;
523} RTDWARFDIEDESC;
524typedef struct RTDWARFDIEDESC const *PCRTDWARFDIEDESC;
525
526
527/**
528 * DIE core structure, all inherits (starts with) this.
529 */
530typedef struct RTDWARFDIE
531{
532 /** Pointer to the parent node. NULL if root unit. */
533 struct RTDWARFDIE *pParent;
534 /** Our node in the sibling list. */
535 RTLISTNODE SiblingNode;
536 /** List of children. */
537 RTLISTNODE ChildList;
538 /** The number of attributes successfully decoded. */
539 uint8_t cDecodedAttrs;
540 /** The number of unknown or otherwise unhandled attributes. */
541 uint8_t cUnhandledAttrs;
542 /** The date tag, indicating which union structure to use. */
543 uint16_t uTag;
544 /** Offset of the abbreviation specification (within debug_abbrev). */
545 uint32_t offSpec;
546} RTDWARFDIE;
547
548
549/**
550 * DWARF address structure.
551 */
552typedef struct RTDWARFADDR
553{
554 /** The address. */
555 uint64_t uAddress;
556} RTDWARFADDR;
557
558
559/**
560 * DWARF address range.
561 */
562typedef struct RTDWARFADDRRANGE
563{
564 uint64_t uLowAddress;
565 uint64_t uHighAddress;
566 uint8_t const *pbRanges; /* ?? */
567 bool fHaveLowAddress : 1;
568 bool fHaveHighAddress : 1;
569 bool fHaveRanges : 1;
570} RTDWARFADDRRANGE;
571typedef RTDWARFADDRRANGE *PRTDWARFADDRRANGE;
572typedef RTDWARFADDRRANGE const *PCRTDWARFADDRRANGE;
573
574/** What a RTDWARFREF is relative to. */
575typedef enum krtDwarfRef
576{
577 krtDwarfRef_NotSet,
578 krtDwarfRef_LineSection,
579 krtDwarfRef_LocSection,
580 krtDwarfRef_RangesSection,
581 krtDwarfRef_InfoSection,
582 krtDwarfRef_SameUnit,
583 krtDwarfRef_TypeId64
584} krtDwarfRef;
585
586/**
587 * DWARF reference.
588 */
589typedef struct RTDWARFREF
590{
591 /** The offset. */
592 uint64_t off;
593 /** What the offset is relative to. */
594 krtDwarfRef enmWrt;
595} RTDWARFREF;
596typedef RTDWARFREF *PRTDWARFREF;
597typedef RTDWARFREF const *PCRTDWARFREF;
598
599
600
601/*******************************************************************************
602* Internal Functions *
603*******************************************************************************/
604static FNRTDWARFATTRDECODER rtDwarfDecode_Bool;
605static FNRTDWARFATTRDECODER rtDwarfDecode_LowHighPc;
606static FNRTDWARFATTRDECODER rtDwarfDecode_Ranges;
607static FNRTDWARFATTRDECODER rtDwarfDecode_Reference;
608static FNRTDWARFATTRDECODER rtDwarfDecode_SectOff;
609static FNRTDWARFATTRDECODER rtDwarfDecode_String;
610static FNRTDWARFATTRDECODER rtDwarfDecode_UnsignedInt;
611
612
613/*******************************************************************************
614* Global Variables *
615*******************************************************************************/
616/**
617 * DW_TAG_compile_unit & DW_TAG_partial_unit.
618 */
619typedef struct RTDWARFDIECOMPILEUNIT
620{
621 /** The DIE core structure. */
622 RTDWARFDIE Core;
623 /** The unit name. */
624 const char *pszName;
625 /** The address range of the code belonging to this unit. */
626 RTDWARFADDRRANGE PcRange;
627 /** The language name. */
628 uint8_t uLanguage;
629 /** The identifier case. */
630 uint8_t uIdentifierCase;
631 /** String are UTF-8 encoded. If not set, the encoding is
632 * unknown. */
633 bool fUseUtf8;
634 /** The unit contains main() or equivalent. */
635 bool fMainFunction;
636 /** The line numbers for this unit. */
637 RTDWARFREF StmtListRef;
638 /** The macro information for this unit. */
639 RTDWARFREF MacroInfoRef;
640 /** Reference to the base types. */
641 RTDWARFREF BaseTypesRef;
642 /** Working directory for the unit. */
643 const char *pszCurDir;
644 /** The name of the compiler or whatever that produced this unit. */
645 const char *pszProducer;
646
647 /** @name From the unit header.
648 * @{ */
649 /** The offset into debug_info of this unit (for references). */
650 uint64_t offUnit;
651 /** The length of this unit. */
652 uint64_t cbUnit;
653 /** The offset into debug_abbrev of the abbreviation for this unit. */
654 uint64_t offAbbrev;
655 /** The native address size. */
656 uint8_t cbNativeAddr;
657 /** The DWARF version. */
658 uint8_t uDwarfVer;
659 /** @} */
660} RTDWARFDIECOMPILEUNIT;
661typedef RTDWARFDIECOMPILEUNIT *PRTDWARFDIECOMPILEUNIT;
662
663
664/** RTDWARFDIECOMPILEUNIT attributes. */
665static const RTDWARFATTRDESC g_aCompileUnitAttrs[] =
666{
667 ATTR_ENTRY(DW_AT_name, RTDWARFDIECOMPILEUNIT, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
668 ATTR_ENTRY(DW_AT_high_pc, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
669 ATTR_ENTRY(DW_AT_ranges, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_Ranges),
670 ATTR_ENTRY(DW_AT_language, RTDWARFDIECOMPILEUNIT, uLanguage, ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
671 ATTR_ENTRY(DW_AT_macro_info, RTDWARFDIECOMPILEUNIT, MacroInfoRef, ATTR_INIT_FFFS, rtDwarfDecode_SectOff),
672 ATTR_ENTRY(DW_AT_stmt_list, RTDWARFDIECOMPILEUNIT, StmtListRef, ATTR_INIT_FFFS, rtDwarfDecode_SectOff),
673 ATTR_ENTRY(DW_AT_comp_dir, RTDWARFDIECOMPILEUNIT, pszCurDir, ATTR_INIT_ZERO, rtDwarfDecode_String),
674 ATTR_ENTRY(DW_AT_producer, RTDWARFDIECOMPILEUNIT, pszProducer, ATTR_INIT_ZERO, rtDwarfDecode_String),
675 ATTR_ENTRY(DW_AT_identifier_case, RTDWARFDIECOMPILEUNIT, uIdentifierCase,ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
676 ATTR_ENTRY(DW_AT_base_types, RTDWARFDIECOMPILEUNIT, BaseTypesRef, ATTR_INIT_ZERO, rtDwarfDecode_Reference),
677 ATTR_ENTRY(DW_AT_use_UTF8, RTDWARFDIECOMPILEUNIT, fUseUtf8, ATTR_INIT_ZERO, rtDwarfDecode_Bool),
678 ATTR_ENTRY(DW_AT_main_subprogram, RTDWARFDIECOMPILEUNIT, fMainFunction, ATTR_INIT_ZERO, rtDwarfDecode_Bool)
679};
680
681/** RTDWARFDIECOMPILEUNIT description. */
682static const RTDWARFDIEDESC g_aCompileUnitDesc = { RT_ELEMENTS(g_aCompileUnitAttrs), &g_aCompileUnitAttrs[0] };
683
684
685#ifndef DEFINE_THESE_TAGS_TOO
686#define DW_TAG_array_type UINT16_C(0x0001)
687#define DW_TAG_class_type UINT16_C(0x0002)
688#define DW_TAG_entry_point UINT16_C(0x0003)
689#define DW_TAG_enumeration_type UINT16_C(0x0004)
690#define DW_TAG_formal_parameter UINT16_C(0x0005)
691#define DW_TAG_imported_declaration UINT16_C(0x0008)
692#define DW_TAG_label UINT16_C(0x000a)
693#define DW_TAG_lexical_block UINT16_C(0x000b)
694#define DW_TAG_member UINT16_C(0x000d)
695#define DW_TAG_pointer_type UINT16_C(0x000f)
696#define DW_TAG_reference_type UINT16_C(0x0010)
697#define DW_TAG_compile_unit UINT16_C(0x0011)
698#define DW_TAG_string_type UINT16_C(0x0012)
699#define DW_TAG_structure_type UINT16_C(0x0013)
700#define DW_TAG_subroutine_type UINT16_C(0x0015)
701#define DW_TAG_typedef UINT16_C(0x0016)
702#define DW_TAG_union_type UINT16_C(0x0017)
703#define DW_TAG_unspecified_parameters UINT16_C(0x0018)
704#define DW_TAG_variant UINT16_C(0x0019)
705#define DW_TAG_common_block UINT16_C(0x001a)
706#define DW_TAG_common_inclusion UINT16_C(0x001b)
707#define DW_TAG_inheritance UINT16_C(0x001c)
708#define DW_TAG_inlined_subroutine UINT16_C(0x001d)
709#define DW_TAG_module UINT16_C(0x001e)
710#define DW_TAG_ptr_to_member_type UINT16_C(0x001f)
711#define DW_TAG_set_type UINT16_C(0x0020)
712#define DW_TAG_subrange_type UINT16_C(0x0021)
713#define DW_TAG_with_stmt UINT16_C(0x0022)
714#define DW_TAG_access_declaration UINT16_C(0x0023)
715#define DW_TAG_base_type UINT16_C(0x0024)
716#define DW_TAG_catch_block UINT16_C(0x0025)
717#define DW_TAG_const_type UINT16_C(0x0026)
718#define DW_TAG_constant UINT16_C(0x0027)
719#define DW_TAG_enumerator UINT16_C(0x0028)
720#define DW_TAG_file_type UINT16_C(0x0029)
721#define DW_TAG_friend UINT16_C(0x002a)
722#define DW_TAG_namelist UINT16_C(0x002b)
723#define DW_TAG_namelist_item UINT16_C(0x002c)
724#define DW_TAG_packed_type UINT16_C(0x002d)
725#define DW_TAG_subprogram UINT16_C(0x002e)
726#define DW_TAG_template_type_parameter UINT16_C(0x002f)
727#define DW_TAG_template_value_parameter UINT16_C(0x0030)
728#define DW_TAG_thrown_type UINT16_C(0x0031)
729#define DW_TAG_try_block UINT16_C(0x0032)
730#define DW_TAG_variant_part UINT16_C(0x0033)
731#define DW_TAG_variable UINT16_C(0x0034)
732#define DW_TAG_volatile_type UINT16_C(0x0035)
733#define DW_TAG_dwarf_procedure UINT16_C(0x0036)
734#define DW_TAG_restrict_type UINT16_C(0x0037)
735#define DW_TAG_interface_type UINT16_C(0x0038)
736#define DW_TAG_namespace UINT16_C(0x0039)
737#define DW_TAG_imported_module UINT16_C(0x003a)
738#define DW_TAG_unspecified_type UINT16_C(0x003b)
739#define DW_TAG_partial_unit UINT16_C(0x003c)
740#define DW_TAG_imported_unit UINT16_C(0x003d)
741#define DW_TAG_condition UINT16_C(0x003f)
742#define DW_TAG_shared_type UINT16_C(0x0040)
743#define DW_TAG_type_unit UINT16_C(0x0041)
744#define DW_TAG_rvalue_reference_type UINT16_C(0x0042)
745#define DW_TAG_template_alias UINT16_C(0x0043)
746#define DW_TAG_lo_user UINT16_C(0x4080)
747#define DW_TAG_hi_user UINT16_C(0xffff)
748#endif
749
750
751
752
753/** @callback_method_impl{FNRTLDRENUMSEGS} */
754static DECLCALLBACK(int) rtDbgModHlpAddSegmentCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
755{
756 PRTDBGMODINT pMod = (PRTDBGMODINT)pvUser;
757 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx\n",
758 pSeg->cchName, pSeg->pchName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb));
759 RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
760#if 1
761 return pMod->pDbgVt->pfnSegmentAdd(pMod, pSeg->RVA, cb, pSeg->pchName, pSeg->cchName, 0 /*fFlags*/, NULL);
762#else
763 return pMod->pDbgVt->pfnSegmentAdd(pMod, pSeg->LinkAddress, cb, pSeg->pchName, pSeg->cchName, 0 /*fFlags*/, NULL);
764#endif
765}
766
767
768/**
769 * Calls pfnSegmentAdd for each segment in the executable image.
770 *
771 * @returns IPRT status code.
772 * @param pMod The debug module.
773 */
774DECLHIDDEN(int) rtDbgModHlpAddSegmentsFromImage(PRTDBGMODINT pMod)
775{
776 AssertReturn(pMod->pImgVt, VERR_INTERNAL_ERROR_2);
777 return pMod->pImgVt->pfnEnumSegments(pMod, rtDbgModHlpAddSegmentCallback, pMod);
778}
779
780
781
782
783/**
784 * Loads a DWARF section from the image file.
785 *
786 * @returns IPRT status code.
787 * @param pThis The DWARF instance.
788 * @param enmSect The section to load.
789 */
790static int rtDbgModDwarfLoadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
791{
792 /*
793 * Don't load stuff twice.
794 */
795 if (pThis->aSections[enmSect].pv)
796 return VINF_SUCCESS;
797
798 /*
799 * Sections that are not present cannot be loaded, treat them like they
800 * are empty
801 */
802 if (!pThis->aSections[enmSect].fPresent)
803 {
804 Assert(pThis->aSections[enmSect].cb);
805 return VINF_SUCCESS;
806 }
807 if (!pThis->aSections[enmSect].cb)
808 return VINF_SUCCESS;
809
810 /*
811 * Sections must be readable with the current image interface.
812 */
813 if (pThis->aSections[enmSect].offFile < 0)
814 return VERR_OUT_OF_RANGE;
815
816 /*
817 * Do the job.
818 */
819 return pThis->pMod->pImgVt->pfnMapPart(pThis->pMod, pThis->aSections[enmSect].offFile, pThis->aSections[enmSect].cb,
820 &pThis->aSections[enmSect].pv);
821}
822
823
824/**
825 * Unloads a DWARF section previously mapped by rtDbgModDwarfLoadSection.
826 *
827 * @returns IPRT status code.
828 * @param pThis The DWARF instance.
829 * @param enmSect The section to unload.
830 */
831static int rtDbgModDwarfUnloadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
832{
833 if (!pThis->aSections[enmSect].pv)
834 return VINF_SUCCESS;
835
836 int rc = pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[enmSect].cb, &pThis->aSections[enmSect].pv);
837 AssertRC(rc);
838 return rc;
839}
840
841
842/**
843 * Converts to UTF-8 or otherwise makes sure it's valid UTF-8.
844 *
845 * @returns IPRT status code.
846 * @param pThis The DWARF instance.
847 * @param ppsz Pointer to the string pointer. May be
848 * reallocated (RTStr*).
849 */
850static int rtDbgModDwarfStringToUtf8(PRTDBGMODDWARF pThis, char **ppsz)
851{
852 RTStrPurgeEncoding(*ppsz);
853 return VINF_SUCCESS;
854}
855
856
857/**
858 * Convers a link address into a segment+offset or RVA.
859 *
860 * @returns IPRT status code.
861 * @param pThis The DWARF instance.
862 * @param LinkAddress The address to convert..
863 * @param piSeg The segment index.
864 * @param poffSeg Where to return the segment offset.
865 */
866static int rtDbgModDwarfLinkAddressToSegOffset(PRTDBGMODDWARF pThis, uint64_t LinkAddress,
867 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg)
868{
869 return pThis->pMod->pImgVt->pfnLinkAddressToSegOffset(pThis->pMod, LinkAddress, piSeg, poffSeg);
870}
871
872
873/*
874 *
875 * DWARF Cursor.
876 * DWARF Cursor.
877 * DWARF Cursor.
878 *
879 */
880
881
882/**
883 * Reads a 8-bit unsigned integer and advances the cursor.
884 *
885 * @returns 8-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
886 * uErrValue is returned.
887 * @param pCursor The cursor.
888 * @param uErrValue What to return on read error.
889 */
890static uint8_t rtDwarfCursor_GetU8(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
891{
892 if (pCursor->cbUnitLeft < 1)
893 {
894 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
895 return uErrValue;
896 }
897
898 uint8_t u8 = pCursor->pb[0];
899 pCursor->pb += 1;
900 pCursor->cbUnitLeft -= 1;
901 pCursor->cbLeft -= 1;
902 return u8;
903}
904
905
906/**
907 * Reads a 16-bit unsigned integer and advances the cursor.
908 *
909 * @returns 16-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
910 * uErrValue is returned.
911 * @param pCursor The cursor.
912 * @param uErrValue What to return on read error.
913 */
914static uint16_t rtDwarfCursor_GetU16(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
915{
916 if (pCursor->cbUnitLeft < 2)
917 {
918 pCursor->pb += pCursor->cbUnitLeft;
919 pCursor->cbLeft -= pCursor->cbUnitLeft;
920 pCursor->cbUnitLeft = 0;
921 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
922 return uErrValue;
923 }
924
925 uint16_t u16 = RT_MAKE_U16(pCursor->pb[0], pCursor->pb[1]);
926 pCursor->pb += 2;
927 pCursor->cbUnitLeft -= 2;
928 pCursor->cbLeft -= 2;
929 if (!pCursor->fNativEndian)
930 u16 = RT_BSWAP_U16(u16);
931 return u16;
932}
933
934
935/**
936 * Reads a 32-bit unsigned integer and advances the cursor.
937 *
938 * @returns 32-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
939 * uErrValue is returned.
940 * @param pCursor The cursor.
941 * @param uErrValue What to return on read error.
942 */
943static uint32_t rtDwarfCursor_GetU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
944{
945 if (pCursor->cbUnitLeft < 4)
946 {
947 pCursor->pb += pCursor->cbUnitLeft;
948 pCursor->cbLeft -= pCursor->cbUnitLeft;
949 pCursor->cbUnitLeft = 0;
950 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
951 return uErrValue;
952 }
953
954 uint32_t u32 = RT_MAKE_U32_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3]);
955 pCursor->pb += 4;
956 pCursor->cbUnitLeft -= 4;
957 pCursor->cbLeft -= 4;
958 if (!pCursor->fNativEndian)
959 u32 = RT_BSWAP_U32(u32);
960 return u32;
961}
962
963
964/**
965 * Reads a 64-bit unsigned integer and advances the cursor.
966 *
967 * @returns 64-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
968 * uErrValue is returned.
969 * @param pCursor The cursor.
970 * @param uErrValue What to return on read error.
971 */
972static uint64_t rtDwarfCursor_GetU64(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
973{
974 if (pCursor->cbUnitLeft < 8)
975 {
976 pCursor->pb += pCursor->cbUnitLeft;
977 pCursor->cbLeft -= pCursor->cbUnitLeft;
978 pCursor->cbUnitLeft = 0;
979 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
980 return uErrValue;
981 }
982
983 uint64_t u64 = RT_MAKE_U64_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3],
984 pCursor->pb[4], pCursor->pb[5], pCursor->pb[6], pCursor->pb[7]);
985 pCursor->pb += 8;
986 pCursor->cbUnitLeft -= 8;
987 pCursor->cbLeft -= 8;
988 if (!pCursor->fNativEndian)
989 u64 = RT_BSWAP_U64(u64);
990 return u64;
991}
992
993
994/**
995 * Reads an unsigned LEB128 encoded number.
996 *
997 * @returns unsigned 64-bit number. On error RTDWARFCURSOR::rc is set and @a
998 * uErrValue is returned.
999 * @param pCursor The cursor.
1000 * @param uErrValue The value to return on error.
1001 */
1002static uint64_t rtDwarfCursor_GetULeb128(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1003{
1004 if (pCursor->cbUnitLeft < 1)
1005 {
1006 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1007 return uErrValue;
1008 }
1009
1010 /*
1011 * Special case - single byte.
1012 */
1013 uint8_t b = pCursor->pb[0];
1014 if (!(b & 0x80))
1015 {
1016 pCursor->pb += 1;
1017 pCursor->cbUnitLeft -= 1;
1018 pCursor->cbLeft -= 1;
1019 return b;
1020 }
1021
1022 /*
1023 * Generic case.
1024 */
1025 /* Decode. */
1026 uint32_t off = 1;
1027 uint64_t u64Ret = b & 0x7f;
1028 do
1029 {
1030 if (off == pCursor->cbUnitLeft)
1031 {
1032 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1033 u64Ret = uErrValue;
1034 break;
1035 }
1036 b = pCursor->pb[off];
1037 u64Ret |= (b & 0x7f) << off * 7;
1038 off++;
1039 } while (b & 0x80);
1040
1041 /* Update the cursor. */
1042 pCursor->pb += off;
1043 pCursor->cbUnitLeft -= off;
1044 pCursor->cbLeft -= off;
1045
1046 /* Check the range. */
1047 uint32_t cBits = off * 7;
1048 if (cBits > 64)
1049 {
1050 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1051 u64Ret = uErrValue;
1052 }
1053
1054 return u64Ret;
1055}
1056
1057
1058/**
1059 * Reads a signed LEB128 encoded number.
1060 *
1061 * @returns signed 64-bit number. On error RTDWARFCURSOR::rc is set and @a
1062 * uErrValue is returned.
1063 * @param pCursor The cursor.
1064 * @param sErrValue The value to return on error.
1065 */
1066static int64_t rtDwarfCursor_GetSLeb128(PRTDWARFCURSOR pCursor, int64_t sErrValue)
1067{
1068 if (pCursor->cbUnitLeft < 1)
1069 {
1070 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1071 return sErrValue;
1072 }
1073
1074 /*
1075 * Special case - single byte.
1076 */
1077 uint8_t b = pCursor->pb[0];
1078 if (!(b & 0x80))
1079 {
1080 pCursor->pb += 1;
1081 pCursor->cbUnitLeft -= 1;
1082 pCursor->cbLeft -= 1;
1083 if (b & 0x40)
1084 b |= 0x80;
1085 return (int8_t)b;
1086 }
1087
1088 /*
1089 * Generic case.
1090 */
1091 /* Decode it. */
1092 uint32_t off = 1;
1093 uint64_t u64Ret = b & 0x7f;
1094 do
1095 {
1096 if (off == pCursor->cbUnitLeft)
1097 {
1098 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1099 u64Ret = (uint64_t)sErrValue;
1100 break;
1101 }
1102 b = pCursor->pb[off];
1103 u64Ret |= (b & 0x7f) << off * 7;
1104 off++;
1105 } while (b & 0x80);
1106
1107 /* Update cursor. */
1108 pCursor->pb += off;
1109 pCursor->cbUnitLeft -= off;
1110 pCursor->cbLeft -= off;
1111
1112 /* Check the range. */
1113 uint32_t cBits = off * 7;
1114 if (cBits > 64)
1115 {
1116 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1117 u64Ret = (uint64_t)sErrValue;
1118 }
1119 /* Sign extend the value. */
1120 else if (u64Ret & RT_BIT_64(cBits - 1))
1121 u64Ret |= ~(RT_BIT_64(cBits - 1) - 1);
1122
1123 return (int64_t)u64Ret;
1124}
1125
1126
1127/**
1128 * Reads an unsigned LEB128 encoded number, max 32-bit width.
1129 *
1130 * @returns unsigned 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1131 * uErrValue is returned.
1132 * @param pCursor The cursor.
1133 * @param uErrValue The value to return on error.
1134 */
1135static uint32_t rtDwarfCursor_GetULeb128AsU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
1136{
1137 uint64_t u64 = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
1138 if (u64 > UINT32_MAX)
1139 {
1140 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1141 return uErrValue;
1142 }
1143 return (uint32_t)u64;
1144}
1145
1146
1147/**
1148 * Reads a signed LEB128 encoded number, max 32-bit width.
1149 *
1150 * @returns signed 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1151 * uErrValue is returned.
1152 * @param pCursor The cursor.
1153 * @param sErrValue The value to return on error.
1154 */
1155static int32_t rtDwarfCursor_GetSLeb128AsS32(PRTDWARFCURSOR pCursor, int32_t sErrValue)
1156{
1157 int64_t s64 = rtDwarfCursor_GetSLeb128(pCursor, sErrValue);
1158 if (s64 > INT32_MAX || s64 < INT32_MIN)
1159 {
1160 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1161 return sErrValue;
1162 }
1163 return (int32_t)s64;
1164}
1165
1166
1167/**
1168 * Skips a LEB128 encoded number.
1169 *
1170 * @returns IPRT status code.
1171 * @param pCursor The cursor.
1172 */
1173static int rtDwarfCursor_SkipLeb128(PRTDWARFCURSOR pCursor)
1174{
1175 if (RT_FAILURE(pCursor->rc))
1176 return pCursor->rc;
1177
1178 if (pCursor->cbUnitLeft < 1)
1179 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1180
1181 uint32_t offSkip = 1;
1182 if (pCursor->pb[0] & 0x80)
1183 do
1184 {
1185 if (offSkip == pCursor->cbUnitLeft)
1186 {
1187 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1188 break;
1189 }
1190 } while (pCursor->pb[offSkip++] & 0x80);
1191
1192 pCursor->pb += offSkip;
1193 pCursor->cbUnitLeft -= offSkip;
1194 pCursor->cbLeft -= offSkip;
1195 return pCursor->rc;
1196}
1197
1198
1199/**
1200 * Advances the cursor a given number of bytes.
1201 *
1202 * @returns IPRT status code.
1203 * @param pCursor The cursor.
1204 * @param offSkip The number of bytes to advance.
1205 */
1206static int rtDwarfCursor_SkipBytes(PRTDWARFCURSOR pCursor, uint64_t offSkip)
1207{
1208 if (RT_FAILURE(pCursor->rc))
1209 return pCursor->rc;
1210 if (pCursor->cbUnitLeft < offSkip)
1211 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1212
1213 size_t const offSkipSizeT = (size_t)offSkip;
1214 pCursor->cbUnitLeft -= offSkipSizeT;
1215 pCursor->cbLeft -= offSkipSizeT;
1216 pCursor->pb += offSkipSizeT;
1217
1218 return VINF_SUCCESS;
1219}
1220
1221
1222/**
1223 * Reads a zero terminated string, advancing the cursor beyond the terminator.
1224 *
1225 * @returns Pointer to the string.
1226 * @param pCursor The cursor.
1227 * @param pszErrValue What to return if the string isn't terminated
1228 * before the end of the unit.
1229 */
1230static const char *rtDwarfCursor_GetSZ(PRTDWARFCURSOR pCursor, const char *pszErrValue)
1231{
1232 const char *pszRet = (const char *)pCursor->pb;
1233 for (;;)
1234 {
1235 if (!pCursor->cbUnitLeft)
1236 {
1237 pCursor->rc = VERR_DWARF_BAD_STRING;
1238 return pszErrValue;
1239 }
1240 pCursor->cbUnitLeft--;
1241 pCursor->cbLeft--;
1242 if (!*pCursor->pb++)
1243 break;
1244 }
1245 return pszRet;
1246}
1247
1248
1249/**
1250 * Reads a 1, 2, 4 or 8 byte unsgined value.
1251 *
1252 * @returns 64-bit unsigned value.
1253 * @param pCursor The cursor.
1254 * @param cbValue The value size.
1255 * @param uErrValue The error value.
1256 */
1257static uint64_t rtDwarfCursor_GetVarSizedU(PRTDWARFCURSOR pCursor, size_t cbValue, uint64_t uErrValue)
1258{
1259 uint64_t u64Ret;
1260 switch (cbValue)
1261 {
1262 case 1: u64Ret = rtDwarfCursor_GetU8( pCursor, UINT8_MAX); break;
1263 case 2: u64Ret = rtDwarfCursor_GetU16(pCursor, UINT16_MAX); break;
1264 case 4: u64Ret = rtDwarfCursor_GetU32(pCursor, UINT32_MAX); break;
1265 case 8: u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX); break;
1266 default:
1267 pCursor->rc = VERR_DWARF_BAD_INFO;
1268 return uErrValue;
1269 }
1270 if (RT_FAILURE(pCursor->rc))
1271 return uErrValue;
1272 return u64Ret;
1273}
1274
1275
1276/**
1277 * Reads an unsigned DWARF half number.
1278 *
1279 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1280 * uErrValue is returned.
1281 * @param pCursor The cursor.
1282 * @param uErrValue What to return on error.
1283 */
1284static uint16_t rtDwarfCursor_GetUHalf(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
1285{
1286 return rtDwarfCursor_GetU16(pCursor, uErrValue);
1287}
1288
1289
1290/**
1291 * Reads an unsigned DWARF byte number.
1292 *
1293 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1294 * uErrValue is returned.
1295 * @param pCursor The cursor.
1296 * @param uErrValue What to return on error.
1297 */
1298static uint8_t rtDwarfCursor_GetUByte(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
1299{
1300 return rtDwarfCursor_GetU8(pCursor, uErrValue);
1301}
1302
1303
1304/**
1305 * Reads a signed DWARF byte number.
1306 *
1307 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1308 * uErrValue is returned.
1309 * @param pCursor The cursor.
1310 * @param uErrValue What to return on error.
1311 */
1312static int8_t rtDwarfCursor_GetSByte(PRTDWARFCURSOR pCursor, int8_t iErrValue)
1313{
1314 return (int8_t)rtDwarfCursor_GetU8(pCursor, (uint8_t)iErrValue);
1315}
1316
1317
1318/**
1319 * Reads a unsigned DWARF offset value.
1320 *
1321 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1322 * uErrValue is returned.
1323 * @param pCursor The cursor.
1324 * @param uErrValue What to return on error.
1325 */
1326static uint64_t rtDwarfCursor_GetUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1327{
1328 if (pCursor->f64bitDwarf)
1329 return rtDwarfCursor_GetU64(pCursor, uErrValue);
1330 return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
1331}
1332
1333
1334/**
1335 * Reads a unsigned DWARF native offset value.
1336 *
1337 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1338 * uErrValue is returned.
1339 * @param pCursor The cursor.
1340 * @param uErrValue What to return on error.
1341 */
1342static uint64_t rtDwarfCursor_GetNativeUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1343{
1344 switch (pCursor->cbNativeAddr)
1345 {
1346 case 1: return rtDwarfCursor_GetU8(pCursor, (uint8_t )uErrValue);
1347 case 2: return rtDwarfCursor_GetU16(pCursor, (uint16_t)uErrValue);
1348 case 4: return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
1349 case 8: return rtDwarfCursor_GetU64(pCursor, uErrValue);
1350 default:
1351 pCursor->rc = VERR_INTERNAL_ERROR_2;
1352 return uErrValue;
1353 }
1354}
1355
1356
1357/**
1358 * Gets the unit length, updating the unit length member and DWARF bitness
1359 * members of the cursor.
1360 *
1361 * @returns The unit length.
1362 * @param pCursor The cursor.
1363 */
1364static uint64_t rtDwarfCursor_GetInitalLength(PRTDWARFCURSOR pCursor)
1365{
1366 /*
1367 * Read the initial length.
1368 */
1369 pCursor->cbUnitLeft = pCursor->cbLeft;
1370 uint64_t cbUnit = rtDwarfCursor_GetU32(pCursor, 0);
1371 if (cbUnit != UINT32_C(0xffffffff))
1372 pCursor->f64bitDwarf = false;
1373 else
1374 {
1375 pCursor->f64bitDwarf = true;
1376 cbUnit = rtDwarfCursor_GetU64(pCursor, 0);
1377 }
1378
1379
1380 /*
1381 * Set the unit length, quitely fixing bad lengths.
1382 */
1383 pCursor->cbUnitLeft = (size_t)cbUnit;
1384 if ( pCursor->cbUnitLeft > pCursor->cbLeft
1385 || pCursor->cbUnitLeft != cbUnit)
1386 pCursor->cbUnitLeft = pCursor->cbLeft;
1387
1388 return cbUnit;
1389}
1390
1391
1392/**
1393 * Calculates the section offset corresponding to the current cursor position.
1394 *
1395 * @returns 32-bit section offset. If out of range, RTDWARFCURSOR::rc will be
1396 * set and UINT32_MAX returned.
1397 * @param pCursor The cursor.
1398 */
1399static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor)
1400{
1401 size_t off = pCursor->pb - (uint8_t const *)pCursor->pDwarfMod->aSections[pCursor->enmSect].pv;
1402 uint32_t offRet = (uint32_t)off;
1403 if (offRet != off)
1404 {
1405 pCursor->rc = VERR_OUT_OF_RANGE;
1406 offRet = UINT32_MAX;
1407 }
1408 return offRet;
1409}
1410
1411
1412/**
1413 * Calculates an absolute cursor position from one relative to the current
1414 * cursor position.
1415 *
1416 * @returns The absolute cursor position.
1417 * @param pCursor The cursor.
1418 * @param offRelative The relative position. Must be a positive
1419 * offset.
1420 */
1421static uint8_t const *rtDwarfCursor_CalcPos(PRTDWARFCURSOR pCursor, size_t offRelative)
1422{
1423 if (offRelative > pCursor->cbUnitLeft)
1424 {
1425 Log(("rtDwarfCursor_CalcPos: bad position %#zx, cbUnitLeft=%#zu\n", offRelative, pCursor->cbUnitLeft));
1426 pCursor->rc = VERR_DWARF_BAD_POS;
1427 return NULL;
1428 }
1429 return pCursor->pb + offRelative;
1430}
1431
1432
1433/**
1434 * Advances the cursor to the given position.
1435 *
1436 * @returns IPRT status code.
1437 * @param pCursor The cursor.
1438 * @param pbNewPos The new position - returned by
1439 * rtDwarfCursor_CalcPos().
1440 */
1441static int rtDwarfCursor_AdvanceToPos(PRTDWARFCURSOR pCursor, uint8_t const *pbNewPos)
1442{
1443 if (RT_FAILURE(pCursor->rc))
1444 return pCursor->rc;
1445 AssertPtr(pbNewPos);
1446 if ((uintptr_t)pbNewPos < (uintptr_t)pCursor->pb)
1447 {
1448 Log(("rtDwarfCursor_AdvanceToPos: bad position %p, current %p\n", pbNewPos, pCursor->pb));
1449 return pCursor->rc = VERR_DWARF_BAD_POS;
1450 }
1451
1452 uintptr_t cbAdj = (uintptr_t)pbNewPos - (uintptr_t)pCursor->pb;
1453 if (RT_UNLIKELY(cbAdj > pCursor->cbUnitLeft))
1454 {
1455 AssertFailed();
1456 pCursor->rc = VERR_DWARF_BAD_POS;
1457 cbAdj = pCursor->cbUnitLeft;
1458 }
1459
1460 pCursor->cbUnitLeft -= cbAdj;
1461 pCursor->cbLeft -= cbAdj;
1462 pCursor->pb += cbAdj;
1463 return pCursor->rc;
1464}
1465
1466
1467/**
1468 * Check if the cursor is at the end of the current DWARF unit.
1469 *
1470 * @retval @c true if at the end or a cursor error is pending.
1471 * @retval @c false if not.
1472 * @param pCursor The cursor.
1473 */
1474static bool rtDwarfCursor_IsAtEndOfUnit(PRTDWARFCURSOR pCursor)
1475{
1476 return !pCursor->cbUnitLeft || RT_FAILURE(pCursor->rc);
1477}
1478
1479
1480/**
1481 * Skips to the end of the current unit.
1482 *
1483 * @returns IPRT status code.
1484 * @param pCursor The cursor.
1485 */
1486static int rtDwarfCursor_SkipUnit(PRTDWARFCURSOR pCursor)
1487{
1488 pCursor->pb += pCursor->cbUnitLeft;
1489 pCursor->cbLeft -= pCursor->cbUnitLeft;
1490 pCursor->cbUnitLeft = 0;
1491 return pCursor->rc;
1492}
1493
1494
1495/**
1496 * Check if the cursor is at the end of the section (or whatever the cursor is
1497 * processing).
1498 *
1499 * @retval @c true if at the end or a cursor error is pending.
1500 * @retval @c false if not.
1501 * @param pCursor The cursor.
1502 */
1503static bool rtDwarfCursor_IsAtEnd(PRTDWARFCURSOR pCursor)
1504{
1505 return !pCursor->cbLeft || RT_FAILURE(pCursor->rc);
1506}
1507
1508
1509/**
1510 * Initialize a section reader cursor.
1511 *
1512 * @returns IPRT status code.
1513 * @param pCursor The cursor.
1514 * @param pThis The dwarf module.
1515 * @param enmSect The name of the section to read.
1516 */
1517static int rtDwarfCursor_Init(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
1518{
1519 int rc = rtDbgModDwarfLoadSection(pThis, enmSect);
1520 if (RT_FAILURE(rc))
1521 return rc;
1522
1523 pCursor->enmSect = enmSect;
1524 pCursor->pbStart = (uint8_t const *)pThis->aSections[enmSect].pv;
1525 pCursor->pb = pCursor->pbStart;
1526 pCursor->cbLeft = pThis->aSections[enmSect].cb;
1527 pCursor->cbUnitLeft = pCursor->cbLeft;
1528 pCursor->pDwarfMod = pThis;
1529 pCursor->f64bitDwarf = false;
1530 /** @todo ask the image about the endian used as well as the address
1531 * width. */
1532 pCursor->fNativEndian = true;
1533 pCursor->cbNativeAddr = 4;
1534 pCursor->rc = VINF_SUCCESS;
1535
1536 return VINF_SUCCESS;
1537}
1538
1539
1540/**
1541 * Initialize a section reader cursor with an offset.
1542 *
1543 * @returns IPRT status code.
1544 * @param pCursor The cursor.
1545 * @param pThis The dwarf module.
1546 * @param enmSect The name of the section to read.
1547 * @param offSect The offset into the section.
1548 */
1549static int rtDwarfCursor_InitWithOffset(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis,
1550 krtDbgModDwarfSect enmSect, uint32_t offSect)
1551{
1552 if (offSect > pThis->aSections[enmSect].cb)
1553 {
1554 Log(("rtDwarfCursor_InitWithOffset: offSect=%#x cb=%#x enmSect=%d\n", offSect, pThis->aSections[enmSect].cb, enmSect));
1555 return VERR_DWARF_BAD_POS;
1556 }
1557
1558 int rc = rtDwarfCursor_Init(pCursor, pThis, enmSect);
1559 if (RT_SUCCESS(rc))
1560 {
1561 pCursor->pbStart += offSect;
1562 pCursor->pb += offSect;
1563 pCursor->cbLeft -= offSect;
1564 pCursor->cbUnitLeft -= offSect;
1565 }
1566
1567 return rc;
1568}
1569
1570
1571/**
1572 * Deletes a section reader initialized by rtDwarfCursor_Init.
1573 *
1574 * @returns @a rcOther or RTDWARCURSOR::rc.
1575 * @param pCursor The section reader.
1576 * @param rcOther Other error code to be returned if it indicates
1577 * error or if the cursor status is OK.
1578 */
1579static int rtDwarfCursor_Delete(PRTDWARFCURSOR pCursor, int rcOther)
1580{
1581 /* ... and a drop of poison. */
1582 pCursor->pb = NULL;
1583 pCursor->cbLeft = ~(size_t)0;
1584 pCursor->cbUnitLeft = ~(size_t)0;
1585 pCursor->pDwarfMod = NULL;
1586 if (RT_FAILURE(pCursor->rc) && RT_SUCCESS(rcOther))
1587 rcOther = pCursor->rc;
1588 pCursor->rc = VERR_INTERNAL_ERROR_4;
1589 return rcOther;
1590}
1591
1592
1593/*
1594 *
1595 * DWARF Line Numbers.
1596 * DWARF Line Numbers.
1597 * DWARF Line Numbers.
1598 *
1599 */
1600
1601
1602/**
1603 * Defines a file name.
1604 *
1605 * @returns IPRT status code.
1606 * @param pLnState The line number program state.
1607 * @param pszFilename The name of the file.
1608 * @param idxInc The include path index.
1609 */
1610static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc)
1611{
1612 /*
1613 * Resize the array if necessary.
1614 */
1615 uint32_t iFileName = pLnState->cFileNames;
1616 if ((iFileName % 2) == 0)
1617 {
1618 void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2));
1619 if (!pv)
1620 return VERR_NO_MEMORY;
1621 pLnState->papszFileNames = (char **)pv;
1622 }
1623
1624 /*
1625 * Add the file name.
1626 */
1627 if ( pszFilename[0] == '/'
1628 || pszFilename[0] == '\\'
1629 || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') )
1630 pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename);
1631 else if (idxInc < pLnState->cIncPaths)
1632 pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename);
1633 else
1634 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
1635 if (!pLnState->papszFileNames[iFileName])
1636 return VERR_NO_STR_MEMORY;
1637 pLnState->cFileNames = iFileName + 1;
1638
1639 /*
1640 * Sanitize the name.
1641 */
1642 int rc = rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]);
1643 Log((" File #%02u = '%s'\n", iFileName, pLnState->papszFileNames[iFileName]));
1644 return rc;
1645}
1646
1647
1648/**
1649 * Adds a line to the table and resets parts of the state (DW_LNS_copy).
1650 *
1651 * @returns IPRT status code
1652 * @param pLnState The line number program state.
1653 * @param offOpCode The opcode offset (for logging
1654 * purposes).
1655 */
1656static int rtDwarfLine_AddLine(PRTDWARFLINESTATE pLnState, uint32_t offOpCode)
1657{
1658 const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames
1659 ? pLnState->papszFileNames[pLnState->Regs.iFile]
1660 : "<bad file name index>";
1661 RTDBGSEGIDX iSeg;
1662 RTUINTPTR offSeg;
1663 int rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uAddress, &iSeg, &offSeg);
1664 if (RT_SUCCESS(rc))
1665 {
1666 Log2(("rtDwarfLine_AddLine: %x:%08llx (%#llx) %s(%d) [offOpCode=%08x]\n", iSeg, offSeg, pLnState->Regs.uAddress, pszFile, pLnState->Regs.uLine, offOpCode));
1667 rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL);
1668
1669 /* Ignore address conflicts for now. */
1670 if (rc == VERR_DBG_ADDRESS_CONFLICT)
1671 rc = VINF_SUCCESS;
1672 }
1673
1674 pLnState->Regs.fBasicBlock = false;
1675 pLnState->Regs.fPrologueEnd = false;
1676 pLnState->Regs.fEpilogueBegin = false;
1677 pLnState->Regs.uDiscriminator = 0;
1678 return rc;
1679}
1680
1681
1682/**
1683 * Reset the program to the start-of-sequence state.
1684 *
1685 * @param pLnState The line number program state.
1686 */
1687static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState)
1688{
1689 pLnState->Regs.uAddress = 0;
1690 pLnState->Regs.idxOp = 0;
1691 pLnState->Regs.iFile = 1;
1692 pLnState->Regs.uLine = 1;
1693 pLnState->Regs.uColumn = 0;
1694 pLnState->Regs.fIsStatement = RT_BOOL(pLnState->Hdr.u8DefIsStmt);
1695 pLnState->Regs.fBasicBlock = false;
1696 pLnState->Regs.fEndSequence = false;
1697 pLnState->Regs.fPrologueEnd = false;
1698 pLnState->Regs.fEpilogueBegin = false;
1699 pLnState->Regs.uIsa = 0;
1700 pLnState->Regs.uDiscriminator = 0;
1701}
1702
1703
1704/**
1705 * Runs the line number program.
1706 *
1707 * @returns IPRT status code.
1708 * @param pLnState The line number program state.
1709 * @param pCursor The cursor.
1710 */
1711static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
1712{
1713 LogFlow(("rtDwarfLine_RunProgram: cbUnitLeft=%zu\n", pCursor->cbUnitLeft));
1714
1715 int rc = VINF_SUCCESS;
1716 rtDwarfLine_ResetState(pLnState);
1717
1718 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
1719 {
1720#ifdef LOG_ENABLED
1721 uint32_t const offOpCode = rtDwarfCursor_CalcSectOffsetU32(pCursor);
1722#else
1723 uint32_t const offOpCode = 0;
1724#endif
1725 uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, DW_LNS_extended);
1726 if (bOpCode >= pLnState->Hdr.u8OpcodeBase)
1727 {
1728 /*
1729 * Special opcode.
1730 */
1731 uint8_t const bLogOpCode = bOpCode; NOREF(bLogOpCode);
1732 bOpCode -= pLnState->Hdr.u8OpcodeBase;
1733
1734 int32_t const cLineDelta = bOpCode % pLnState->Hdr.u8LineRange + (int32_t)pLnState->Hdr.s8LineBase;
1735 bOpCode /= pLnState->Hdr.u8LineRange;
1736
1737 uint64_t uTmp = bOpCode + pLnState->Regs.idxOp + bOpCode;
1738 uint64_t const cAddressDelta = uTmp / pLnState->Hdr.cMaxOpsPerInstr * pLnState->Hdr.cbMinInstr;
1739 uint64_t const cOpIndexDelta = uTmp % pLnState->Hdr.cMaxOpsPerInstr;
1740
1741 pLnState->Regs.uLine += cLineDelta;
1742 pLnState->Regs.uAddress += cAddressDelta;
1743 pLnState->Regs.idxOp += cOpIndexDelta;
1744 Log2(("%08x: DW Special Opcode %#04x: uLine + %d => %u; uAddress + %#llx => %#llx; idxOp + %#llx => %#llx\n",
1745 offOpCode, bLogOpCode, cLineDelta, pLnState->Regs.uLine, cAddressDelta, pLnState->Regs.uAddress,
1746 cOpIndexDelta, pLnState->Regs.idxOp));
1747
1748 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
1749 }
1750 else
1751 {
1752 switch (bOpCode)
1753 {
1754 /*
1755 * Standard opcode.
1756 */
1757 case DW_LNS_copy:
1758 Log2(("%08x: DW_LNS_copy\n", offOpCode));
1759 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
1760 break;
1761
1762 case DW_LNS_advance_pc:
1763 {
1764 uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0);
1765 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->Hdr.cMaxOpsPerInstr
1766 * pLnState->Hdr.cbMinInstr;
1767 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + u64Adv) % pLnState->Hdr.cMaxOpsPerInstr;
1768 Log2(("%08x: DW_LNS_advance_pc: u64Adv=%#llx (%lld) )\n", offOpCode, u64Adv, u64Adv));
1769 break;
1770 }
1771
1772 case DW_LNS_advance_line:
1773 {
1774 int32_t cLineDelta = rtDwarfCursor_GetSLeb128AsS32(pCursor, 0);
1775 pLnState->Regs.uLine += cLineDelta;
1776 Log2(("%08x: DW_LNS_advance_line: uLine + %d => %u\n", offOpCode, cLineDelta, pLnState->Regs.uLine));
1777 break;
1778 }
1779
1780 case DW_LNS_set_file:
1781 pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
1782 Log2(("%08x: DW_LNS_set_file: iFile=%u\n", offOpCode, pLnState->Regs.iFile));
1783 break;
1784
1785 case DW_LNS_set_column:
1786 pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
1787 Log2(("%08x: DW_LNS_set_column\n", offOpCode));
1788 break;
1789
1790 case DW_LNS_negate_stmt:
1791 pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement;
1792 Log2(("%08x: DW_LNS_negate_stmt\n", offOpCode));
1793 break;
1794
1795 case DW_LNS_set_basic_block:
1796 pLnState->Regs.fBasicBlock = true;
1797 Log2(("%08x: DW_LNS_set_basic_block\n", offOpCode));
1798 break;
1799
1800 case DW_LNS_const_add_pc:
1801 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + 255) / pLnState->Hdr.cMaxOpsPerInstr
1802 * pLnState->Hdr.cbMinInstr;
1803 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + 255) % pLnState->Hdr.cMaxOpsPerInstr;
1804 Log2(("%08x: DW_LNS_const_add_pc\n", offOpCode));
1805 break;
1806
1807 case DW_LNS_fixed_advance_pc:
1808 pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0);
1809 pLnState->Regs.idxOp = 0;
1810 Log2(("%08x: DW_LNS_fixed_advance_pc\n", offOpCode));
1811 break;
1812
1813 case DW_LNS_set_prologue_end:
1814 pLnState->Regs.fPrologueEnd = true;
1815 Log2(("%08x: DW_LNS_set_prologue_end\n", offOpCode));
1816 break;
1817
1818 case DW_LNS_set_epilogue_begin:
1819 pLnState->Regs.fEpilogueBegin = true;
1820 Log2(("%08x: DW_LNS_set_epilogue_begin\n", offOpCode));
1821 break;
1822
1823 case DW_LNS_set_isa:
1824 pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
1825 Log2(("%08x: DW_LNS_set_isa %#x\n", offOpCode, pLnState->Regs.uIsa));
1826 break;
1827
1828 default:
1829 {
1830 unsigned cOpsToSkip = pLnState->Hdr.pacStdOperands[bOpCode - 1];
1831 Log(("rtDwarfLine_RunProgram: Unknown standard opcode %#x, %#x operands, at %08x.\n", bOpCode, cOpsToSkip, offOpCode));
1832 while (cOpsToSkip-- > 0)
1833 rc = rtDwarfCursor_SkipLeb128(pCursor);
1834 break;
1835 }
1836
1837 /*
1838 * Extended opcode.
1839 */
1840 case DW_LNS_extended:
1841 {
1842 /* The instruction has a length prefix. */
1843 uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
1844 if (RT_FAILURE(pCursor->rc))
1845 return pCursor->rc;
1846 if (cbInstr > pCursor->cbUnitLeft)
1847 return VERR_DWARF_BAD_LNE;
1848 uint8_t const * const pbEndOfInstr = rtDwarfCursor_CalcPos(pCursor, cbInstr);
1849
1850 /* Get the opcode and deal with it if we know it. */
1851 bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
1852 switch (bOpCode)
1853 {
1854 case DW_LNE_end_sequence:
1855#if 0 /* No need for this, I think. */
1856 pLnState->Regs.fEndSequence = true;
1857 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
1858#endif
1859 rtDwarfLine_ResetState(pLnState);
1860 Log2(("%08x: DW_LNE_end_sequence\n", offOpCode));
1861 break;
1862
1863 case DW_LNE_set_address:
1864 pLnState->Regs.uAddress = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
1865 pLnState->Regs.idxOp = 0;
1866 Log2(("%08x: DW_LNE_set_address: %#llx\n", offOpCode, pLnState->Regs.uAddress));
1867 break;
1868
1869 case DW_LNE_define_file:
1870 {
1871 const char *pszFilename = rtDwarfCursor_GetSZ(pCursor, NULL);
1872 uint32_t idxInc = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
1873 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
1874 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
1875 Log2(("%08x: DW_LNE_define_file: {%d}/%s\n", offOpCode, idxInc, pszFilename));
1876
1877 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
1878 if (RT_SUCCESS(rc))
1879 rc = rtDwarfLine_DefineFileName(pLnState, pszFilename, idxInc);
1880 }
1881
1882 /*
1883 * Note! Was defined in DWARF 4. But... Watcom used it
1884 * for setting the segment in DWARF 2, creating
1885 * an incompatibility with the newer standard.
1886 */
1887 case DW_LNE_set_descriminator:
1888 if (pLnState->Hdr.uVer != 2)
1889 {
1890 Assert(pLnState->Hdr.uVer >= 4);
1891 pLnState->Regs.uDiscriminator = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
1892 Log2(("%08x: DW_LNE_set_descriminator: %u\n", offOpCode, pLnState->Regs.uDiscriminator));
1893 }
1894 else
1895 {
1896 uint64_t uSeg = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
1897 Log2(("%08x: DW_LNE_set_segment: %ll#x - Watcom Extension\n", offOpCode, uSeg));
1898 /** @todo make use of this? */
1899 }
1900 break;
1901
1902 default:
1903 Log(("rtDwarfLine_RunProgram: Unknown extended opcode %#x, length %#x at %08x\n", bOpCode, cbInstr, offOpCode));
1904 break;
1905 }
1906
1907 /* Advance the cursor to the end of the instruction . */
1908 rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
1909 break;
1910 }
1911 }
1912 }
1913
1914 /*
1915 * Check the status before looping.
1916 */
1917 if (RT_FAILURE(rc))
1918 return rc;
1919 if (RT_FAILURE(pCursor->rc))
1920 return pCursor->rc;
1921 }
1922 return rc;
1923}
1924
1925
1926/**
1927 * Reads the include directories for a line number unit.
1928 *
1929 * @returns IPRT status code
1930 * @param pLnState The line number program state.
1931 * @param pCursor The cursor.
1932 */
1933static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
1934{
1935 int rc = rtDwarfLine_DefineFileName(pLnState, "/<bad-zero-file-name-entry>", 0);
1936 if (RT_FAILURE(rc))
1937 return rc;
1938
1939 for (;;)
1940 {
1941 const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL);
1942 if (!*psz)
1943 break;
1944
1945 uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
1946 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
1947 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
1948
1949 rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc);
1950 if (RT_FAILURE(rc))
1951 return rc;
1952 }
1953 return pCursor->rc;
1954}
1955
1956
1957/**
1958 * Reads the include directories for a line number unit.
1959 *
1960 * @returns IPRT status code
1961 * @param pLnState The line number program state.
1962 * @param pCursor The cursor.
1963 */
1964static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
1965{
1966 const char *psz = ""; /* The zeroth is the unit dir. */
1967 for (;;)
1968 {
1969 if ((pLnState->cIncPaths % 2) == 0)
1970 {
1971 void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2));
1972 if (!pv)
1973 return VERR_NO_MEMORY;
1974 pLnState->papszIncPaths = (const char **)pv;
1975 }
1976 Log((" Path #%02u = '%s'\n", pLnState->cIncPaths, psz));
1977 pLnState->papszIncPaths[pLnState->cIncPaths] = psz;
1978 pLnState->cIncPaths++;
1979
1980 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
1981 if (!*psz)
1982 break;
1983 }
1984
1985 return pCursor->rc;
1986}
1987
1988
1989/**
1990 * Explodes the line number table for a compilation unit.
1991 *
1992 * @returns IPRT status code
1993 * @param pThis The DWARF instance.
1994 * @param pCursor The cursor to read the line number information
1995 * via.
1996 */
1997static int rtDwarfLine_ExplodeUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
1998{
1999 RTDWARFLINESTATE LnState;
2000 RT_ZERO(LnState);
2001 LnState.pDwarfMod = pThis;
2002
2003 /*
2004 * Parse the header.
2005 */
2006 rtDwarfCursor_GetInitalLength(pCursor);
2007 LnState.Hdr.uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
2008 if ( LnState.Hdr.uVer < 2
2009 || LnState.Hdr.uVer > 4)
2010 return rtDwarfCursor_SkipUnit(pCursor);
2011
2012 LnState.Hdr.offFirstOpcode = rtDwarfCursor_GetUOff(pCursor, 0);
2013 uint8_t const * const pbFirstOpcode = rtDwarfCursor_CalcPos(pCursor, LnState.Hdr.offFirstOpcode);
2014
2015 LnState.Hdr.cbMinInstr = rtDwarfCursor_GetUByte(pCursor, 0);
2016 if (LnState.Hdr.uVer >= 4)
2017 LnState.Hdr.cMaxOpsPerInstr = rtDwarfCursor_GetUByte(pCursor, 0);
2018 else
2019 LnState.Hdr.cMaxOpsPerInstr = 1;
2020 LnState.Hdr.u8DefIsStmt = rtDwarfCursor_GetUByte(pCursor, 0);
2021 LnState.Hdr.s8LineBase = rtDwarfCursor_GetSByte(pCursor, 0);
2022 LnState.Hdr.u8LineRange = rtDwarfCursor_GetUByte(pCursor, 0);
2023 LnState.Hdr.u8OpcodeBase = rtDwarfCursor_GetUByte(pCursor, 0);
2024
2025 if ( !LnState.Hdr.u8OpcodeBase
2026 || !LnState.Hdr.cMaxOpsPerInstr
2027 || !LnState.Hdr.u8LineRange
2028 || LnState.Hdr.u8DefIsStmt > 1)
2029 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
2030 Log2(("DWARF Line number header:\n"
2031 " uVer %d\n"
2032 " offFirstOpcode %#llx\n"
2033 " cbMinInstr %u\n"
2034 " cMaxOpsPerInstr %u\n"
2035 " u8DefIsStmt %u\n"
2036 " s8LineBase %d\n"
2037 " u8LineRange %u\n"
2038 " u8OpcodeBase %u\n",
2039 LnState.Hdr.uVer, LnState.Hdr.offFirstOpcode, LnState.Hdr.cbMinInstr, LnState.Hdr.cMaxOpsPerInstr,
2040 LnState.Hdr.u8DefIsStmt, LnState.Hdr.s8LineBase, LnState.Hdr.u8LineRange, LnState.Hdr.u8OpcodeBase));
2041
2042 LnState.Hdr.pacStdOperands = pCursor->pb;
2043 for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.Hdr.u8OpcodeBase; iStdOpcode++)
2044 rtDwarfCursor_GetUByte(pCursor, 0);
2045
2046 int rc = pCursor->rc;
2047 if (RT_SUCCESS(rc))
2048 rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor);
2049 if (RT_SUCCESS(rc))
2050 rc = rtDwarfLine_ReadFileNames(&LnState, pCursor);
2051
2052 /*
2053 * Run the program....
2054 */
2055 if (RT_SUCCESS(rc))
2056 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbFirstOpcode);
2057 if (RT_SUCCESS(rc))
2058 rc = rtDwarfLine_RunProgram(&LnState, pCursor);
2059
2060 /*
2061 * Clean up.
2062 */
2063 size_t i = LnState.cFileNames;
2064 while (i-- > 0)
2065 RTStrFree(LnState.papszFileNames[i]);
2066 RTMemFree(LnState.papszFileNames);
2067 RTMemFree(LnState.papszIncPaths);
2068
2069 Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc));
2070 return rc;
2071}
2072
2073
2074/**
2075 * Explodes the line number table.
2076 *
2077 * The line numbers are insered into the debug info container.
2078 *
2079 * @returns IPRT status code
2080 * @param pThis The DWARF instance.
2081 */
2082static int rtDwarfLine_ExplodeAll(PRTDBGMODDWARF pThis)
2083{
2084 if (!pThis->aSections[krtDbgModDwarfSect_line].fPresent)
2085 return VINF_SUCCESS;
2086
2087 RTDWARFCURSOR Cursor;
2088 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line);
2089 if (RT_FAILURE(rc))
2090 return rc;
2091
2092 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
2093 && RT_SUCCESS(rc))
2094 rc = rtDwarfLine_ExplodeUnit(pThis, &Cursor);
2095
2096 return rtDwarfCursor_Delete(&Cursor, rc);
2097}
2098
2099
2100/*
2101 *
2102 * DWARF Abbreviations.
2103 * DWARF Abbreviations.
2104 * DWARF Abbreviations.
2105 *
2106 */
2107
2108/**
2109 * Deals with a cache miss in rtDwarfAbbrev_Lookup.
2110 *
2111 * @returns Pointer to abbreviation cache entry (read only). May be rendered
2112 * invalid by subsequent calls to this function.
2113 * @param pThis The DWARF instance.
2114 * @param uCode The abbreviation code to lookup.
2115 */
2116static PCRTDWARFABBREV rtDwarfAbbrev_LookupMiss(PRTDBGMODDWARF pThis, uint32_t uCode)
2117{
2118 /*
2119 * There is no entry with code zero.
2120 */
2121 if (!uCode)
2122 return NULL;
2123
2124 /*
2125 * Resize the cache array if the code is considered cachable.
2126 */
2127 bool fFillCache = true;
2128 if (pThis->cCachedAbbrevsAlloced < uCode)
2129 {
2130 if (uCode > _64K)
2131 fFillCache = false;
2132 else
2133 {
2134 uint32_t cNew = RT_ALIGN(uCode, 64);
2135 void *pv = RTMemRealloc(pThis->paCachedAbbrevs, sizeof(pThis->paCachedAbbrevs[0]) * cNew);
2136 if (!pv)
2137 fFillCache = false;
2138 else
2139 {
2140 pThis->cCachedAbbrevsAlloced = cNew;
2141 pThis->paCachedAbbrevs = (PRTDWARFABBREV)pv;
2142 }
2143 }
2144 }
2145
2146 /*
2147 * Walk the abbreviations till we find the desired code.
2148 */
2149 RTDWARFCURSOR Cursor;
2150 int rc = rtDwarfCursor_InitWithOffset(&Cursor, pThis, krtDbgModDwarfSect_abbrev, pThis->offCachedAbbrev);
2151 if (RT_FAILURE(rc))
2152 return NULL;
2153
2154 PRTDWARFABBREV pRet = NULL;
2155 if (fFillCache)
2156 {
2157 /*
2158 * Search for the entry and fill the cache while doing so.
2159 */
2160 for (;;)
2161 {
2162 /* Read the 'header'. */
2163 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2164 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2165 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
2166 if (RT_FAILURE(Cursor.rc))
2167 break;
2168 if ( uCurTag > 0xffff
2169 || uChildren > 1)
2170 {
2171 Cursor.rc = VERR_DWARF_BAD_ABBREV;
2172 break;
2173 }
2174
2175 /* Cache it? */
2176 if (uCurCode <= pThis->cCachedAbbrevsAlloced)
2177 {
2178 PRTDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
2179 while (pThis->cCachedAbbrevs < uCurCode)
2180 {
2181 pThis->paCachedAbbrevs[pThis->cCachedAbbrevs].fFilled = false;
2182 pThis->cCachedAbbrevs++;
2183 }
2184
2185 pEntry->fFilled = true;
2186 pEntry->fChildren = RT_BOOL(uChildren);
2187 pEntry->uTag = uCurTag;
2188 pEntry->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
2189
2190 if (uCurCode == uCode)
2191 {
2192 pRet = pEntry;
2193 if (uCurCode == pThis->cCachedAbbrevsAlloced)
2194 break;
2195 }
2196 }
2197
2198 /* Skip the specification. */
2199 uint32_t uAttr, uForm;
2200 do
2201 {
2202 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2203 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2204 } while (uAttr != 0);
2205 if (RT_FAILURE(Cursor.rc))
2206 break;
2207
2208 /* Done? (Maximize cache filling.) */
2209 if ( pRet != NULL
2210 && uCurCode >= pThis->cCachedAbbrevsAlloced)
2211 break;
2212 }
2213 }
2214 else
2215 {
2216 /*
2217 * Search for the entry with the desired code, no cache filling.
2218 */
2219 for (;;)
2220 {
2221 /* Read the 'header'. */
2222 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2223 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2224 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
2225 if (RT_FAILURE(Cursor.rc))
2226 break;
2227 if ( uCurTag > 0xffff
2228 || uChildren > 1)
2229 {
2230 Cursor.rc = VERR_DWARF_BAD_ABBREV;
2231 break;
2232 }
2233
2234 /* Do we have a match? */
2235 if (uCurCode == uCode)
2236 {
2237 pRet = &pThis->LookupAbbrev;
2238 pRet->fFilled = true;
2239 pRet->fChildren = RT_BOOL(uChildren);
2240 pRet->uTag = uCurTag;
2241 pRet->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
2242 break;
2243 }
2244
2245 /* Skip the specification. */
2246 uint32_t uAttr, uForm;
2247 do
2248 {
2249 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2250 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2251 } while (uAttr != 0);
2252 if (RT_FAILURE(Cursor.rc))
2253 break;
2254 }
2255 }
2256
2257 rtDwarfCursor_Delete(&Cursor, VINF_SUCCESS);
2258 return pRet;
2259}
2260
2261
2262/**
2263 * Looks up an abbreviation.
2264 *
2265 * @returns Pointer to abbreviation cache entry (read only). May be rendered
2266 * invalid by subsequent calls to this function.
2267 * @param pThis The DWARF instance.
2268 * @param uCode The abbreviation code to lookup.
2269 */
2270static PCRTDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
2271{
2272 if ( uCode - 1 >= pThis->cCachedAbbrevs
2273 || !pThis->paCachedAbbrevs[uCode - 1].fFilled)
2274 return rtDwarfAbbrev_LookupMiss(pThis, uCode);
2275 return &pThis->paCachedAbbrevs[uCode - 1];
2276}
2277
2278
2279/**
2280 * Sets the abbreviation offset of the current unit.
2281 *
2282 * This will flush the cached abbreviation entries if the offset differs from
2283 * the previous unit.
2284 *
2285 * @param pThis The DWARF instance.
2286 * @param offAbbrev The offset into the abbreviation section.
2287 */
2288static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
2289{
2290 if (pThis->offCachedAbbrev != offAbbrev)
2291 {
2292 pThis->offCachedAbbrev = offAbbrev;
2293 pThis->cCachedAbbrevs = 0;
2294 }
2295}
2296
2297
2298
2299/*
2300 *
2301 * DIE Attribute Parsers.
2302 * DIE Attribute Parsers.
2303 * DIE Attribute Parsers.
2304 *
2305 */
2306
2307/**
2308 * Gets the compilation unit a DIE belongs to.
2309 *
2310 * @returns The compilation unit DIE.
2311 * @param pDie Some DIE in the unit.
2312 */
2313static PRTDWARFDIECOMPILEUNIT rtDwarfDie_GetCompileUnit(PRTDWARFDIE pDie)
2314{
2315 while (pDie->pParent)
2316 pDie = pDie->pParent;
2317 AssertReturn( pDie->uTag == DW_TAG_compile_unit
2318 || pDie->uTag == DW_TAG_partial_unit,
2319 NULL);
2320 return (PRTDWARFDIECOMPILEUNIT)pDie;
2321}
2322
2323
2324/**
2325 * Resolves a string section (debug_str) reference.
2326 *
2327 * @returns Pointer to the string (inside the string section).
2328 * @param pThis The DWARF instance.
2329 * @param pCursor The cursor.
2330 * @param pszErrValue What to return on failure (@a
2331 * pCursor->rc is set).
2332 */
2333static const char *rtDwarfDecode_GetStrp(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, const char *pszErrValue)
2334{
2335 uint64_t offDebugStr = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
2336 if (RT_FAILURE(pCursor->rc))
2337 return pszErrValue;
2338
2339 if (offDebugStr >= pThis->aSections[krtDbgModDwarfSect_str].cb)
2340 {
2341 /* Ugly: Exploit the cursor status field for reporting errors. */
2342 pCursor->rc = VERR_DWARF_BAD_INFO;
2343 return pszErrValue;
2344 }
2345
2346 if (!pThis->aSections[krtDbgModDwarfSect_str].pv)
2347 {
2348 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_str);
2349 if (RT_FAILURE(rc))
2350 {
2351 /* Ugly: Exploit the cursor status field for reporting errors. */
2352 pCursor->rc = rc;
2353 return pszErrValue;
2354 }
2355 }
2356
2357 return (const char *)pThis->aSections[krtDbgModDwarfSect_str].pv + (size_t)offDebugStr;
2358}
2359
2360
2361/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2362static DECLCALLBACK(int) rtDwarfDecode_Bool(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2363 uint32_t uForm, PRTDWARFCURSOR pCursor)
2364{
2365 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(bool), VERR_INTERNAL_ERROR_3);
2366
2367 bool *pfMember = (bool *)pbMember;
2368 switch (uForm)
2369 {
2370 case DW_FORM_flag:
2371 {
2372 uint8_t b = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
2373 if (b > 1)
2374 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pCursor->rc = VERR_DWARF_BAD_INFO;
2375 *pfMember = RT_BOOL(b);
2376 break;
2377 }
2378
2379 case DW_FORM_flag_present:
2380 *pfMember = true;
2381 break;
2382
2383 default:
2384 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2385 }
2386
2387 return VINF_SUCCESS;
2388}
2389
2390
2391/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2392static DECLCALLBACK(int) rtDwarfDecode_LowHighPc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2393 uint32_t uForm, PRTDWARFCURSOR pCursor)
2394{
2395 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
2396 AssertReturn(pDesc->uAttr == DW_AT_low_pc || pDesc->uAttr == DW_AT_high_pc, VERR_INTERNAL_ERROR_3);
2397
2398 uint64_t uAddr;
2399 switch (uForm)
2400 {
2401 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
2402 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
2403 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
2404 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
2405 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
2406 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
2407 default:
2408 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2409 }
2410 if (RT_FAILURE(pCursor->rc))
2411 return pCursor->rc;
2412
2413 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
2414 if (pDesc->uAttr == DW_AT_low_pc)
2415 {
2416 pRange->uLowAddress = uAddr;
2417 pRange->fHaveLowAddress = true;
2418 }
2419 else
2420 {
2421 pRange->uHighAddress = uAddr;
2422 pRange->fHaveHighAddress = true;
2423 }
2424
2425 return VINF_SUCCESS;
2426}
2427
2428
2429/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2430static DECLCALLBACK(int) rtDwarfDecode_Ranges(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2431 uint32_t uForm, PRTDWARFCURSOR pCursor)
2432{
2433 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
2434 AssertReturn(pDesc->uAttr == DW_AT_low_pc || pDesc->uAttr == DW_AT_high_pc, VERR_INTERNAL_ERROR_3);
2435
2436 /* Decode it. */
2437 uint64_t off;
2438 switch (uForm)
2439 {
2440 case DW_FORM_addr: off = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
2441 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
2442 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
2443 default:
2444 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2445 }
2446 if (RT_FAILURE(pCursor->rc))
2447 return pCursor->rc;
2448
2449 /* Validate the offset and load the ranges. */
2450 PRTDBGMODDWARF pThis = pCursor->pDwarfMod;
2451 if (off >= pThis->aSections[krtDbgModDwarfSect_ranges].cb)
2452 return pCursor->rc = VERR_DWARF_BAD_POS;
2453
2454 if (!pThis->aSections[krtDbgModDwarfSect_ranges].pv)
2455 {
2456 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_ranges);
2457 if (RT_FAILURE(rc))
2458 return pCursor->rc = rc;
2459 }
2460
2461 /* Store the result. */
2462 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
2463 pRange->pbRanges = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_ranges].pv + (size_t)off;
2464 pRange->fHaveRanges = true;
2465
2466 return VINF_SUCCESS;
2467}
2468
2469
2470/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2471static DECLCALLBACK(int) rtDwarfDecode_Reference(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2472 uint32_t uForm, PRTDWARFCURSOR pCursor)
2473{
2474 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
2475
2476 /* Decode it. */
2477 uint64_t off;
2478 krtDwarfRef enmWrt = krtDwarfRef_InfoSection;
2479 switch (uForm)
2480 {
2481 case DW_FORM_ref1: off = rtDwarfCursor_GetU8(pCursor, 0); break;
2482 case DW_FORM_ref2: off = rtDwarfCursor_GetU16(pCursor, 0); break;
2483 case DW_FORM_ref4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
2484 case DW_FORM_ref8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
2485 case DW_FORM_ref_udata: off = rtDwarfCursor_GetULeb128(pCursor, 0); break;
2486
2487 case DW_FORM_ref_addr:
2488 enmWrt = krtDwarfRef_InfoSection;
2489 off = rtDwarfCursor_GetUOff(pCursor, 0);
2490 break;
2491
2492 case DW_FORM_ref_sig8:
2493 enmWrt = krtDwarfRef_TypeId64;
2494 off = rtDwarfCursor_GetU64(pCursor, 0);
2495 break;
2496
2497 default:
2498 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2499 }
2500 if (RT_FAILURE(pCursor->rc))
2501 return pCursor->rc;
2502
2503 /* Validate the offset and convert to debug_info relative offsets. */
2504 if (enmWrt == krtDwarfRef_InfoSection)
2505 {
2506 if (off >= pCursor->pDwarfMod->aSections[krtDbgModDwarfSect_info].cb)
2507 return pCursor->rc = VERR_DWARF_BAD_POS;
2508 }
2509 else if (enmWrt == krtDwarfRef_SameUnit)
2510 {
2511 PRTDWARFDIECOMPILEUNIT pUnit = rtDwarfDie_GetCompileUnit(pDie);
2512 if (off >= pUnit->cbUnit)
2513 return pCursor->rc = VERR_DWARF_BAD_POS;
2514 off += pUnit->offUnit;
2515 enmWrt = krtDwarfRef_InfoSection;
2516 }
2517 /* else: not bother verifying/resolving the indirect type reference yet. */
2518
2519 /* Store it */
2520 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
2521 pRef->enmWrt = enmWrt;
2522 pRef->off = off;
2523
2524 return VINF_SUCCESS;
2525}
2526
2527
2528/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2529static DECLCALLBACK(int) rtDwarfDecode_SectOff(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2530 uint32_t uForm, PRTDWARFCURSOR pCursor)
2531{
2532 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
2533
2534 uint64_t off;
2535 switch (uForm)
2536 {
2537 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
2538 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
2539 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
2540 default:
2541 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2542 }
2543 if (RT_FAILURE(pCursor->rc))
2544 return pCursor->rc;
2545
2546 krtDbgModDwarfSect enmSect;
2547 krtDwarfRef enmWrt;
2548 switch (pDesc->uAttr)
2549 {
2550 case DW_AT_stmt_list: enmSect = krtDbgModDwarfSect_line; enmWrt = krtDwarfRef_LineSection; break;
2551 case DW_AT_macro_info: enmSect = krtDbgModDwarfSect_loc; enmWrt = krtDwarfRef_LocSection; break;
2552 case DW_AT_ranges: enmSect = krtDbgModDwarfSect_ranges; enmWrt = krtDwarfRef_RangesSection; break;
2553 default: AssertMsgFailedReturn(("%u\n", pDesc->uAttr), VERR_INTERNAL_ERROR_4);
2554 }
2555 if (off > pCursor->pDwarfMod->aSections[enmSect].cb)
2556 return pCursor->rc = VERR_DWARF_BAD_POS;
2557
2558 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
2559 pRef->enmWrt = enmWrt;
2560 pRef->off = off;
2561
2562 return VINF_SUCCESS;
2563}
2564
2565
2566/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2567static DECLCALLBACK(int) rtDwarfDecode_String(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2568 uint32_t uForm, PRTDWARFCURSOR pCursor)
2569{
2570 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(const char *), VERR_INTERNAL_ERROR_3);
2571
2572 switch (uForm)
2573 {
2574 case DW_FORM_string:
2575 *(const char **)pbMember = rtDwarfCursor_GetSZ(pCursor, NULL);
2576 break;
2577
2578 case DW_FORM_strp:
2579 *(const char **)pbMember = rtDwarfDecode_GetStrp(pCursor->pDwarfMod, pCursor, NULL);
2580 break;
2581
2582 default:
2583 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2584 }
2585
2586 return pCursor->rc;
2587}
2588
2589
2590/** @callback_method_impl{FNRTDWARFATTRDECODER} */
2591static DECLCALLBACK(int) rtDwarfDecode_UnsignedInt(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
2592 uint32_t uForm, PRTDWARFCURSOR pCursor)
2593{
2594 uint64_t u64Val;
2595 switch (uForm)
2596 {
2597 case DW_FORM_udata: u64Val = rtDwarfCursor_GetULeb128(pCursor, 0); break;
2598 case DW_FORM_data1: u64Val = rtDwarfCursor_GetU8(pCursor, 0); break;
2599 case DW_FORM_data2: u64Val = rtDwarfCursor_GetU16(pCursor, 0); break;
2600 case DW_FORM_data4: u64Val = rtDwarfCursor_GetU32(pCursor, 0); break;
2601 case DW_FORM_data8: u64Val = rtDwarfCursor_GetU64(pCursor, 0); break;
2602 default:
2603 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
2604 }
2605 if (RT_FAILURE(pCursor->rc))
2606 return pCursor->rc;
2607
2608 switch (ATTR_GET_SIZE(pDesc))
2609 {
2610 case 1:
2611 *pbMember = (uint8_t)u64Val;
2612 if (*pbMember != u64Val)
2613 return VERR_OUT_OF_RANGE;
2614 break;
2615
2616 case 2:
2617 *(uint16_t *)pbMember = (uint16_t)u64Val;
2618 if (*(uint16_t *)pbMember != u64Val)
2619 return VERR_OUT_OF_RANGE;
2620 break;
2621
2622 case 4:
2623 *(uint32_t *)pbMember = (uint32_t)u64Val;
2624 if (*(uint32_t *)pbMember != u64Val)
2625 return VERR_OUT_OF_RANGE;
2626 break;
2627
2628 case 8:
2629 *(uint64_t *)pbMember = (uint64_t)u64Val;
2630 if (*(uint64_t *)pbMember != u64Val)
2631 return VERR_OUT_OF_RANGE;
2632 break;
2633
2634 default:
2635 AssertMsgFailedReturn(("%#x\n", ATTR_GET_SIZE(pDesc)), VERR_INTERNAL_ERROR_2);
2636 }
2637 return VINF_SUCCESS;
2638}
2639
2640
2641
2642/*
2643 *
2644 * DWARF debug_info parser
2645 * DWARF debug_info parser
2646 * DWARF debug_info parser
2647 *
2648 */
2649
2650
2651
2652static const char *rtDwarfForm_GetString(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, uint16_t uForm, const char *pszErrValue)
2653{
2654 switch (uForm)
2655 {
2656 case DW_FORM_string:
2657 return rtDwarfCursor_GetSZ(pCursor, pszErrValue);
2658
2659 case DW_FORM_strp:
2660 return rtDwarfDecode_GetStrp(pThis, pCursor, pszErrValue);
2661
2662 default:
2663 pCursor->rc = VERR_DWARF_UNEXPECTED_FORM;
2664 return pszErrValue;
2665 }
2666}
2667
2668
2669/**
2670 * Creates a new internal DIE structure and links it up.
2671 *
2672 * @returns Pointer to the new DIE structure.
2673 * @param pThis The DWARF instance.
2674 * @param cbUnit The size required for this unit.
2675 * @param pAbbrev The abbreviation cache entry.
2676 * @param pParent The parent DIE (NULL if unit).
2677 */
2678static PRTDWARFDIE rtDwarfInfo_NewDie(PRTDBGMODDWARF pThis, size_t cbUnit, PCRTDWARFABBREV pAbbrev, PRTDWARFDIE pParent)
2679{
2680 Assert(cbUnit >= sizeof(RTDWARFDIE));
2681 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemAllocZ(cbUnit);
2682 if (pDie)
2683 {
2684 pDie->uTag = pAbbrev->uTag;
2685 pDie->offSpec = pAbbrev->offSpec;
2686 pDie->pParent = pParent;
2687 if (pParent)
2688 RTListAppend(&pParent->ChildList, &pDie->SiblingNode);
2689 else
2690 RTListInit(&pDie->SiblingNode);
2691 RTListInit(&pDie->ChildList);
2692 }
2693 return pDie;
2694}
2695
2696
2697/**
2698 * Skips a form.
2699 * @returns IPRT status code
2700 * @param pCursor The cursor.
2701 * @param uForm The form to skip.
2702 */
2703static int rtDwarfInfo_SkipForm(PRTDWARFCURSOR pCursor, uint32_t uForm)
2704{
2705 switch (uForm)
2706 {
2707 case DW_FORM_addr:
2708 return rtDwarfCursor_SkipBytes(pCursor, pCursor->cbNativeAddr);
2709
2710 case DW_FORM_block:
2711 case DW_FORM_exprloc:
2712 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetULeb128(pCursor, 0));
2713
2714 case DW_FORM_block1:
2715 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU8(pCursor, 0));
2716
2717 case DW_FORM_block2:
2718 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU16(pCursor, 0));
2719
2720 case DW_FORM_block4:
2721 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU32(pCursor, 0));
2722
2723 case DW_FORM_data1:
2724 case DW_FORM_ref1:
2725 case DW_FORM_flag:
2726 return rtDwarfCursor_SkipBytes(pCursor, 1);
2727
2728 case DW_FORM_data2:
2729 case DW_FORM_ref2:
2730 return rtDwarfCursor_SkipBytes(pCursor, 2);
2731
2732 case DW_FORM_data4:
2733 case DW_FORM_ref4:
2734 return rtDwarfCursor_SkipBytes(pCursor, 4);
2735
2736 case DW_FORM_data8:
2737 case DW_FORM_ref8:
2738 case DW_FORM_ref_sig8:
2739 return rtDwarfCursor_SkipBytes(pCursor, 8);
2740
2741 case DW_FORM_udata:
2742 case DW_FORM_sdata:
2743 case DW_FORM_ref_udata:
2744 return rtDwarfCursor_SkipLeb128(pCursor);
2745
2746 case DW_FORM_string:
2747 rtDwarfCursor_GetSZ(pCursor, NULL);
2748 return pCursor->rc;
2749
2750 case DW_FORM_indirect:
2751 return rtDwarfInfo_SkipForm(pCursor, rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX));
2752
2753 case DW_FORM_strp:
2754 case DW_FORM_ref_addr:
2755 case DW_FORM_sec_offset:
2756 return rtDwarfCursor_SkipBytes(pCursor, pCursor->f64bitDwarf ? 8 : 4);
2757
2758 case DW_FORM_flag_present:
2759 return pCursor->rc; /* no data */
2760
2761 default:
2762 return VERR_DWARF_UNKNOWN_FORM;
2763 }
2764}
2765
2766
2767
2768/**
2769 * Skips a DIE.
2770 *
2771 * @returns IPRT status code.
2772 * @param pCursor The cursor.
2773 * @param pAbbrevCursor The abbreviation cursor.
2774 */
2775static int rtDwarfInfo_SkipDie(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pAbbrevCursor)
2776{
2777 for (;;)
2778 {
2779 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2780 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2781 if (uAttr == 0 && uForm == 0)
2782 break;
2783
2784 int rc = rtDwarfInfo_SkipForm(pCursor, uForm);
2785 if (RT_FAILURE(rc))
2786 return rc;
2787 }
2788 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pAbbrevCursor->rc;
2789}
2790
2791
2792#if 0
2793/**
2794 * Parse a DIE.
2795 *
2796 * @returns IPRT status code.
2797 * @param pThis The DWARF instance.
2798 * @param pCursor The debug_info cursor.
2799 * @param pAbbrev The abbreviation entry.
2800 * @param pAbbrevCursor The abbreviation cursor.
2801 * @param pStack The DIE stack.
2802 */
2803static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor,
2804 PCRTDWARFABBREV pAbbrev, PRTDWARFCURSOR pAbbrevCursor,
2805 PRTDWARFDIESTACK pStack)
2806{
2807 /*
2808 * Pick out DIEs which tag we find interesting.
2809 */
2810 switch (pAbbrev->uTag)
2811 {
2812 case DW_TAG_compile_unit:
2813 case DW_TAG_partial_unit:
2814 Log((" - DW_TAG_%s_unit:\n", pAbbrev->uTag == DW_TAG_compile_unit ? "compile" : "partial"));
2815 for (;;)
2816 {
2817 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2818 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2819 switch (uAttr)
2820 {
2821 case 0:
2822 return VINF_SUCCESS;
2823
2824 case DW_AT_name:
2825 {
2826 const char *pszName = rtDwarfForm_GetString(pThis, pCursor, uForm, "<error>");
2827 rtDwarfDieStack_SetName(pStack, pszName);
2828 Log4(("%*s - name=%s\n", pStack->cOnStack*2, "", pszName));
2829 break;
2830 }
2831
2832 case DW_AT_stmt_list:
2833 /** @todo */
2834 default:
2835 Log4(("%*s - attr=%#x form=%#x\n", pStack->cOnStack*2, "", uAttr, uForm));
2836 rtDwarfInfo_SkipForm(pCursor, uForm);
2837 }
2838 if (RT_FAILURE(pCursor->rc))
2839 return pCursor->rc;
2840 }
2841 break; /* not reached. */
2842
2843 case DW_TAG_subprogram:
2844 Log((" - DW_TAG_subprogram:\n"));
2845 for (;;)
2846 {
2847 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2848 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
2849 switch (uAttr)
2850 {
2851 case 0:
2852 return VINF_SUCCESS;
2853
2854 case DW_AT_name:
2855 {
2856 const char *pszName = rtDwarfForm_GetString(pThis, pCursor, uForm, "<error>");
2857 rtDwarfDieStack_SetName(pStack, pszName);
2858 Log4(("%*s - name=%s\n", pStack->cOnStack*2, "", pszName));
2859 break;
2860 }
2861
2862 default:
2863 Log4(("%*s - attr=%#x form=%#x\n", pStack->cOnStack*2, "", uAttr, uForm));
2864 rtDwarfInfo_SkipForm(pCursor, uForm);
2865 }
2866 if (RT_FAILURE(pCursor->rc))
2867 return pCursor->rc;
2868 }
2869 break; /* not reached. */
2870
2871 }
2872
2873 return rtDwarfInfo_SkipDie(pCursor, pAbbrevCursor);
2874}
2875#endif
2876
2877
2878
2879static int rtDwarfInfo_LoadUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
2880{
2881 Log(("rtDwarfInfo_LoadUnit: %#x\n", rtDwarfCursor_CalcSectOffsetU32(pCursor)));
2882
2883 /*
2884 * Read the compilation unit header.
2885 */
2886 uint64_t offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
2887 uint64_t cbUnit = rtDwarfCursor_GetInitalLength(pCursor);
2888 cbUnit += rtDwarfCursor_CalcSectOffsetU32(pCursor) - offUnit;
2889 uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
2890 if ( uVer < 2
2891 || uVer > 4)
2892 return rtDwarfCursor_SkipUnit(pCursor);
2893 uint64_t const offAbbrev = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
2894 uint8_t const cbNativeAddr = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
2895 if (RT_FAILURE(pCursor->rc))
2896 return pCursor->rc;
2897 Log((" uVer=%d offAbbrev=%#llx cbNativeAddr=%d\n", uVer, offAbbrev, cbNativeAddr));
2898
2899 /*
2900 * Set up the abbreviation cache and store the native address size in the cursor.
2901 */
2902 if (offAbbrev > UINT32_MAX)
2903 return VERR_DWARF_BAD_INFO;
2904 rtDwarfAbbrev_SetUnitOffset(pThis, offAbbrev);
2905 pCursor->cbNativeAddr = cbNativeAddr;
2906
2907 /*
2908 * The first DIE is a compile or partial unit, parse it here.
2909 */
2910 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
2911 if (!uAbbrCode)
2912 return VERR_DWARF_BAD_INFO;
2913 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
2914 if (!pAbbrev)
2915 return VERR_DWARF_ABBREV_NOT_FOUND;
2916 if ( pAbbrev->uTag != DW_TAG_compile_unit
2917 && pAbbrev->uTag != DW_TAG_partial_unit)
2918 {
2919 Log(("Unexpected compile/partial unit tag %#x\n", pAbbrev->uTag));
2920 return VERR_DWARF_BAD_INFO;
2921 }
2922
2923 PRTDWARFDIECOMPILEUNIT pUnit = (PRTDWARFDIECOMPILEUNIT)rtDwarfInfo_NewDie(pThis, sizeof(*pUnit), pAbbrev, NULL /*pParent*/);
2924 if (!pUnit)
2925 return VERR_NO_MEMORY;
2926 pUnit->offUnit = offUnit;
2927 pUnit->cbUnit = cbUnit;
2928 pUnit->offAbbrev = offAbbrev;
2929 pUnit->cbNativeAddr = cbNativeAddr;
2930 pUnit->uDwarfVer = uVer;
2931 RTListAppend(&pThis->CompileUnitList, &pUnit->Core.SiblingNode);
2932
2933 /** @todo Parse the DIE data using the descriptor. */
2934 RTDWARFCURSOR AbbrevCursor;
2935 int rc = rtDwarfCursor_InitWithOffset(&AbbrevCursor, pThis, krtDbgModDwarfSect_abbrev, pAbbrev->offSpec);
2936#if 0
2937 if (RT_SUCCESS(rc))
2938 {
2939 rc = rtDwarfInfo_ParseDie(pThis, pCursor, pAbbrev, &AbbrevCursor, &Stack);
2940 rc = rtDwarfCursor_Delete(&AbbrevCursor, rc);
2941 }
2942 if (RT_FAILURE(rc))
2943 break;
2944
2945 /*
2946 * Parse DIEs.
2947 */
2948 int rc = VINF_SUCCESS;
2949 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
2950 {
2951 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
2952 if (!uAbbrCode)
2953 {
2954 /* End of siblings, pop the stack. */
2955 rc = rtDwarfDieStack_Pop(&Stack);
2956 if (RT_FAILURE(rc))
2957 break;
2958 }
2959 else
2960 {
2961 /*
2962 * Look up the abbreviation.
2963 */
2964 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
2965 if (!pAbbrev)
2966 {
2967 rc = VERR_DWARF_ABBREV_NOT_FOUND;
2968 break;
2969 }
2970 Log4((" %*stag=%#x%s\n", Stack.cOnStack * 2, "", pAbbrev->uTag, pAbbrev->fChildren ? " has children" : ""));
2971
2972 /*
2973 * If this DIE has children, push it onto the stack.
2974 */
2975 if (pAbbrev->fChildren)
2976 {
2977 rc = rtDwarfDieStack_Push(&Stack, uAbbrCode, pAbbrev->uTag, rtDwarfCursor_CalcSectOffsetU32(pCursor));
2978 if (RT_FAILURE(rc))
2979 break;
2980 }
2981
2982 /*
2983 * Parse it.
2984 */
2985 RTDWARFCURSOR AbbrevCursor;
2986 rc = rtDwarfCursor_InitWithOffset(&AbbrevCursor, pThis, krtDbgModDwarfSect_abbrev, pAbbrev->offSpec);
2987 if (RT_SUCCESS(rc))
2988 {
2989 rc = rtDwarfInfo_ParseDie(pThis, pCursor, pAbbrev, &AbbrevCursor, &Stack);
2990 rc = rtDwarfCursor_Delete(&AbbrevCursor, rc);
2991 }
2992 if (RT_FAILURE(rc))
2993 break;
2994 }
2995 }
2996
2997 rtDwarfDieStack_Delete(&Stack);
2998#endif
2999 return RT_SUCCESS(rc) ? pCursor->rc : rc;
3000}
3001
3002
3003/**
3004 * Extracts the symbols.
3005 *
3006 * The symbols are insered into the debug info container.
3007 *
3008 * @returns IPRT status code
3009 * @param pThis The DWARF instance.
3010 */
3011static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis)
3012{
3013 RTDWARFCURSOR Cursor;
3014 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
3015 if (RT_FAILURE(rc))
3016 return rc;
3017
3018 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
3019 && RT_SUCCESS(rc))
3020 rc = rtDwarfInfo_LoadUnit(pThis, &Cursor);
3021
3022 return rtDwarfCursor_Delete(&Cursor, rc);
3023}
3024
3025
3026
3027
3028/*
3029 *
3030 * DWARF Debug module implementation.
3031 * DWARF Debug module implementation.
3032 * DWARF Debug module implementation.
3033 *
3034 */
3035
3036
3037/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
3038static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
3039 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
3040{
3041 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3042 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
3043}
3044
3045
3046/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
3047static DECLCALLBACK(int) rtDbgModDwarf_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
3048{
3049 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3050 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
3051}
3052
3053
3054/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
3055static DECLCALLBACK(uint32_t) rtDbgModDwarf_LineCount(PRTDBGMODINT pMod)
3056{
3057 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3058 return RTDbgModLineCount(pThis->hCnt);
3059}
3060
3061
3062/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
3063static DECLCALLBACK(int) rtDbgModDwarf_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
3064 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
3065{
3066 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3067 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
3068}
3069
3070
3071/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
3072static DECLCALLBACK(int) rtDbgModDwarf_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
3073 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
3074{
3075 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3076 return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, poffDisp, pSymInfo);
3077}
3078
3079
3080/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
3081static DECLCALLBACK(int) rtDbgModDwarf_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
3082 PRTDBGSYMBOL pSymInfo)
3083{
3084 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3085 Assert(!pszSymbol[cchSymbol]);
3086 return RTDbgModSymbolByName(pThis->hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
3087}
3088
3089
3090/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
3091static DECLCALLBACK(int) rtDbgModDwarf_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
3092{
3093 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3094 return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
3095}
3096
3097
3098/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
3099static DECLCALLBACK(uint32_t) rtDbgModDwarf_SymbolCount(PRTDBGMODINT pMod)
3100{
3101 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3102 return RTDbgModSymbolCount(pThis->hCnt);
3103}
3104
3105
3106/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
3107static DECLCALLBACK(int) rtDbgModDwarf_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
3108 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
3109 uint32_t *piOrdinal)
3110{
3111 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3112 return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
3113}
3114
3115
3116/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
3117static DECLCALLBACK(int) rtDbgModDwarf_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
3118{
3119 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3120 return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
3121}
3122
3123
3124/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
3125static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_SegmentCount(PRTDBGMODINT pMod)
3126{
3127 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3128 return RTDbgModSegmentCount(pThis->hCnt);
3129}
3130
3131
3132/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
3133static DECLCALLBACK(int) rtDbgModDwarf_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
3134 uint32_t fFlags, PRTDBGSEGIDX piSeg)
3135{
3136 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3137 return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
3138}
3139
3140
3141/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
3142static DECLCALLBACK(RTUINTPTR) rtDbgModDwarf_ImageSize(PRTDBGMODINT pMod)
3143{
3144 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3145 RTUINTPTR cb1 = RTDbgModImageSize(pThis->hCnt);
3146 RTUINTPTR cb2 = pMod->pImgVt->pfnImageSize(pMod);
3147 return RT_MAX(cb1, cb2);
3148}
3149
3150
3151/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
3152static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
3153{
3154 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3155 return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
3156}
3157
3158
3159/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
3160static DECLCALLBACK(int) rtDbgModDwarf_Close(PRTDBGMODINT pMod)
3161{
3162 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
3163
3164 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
3165 if (pThis->aSections[iSect].pv)
3166 pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[iSect].cb, &pThis->aSections[iSect].pv);
3167
3168 RTDbgModRelease(pThis->hCnt);
3169 RTMemFree(pThis->paCachedAbbrevs);
3170 RTMemFree(pThis);
3171
3172 return VINF_SUCCESS;
3173}
3174
3175
3176/** @callback_method_impl{FNRTLDRENUMDBG} */
3177static DECLCALLBACK(int) rtDbgModDwarfEnumCallback(RTLDRMOD hLdrMod, uint32_t iDbgInfo, RTLDRDBGINFOTYPE enmType,
3178 uint16_t iMajorVer, uint16_t iMinorVer, const char *pszPartNm,
3179 RTFOFF offFile, RTLDRADDR LinkAddress, RTLDRADDR cb,
3180 const char *pszExtFile, void *pvUser)
3181{
3182 /*
3183 * Skip stuff we can't handle.
3184 */
3185 if ( enmType != RTLDRDBGINFOTYPE_DWARF
3186 || !pszPartNm
3187 || pszExtFile)
3188 return VINF_SUCCESS;
3189
3190 /*
3191 * Must have a part name starting with debug_ and possibly prefixed by dots
3192 * or underscores.
3193 */
3194 if (!strncmp(pszPartNm, ".debug_", sizeof(".debug_") - 1)) /* ELF */
3195 pszPartNm += sizeof(".debug_") - 1;
3196 else if (!strncmp(pszPartNm, "__debug_", sizeof("__debug_") - 1)) /* Mach-O */
3197 pszPartNm += sizeof("__debug_") - 1;
3198 else
3199 AssertMsgFailedReturn(("%s\n", pszPartNm), VINF_SUCCESS /*ignore*/);
3200
3201 /*
3202 * Figure out which part we're talking about.
3203 */
3204 krtDbgModDwarfSect enmSect;
3205 if (0) { /* dummy */ }
3206#define ELSE_IF_STRCMP_SET(a_Name) else if (!strcmp(pszPartNm, #a_Name)) enmSect = krtDbgModDwarfSect_ ## a_Name
3207 ELSE_IF_STRCMP_SET(abbrev);
3208 ELSE_IF_STRCMP_SET(aranges);
3209 ELSE_IF_STRCMP_SET(frame);
3210 ELSE_IF_STRCMP_SET(info);
3211 ELSE_IF_STRCMP_SET(inlined);
3212 ELSE_IF_STRCMP_SET(line);
3213 ELSE_IF_STRCMP_SET(loc);
3214 ELSE_IF_STRCMP_SET(macinfo);
3215 ELSE_IF_STRCMP_SET(pubnames);
3216 ELSE_IF_STRCMP_SET(pubtypes);
3217 ELSE_IF_STRCMP_SET(ranges);
3218 ELSE_IF_STRCMP_SET(str);
3219 ELSE_IF_STRCMP_SET(types);
3220#undef ELSE_IF_STRCMP_SET
3221 else
3222 {
3223 AssertMsgFailed(("%s\n", pszPartNm));
3224 return VINF_SUCCESS;
3225 }
3226
3227 /*
3228 * Record the section.
3229 */
3230 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
3231 AssertMsgReturn(!pThis->aSections[enmSect].fPresent, ("duplicate %s\n", pszPartNm), VINF_SUCCESS /*ignore*/);
3232
3233 pThis->aSections[enmSect].fPresent = true;
3234 pThis->aSections[enmSect].offFile = offFile;
3235 pThis->aSections[enmSect].pv = NULL;
3236 pThis->aSections[enmSect].cb = (size_t)cb;
3237 if (pThis->aSections[enmSect].cb != cb)
3238 pThis->aSections[enmSect].cb = ~(size_t)0;
3239
3240 return VINF_SUCCESS;
3241}
3242
3243
3244/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
3245static DECLCALLBACK(int) rtDbgModDwarf_TryOpen(PRTDBGMODINT pMod)
3246{
3247 /*
3248 * DWARF is only supported when part of an image.
3249 */
3250 if (!pMod->pImgVt)
3251 return VERR_DBG_NO_MATCHING_INTERPRETER;
3252
3253 /*
3254 * Enumerate the debug info in the module, looking for DWARF bits.
3255 */
3256 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)RTMemAllocZ(sizeof(*pThis));
3257 if (!pThis)
3258 return VERR_NO_MEMORY;
3259 pThis->pMod = pMod;
3260
3261 int rc = pMod->pImgVt->pfnEnumDbgInfo(pMod, rtDbgModDwarfEnumCallback, pThis);
3262 if (RT_SUCCESS(rc))
3263 {
3264 if (pThis->aSections[krtDbgModDwarfSect_info].fPresent)
3265 {
3266 /*
3267 * Extract / explode the data we want (symbols and line numbers)
3268 * storing them in a container module.
3269 */
3270 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
3271 if (RT_SUCCESS(rc))
3272 {
3273 pMod->pvDbgPriv = pThis;
3274
3275 rc = rtDbgModHlpAddSegmentsFromImage(pMod);
3276 if (RT_SUCCESS(rc))
3277 rc = rtDwarfInfo_LoadAll(pThis);
3278 if (RT_SUCCESS(rc))
3279 rc = rtDwarfLine_ExplodeAll(pThis);
3280 if (RT_SUCCESS(rc))
3281 {
3282 /*
3283 * Free the cached abbreviations and unload all sections.
3284 */
3285 pThis->cCachedAbbrevs = pThis->cCachedAbbrevsAlloced = 0;
3286 RTMemFree(pThis->paCachedAbbrevs);
3287
3288 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
3289 if (pThis->aSections[iSect].pv)
3290 pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[iSect].cb,
3291 &pThis->aSections[iSect].pv);
3292
3293
3294 return VINF_SUCCESS;
3295 }
3296
3297 /* bail out. */
3298 RTDbgModRelease(pThis->hCnt);
3299 pMod->pvDbgPriv = NULL;
3300 }
3301 }
3302 else
3303 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
3304 }
3305 RTMemFree(pThis->paCachedAbbrevs);
3306 RTMemFree(pThis);
3307
3308 return rc;
3309}
3310
3311
3312
3313/** Virtual function table for the DWARF debug info reader. */
3314DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDwarf =
3315{
3316 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
3317 /*.fSupports = */ RT_DBGTYPE_DWARF,
3318 /*.pszName = */ "dwarf",
3319 /*.pfnTryOpen = */ rtDbgModDwarf_TryOpen,
3320 /*.pfnClose = */ rtDbgModDwarf_Close,
3321
3322 /*.pfnRvaToSegOff = */ rtDbgModDwarf_RvaToSegOff,
3323 /*.pfnImageSize = */ rtDbgModDwarf_ImageSize,
3324
3325 /*.pfnSegmentAdd = */ rtDbgModDwarf_SegmentAdd,
3326 /*.pfnSegmentCount = */ rtDbgModDwarf_SegmentCount,
3327 /*.pfnSegmentByIndex = */ rtDbgModDwarf_SegmentByIndex,
3328
3329 /*.pfnSymbolAdd = */ rtDbgModDwarf_SymbolAdd,
3330 /*.pfnSymbolCount = */ rtDbgModDwarf_SymbolCount,
3331 /*.pfnSymbolByOrdinal = */ rtDbgModDwarf_SymbolByOrdinal,
3332 /*.pfnSymbolByName = */ rtDbgModDwarf_SymbolByName,
3333 /*.pfnSymbolByAddr = */ rtDbgModDwarf_SymbolByAddr,
3334
3335 /*.pfnLineAdd = */ rtDbgModDwarf_LineAdd,
3336 /*.pfnLineCount = */ rtDbgModDwarf_LineCount,
3337 /*.pfnLineByOrdinal = */ rtDbgModDwarf_LineByOrdinal,
3338 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr,
3339
3340 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
3341};
3342
Note: See TracBrowser for help on using the repository browser.

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