VirtualBox

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

Last change on this file since 47057 was 47057, checked in by vboxsync, 11 years ago

RTLdrFlt,dwarf: Sequeeze more info out of the darwin kernel debug info.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 171.4 KB
Line 
1/* $Id: dbgmoddwarf.cpp 47057 2013-07-09 16:02:56Z vboxsync $ */
2/** @file
3 * IPRT - Debug Info Reader For DWARF.
4 */
5
6/*
7 * Copyright (C) 2011-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DBG_DWARF
32#include <iprt/dbg.h>
33#include "internal/iprt.h"
34
35#include <iprt/asm.h>
36#include <iprt/ctype.h>
37#include <iprt/err.h>
38#include <iprt/list.h>
39#include <iprt/log.h>
40#include <iprt/mem.h>
41#define RTDBGMODDWARF_WITH_MEM_CACHE
42#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
43# include <iprt/memcache.h>
44#endif
45#include <iprt/path.h>
46#include <iprt/string.h>
47#include <iprt/strcache.h>
48#include "internal/dbgmod.h"
49
50
51/*******************************************************************************
52* Defined Constants And Macros *
53*******************************************************************************/
54/** @name Standard DWARF Line Number Opcodes
55 * @{ */
56#define DW_LNS_extended UINT8_C(0x00)
57#define DW_LNS_copy UINT8_C(0x01)
58#define DW_LNS_advance_pc UINT8_C(0x02)
59#define DW_LNS_advance_line UINT8_C(0x03)
60#define DW_LNS_set_file UINT8_C(0x04)
61#define DW_LNS_set_column UINT8_C(0x05)
62#define DW_LNS_negate_stmt UINT8_C(0x06)
63#define DW_LNS_set_basic_block UINT8_C(0x07)
64#define DW_LNS_const_add_pc UINT8_C(0x08)
65#define DW_LNS_fixed_advance_pc UINT8_C(0x09)
66#define DW_LNS_set_prologue_end UINT8_C(0x0a)
67#define DW_LNS_set_epilogue_begin UINT8_C(0x0b)
68#define DW_LNS_set_isa UINT8_C(0x0c)
69#define DW_LNS_what_question_mark UINT8_C(0x0d)
70/** @} */
71
72
73/** @name Extended DWARF Line Number Opcodes
74 * @{ */
75#define DW_LNE_end_sequence UINT8_C(1)
76#define DW_LNE_set_address UINT8_C(2)
77#define DW_LNE_define_file UINT8_C(3)
78#define DW_LNE_set_descriminator UINT8_C(4)
79/** @} */
80
81/** @name DIE Tags.
82 * @{ */
83#define DW_TAG_array_type UINT16_C(0x0001)
84#define DW_TAG_class_type UINT16_C(0x0002)
85#define DW_TAG_entry_point UINT16_C(0x0003)
86#define DW_TAG_enumeration_type UINT16_C(0x0004)
87#define DW_TAG_formal_parameter UINT16_C(0x0005)
88#define DW_TAG_imported_declaration UINT16_C(0x0008)
89#define DW_TAG_label UINT16_C(0x000a)
90#define DW_TAG_lexical_block UINT16_C(0x000b)
91#define DW_TAG_member UINT16_C(0x000d)
92#define DW_TAG_pointer_type UINT16_C(0x000f)
93#define DW_TAG_reference_type UINT16_C(0x0010)
94#define DW_TAG_compile_unit UINT16_C(0x0011)
95#define DW_TAG_string_type UINT16_C(0x0012)
96#define DW_TAG_structure_type UINT16_C(0x0013)
97#define DW_TAG_subroutine_type UINT16_C(0x0015)
98#define DW_TAG_typedef UINT16_C(0x0016)
99#define DW_TAG_union_type UINT16_C(0x0017)
100#define DW_TAG_unspecified_parameters UINT16_C(0x0018)
101#define DW_TAG_variant UINT16_C(0x0019)
102#define DW_TAG_common_block UINT16_C(0x001a)
103#define DW_TAG_common_inclusion UINT16_C(0x001b)
104#define DW_TAG_inheritance UINT16_C(0x001c)
105#define DW_TAG_inlined_subroutine UINT16_C(0x001d)
106#define DW_TAG_module UINT16_C(0x001e)
107#define DW_TAG_ptr_to_member_type UINT16_C(0x001f)
108#define DW_TAG_set_type UINT16_C(0x0020)
109#define DW_TAG_subrange_type UINT16_C(0x0021)
110#define DW_TAG_with_stmt UINT16_C(0x0022)
111#define DW_TAG_access_declaration UINT16_C(0x0023)
112#define DW_TAG_base_type UINT16_C(0x0024)
113#define DW_TAG_catch_block UINT16_C(0x0025)
114#define DW_TAG_const_type UINT16_C(0x0026)
115#define DW_TAG_constant UINT16_C(0x0027)
116#define DW_TAG_enumerator UINT16_C(0x0028)
117#define DW_TAG_file_type UINT16_C(0x0029)
118#define DW_TAG_friend UINT16_C(0x002a)
119#define DW_TAG_namelist UINT16_C(0x002b)
120#define DW_TAG_namelist_item UINT16_C(0x002c)
121#define DW_TAG_packed_type UINT16_C(0x002d)
122#define DW_TAG_subprogram UINT16_C(0x002e)
123#define DW_TAG_template_type_parameter UINT16_C(0x002f)
124#define DW_TAG_template_value_parameter UINT16_C(0x0030)
125#define DW_TAG_thrown_type UINT16_C(0x0031)
126#define DW_TAG_try_block UINT16_C(0x0032)
127#define DW_TAG_variant_part UINT16_C(0x0033)
128#define DW_TAG_variable UINT16_C(0x0034)
129#define DW_TAG_volatile_type UINT16_C(0x0035)
130#define DW_TAG_dwarf_procedure UINT16_C(0x0036)
131#define DW_TAG_restrict_type UINT16_C(0x0037)
132#define DW_TAG_interface_type UINT16_C(0x0038)
133#define DW_TAG_namespace UINT16_C(0x0039)
134#define DW_TAG_imported_module UINT16_C(0x003a)
135#define DW_TAG_unspecified_type UINT16_C(0x003b)
136#define DW_TAG_partial_unit UINT16_C(0x003c)
137#define DW_TAG_imported_unit UINT16_C(0x003d)
138#define DW_TAG_condition UINT16_C(0x003f)
139#define DW_TAG_shared_type UINT16_C(0x0040)
140#define DW_TAG_type_unit UINT16_C(0x0041)
141#define DW_TAG_rvalue_reference_type UINT16_C(0x0042)
142#define DW_TAG_template_alias UINT16_C(0x0043)
143#define DW_TAG_lo_user UINT16_C(0x4080)
144#define DW_TAG_hi_user UINT16_C(0xffff)
145/** @} */
146
147
148/** @name DIE Attributes.
149 * @{ */
150#define DW_AT_sibling UINT16_C(0x0001)
151#define DW_AT_location UINT16_C(0x0002)
152#define DW_AT_name UINT16_C(0x0003)
153#define DW_AT_ordering UINT16_C(0x0009)
154#define DW_AT_byte_size UINT16_C(0x000b)
155#define DW_AT_bit_offset UINT16_C(0x000c)
156#define DW_AT_bit_size UINT16_C(0x000d)
157#define DW_AT_stmt_list UINT16_C(0x0010)
158#define DW_AT_low_pc UINT16_C(0x0011)
159#define DW_AT_high_pc UINT16_C(0x0012)
160#define DW_AT_language UINT16_C(0x0013)
161#define DW_AT_discr UINT16_C(0x0015)
162#define DW_AT_discr_value UINT16_C(0x0016)
163#define DW_AT_visibility UINT16_C(0x0017)
164#define DW_AT_import UINT16_C(0x0018)
165#define DW_AT_string_length UINT16_C(0x0019)
166#define DW_AT_common_reference UINT16_C(0x001a)
167#define DW_AT_comp_dir UINT16_C(0x001b)
168#define DW_AT_const_value UINT16_C(0x001c)
169#define DW_AT_containing_type UINT16_C(0x001d)
170#define DW_AT_default_value UINT16_C(0x001e)
171#define DW_AT_inline UINT16_C(0x0020)
172#define DW_AT_is_optional UINT16_C(0x0021)
173#define DW_AT_lower_bound UINT16_C(0x0022)
174#define DW_AT_producer UINT16_C(0x0025)
175#define DW_AT_prototyped UINT16_C(0x0027)
176#define DW_AT_return_addr UINT16_C(0x002a)
177#define DW_AT_start_scope UINT16_C(0x002c)
178#define DW_AT_bit_stride UINT16_C(0x002e)
179#define DW_AT_upper_bound UINT16_C(0x002f)
180#define DW_AT_abstract_origin UINT16_C(0x0031)
181#define DW_AT_accessibility UINT16_C(0x0032)
182#define DW_AT_address_class UINT16_C(0x0033)
183#define DW_AT_artificial UINT16_C(0x0034)
184#define DW_AT_base_types UINT16_C(0x0035)
185#define DW_AT_calling_convention UINT16_C(0x0036)
186#define DW_AT_count UINT16_C(0x0037)
187#define DW_AT_data_member_location UINT16_C(0x0038)
188#define DW_AT_decl_column UINT16_C(0x0039)
189#define DW_AT_decl_file UINT16_C(0x003a)
190#define DW_AT_decl_line UINT16_C(0x003b)
191#define DW_AT_declaration UINT16_C(0x003c)
192#define DW_AT_discr_list UINT16_C(0x003d)
193#define DW_AT_encoding UINT16_C(0x003e)
194#define DW_AT_external UINT16_C(0x003f)
195#define DW_AT_frame_base UINT16_C(0x0040)
196#define DW_AT_friend UINT16_C(0x0041)
197#define DW_AT_identifier_case UINT16_C(0x0042)
198#define DW_AT_macro_info UINT16_C(0x0043)
199#define DW_AT_namelist_item UINT16_C(0x0044)
200#define DW_AT_priority UINT16_C(0x0045)
201#define DW_AT_segment UINT16_C(0x0046)
202#define DW_AT_specification UINT16_C(0x0047)
203#define DW_AT_static_link UINT16_C(0x0048)
204#define DW_AT_type UINT16_C(0x0049)
205#define DW_AT_use_location UINT16_C(0x004a)
206#define DW_AT_variable_parameter UINT16_C(0x004b)
207#define DW_AT_virtuality UINT16_C(0x004c)
208#define DW_AT_vtable_elem_location UINT16_C(0x004d)
209#define DW_AT_allocated UINT16_C(0x004e)
210#define DW_AT_associated UINT16_C(0x004f)
211#define DW_AT_data_location UINT16_C(0x0050)
212#define DW_AT_byte_stride UINT16_C(0x0051)
213#define DW_AT_entry_pc UINT16_C(0x0052)
214#define DW_AT_use_UTF8 UINT16_C(0x0053)
215#define DW_AT_extension UINT16_C(0x0054)
216#define DW_AT_ranges UINT16_C(0x0055)
217#define DW_AT_trampoline UINT16_C(0x0056)
218#define DW_AT_call_column UINT16_C(0x0057)
219#define DW_AT_call_file UINT16_C(0x0058)
220#define DW_AT_call_line UINT16_C(0x0059)
221#define DW_AT_description UINT16_C(0x005a)
222#define DW_AT_binary_scale UINT16_C(0x005b)
223#define DW_AT_decimal_scale UINT16_C(0x005c)
224#define DW_AT_small UINT16_C(0x005d)
225#define DW_AT_decimal_sign UINT16_C(0x005e)
226#define DW_AT_digit_count UINT16_C(0x005f)
227#define DW_AT_picture_string UINT16_C(0x0060)
228#define DW_AT_mutable UINT16_C(0x0061)
229#define DW_AT_threads_scaled UINT16_C(0x0062)
230#define DW_AT_explicit UINT16_C(0x0063)
231#define DW_AT_object_pointer UINT16_C(0x0064)
232#define DW_AT_endianity UINT16_C(0x0065)
233#define DW_AT_elemental UINT16_C(0x0066)
234#define DW_AT_pure UINT16_C(0x0067)
235#define DW_AT_recursive UINT16_C(0x0068)
236#define DW_AT_signature UINT16_C(0x0069)
237#define DW_AT_main_subprogram UINT16_C(0x006a)
238#define DW_AT_data_bit_offset UINT16_C(0x006b)
239#define DW_AT_const_expr UINT16_C(0x006c)
240#define DW_AT_enum_class UINT16_C(0x006d)
241#define DW_AT_linkage_name UINT16_C(0x006e)
242#define DW_AT_lo_user UINT16_C(0x2000)
243/** Used by GCC and others, same as DW_AT_linkage_name. See http://wiki.dwarfstd.org/index.php?title=DW_AT_linkage_name*/
244#define DW_AT_MIPS_linkage_name UINT16_C(0x2007)
245#define DW_AT_hi_user UINT16_C(0x3fff)
246/** @} */
247
248/** @name DIE Forms.
249 * @{ */
250#define DW_FORM_addr UINT16_C(0x01)
251/* What was 0x02? */
252#define DW_FORM_block2 UINT16_C(0x03)
253#define DW_FORM_block4 UINT16_C(0x04)
254#define DW_FORM_data2 UINT16_C(0x05)
255#define DW_FORM_data4 UINT16_C(0x06)
256#define DW_FORM_data8 UINT16_C(0x07)
257#define DW_FORM_string UINT16_C(0x08)
258#define DW_FORM_block UINT16_C(0x09)
259#define DW_FORM_block1 UINT16_C(0x0a)
260#define DW_FORM_data1 UINT16_C(0x0b)
261#define DW_FORM_flag UINT16_C(0x0c)
262#define DW_FORM_sdata UINT16_C(0x0d)
263#define DW_FORM_strp UINT16_C(0x0e)
264#define DW_FORM_udata UINT16_C(0x0f)
265#define DW_FORM_ref_addr UINT16_C(0x10)
266#define DW_FORM_ref1 UINT16_C(0x11)
267#define DW_FORM_ref2 UINT16_C(0x12)
268#define DW_FORM_ref4 UINT16_C(0x13)
269#define DW_FORM_ref8 UINT16_C(0x14)
270#define DW_FORM_ref_udata UINT16_C(0x15)
271#define DW_FORM_indirect UINT16_C(0x16)
272#define DW_FORM_sec_offset UINT16_C(0x17)
273#define DW_FORM_exprloc UINT16_C(0x18)
274#define DW_FORM_flag_present UINT16_C(0x19)
275#define DW_FORM_ref_sig8 UINT16_C(0x20)
276/** @} */
277
278/** @name Address classes.
279 * @{ */
280#define DW_ADDR_none UINT8_C(0)
281#define DW_ADDR_i386_near16 UINT8_C(1)
282#define DW_ADDR_i386_far16 UINT8_C(2)
283#define DW_ADDR_i386_huge16 UINT8_C(3)
284#define DW_ADDR_i386_near32 UINT8_C(4)
285#define DW_ADDR_i386_far32 UINT8_C(5)
286/** @} */
287
288
289/** @name Location Expression Opcodes
290 * @{ */
291#define DW_OP_addr UINT8_C(0x03) /**< 1 operand, a constant address (size target specific). */
292#define DW_OP_deref UINT8_C(0x06) /**< 0 operands. */
293#define DW_OP_const1u UINT8_C(0x08) /**< 1 operand, a 1-byte constant. */
294#define DW_OP_const1s UINT8_C(0x09) /**< 1 operand, a 1-byte constant. */
295#define DW_OP_const2u UINT8_C(0x0a) /**< 1 operand, a 2-byte constant. */
296#define DW_OP_const2s UINT8_C(0x0b) /**< 1 operand, a 2-byte constant. */
297#define DW_OP_const4u UINT8_C(0x0c) /**< 1 operand, a 4-byte constant. */
298#define DW_OP_const4s UINT8_C(0x0d) /**< 1 operand, a 4-byte constant. */
299#define DW_OP_const8u UINT8_C(0x0e) /**< 1 operand, a 8-byte constant. */
300#define DW_OP_const8s UINT8_C(0x0f) /**< 1 operand, a 8-byte constant. */
301#define DW_OP_constu UINT8_C(0x10) /**< 1 operand, a ULEB128 constant. */
302#define DW_OP_consts UINT8_C(0x11) /**< 1 operand, a SLEB128 constant. */
303#define DW_OP_dup UINT8_C(0x12) /**< 0 operands. */
304#define DW_OP_drop UINT8_C(0x13) /**< 0 operands. */
305#define DW_OP_over UINT8_C(0x14) /**< 0 operands. */
306#define DW_OP_pick UINT8_C(0x15) /**< 1 operands, a 1-byte stack index. */
307#define DW_OP_swap UINT8_C(0x16) /**< 0 operands. */
308#define DW_OP_rot UINT8_C(0x17) /**< 0 operands. */
309#define DW_OP_xderef UINT8_C(0x18) /**< 0 operands. */
310#define DW_OP_abs UINT8_C(0x19) /**< 0 operands. */
311#define DW_OP_and UINT8_C(0x1a) /**< 0 operands. */
312#define DW_OP_div UINT8_C(0x1b) /**< 0 operands. */
313#define DW_OP_minus UINT8_C(0x1c) /**< 0 operands. */
314#define DW_OP_mod UINT8_C(0x1d) /**< 0 operands. */
315#define DW_OP_mul UINT8_C(0x1e) /**< 0 operands. */
316#define DW_OP_neg UINT8_C(0x1f) /**< 0 operands. */
317#define DW_OP_not UINT8_C(0x20) /**< 0 operands. */
318#define DW_OP_or UINT8_C(0x21) /**< 0 operands. */
319#define DW_OP_plus UINT8_C(0x22) /**< 0 operands. */
320#define DW_OP_plus_uconst UINT8_C(0x23) /**< 1 operands, a ULEB128 addend. */
321#define DW_OP_shl UINT8_C(0x24) /**< 0 operands. */
322#define DW_OP_shr UINT8_C(0x25) /**< 0 operands. */
323#define DW_OP_shra UINT8_C(0x26) /**< 0 operands. */
324#define DW_OP_xor UINT8_C(0x27) /**< 0 operands. */
325#define DW_OP_skip UINT8_C(0x2f) /**< 1 signed 2-byte constant. */
326#define DW_OP_bra UINT8_C(0x28) /**< 1 signed 2-byte constant. */
327#define DW_OP_eq UINT8_C(0x29) /**< 0 operands. */
328#define DW_OP_ge UINT8_C(0x2a) /**< 0 operands. */
329#define DW_OP_gt UINT8_C(0x2b) /**< 0 operands. */
330#define DW_OP_le UINT8_C(0x2c) /**< 0 operands. */
331#define DW_OP_lt UINT8_C(0x2d) /**< 0 operands. */
332#define DW_OP_ne UINT8_C(0x2e) /**< 0 operands. */
333#define DW_OP_lit0 UINT8_C(0x30) /**< 0 operands - literals 0..31 */
334#define DW_OP_lit31 UINT8_C(0x4f) /**< last litteral. */
335#define DW_OP_reg0 UINT8_C(0x50) /**< 0 operands - reg 0..31. */
336#define DW_OP_reg31 UINT8_C(0x6f) /**< last register. */
337#define DW_OP_breg0 UINT8_C(0x70) /**< 1 operand, a SLEB128 offset. */
338#define DW_OP_breg31 UINT8_C(0x8f) /**< last branch register. */
339#define DW_OP_regx UINT8_C(0x90) /**< 1 operand, a ULEB128 register. */
340#define DW_OP_fbreg UINT8_C(0x91) /**< 1 operand, a SLEB128 offset. */
341#define DW_OP_bregx UINT8_C(0x92) /**< 2 operands, a ULEB128 register followed by a SLEB128 offset. */
342#define DW_OP_piece UINT8_C(0x93) /**< 1 operand, a ULEB128 size of piece addressed. */
343#define DW_OP_deref_size UINT8_C(0x94) /**< 1 operand, a 1-byte size of data retrieved. */
344#define DW_OP_xderef_size UINT8_C(0x95) /**< 1 operand, a 1-byte size of data retrieved. */
345#define DW_OP_nop UINT8_C(0x96) /**< 0 operands. */
346#define DW_OP_lo_user UINT8_C(0xe0) /**< First user opcode */
347#define DW_OP_hi_user UINT8_C(0xff) /**< Last user opcode. */
348/** @} */
349
350
351/*******************************************************************************
352* Structures and Typedefs *
353*******************************************************************************/
354/** Pointer to a DWARF section reader. */
355typedef struct RTDWARFCURSOR *PRTDWARFCURSOR;
356/** Pointer to an attribute descriptor. */
357typedef struct RTDWARFATTRDESC const *PCRTDWARFATTRDESC;
358/** Pointer to a DIE. */
359typedef struct RTDWARFDIE *PRTDWARFDIE;
360/** Pointer to a const DIE. */
361typedef struct RTDWARFDIE const *PCRTDWARFDIE;
362
363/**
364 * DWARF sections.
365 */
366typedef enum krtDbgModDwarfSect
367{
368 krtDbgModDwarfSect_abbrev = 0,
369 krtDbgModDwarfSect_aranges,
370 krtDbgModDwarfSect_frame,
371 krtDbgModDwarfSect_info,
372 krtDbgModDwarfSect_inlined,
373 krtDbgModDwarfSect_line,
374 krtDbgModDwarfSect_loc,
375 krtDbgModDwarfSect_macinfo,
376 krtDbgModDwarfSect_pubnames,
377 krtDbgModDwarfSect_pubtypes,
378 krtDbgModDwarfSect_ranges,
379 krtDbgModDwarfSect_str,
380 krtDbgModDwarfSect_types,
381 /** End of valid parts (exclusive). */
382 krtDbgModDwarfSect_End
383} krtDbgModDwarfSect;
384
385/**
386 * Abbreviation cache entry.
387 */
388typedef struct RTDWARFABBREV
389{
390 /** Whether this entry is filled in or not. */
391 bool fFilled;
392 /** Whether there are children or not. */
393 bool fChildren;
394 /** The tag. */
395 uint16_t uTag;
396 /** Offset into the abbrev section of the specification pairs. */
397 uint32_t offSpec;
398} RTDWARFABBREV;
399/** Pointer to an abbreviation cache entry. */
400typedef RTDWARFABBREV *PRTDWARFABBREV;
401/** Pointer to a const abbreviation cache entry. */
402typedef RTDWARFABBREV const *PCRTDWARFABBREV;
403
404/**
405 * Structure for gathering segment info.
406 */
407typedef struct RTDBGDWARFSEG
408{
409 /** The highest offset in the segment. */
410 uint64_t offHighest;
411 /** Calculated base address. */
412 uint64_t uBaseAddr;
413 /** Estimated The segment size. */
414 uint64_t cbSegment;
415 /** Segment number (RTLDRSEG::Sel16bit). */
416 RTSEL uSegment;
417} RTDBGDWARFSEG;
418/** Pointer to segment info. */
419typedef RTDBGDWARFSEG *PRTDBGDWARFSEG;
420
421
422/**
423 * The instance data of the DWARF reader.
424 */
425typedef struct RTDBGMODDWARF
426{
427 /** The debug container containing doing the real work. */
428 RTDBGMOD hCnt;
429 /** The image module (no reference). */
430 PRTDBGMODINT pImgMod;
431 /** The debug info module (no reference). */
432 PRTDBGMODINT pDbgInfoMod;
433 /** Nested image module (with reference ofc). */
434 PRTDBGMODINT pNestedMod;
435
436 /** DWARF debug info sections. */
437 struct
438 {
439 /** The file offset of the part. */
440 RTFOFF offFile;
441 /** The size of the part. */
442 size_t cb;
443 /** The memory mapping of the part. */
444 void const *pv;
445 /** Set if present. */
446 bool fPresent;
447 /** The debug info ordinal number in the image file. */
448 uint32_t iDbgInfo;
449 } aSections[krtDbgModDwarfSect_End];
450
451 /** The offset into the abbreviation section of the current cache. */
452 uint32_t offCachedAbbrev;
453 /** The number of cached abbreviations we've allocated space for. */
454 uint32_t cCachedAbbrevsAlloced;
455 /** Used for range checking cache lookups. */
456 uint32_t cCachedAbbrevs;
457 /** Array of cached abbreviations, indexed by code. */
458 PRTDWARFABBREV paCachedAbbrevs;
459 /** Used by rtDwarfAbbrev_Lookup when the result is uncachable. */
460 RTDWARFABBREV LookupAbbrev;
461
462 /** The list of compilation units (RTDWARFDIE). */
463 RTLISTANCHOR CompileUnitList;
464
465 /** This is set to -1 if we're doing everything in one pass.
466 * Otherwise it's 1 or 2:
467 * - In pass 1, we collect segment info.
468 * - In pass 2, we add debug info to the container.
469 * The two pass parsing is necessary for watcom generated symbol files as
470 * these contains no information about the code and data segments in the
471 * image. So we have to figure out some approximate stuff based on the
472 * segments and offsets we encounter in the debug info. */
473 int8_t iWatcomPass;
474 /** Segment index hint. */
475 uint16_t iSegHint;
476 /** The number of segments in paSegs.
477 * (During segment copying, this is abused to count useful segments.) */
478 uint32_t cSegs;
479 /** Pointer to segments if iWatcomPass isn't -1. */
480 PRTDBGDWARFSEG paSegs;
481#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
482 /** DIE allocators. */
483 struct
484 {
485 RTMEMCACHE hMemCache;
486 uint32_t cbMax;
487 } aDieAllocators[2];
488#endif
489} RTDBGMODDWARF;
490/** Pointer to instance data of the DWARF reader. */
491typedef RTDBGMODDWARF *PRTDBGMODDWARF;
492
493/**
494 * DWARF cursor for reading byte data.
495 */
496typedef struct RTDWARFCURSOR
497{
498 /** The current position. */
499 uint8_t const *pb;
500 /** The number of bytes left to read. */
501 size_t cbLeft;
502 /** The number of bytes left to read in the current unit. */
503 size_t cbUnitLeft;
504 /** The DWARF debug info reader instance. */
505 PRTDBGMODDWARF pDwarfMod;
506 /** Set if this is 64-bit DWARF, clear if 32-bit. */
507 bool f64bitDwarf;
508 /** Set if the format endian is native, clear if endian needs to be
509 * inverted. */
510 bool fNativEndian;
511 /** The size of a native address. */
512 uint8_t cbNativeAddr;
513 /** The cursor status code. This is VINF_SUCCESS until some error
514 * occurs. */
515 int rc;
516 /** The start of the area covered by the cursor.
517 * Used for repositioning the cursor relative to the start of a section. */
518 uint8_t const *pbStart;
519 /** The section. */
520 krtDbgModDwarfSect enmSect;
521} RTDWARFCURSOR;
522
523
524/**
525 * DWARF line number program state.
526 */
527typedef struct RTDWARFLINESTATE
528{
529 /** Virtual Line Number Machine Registers. */
530 struct
531 {
532 uint64_t uAddress;
533 uint64_t idxOp;
534 uint32_t iFile;
535 uint32_t uLine;
536 uint32_t uColumn;
537 bool fIsStatement;
538 bool fBasicBlock;
539 bool fEndSequence;
540 bool fPrologueEnd;
541 bool fEpilogueBegin;
542 uint32_t uIsa;
543 uint32_t uDiscriminator;
544 RTSEL uSegment;
545 } Regs;
546 /** @} */
547
548 /** Header. */
549 struct
550 {
551 uint32_t uVer;
552 uint64_t offFirstOpcode;
553 uint8_t cbMinInstr;
554 uint8_t cMaxOpsPerInstr;
555 uint8_t u8DefIsStmt;
556 int8_t s8LineBase;
557 uint8_t u8LineRange;
558 uint8_t u8OpcodeBase;
559 uint8_t const *pacStdOperands;
560 } Hdr;
561
562 /** @name Include Path Table (0-based)
563 * @{ */
564 const char **papszIncPaths;
565 uint32_t cIncPaths;
566 /** @} */
567
568 /** @name File Name Table (0-based, dummy zero entry)
569 * @{ */
570 char **papszFileNames;
571 uint32_t cFileNames;
572 /** @} */
573
574 /** The DWARF debug info reader instance. */
575 PRTDBGMODDWARF pDwarfMod;
576} RTDWARFLINESTATE;
577/** Pointer to a DWARF line number program state. */
578typedef RTDWARFLINESTATE *PRTDWARFLINESTATE;
579
580
581/**
582 * Decodes an attribute and stores it in the specified DIE member field.
583 *
584 * @returns IPRT status code.
585 * @param pDie Pointer to the DIE structure.
586 * @param pbMember Pointer to the first byte in the member.
587 * @param pDesc The attribute descriptor.
588 * @param uForm The data form.
589 * @param pDataCursor The cursor to read data from.
590 */
591typedef DECLCALLBACK(int) FNRTDWARFATTRDECODER(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
592 uint32_t uForm, PRTDWARFCURSOR pCursor);
593/** Pointer to an attribute decoder callback. */
594typedef FNRTDWARFATTRDECODER *PFNRTDWARFATTRDECODER;
595
596/**
597 * Attribute descriptor.
598 */
599typedef struct RTDWARFATTRDESC
600{
601 /** The attribute. */
602 uint16_t uAttr;
603 /** The data member offset. */
604 uint16_t off;
605 /** The data member size and initialization method. */
606 uint8_t cbInit;
607 uint8_t bPadding[3]; /**< Alignment padding. */
608 /** The decoder function. */
609 PFNRTDWARFATTRDECODER pfnDecoder;
610} RTDWARFATTRDESC;
611
612/** Define a attribute entry. */
613#define ATTR_ENTRY(a_uAttr, a_Struct, a_Member, a_Init, a_pfnDecoder) \
614 { \
615 a_uAttr, \
616 (uint16_t)RT_OFFSETOF(a_Struct, a_Member), \
617 a_Init | ((uint8_t)RT_SIZEOFMEMB(a_Struct, a_Member) & ATTR_SIZE_MASK), \
618 { 0, 0, 0 }, \
619 a_pfnDecoder\
620 }
621
622/** @name Attribute size and init methods.
623 * @{ */
624#define ATTR_INIT_ZERO UINT8_C(0x00)
625#define ATTR_INIT_FFFS UINT8_C(0x80)
626#define ATTR_INIT_MASK UINT8_C(0x80)
627#define ATTR_SIZE_MASK UINT8_C(0x3f)
628#define ATTR_GET_SIZE(a_pAttrDesc) ((a_pAttrDesc)->cbInit & ATTR_SIZE_MASK)
629/** @} */
630
631
632/**
633 * DIE descriptor.
634 */
635typedef struct RTDWARFDIEDESC
636{
637 /** The size of the DIE. */
638 size_t cbDie;
639 /** The number of attributes. */
640 size_t cAttributes;
641 /** The */
642 PCRTDWARFATTRDESC paAttributes;
643} RTDWARFDIEDESC;
644typedef struct RTDWARFDIEDESC const *PCRTDWARFDIEDESC;
645/** DIE descriptor initializer. */
646#define DIE_DESC_INIT(a_Type, a_aAttrs) { sizeof(a_Type), RT_ELEMENTS(a_aAttrs), &a_aAttrs[0] }
647
648
649/**
650 * DIE core structure, all inherits (starts with) this.
651 */
652typedef struct RTDWARFDIE
653{
654 /** Pointer to the parent node. NULL if root unit. */
655 struct RTDWARFDIE *pParent;
656 /** Our node in the sibling list. */
657 RTLISTNODE SiblingNode;
658 /** List of children. */
659 RTLISTNODE ChildList;
660 /** The number of attributes successfully decoded. */
661 uint8_t cDecodedAttrs;
662 /** The number of unknown or otherwise unhandled attributes. */
663 uint8_t cUnhandledAttrs;
664#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
665 /** The allocator index. */
666 uint8_t iAllocator;
667#endif
668 /** The die tag, indicating which union structure to use. */
669 uint16_t uTag;
670 /** Offset of the abbreviation specification (within debug_abbrev). */
671 uint32_t offSpec;
672} RTDWARFDIE;
673
674
675/**
676 * DWARF address structure.
677 */
678typedef struct RTDWARFADDR
679{
680 /** The address. */
681 uint64_t uAddress;
682} RTDWARFADDR;
683typedef RTDWARFADDR *PRTDWARFADDR;
684typedef RTDWARFADDR const *PCRTDWARFADDR;
685
686
687/**
688 * DWARF address range.
689 */
690typedef struct RTDWARFADDRRANGE
691{
692 uint64_t uLowAddress;
693 uint64_t uHighAddress;
694 uint8_t const *pbRanges; /* ?? */
695 uint8_t cAttrs : 2;
696 uint8_t fHaveLowAddress : 1;
697 uint8_t fHaveHighAddress : 1;
698 uint8_t fHaveRanges : 1;
699} RTDWARFADDRRANGE;
700typedef RTDWARFADDRRANGE *PRTDWARFADDRRANGE;
701typedef RTDWARFADDRRANGE const *PCRTDWARFADDRRANGE;
702
703/** What a RTDWARFREF is relative to. */
704typedef enum krtDwarfRef
705{
706 krtDwarfRef_NotSet,
707 krtDwarfRef_LineSection,
708 krtDwarfRef_LocSection,
709 krtDwarfRef_RangesSection,
710 krtDwarfRef_InfoSection,
711 krtDwarfRef_SameUnit,
712 krtDwarfRef_TypeId64
713} krtDwarfRef;
714
715/**
716 * DWARF reference.
717 */
718typedef struct RTDWARFREF
719{
720 /** The offset. */
721 uint64_t off;
722 /** What the offset is relative to. */
723 krtDwarfRef enmWrt;
724} RTDWARFREF;
725typedef RTDWARFREF *PRTDWARFREF;
726typedef RTDWARFREF const *PCRTDWARFREF;
727
728
729/**
730 * DWARF Location state.
731 */
732typedef struct RTDWARFLOCST
733{
734 /** The input cursor. */
735 RTDWARFCURSOR Cursor;
736 /** Points to the current top of the stack. Initial value -1. */
737 int32_t iTop;
738 /** The value stack. */
739 uint64_t auStack[64];
740} RTDWARFLOCST;
741/** Pointer to location state. */
742typedef RTDWARFLOCST *PRTDWARFLOCST;
743
744
745
746/*******************************************************************************
747* Internal Functions *
748*******************************************************************************/
749static FNRTDWARFATTRDECODER rtDwarfDecode_Address;
750static FNRTDWARFATTRDECODER rtDwarfDecode_Bool;
751static FNRTDWARFATTRDECODER rtDwarfDecode_LowHighPc;
752static FNRTDWARFATTRDECODER rtDwarfDecode_Ranges;
753static FNRTDWARFATTRDECODER rtDwarfDecode_Reference;
754static FNRTDWARFATTRDECODER rtDwarfDecode_SectOff;
755static FNRTDWARFATTRDECODER rtDwarfDecode_String;
756static FNRTDWARFATTRDECODER rtDwarfDecode_UnsignedInt;
757static FNRTDWARFATTRDECODER rtDwarfDecode_SegmentLoc;
758
759
760/*******************************************************************************
761* Global Variables *
762*******************************************************************************/
763/** RTDWARFDIE description. */
764static const RTDWARFDIEDESC g_CoreDieDesc = { sizeof(RTDWARFDIE), 0, NULL };
765
766
767/**
768 * DW_TAG_compile_unit & DW_TAG_partial_unit.
769 */
770typedef struct RTDWARFDIECOMPILEUNIT
771{
772 /** The DIE core structure. */
773 RTDWARFDIE Core;
774 /** The unit name. */
775 const char *pszName;
776 /** The address range of the code belonging to this unit. */
777 RTDWARFADDRRANGE PcRange;
778 /** The language name. */
779 uint16_t uLanguage;
780 /** The identifier case. */
781 uint8_t uIdentifierCase;
782 /** String are UTF-8 encoded. If not set, the encoding is
783 * unknown. */
784 bool fUseUtf8;
785 /** The unit contains main() or equivalent. */
786 bool fMainFunction;
787 /** The line numbers for this unit. */
788 RTDWARFREF StmtListRef;
789 /** The macro information for this unit. */
790 RTDWARFREF MacroInfoRef;
791 /** Reference to the base types. */
792 RTDWARFREF BaseTypesRef;
793 /** Working directory for the unit. */
794 const char *pszCurDir;
795 /** The name of the compiler or whatever that produced this unit. */
796 const char *pszProducer;
797
798 /** @name From the unit header.
799 * @{ */
800 /** The offset into debug_info of this unit (for references). */
801 uint64_t offUnit;
802 /** The length of this unit. */
803 uint64_t cbUnit;
804 /** The offset into debug_abbrev of the abbreviation for this unit. */
805 uint64_t offAbbrev;
806 /** The native address size. */
807 uint8_t cbNativeAddr;
808 /** The DWARF version. */
809 uint8_t uDwarfVer;
810 /** @} */
811} RTDWARFDIECOMPILEUNIT;
812typedef RTDWARFDIECOMPILEUNIT *PRTDWARFDIECOMPILEUNIT;
813
814
815/** RTDWARFDIECOMPILEUNIT attributes. */
816static const RTDWARFATTRDESC g_aCompileUnitAttrs[] =
817{
818 ATTR_ENTRY(DW_AT_name, RTDWARFDIECOMPILEUNIT, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
819 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
820 ATTR_ENTRY(DW_AT_high_pc, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
821 ATTR_ENTRY(DW_AT_ranges, RTDWARFDIECOMPILEUNIT, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_Ranges),
822 ATTR_ENTRY(DW_AT_language, RTDWARFDIECOMPILEUNIT, uLanguage, ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
823 ATTR_ENTRY(DW_AT_macro_info, RTDWARFDIECOMPILEUNIT, MacroInfoRef, ATTR_INIT_ZERO, rtDwarfDecode_SectOff),
824 ATTR_ENTRY(DW_AT_stmt_list, RTDWARFDIECOMPILEUNIT, StmtListRef, ATTR_INIT_ZERO, rtDwarfDecode_SectOff),
825 ATTR_ENTRY(DW_AT_comp_dir, RTDWARFDIECOMPILEUNIT, pszCurDir, ATTR_INIT_ZERO, rtDwarfDecode_String),
826 ATTR_ENTRY(DW_AT_producer, RTDWARFDIECOMPILEUNIT, pszProducer, ATTR_INIT_ZERO, rtDwarfDecode_String),
827 ATTR_ENTRY(DW_AT_identifier_case, RTDWARFDIECOMPILEUNIT, uIdentifierCase,ATTR_INIT_ZERO, rtDwarfDecode_UnsignedInt),
828 ATTR_ENTRY(DW_AT_base_types, RTDWARFDIECOMPILEUNIT, BaseTypesRef, ATTR_INIT_ZERO, rtDwarfDecode_Reference),
829 ATTR_ENTRY(DW_AT_use_UTF8, RTDWARFDIECOMPILEUNIT, fUseUtf8, ATTR_INIT_ZERO, rtDwarfDecode_Bool),
830 ATTR_ENTRY(DW_AT_main_subprogram, RTDWARFDIECOMPILEUNIT, fMainFunction, ATTR_INIT_ZERO, rtDwarfDecode_Bool)
831};
832
833/** RTDWARFDIECOMPILEUNIT description. */
834static const RTDWARFDIEDESC g_CompileUnitDesc = DIE_DESC_INIT(RTDWARFDIECOMPILEUNIT, g_aCompileUnitAttrs);
835
836
837/**
838 * DW_TAG_subprogram.
839 */
840typedef struct RTDWARFDIESUBPROGRAM
841{
842 /** The DIE core structure. */
843 RTDWARFDIE Core;
844 /** The name. */
845 const char *pszName;
846 /** The linkage name. */
847 const char *pszLinkageName;
848 /** The address range of the code belonging to this unit. */
849 RTDWARFADDRRANGE PcRange;
850 /** The first instruction in the function. */
851 RTDWARFADDR EntryPc;
852 /** Segment number (watcom). */
853 RTSEL uSegment;
854 /** Reference to the specification. */
855 RTDWARFREF SpecRef;
856} RTDWARFDIESUBPROGRAM;
857/** Pointer to a DW_TAG_subprogram DIE. */
858typedef RTDWARFDIESUBPROGRAM *PRTDWARFDIESUBPROGRAM;
859/** Pointer to a const DW_TAG_subprogram DIE. */
860typedef RTDWARFDIESUBPROGRAM const *PCRTDWARFDIESUBPROGRAM;
861
862
863/** RTDWARFDIESUBPROGRAM attributes. */
864static const RTDWARFATTRDESC g_aSubProgramAttrs[] =
865{
866 ATTR_ENTRY(DW_AT_name, RTDWARFDIESUBPROGRAM, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
867 ATTR_ENTRY(DW_AT_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
868 ATTR_ENTRY(DW_AT_MIPS_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
869 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
870 ATTR_ENTRY(DW_AT_high_pc, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_LowHighPc),
871 ATTR_ENTRY(DW_AT_ranges, RTDWARFDIESUBPROGRAM, PcRange, ATTR_INIT_ZERO, rtDwarfDecode_Ranges),
872 ATTR_ENTRY(DW_AT_entry_pc, RTDWARFDIESUBPROGRAM, EntryPc, ATTR_INIT_ZERO, rtDwarfDecode_Address),
873 ATTR_ENTRY(DW_AT_segment, RTDWARFDIESUBPROGRAM, uSegment, ATTR_INIT_ZERO, rtDwarfDecode_SegmentLoc),
874 ATTR_ENTRY(DW_AT_specification, RTDWARFDIESUBPROGRAM, SpecRef, ATTR_INIT_ZERO, rtDwarfDecode_Reference)
875};
876
877/** RTDWARFDIESUBPROGRAM description. */
878static const RTDWARFDIEDESC g_SubProgramDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramAttrs);
879
880
881/** RTDWARFDIESUBPROGRAM attributes for the specification hack. */
882static const RTDWARFATTRDESC g_aSubProgramSpecHackAttrs[] =
883{
884 ATTR_ENTRY(DW_AT_name, RTDWARFDIESUBPROGRAM, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
885 ATTR_ENTRY(DW_AT_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
886 ATTR_ENTRY(DW_AT_MIPS_linkage_name, RTDWARFDIESUBPROGRAM, pszLinkageName, ATTR_INIT_ZERO, rtDwarfDecode_String),
887};
888
889/** RTDWARFDIESUBPROGRAM description for the specification hack. */
890static const RTDWARFDIEDESC g_SubProgramSpecHackDesc = DIE_DESC_INIT(RTDWARFDIESUBPROGRAM, g_aSubProgramSpecHackAttrs);
891
892
893/**
894 * DW_TAG_label.
895 */
896typedef struct RTDWARFDIELABEL
897{
898 /** The DIE core structure. */
899 RTDWARFDIE Core;
900 /** The name. */
901 const char *pszName;
902 /** The address of the first instruction. */
903 RTDWARFADDR Address;
904 /** Segment number (watcom). */
905 RTSEL uSegment;
906 /** Externally visible? */
907 bool fExternal;
908} RTDWARFDIELABEL;
909/** Pointer to a DW_TAG_label DIE. */
910typedef RTDWARFDIELABEL *PRTDWARFDIELABEL;
911/** Pointer to a const DW_TAG_label DIE. */
912typedef RTDWARFDIELABEL const *PCRTDWARFDIELABEL;
913
914
915/** RTDWARFDIESUBPROGRAM attributes. */
916static const RTDWARFATTRDESC g_aLabelAttrs[] =
917{
918 ATTR_ENTRY(DW_AT_name, RTDWARFDIELABEL, pszName, ATTR_INIT_ZERO, rtDwarfDecode_String),
919 ATTR_ENTRY(DW_AT_low_pc, RTDWARFDIELABEL, Address, ATTR_INIT_ZERO, rtDwarfDecode_Address),
920 ATTR_ENTRY(DW_AT_segment, RTDWARFDIELABEL, uSegment, ATTR_INIT_ZERO, rtDwarfDecode_SegmentLoc),
921 ATTR_ENTRY(DW_AT_external, RTDWARFDIELABEL, fExternal, ATTR_INIT_ZERO, rtDwarfDecode_Bool)
922};
923
924/** RTDWARFDIESUBPROGRAM description. */
925static const RTDWARFDIEDESC g_LabelDesc = DIE_DESC_INIT(RTDWARFDIELABEL, g_aLabelAttrs);
926
927
928/**
929 * Tag names and descriptors.
930 */
931static const struct RTDWARFTAGDESC
932{
933 /** The tag value. */
934 uint16_t uTag;
935 /** The tag name as string. */
936 const char *pszName;
937 /** The DIE descriptor to use. */
938 PCRTDWARFDIEDESC pDesc;
939} g_aTagDescs[] =
940{
941#define TAGDESC(a_Name, a_pDesc) { DW_ ## a_Name, #a_Name, a_pDesc }
942#define TAGDESC_EMPTY() { 0, NULL, NULL }
943#define TAGDESC_CORE(a_Name) TAGDESC(a_Name, &g_CoreDieDesc)
944 TAGDESC_EMPTY(), /* 0x00 */
945 TAGDESC_CORE(TAG_array_type),
946 TAGDESC_CORE(TAG_class_type),
947 TAGDESC_CORE(TAG_entry_point),
948 TAGDESC_CORE(TAG_enumeration_type), /* 0x04 */
949 TAGDESC_CORE(TAG_formal_parameter),
950 TAGDESC_EMPTY(),
951 TAGDESC_EMPTY(),
952 TAGDESC_CORE(TAG_imported_declaration), /* 0x08 */
953 TAGDESC_EMPTY(),
954 TAGDESC(TAG_label, &g_LabelDesc),
955 TAGDESC_CORE(TAG_lexical_block),
956 TAGDESC_EMPTY(), /* 0x0c */
957 TAGDESC_CORE(TAG_member),
958 TAGDESC_EMPTY(),
959 TAGDESC_CORE(TAG_pointer_type),
960 TAGDESC_CORE(TAG_reference_type), /* 0x10 */
961 TAGDESC_CORE(TAG_compile_unit),
962 TAGDESC_CORE(TAG_string_type),
963 TAGDESC_CORE(TAG_structure_type),
964 TAGDESC_EMPTY(), /* 0x14 */
965 TAGDESC_CORE(TAG_subroutine_type),
966 TAGDESC_CORE(TAG_typedef),
967 TAGDESC_CORE(TAG_union_type),
968 TAGDESC_CORE(TAG_unspecified_parameters), /* 0x18 */
969 TAGDESC_CORE(TAG_variant),
970 TAGDESC_CORE(TAG_common_block),
971 TAGDESC_CORE(TAG_common_inclusion),
972 TAGDESC_CORE(TAG_inheritance), /* 0x1c */
973 TAGDESC_CORE(TAG_inlined_subroutine),
974 TAGDESC_CORE(TAG_module),
975 TAGDESC_CORE(TAG_ptr_to_member_type),
976 TAGDESC_CORE(TAG_set_type), /* 0x20 */
977 TAGDESC_CORE(TAG_subrange_type),
978 TAGDESC_CORE(TAG_with_stmt),
979 TAGDESC_CORE(TAG_access_declaration),
980 TAGDESC_CORE(TAG_base_type), /* 0x24 */
981 TAGDESC_CORE(TAG_catch_block),
982 TAGDESC_CORE(TAG_const_type),
983 TAGDESC_CORE(TAG_constant),
984 TAGDESC_CORE(TAG_enumerator), /* 0x28 */
985 TAGDESC_CORE(TAG_file_type),
986 TAGDESC_CORE(TAG_friend),
987 TAGDESC_CORE(TAG_namelist),
988 TAGDESC_CORE(TAG_namelist_item), /* 0x2c */
989 TAGDESC_CORE(TAG_packed_type),
990 TAGDESC(TAG_subprogram, &g_SubProgramDesc),
991 TAGDESC_CORE(TAG_template_type_parameter),
992 TAGDESC_CORE(TAG_template_value_parameter), /* 0x30 */
993 TAGDESC_CORE(TAG_thrown_type),
994 TAGDESC_CORE(TAG_try_block),
995 TAGDESC_CORE(TAG_variant_part),
996 TAGDESC_CORE(TAG_variable), /* 0x34 */
997 TAGDESC_CORE(TAG_volatile_type),
998 TAGDESC_CORE(TAG_dwarf_procedure),
999 TAGDESC_CORE(TAG_restrict_type),
1000 TAGDESC_CORE(TAG_interface_type), /* 0x38 */
1001 TAGDESC_CORE(TAG_namespace),
1002 TAGDESC_CORE(TAG_imported_module),
1003 TAGDESC_CORE(TAG_unspecified_type),
1004 TAGDESC_CORE(TAG_partial_unit), /* 0x3c */
1005 TAGDESC_CORE(TAG_imported_unit),
1006 TAGDESC_EMPTY(),
1007 TAGDESC_CORE(TAG_condition),
1008 TAGDESC_CORE(TAG_shared_type), /* 0x40 */
1009 TAGDESC_CORE(TAG_type_unit),
1010 TAGDESC_CORE(TAG_rvalue_reference_type),
1011 TAGDESC_CORE(TAG_template_alias)
1012#undef TAGDESC
1013#undef TAGDESC_EMPTY
1014#undef TAGDESC_CORE
1015};
1016
1017
1018/*******************************************************************************
1019* Internal Functions *
1020*******************************************************************************/
1021static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc,
1022 PRTDWARFCURSOR pCursor, PCRTDWARFABBREV pAbbrev, bool fInitDie);
1023
1024
1025
1026#if defined(LOG_ENABLED) || defined(RT_STRICT)
1027
1028/**
1029 * Turns a tag value into a string for logging purposes.
1030 *
1031 * @returns String name.
1032 * @param uTag The tag.
1033 */
1034static const char *rtDwarfLog_GetTagName(uint32_t uTag)
1035{
1036 if (uTag < RT_ELEMENTS(g_aTagDescs))
1037 {
1038 const char *pszTag = g_aTagDescs[uTag].pszName;
1039 if (pszTag)
1040 return pszTag;
1041 }
1042
1043 static char s_szStatic[32];
1044 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_TAG_%#x", uTag);
1045 return s_szStatic;
1046}
1047
1048
1049/**
1050 * Turns an attributevalue into a string for logging purposes.
1051 *
1052 * @returns String name.
1053 * @param uAttr The attribute.
1054 */
1055static const char *rtDwarfLog_AttrName(uint32_t uAttr)
1056{
1057 switch (uAttr)
1058 {
1059 RT_CASE_RET_STR(DW_AT_sibling);
1060 RT_CASE_RET_STR(DW_AT_location);
1061 RT_CASE_RET_STR(DW_AT_name);
1062 RT_CASE_RET_STR(DW_AT_ordering);
1063 RT_CASE_RET_STR(DW_AT_byte_size);
1064 RT_CASE_RET_STR(DW_AT_bit_offset);
1065 RT_CASE_RET_STR(DW_AT_bit_size);
1066 RT_CASE_RET_STR(DW_AT_stmt_list);
1067 RT_CASE_RET_STR(DW_AT_low_pc);
1068 RT_CASE_RET_STR(DW_AT_high_pc);
1069 RT_CASE_RET_STR(DW_AT_language);
1070 RT_CASE_RET_STR(DW_AT_discr);
1071 RT_CASE_RET_STR(DW_AT_discr_value);
1072 RT_CASE_RET_STR(DW_AT_visibility);
1073 RT_CASE_RET_STR(DW_AT_import);
1074 RT_CASE_RET_STR(DW_AT_string_length);
1075 RT_CASE_RET_STR(DW_AT_common_reference);
1076 RT_CASE_RET_STR(DW_AT_comp_dir);
1077 RT_CASE_RET_STR(DW_AT_const_value);
1078 RT_CASE_RET_STR(DW_AT_containing_type);
1079 RT_CASE_RET_STR(DW_AT_default_value);
1080 RT_CASE_RET_STR(DW_AT_inline);
1081 RT_CASE_RET_STR(DW_AT_is_optional);
1082 RT_CASE_RET_STR(DW_AT_lower_bound);
1083 RT_CASE_RET_STR(DW_AT_producer);
1084 RT_CASE_RET_STR(DW_AT_prototyped);
1085 RT_CASE_RET_STR(DW_AT_return_addr);
1086 RT_CASE_RET_STR(DW_AT_start_scope);
1087 RT_CASE_RET_STR(DW_AT_bit_stride);
1088 RT_CASE_RET_STR(DW_AT_upper_bound);
1089 RT_CASE_RET_STR(DW_AT_abstract_origin);
1090 RT_CASE_RET_STR(DW_AT_accessibility);
1091 RT_CASE_RET_STR(DW_AT_address_class);
1092 RT_CASE_RET_STR(DW_AT_artificial);
1093 RT_CASE_RET_STR(DW_AT_base_types);
1094 RT_CASE_RET_STR(DW_AT_calling_convention);
1095 RT_CASE_RET_STR(DW_AT_count);
1096 RT_CASE_RET_STR(DW_AT_data_member_location);
1097 RT_CASE_RET_STR(DW_AT_decl_column);
1098 RT_CASE_RET_STR(DW_AT_decl_file);
1099 RT_CASE_RET_STR(DW_AT_decl_line);
1100 RT_CASE_RET_STR(DW_AT_declaration);
1101 RT_CASE_RET_STR(DW_AT_discr_list);
1102 RT_CASE_RET_STR(DW_AT_encoding);
1103 RT_CASE_RET_STR(DW_AT_external);
1104 RT_CASE_RET_STR(DW_AT_frame_base);
1105 RT_CASE_RET_STR(DW_AT_friend);
1106 RT_CASE_RET_STR(DW_AT_identifier_case);
1107 RT_CASE_RET_STR(DW_AT_macro_info);
1108 RT_CASE_RET_STR(DW_AT_namelist_item);
1109 RT_CASE_RET_STR(DW_AT_priority);
1110 RT_CASE_RET_STR(DW_AT_segment);
1111 RT_CASE_RET_STR(DW_AT_specification);
1112 RT_CASE_RET_STR(DW_AT_static_link);
1113 RT_CASE_RET_STR(DW_AT_type);
1114 RT_CASE_RET_STR(DW_AT_use_location);
1115 RT_CASE_RET_STR(DW_AT_variable_parameter);
1116 RT_CASE_RET_STR(DW_AT_virtuality);
1117 RT_CASE_RET_STR(DW_AT_vtable_elem_location);
1118 RT_CASE_RET_STR(DW_AT_allocated);
1119 RT_CASE_RET_STR(DW_AT_associated);
1120 RT_CASE_RET_STR(DW_AT_data_location);
1121 RT_CASE_RET_STR(DW_AT_byte_stride);
1122 RT_CASE_RET_STR(DW_AT_entry_pc);
1123 RT_CASE_RET_STR(DW_AT_use_UTF8);
1124 RT_CASE_RET_STR(DW_AT_extension);
1125 RT_CASE_RET_STR(DW_AT_ranges);
1126 RT_CASE_RET_STR(DW_AT_trampoline);
1127 RT_CASE_RET_STR(DW_AT_call_column);
1128 RT_CASE_RET_STR(DW_AT_call_file);
1129 RT_CASE_RET_STR(DW_AT_call_line);
1130 RT_CASE_RET_STR(DW_AT_description);
1131 RT_CASE_RET_STR(DW_AT_binary_scale);
1132 RT_CASE_RET_STR(DW_AT_decimal_scale);
1133 RT_CASE_RET_STR(DW_AT_small);
1134 RT_CASE_RET_STR(DW_AT_decimal_sign);
1135 RT_CASE_RET_STR(DW_AT_digit_count);
1136 RT_CASE_RET_STR(DW_AT_picture_string);
1137 RT_CASE_RET_STR(DW_AT_mutable);
1138 RT_CASE_RET_STR(DW_AT_threads_scaled);
1139 RT_CASE_RET_STR(DW_AT_explicit);
1140 RT_CASE_RET_STR(DW_AT_object_pointer);
1141 RT_CASE_RET_STR(DW_AT_endianity);
1142 RT_CASE_RET_STR(DW_AT_elemental);
1143 RT_CASE_RET_STR(DW_AT_pure);
1144 RT_CASE_RET_STR(DW_AT_recursive);
1145 RT_CASE_RET_STR(DW_AT_signature);
1146 RT_CASE_RET_STR(DW_AT_main_subprogram);
1147 RT_CASE_RET_STR(DW_AT_data_bit_offset);
1148 RT_CASE_RET_STR(DW_AT_const_expr);
1149 RT_CASE_RET_STR(DW_AT_enum_class);
1150 RT_CASE_RET_STR(DW_AT_linkage_name);
1151 RT_CASE_RET_STR(DW_AT_MIPS_linkage_name);
1152 }
1153 static char s_szStatic[32];
1154 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_AT_%#x", uAttr);
1155 return s_szStatic;
1156}
1157
1158
1159/**
1160 * Turns a form value into a string for logging purposes.
1161 *
1162 * @returns String name.
1163 * @param uForm The form.
1164 */
1165static const char *rtDwarfLog_FormName(uint32_t uForm)
1166{
1167 switch (uForm)
1168 {
1169 RT_CASE_RET_STR(DW_FORM_addr);
1170 RT_CASE_RET_STR(DW_FORM_block2);
1171 RT_CASE_RET_STR(DW_FORM_block4);
1172 RT_CASE_RET_STR(DW_FORM_data2);
1173 RT_CASE_RET_STR(DW_FORM_data4);
1174 RT_CASE_RET_STR(DW_FORM_data8);
1175 RT_CASE_RET_STR(DW_FORM_string);
1176 RT_CASE_RET_STR(DW_FORM_block);
1177 RT_CASE_RET_STR(DW_FORM_block1);
1178 RT_CASE_RET_STR(DW_FORM_data1);
1179 RT_CASE_RET_STR(DW_FORM_flag);
1180 RT_CASE_RET_STR(DW_FORM_sdata);
1181 RT_CASE_RET_STR(DW_FORM_strp);
1182 RT_CASE_RET_STR(DW_FORM_udata);
1183 RT_CASE_RET_STR(DW_FORM_ref_addr);
1184 RT_CASE_RET_STR(DW_FORM_ref1);
1185 RT_CASE_RET_STR(DW_FORM_ref2);
1186 RT_CASE_RET_STR(DW_FORM_ref4);
1187 RT_CASE_RET_STR(DW_FORM_ref8);
1188 RT_CASE_RET_STR(DW_FORM_ref_udata);
1189 RT_CASE_RET_STR(DW_FORM_indirect);
1190 RT_CASE_RET_STR(DW_FORM_sec_offset);
1191 RT_CASE_RET_STR(DW_FORM_exprloc);
1192 RT_CASE_RET_STR(DW_FORM_flag_present);
1193 RT_CASE_RET_STR(DW_FORM_ref_sig8);
1194 }
1195 static char s_szStatic[32];
1196 RTStrPrintf(s_szStatic, sizeof(s_szStatic),"DW_FORM_%#x", uForm);
1197 return s_szStatic;
1198}
1199
1200#endif /* LOG_ENABLED || RT_STRICT */
1201
1202
1203/** @callback_method_impl{FNRTLDRENUMSEGS} */
1204static DECLCALLBACK(int) rtDbgModDwarfScanSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
1205{
1206 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
1207 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx\n",
1208 pSeg->cchName, pSeg->pszName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb));
1209 NOREF(hLdrMod);
1210
1211 /* Count relevant segments. */
1212 if (pSeg->RVA != NIL_RTLDRADDR)
1213 pThis->cSegs++;
1214
1215 return VINF_SUCCESS;
1216}
1217
1218
1219/** @callback_method_impl{FNRTLDRENUMSEGS} */
1220static DECLCALLBACK(int) rtDbgModDwarfAddSegmentsCallback(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
1221{
1222 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
1223 Log(("Segment %.*s: LinkAddress=%#llx RVA=%#llx cb=%#llx cbMapped=%#llx\n",
1224 pSeg->cchName, pSeg->pszName, (uint64_t)pSeg->LinkAddress, (uint64_t)pSeg->RVA, pSeg->cb, pSeg->cbMapped));
1225 NOREF(hLdrMod);
1226 Assert(pSeg->cchName > 0);
1227 Assert(!pSeg->pszName[pSeg->cchName]);
1228
1229 /* If the segment doesn't have a mapping, just add a dummy so the indexing
1230 works out correctly (same as for the image). */
1231 if (pSeg->RVA == NIL_RTLDRADDR)
1232 return RTDbgModSegmentAdd(pThis->hCnt, 0, 0, pSeg->pszName, 0 /*fFlags*/, NULL);
1233
1234 /* The link address is 0 for all segments in a relocatable ELF image. */
1235 RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
1236 return RTDbgModSegmentAdd(pThis->hCnt, pSeg->RVA, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
1237}
1238
1239
1240/**
1241 * Calls pfnSegmentAdd for each segment in the executable image.
1242 *
1243 * @returns IPRT status code.
1244 * @param pThis The DWARF instance.
1245 */
1246static int rtDbgModDwarfAddSegmentsFromImage(PRTDBGMODDWARF pThis)
1247{
1248 AssertReturn(pThis->pImgMod && pThis->pImgMod->pImgVt, VERR_INTERNAL_ERROR_2);
1249 Assert(!pThis->cSegs);
1250 int rc = pThis->pImgMod->pImgVt->pfnEnumSegments(pThis->pImgMod, rtDbgModDwarfScanSegmentsCallback, pThis);
1251 if (RT_SUCCESS(rc))
1252 {
1253 if (pThis->cSegs == 0)
1254 pThis->iWatcomPass = 1;
1255 else
1256 {
1257 pThis->cSegs = 0;
1258 pThis->iWatcomPass = -1;
1259 rc = pThis->pImgMod->pImgVt->pfnEnumSegments(pThis->pImgMod, rtDbgModDwarfAddSegmentsCallback, pThis);
1260 }
1261 }
1262
1263 return rc;
1264}
1265
1266
1267/**
1268 * Looks up a segment.
1269 *
1270 * @returns Pointer to the segment on success, NULL if not found.
1271 * @param pThis The DWARF instance.
1272 * @param uSeg The segment number / selector.
1273 */
1274static PRTDBGDWARFSEG rtDbgModDwarfFindSegment(PRTDBGMODDWARF pThis, RTSEL uSeg)
1275{
1276 uint32_t cSegs = pThis->cSegs;
1277 uint32_t iSeg = pThis->iSegHint;
1278 PRTDBGDWARFSEG paSegs = pThis->paSegs;
1279 if ( iSeg < cSegs
1280 && paSegs[iSeg].uSegment == uSeg)
1281 return &paSegs[iSeg];
1282
1283 for (iSeg = 0; iSeg < cSegs; iSeg++)
1284 if (uSeg == paSegs[iSeg].uSegment)
1285 {
1286 pThis->iSegHint = iSeg;
1287 return &paSegs[iSeg];
1288 }
1289
1290 AssertFailed();
1291 return NULL;
1292}
1293
1294
1295/**
1296 * Record a segment:offset during pass 1.
1297 *
1298 * @returns IPRT status code.
1299 * @param pThis The DWARF instance.
1300 * @param uSeg The segment number / selector.
1301 * @param offSeg The segment offset.
1302 */
1303static int rtDbgModDwarfRecordSegOffset(PRTDBGMODDWARF pThis, RTSEL uSeg, uint64_t offSeg)
1304{
1305 /* Look up the segment. */
1306 uint32_t cSegs = pThis->cSegs;
1307 uint32_t iSeg = pThis->iSegHint;
1308 PRTDBGDWARFSEG paSegs = pThis->paSegs;
1309 if ( iSeg >= cSegs
1310 || paSegs[iSeg].uSegment != uSeg)
1311 {
1312 for (iSeg = 0; iSeg < cSegs; iSeg++)
1313 if (uSeg <= paSegs[iSeg].uSegment)
1314 break;
1315 if ( iSeg >= cSegs
1316 || paSegs[iSeg].uSegment != uSeg)
1317 {
1318 /* Add */
1319 void *pvNew = RTMemRealloc(paSegs, (pThis->cSegs + 1) * sizeof(paSegs[0]));
1320 if (!pvNew)
1321 return VERR_NO_MEMORY;
1322 pThis->paSegs = paSegs = (PRTDBGDWARFSEG)pvNew;
1323 if (iSeg != cSegs)
1324 memmove(&paSegs[iSeg + 1], &paSegs[iSeg], (cSegs - iSeg) * sizeof(paSegs[0]));
1325 paSegs[iSeg].offHighest = offSeg;
1326 paSegs[iSeg].uBaseAddr = 0;
1327 paSegs[iSeg].cbSegment = 0;
1328 paSegs[iSeg].uSegment = uSeg;
1329 pThis->cSegs++;
1330 }
1331
1332 pThis->iSegHint = iSeg;
1333 }
1334
1335 /* Increase it's range? */
1336 if (paSegs[iSeg].offHighest < offSeg)
1337 {
1338 Log3(("rtDbgModDwarfRecordSegOffset: iSeg=%d uSeg=%#06x offSeg=%#llx\n", iSeg, uSeg, offSeg));
1339 paSegs[iSeg].offHighest = offSeg;
1340 }
1341
1342 return VINF_SUCCESS;
1343}
1344
1345
1346/**
1347 * Calls pfnSegmentAdd for each segment in the executable image.
1348 *
1349 * @returns IPRT status code.
1350 * @param pThis The DWARF instance.
1351 */
1352static int rtDbgModDwarfAddSegmentsFromPass1(PRTDBGMODDWARF pThis)
1353{
1354 AssertReturn(pThis->cSegs, VERR_DWARF_BAD_INFO);
1355 uint32_t const cSegs = pThis->cSegs;
1356 PRTDBGDWARFSEG paSegs = pThis->paSegs;
1357
1358 /*
1359 * Are the segments assigned more or less in numerical order?
1360 */
1361 if ( paSegs[0].uSegment < 16U
1362 && paSegs[cSegs - 1].uSegment - paSegs[0].uSegment + 1U <= cSegs + 16U)
1363 {
1364 /** @todo heuristics, plase. */
1365 AssertFailedReturn(VERR_DWARF_TODO);
1366
1367 }
1368 /*
1369 * Assume DOS segmentation.
1370 */
1371 else
1372 {
1373 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1374 paSegs[iSeg].uBaseAddr = (uint32_t)paSegs[iSeg].uSegment << 16;
1375 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1376 paSegs[iSeg].cbSegment = paSegs[iSeg].offHighest;
1377 }
1378
1379 /*
1380 * Add them.
1381 */
1382 for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
1383 {
1384 Log3(("rtDbgModDwarfAddSegmentsFromPass1: Seg#%u: %#010llx LB %#llx uSegment=%#x\n",
1385 iSeg, paSegs[iSeg].uBaseAddr, paSegs[iSeg].cbSegment, paSegs[iSeg].uSegment));
1386 char szName[32];
1387 RTStrPrintf(szName, sizeof(szName), "seg-%#04xh", paSegs[iSeg].uSegment);
1388 int rc = RTDbgModSegmentAdd(pThis->hCnt, paSegs[iSeg].uBaseAddr, paSegs[iSeg].cbSegment,
1389 szName, 0 /*fFlags*/, NULL);
1390 if (RT_FAILURE(rc))
1391 return rc;
1392 }
1393
1394 return VINF_SUCCESS;
1395}
1396
1397
1398/**
1399 * Loads a DWARF section from the image file.
1400 *
1401 * @returns IPRT status code.
1402 * @param pThis The DWARF instance.
1403 * @param enmSect The section to load.
1404 */
1405static int rtDbgModDwarfLoadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
1406{
1407 /*
1408 * Don't load stuff twice.
1409 */
1410 if (pThis->aSections[enmSect].pv)
1411 return VINF_SUCCESS;
1412
1413 /*
1414 * Sections that are not present cannot be loaded, treat them like they
1415 * are empty
1416 */
1417 if (!pThis->aSections[enmSect].fPresent)
1418 {
1419 Assert(pThis->aSections[enmSect].cb);
1420 return VINF_SUCCESS;
1421 }
1422 if (!pThis->aSections[enmSect].cb)
1423 return VINF_SUCCESS;
1424
1425 /*
1426 * Sections must be readable with the current image interface.
1427 */
1428 if (pThis->aSections[enmSect].offFile < 0)
1429 return VERR_OUT_OF_RANGE;
1430
1431 /*
1432 * Do the job.
1433 */
1434 return pThis->pDbgInfoMod->pImgVt->pfnMapPart(pThis->pDbgInfoMod,
1435 pThis->aSections[enmSect].iDbgInfo,
1436 pThis->aSections[enmSect].offFile,
1437 pThis->aSections[enmSect].cb,
1438 &pThis->aSections[enmSect].pv);
1439}
1440
1441
1442#ifdef SOME_UNUSED_FUNCTION
1443/**
1444 * Unloads a DWARF section previously mapped by rtDbgModDwarfLoadSection.
1445 *
1446 * @returns IPRT status code.
1447 * @param pThis The DWARF instance.
1448 * @param enmSect The section to unload.
1449 */
1450static int rtDbgModDwarfUnloadSection(PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
1451{
1452 if (!pThis->aSections[enmSect].pv)
1453 return VINF_SUCCESS;
1454
1455 int rc = pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[enmSect].cb, &pThis->aSections[enmSect].pv);
1456 AssertRC(rc);
1457 return rc;
1458}
1459#endif
1460
1461
1462/**
1463 * Converts to UTF-8 or otherwise makes sure it's valid UTF-8.
1464 *
1465 * @returns IPRT status code.
1466 * @param pThis The DWARF instance.
1467 * @param ppsz Pointer to the string pointer. May be
1468 * reallocated (RTStr*).
1469 */
1470static int rtDbgModDwarfStringToUtf8(PRTDBGMODDWARF pThis, char **ppsz)
1471{
1472 /** @todo DWARF & UTF-8. */
1473 NOREF(pThis);
1474 RTStrPurgeEncoding(*ppsz);
1475 return VINF_SUCCESS;
1476}
1477
1478
1479/**
1480 * Convers a link address into a segment+offset or RVA.
1481 *
1482 * @returns IPRT status code.
1483 * @param pThis The DWARF instance.
1484 * @param uSegment The segment, 0 if not applicable.
1485 * @param LinkAddress The address to convert..
1486 * @param piSeg The segment index.
1487 * @param poffSeg Where to return the segment offset.
1488 */
1489static int rtDbgModDwarfLinkAddressToSegOffset(PRTDBGMODDWARF pThis, RTSEL uSegment, uint64_t LinkAddress,
1490 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg)
1491{
1492 if (pThis->paSegs)
1493 {
1494 PRTDBGDWARFSEG pSeg = rtDbgModDwarfFindSegment(pThis, uSegment);
1495 if (pSeg)
1496 {
1497 *piSeg = pSeg - pThis->paSegs;
1498 *poffSeg = LinkAddress;
1499 return VINF_SUCCESS;
1500 }
1501 }
1502
1503 //return pThis->pImgMod->pImgVt->pfnRvaToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
1504 return pThis->pImgMod->pImgVt->pfnLinkAddressToSegOffset(pThis->pImgMod, LinkAddress, piSeg, poffSeg);
1505}
1506
1507
1508/*
1509 *
1510 * DWARF Cursor.
1511 * DWARF Cursor.
1512 * DWARF Cursor.
1513 *
1514 */
1515
1516
1517/**
1518 * Reads a 8-bit unsigned integer and advances the cursor.
1519 *
1520 * @returns 8-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1521 * uErrValue is returned.
1522 * @param pCursor The cursor.
1523 * @param uErrValue What to return on read error.
1524 */
1525static uint8_t rtDwarfCursor_GetU8(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
1526{
1527 if (pCursor->cbUnitLeft < 1)
1528 {
1529 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1530 return uErrValue;
1531 }
1532
1533 uint8_t u8 = pCursor->pb[0];
1534 pCursor->pb += 1;
1535 pCursor->cbUnitLeft -= 1;
1536 pCursor->cbLeft -= 1;
1537 return u8;
1538}
1539
1540
1541/**
1542 * Reads a 16-bit unsigned integer and advances the cursor.
1543 *
1544 * @returns 16-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1545 * uErrValue is returned.
1546 * @param pCursor The cursor.
1547 * @param uErrValue What to return on read error.
1548 */
1549static uint16_t rtDwarfCursor_GetU16(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
1550{
1551 if (pCursor->cbUnitLeft < 2)
1552 {
1553 pCursor->pb += pCursor->cbUnitLeft;
1554 pCursor->cbLeft -= pCursor->cbUnitLeft;
1555 pCursor->cbUnitLeft = 0;
1556 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1557 return uErrValue;
1558 }
1559
1560 uint16_t u16 = RT_MAKE_U16(pCursor->pb[0], pCursor->pb[1]);
1561 pCursor->pb += 2;
1562 pCursor->cbUnitLeft -= 2;
1563 pCursor->cbLeft -= 2;
1564 if (!pCursor->fNativEndian)
1565 u16 = RT_BSWAP_U16(u16);
1566 return u16;
1567}
1568
1569
1570/**
1571 * Reads a 32-bit unsigned integer and advances the cursor.
1572 *
1573 * @returns 32-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1574 * uErrValue is returned.
1575 * @param pCursor The cursor.
1576 * @param uErrValue What to return on read error.
1577 */
1578static uint32_t rtDwarfCursor_GetU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
1579{
1580 if (pCursor->cbUnitLeft < 4)
1581 {
1582 pCursor->pb += pCursor->cbUnitLeft;
1583 pCursor->cbLeft -= pCursor->cbUnitLeft;
1584 pCursor->cbUnitLeft = 0;
1585 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1586 return uErrValue;
1587 }
1588
1589 uint32_t u32 = RT_MAKE_U32_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3]);
1590 pCursor->pb += 4;
1591 pCursor->cbUnitLeft -= 4;
1592 pCursor->cbLeft -= 4;
1593 if (!pCursor->fNativEndian)
1594 u32 = RT_BSWAP_U32(u32);
1595 return u32;
1596}
1597
1598
1599/**
1600 * Reads a 64-bit unsigned integer and advances the cursor.
1601 *
1602 * @returns 64-bit unsigned integer. On error RTDWARFCURSOR::rc is set and @a
1603 * uErrValue is returned.
1604 * @param pCursor The cursor.
1605 * @param uErrValue What to return on read error.
1606 */
1607static uint64_t rtDwarfCursor_GetU64(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1608{
1609 if (pCursor->cbUnitLeft < 8)
1610 {
1611 pCursor->pb += pCursor->cbUnitLeft;
1612 pCursor->cbLeft -= pCursor->cbUnitLeft;
1613 pCursor->cbUnitLeft = 0;
1614 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1615 return uErrValue;
1616 }
1617
1618 uint64_t u64 = RT_MAKE_U64_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3],
1619 pCursor->pb[4], pCursor->pb[5], pCursor->pb[6], pCursor->pb[7]);
1620 pCursor->pb += 8;
1621 pCursor->cbUnitLeft -= 8;
1622 pCursor->cbLeft -= 8;
1623 if (!pCursor->fNativEndian)
1624 u64 = RT_BSWAP_U64(u64);
1625 return u64;
1626}
1627
1628
1629/**
1630 * Reads an unsigned LEB128 encoded number.
1631 *
1632 * @returns unsigned 64-bit number. On error RTDWARFCURSOR::rc is set and @a
1633 * uErrValue is returned.
1634 * @param pCursor The cursor.
1635 * @param uErrValue The value to return on error.
1636 */
1637static uint64_t rtDwarfCursor_GetULeb128(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1638{
1639 if (pCursor->cbUnitLeft < 1)
1640 {
1641 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1642 return uErrValue;
1643 }
1644
1645 /*
1646 * Special case - single byte.
1647 */
1648 uint8_t b = pCursor->pb[0];
1649 if (!(b & 0x80))
1650 {
1651 pCursor->pb += 1;
1652 pCursor->cbUnitLeft -= 1;
1653 pCursor->cbLeft -= 1;
1654 return b;
1655 }
1656
1657 /*
1658 * Generic case.
1659 */
1660 /* Decode. */
1661 uint32_t off = 1;
1662 uint64_t u64Ret = b & 0x7f;
1663 do
1664 {
1665 if (off == pCursor->cbUnitLeft)
1666 {
1667 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1668 u64Ret = uErrValue;
1669 break;
1670 }
1671 b = pCursor->pb[off];
1672 u64Ret |= (b & 0x7f) << off * 7;
1673 off++;
1674 } while (b & 0x80);
1675
1676 /* Update the cursor. */
1677 pCursor->pb += off;
1678 pCursor->cbUnitLeft -= off;
1679 pCursor->cbLeft -= off;
1680
1681 /* Check the range. */
1682 uint32_t cBits = off * 7;
1683 if (cBits > 64)
1684 {
1685 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1686 u64Ret = uErrValue;
1687 }
1688
1689 return u64Ret;
1690}
1691
1692
1693/**
1694 * Reads a signed LEB128 encoded number.
1695 *
1696 * @returns signed 64-bit number. On error RTDWARFCURSOR::rc is set and @a
1697 * uErrValue is returned.
1698 * @param pCursor The cursor.
1699 * @param sErrValue The value to return on error.
1700 */
1701static int64_t rtDwarfCursor_GetSLeb128(PRTDWARFCURSOR pCursor, int64_t sErrValue)
1702{
1703 if (pCursor->cbUnitLeft < 1)
1704 {
1705 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1706 return sErrValue;
1707 }
1708
1709 /*
1710 * Special case - single byte.
1711 */
1712 uint8_t b = pCursor->pb[0];
1713 if (!(b & 0x80))
1714 {
1715 pCursor->pb += 1;
1716 pCursor->cbUnitLeft -= 1;
1717 pCursor->cbLeft -= 1;
1718 if (b & 0x40)
1719 b |= 0x80;
1720 return (int8_t)b;
1721 }
1722
1723 /*
1724 * Generic case.
1725 */
1726 /* Decode it. */
1727 uint32_t off = 1;
1728 uint64_t u64Ret = b & 0x7f;
1729 do
1730 {
1731 if (off == pCursor->cbUnitLeft)
1732 {
1733 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1734 u64Ret = (uint64_t)sErrValue;
1735 break;
1736 }
1737 b = pCursor->pb[off];
1738 u64Ret |= (b & 0x7f) << off * 7;
1739 off++;
1740 } while (b & 0x80);
1741
1742 /* Update cursor. */
1743 pCursor->pb += off;
1744 pCursor->cbUnitLeft -= off;
1745 pCursor->cbLeft -= off;
1746
1747 /* Check the range. */
1748 uint32_t cBits = off * 7;
1749 if (cBits > 64)
1750 {
1751 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1752 u64Ret = (uint64_t)sErrValue;
1753 }
1754 /* Sign extend the value. */
1755 else if (u64Ret & RT_BIT_64(cBits - 1))
1756 u64Ret |= ~(RT_BIT_64(cBits - 1) - 1);
1757
1758 return (int64_t)u64Ret;
1759}
1760
1761
1762/**
1763 * Reads an unsigned LEB128 encoded number, max 32-bit width.
1764 *
1765 * @returns unsigned 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1766 * uErrValue is returned.
1767 * @param pCursor The cursor.
1768 * @param uErrValue The value to return on error.
1769 */
1770static uint32_t rtDwarfCursor_GetULeb128AsU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
1771{
1772 uint64_t u64 = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
1773 if (u64 > UINT32_MAX)
1774 {
1775 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1776 return uErrValue;
1777 }
1778 return (uint32_t)u64;
1779}
1780
1781
1782/**
1783 * Reads a signed LEB128 encoded number, max 32-bit width.
1784 *
1785 * @returns signed 32-bit number. On error RTDWARFCURSOR::rc is set and @a
1786 * uErrValue is returned.
1787 * @param pCursor The cursor.
1788 * @param sErrValue The value to return on error.
1789 */
1790static int32_t rtDwarfCursor_GetSLeb128AsS32(PRTDWARFCURSOR pCursor, int32_t sErrValue)
1791{
1792 int64_t s64 = rtDwarfCursor_GetSLeb128(pCursor, sErrValue);
1793 if (s64 > INT32_MAX || s64 < INT32_MIN)
1794 {
1795 pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
1796 return sErrValue;
1797 }
1798 return (int32_t)s64;
1799}
1800
1801
1802/**
1803 * Skips a LEB128 encoded number.
1804 *
1805 * @returns IPRT status code.
1806 * @param pCursor The cursor.
1807 */
1808static int rtDwarfCursor_SkipLeb128(PRTDWARFCURSOR pCursor)
1809{
1810 if (RT_FAILURE(pCursor->rc))
1811 return pCursor->rc;
1812
1813 if (pCursor->cbUnitLeft < 1)
1814 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1815
1816 uint32_t offSkip = 1;
1817 if (pCursor->pb[0] & 0x80)
1818 do
1819 {
1820 if (offSkip == pCursor->cbUnitLeft)
1821 {
1822 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1823 break;
1824 }
1825 } while (pCursor->pb[offSkip++] & 0x80);
1826
1827 pCursor->pb += offSkip;
1828 pCursor->cbUnitLeft -= offSkip;
1829 pCursor->cbLeft -= offSkip;
1830 return pCursor->rc;
1831}
1832
1833
1834/**
1835 * Advances the cursor a given number of bytes.
1836 *
1837 * @returns IPRT status code.
1838 * @param pCursor The cursor.
1839 * @param offSkip The number of bytes to advance.
1840 */
1841static int rtDwarfCursor_SkipBytes(PRTDWARFCURSOR pCursor, uint64_t offSkip)
1842{
1843 if (RT_FAILURE(pCursor->rc))
1844 return pCursor->rc;
1845 if (pCursor->cbUnitLeft < offSkip)
1846 return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1847
1848 size_t const offSkipSizeT = (size_t)offSkip;
1849 pCursor->cbUnitLeft -= offSkipSizeT;
1850 pCursor->cbLeft -= offSkipSizeT;
1851 pCursor->pb += offSkipSizeT;
1852
1853 return VINF_SUCCESS;
1854}
1855
1856
1857/**
1858 * Reads a zero terminated string, advancing the cursor beyond the terminator.
1859 *
1860 * @returns Pointer to the string.
1861 * @param pCursor The cursor.
1862 * @param pszErrValue What to return if the string isn't terminated
1863 * before the end of the unit.
1864 */
1865static const char *rtDwarfCursor_GetSZ(PRTDWARFCURSOR pCursor, const char *pszErrValue)
1866{
1867 const char *pszRet = (const char *)pCursor->pb;
1868 for (;;)
1869 {
1870 if (!pCursor->cbUnitLeft)
1871 {
1872 pCursor->rc = VERR_DWARF_BAD_STRING;
1873 return pszErrValue;
1874 }
1875 pCursor->cbUnitLeft--;
1876 pCursor->cbLeft--;
1877 if (!*pCursor->pb++)
1878 break;
1879 }
1880 return pszRet;
1881}
1882
1883
1884/**
1885 * Reads a 1, 2, 4 or 8 byte unsgined value.
1886 *
1887 * @returns 64-bit unsigned value.
1888 * @param pCursor The cursor.
1889 * @param cbValue The value size.
1890 * @param uErrValue The error value.
1891 */
1892static uint64_t rtDwarfCursor_GetVarSizedU(PRTDWARFCURSOR pCursor, size_t cbValue, uint64_t uErrValue)
1893{
1894 uint64_t u64Ret;
1895 switch (cbValue)
1896 {
1897 case 1: u64Ret = rtDwarfCursor_GetU8( pCursor, UINT8_MAX); break;
1898 case 2: u64Ret = rtDwarfCursor_GetU16(pCursor, UINT16_MAX); break;
1899 case 4: u64Ret = rtDwarfCursor_GetU32(pCursor, UINT32_MAX); break;
1900 case 8: u64Ret = rtDwarfCursor_GetU64(pCursor, UINT64_MAX); break;
1901 default:
1902 pCursor->rc = VERR_DWARF_BAD_INFO;
1903 return uErrValue;
1904 }
1905 if (RT_FAILURE(pCursor->rc))
1906 return uErrValue;
1907 return u64Ret;
1908}
1909
1910
1911#if 0 /* unused */
1912/**
1913 * Gets the pointer to a variable size block and advances the cursor.
1914 *
1915 * @returns Pointer to the block at the current cursor location. On error
1916 * RTDWARFCURSOR::rc is set and NULL returned.
1917 * @param pCursor The cursor.
1918 * @param cbBlock The block size.
1919 */
1920static const uint8_t *rtDwarfCursor_GetBlock(PRTDWARFCURSOR pCursor, uint32_t cbBlock)
1921{
1922 if (cbBlock > pCursor->cbUnitLeft)
1923 {
1924 pCursor->rc = VERR_DWARF_UNEXPECTED_END;
1925 return NULL;
1926 }
1927
1928 uint8_t const *pb = &pCursor->pb[0];
1929 pCursor->pb += cbBlock;
1930 pCursor->cbUnitLeft -= cbBlock;
1931 pCursor->cbLeft -= cbBlock;
1932 return pb;
1933}
1934#endif
1935
1936
1937/**
1938 * Reads an unsigned DWARF half number.
1939 *
1940 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1941 * uErrValue is returned.
1942 * @param pCursor The cursor.
1943 * @param uErrValue What to return on error.
1944 */
1945static uint16_t rtDwarfCursor_GetUHalf(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
1946{
1947 return rtDwarfCursor_GetU16(pCursor, uErrValue);
1948}
1949
1950
1951/**
1952 * Reads an unsigned DWARF byte number.
1953 *
1954 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1955 * uErrValue is returned.
1956 * @param pCursor The cursor.
1957 * @param uErrValue What to return on error.
1958 */
1959static uint8_t rtDwarfCursor_GetUByte(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
1960{
1961 return rtDwarfCursor_GetU8(pCursor, uErrValue);
1962}
1963
1964
1965/**
1966 * Reads a signed DWARF byte number.
1967 *
1968 * @returns The number. On error RTDWARFCURSOR::rc is set and @a
1969 * uErrValue is returned.
1970 * @param pCursor The cursor.
1971 * @param uErrValue What to return on error.
1972 */
1973static int8_t rtDwarfCursor_GetSByte(PRTDWARFCURSOR pCursor, int8_t iErrValue)
1974{
1975 return (int8_t)rtDwarfCursor_GetU8(pCursor, (uint8_t)iErrValue);
1976}
1977
1978
1979/**
1980 * Reads a unsigned DWARF offset value.
1981 *
1982 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1983 * uErrValue is returned.
1984 * @param pCursor The cursor.
1985 * @param uErrValue What to return on error.
1986 */
1987static uint64_t rtDwarfCursor_GetUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
1988{
1989 if (pCursor->f64bitDwarf)
1990 return rtDwarfCursor_GetU64(pCursor, uErrValue);
1991 return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
1992}
1993
1994
1995/**
1996 * Reads a unsigned DWARF native offset value.
1997 *
1998 * @returns The value. On error RTDWARFCURSOR::rc is set and @a
1999 * uErrValue is returned.
2000 * @param pCursor The cursor.
2001 * @param uErrValue What to return on error.
2002 */
2003static uint64_t rtDwarfCursor_GetNativeUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
2004{
2005 switch (pCursor->cbNativeAddr)
2006 {
2007 case 1: return rtDwarfCursor_GetU8(pCursor, (uint8_t )uErrValue);
2008 case 2: return rtDwarfCursor_GetU16(pCursor, (uint16_t)uErrValue);
2009 case 4: return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
2010 case 8: return rtDwarfCursor_GetU64(pCursor, uErrValue);
2011 default:
2012 pCursor->rc = VERR_INTERNAL_ERROR_2;
2013 return uErrValue;
2014 }
2015}
2016
2017
2018/**
2019 * Gets the unit length, updating the unit length member and DWARF bitness
2020 * members of the cursor.
2021 *
2022 * @returns The unit length.
2023 * @param pCursor The cursor.
2024 */
2025static uint64_t rtDwarfCursor_GetInitalLength(PRTDWARFCURSOR pCursor)
2026{
2027 /*
2028 * Read the initial length.
2029 */
2030 pCursor->cbUnitLeft = pCursor->cbLeft;
2031 uint64_t cbUnit = rtDwarfCursor_GetU32(pCursor, 0);
2032 if (cbUnit != UINT32_C(0xffffffff))
2033 pCursor->f64bitDwarf = false;
2034 else
2035 {
2036 pCursor->f64bitDwarf = true;
2037 cbUnit = rtDwarfCursor_GetU64(pCursor, 0);
2038 }
2039
2040
2041 /*
2042 * Set the unit length, quitely fixing bad lengths.
2043 */
2044 pCursor->cbUnitLeft = (size_t)cbUnit;
2045 if ( pCursor->cbUnitLeft > pCursor->cbLeft
2046 || pCursor->cbUnitLeft != cbUnit)
2047 pCursor->cbUnitLeft = pCursor->cbLeft;
2048
2049 return cbUnit;
2050}
2051
2052
2053/**
2054 * Calculates the section offset corresponding to the current cursor position.
2055 *
2056 * @returns 32-bit section offset. If out of range, RTDWARFCURSOR::rc will be
2057 * set and UINT32_MAX returned.
2058 * @param pCursor The cursor.
2059 */
2060static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor)
2061{
2062 size_t off = pCursor->pb - (uint8_t const *)pCursor->pDwarfMod->aSections[pCursor->enmSect].pv;
2063 uint32_t offRet = (uint32_t)off;
2064 if (offRet != off)
2065 {
2066 AssertFailed();
2067 pCursor->rc = VERR_OUT_OF_RANGE;
2068 offRet = UINT32_MAX;
2069 }
2070 return offRet;
2071}
2072
2073
2074/**
2075 * Calculates an absolute cursor position from one relative to the current
2076 * cursor position.
2077 *
2078 * @returns The absolute cursor position.
2079 * @param pCursor The cursor.
2080 * @param offRelative The relative position. Must be a positive
2081 * offset.
2082 */
2083static uint8_t const *rtDwarfCursor_CalcPos(PRTDWARFCURSOR pCursor, size_t offRelative)
2084{
2085 if (offRelative > pCursor->cbUnitLeft)
2086 {
2087 Log(("rtDwarfCursor_CalcPos: bad position %#zx, cbUnitLeft=%#zu\n", offRelative, pCursor->cbUnitLeft));
2088 pCursor->rc = VERR_DWARF_BAD_POS;
2089 return NULL;
2090 }
2091 return pCursor->pb + offRelative;
2092}
2093
2094
2095/**
2096 * Advances the cursor to the given position.
2097 *
2098 * @returns IPRT status code.
2099 * @param pCursor The cursor.
2100 * @param pbNewPos The new position - returned by
2101 * rtDwarfCursor_CalcPos().
2102 */
2103static int rtDwarfCursor_AdvanceToPos(PRTDWARFCURSOR pCursor, uint8_t const *pbNewPos)
2104{
2105 if (RT_FAILURE(pCursor->rc))
2106 return pCursor->rc;
2107 AssertPtr(pbNewPos);
2108 if ((uintptr_t)pbNewPos < (uintptr_t)pCursor->pb)
2109 {
2110 Log(("rtDwarfCursor_AdvanceToPos: bad position %p, current %p\n", pbNewPos, pCursor->pb));
2111 return pCursor->rc = VERR_DWARF_BAD_POS;
2112 }
2113
2114 uintptr_t cbAdj = (uintptr_t)pbNewPos - (uintptr_t)pCursor->pb;
2115 if (RT_UNLIKELY(cbAdj > pCursor->cbUnitLeft))
2116 {
2117 AssertFailed();
2118 pCursor->rc = VERR_DWARF_BAD_POS;
2119 cbAdj = pCursor->cbUnitLeft;
2120 }
2121
2122 pCursor->cbUnitLeft -= cbAdj;
2123 pCursor->cbLeft -= cbAdj;
2124 pCursor->pb += cbAdj;
2125 return pCursor->rc;
2126}
2127
2128
2129/**
2130 * Check if the cursor is at the end of the current DWARF unit.
2131 *
2132 * @retval @c true if at the end or a cursor error is pending.
2133 * @retval @c false if not.
2134 * @param pCursor The cursor.
2135 */
2136static bool rtDwarfCursor_IsAtEndOfUnit(PRTDWARFCURSOR pCursor)
2137{
2138 return !pCursor->cbUnitLeft || RT_FAILURE(pCursor->rc);
2139}
2140
2141
2142/**
2143 * Skips to the end of the current unit.
2144 *
2145 * @returns IPRT status code.
2146 * @param pCursor The cursor.
2147 */
2148static int rtDwarfCursor_SkipUnit(PRTDWARFCURSOR pCursor)
2149{
2150 pCursor->pb += pCursor->cbUnitLeft;
2151 pCursor->cbLeft -= pCursor->cbUnitLeft;
2152 pCursor->cbUnitLeft = 0;
2153 return pCursor->rc;
2154}
2155
2156
2157/**
2158 * Check if the cursor is at the end of the section (or whatever the cursor is
2159 * processing).
2160 *
2161 * @retval @c true if at the end or a cursor error is pending.
2162 * @retval @c false if not.
2163 * @param pCursor The cursor.
2164 */
2165static bool rtDwarfCursor_IsAtEnd(PRTDWARFCURSOR pCursor)
2166{
2167 return !pCursor->cbLeft || RT_FAILURE(pCursor->rc);
2168}
2169
2170
2171/**
2172 * Initialize a section reader cursor.
2173 *
2174 * @returns IPRT status code.
2175 * @param pCursor The cursor.
2176 * @param pThis The dwarf module.
2177 * @param enmSect The name of the section to read.
2178 */
2179static int rtDwarfCursor_Init(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
2180{
2181 int rc = rtDbgModDwarfLoadSection(pThis, enmSect);
2182 if (RT_FAILURE(rc))
2183 return rc;
2184
2185 pCursor->enmSect = enmSect;
2186 pCursor->pbStart = (uint8_t const *)pThis->aSections[enmSect].pv;
2187 pCursor->pb = pCursor->pbStart;
2188 pCursor->cbLeft = pThis->aSections[enmSect].cb;
2189 pCursor->cbUnitLeft = pCursor->cbLeft;
2190 pCursor->pDwarfMod = pThis;
2191 pCursor->f64bitDwarf = false;
2192 /** @todo ask the image about the endian used as well as the address
2193 * width. */
2194 pCursor->fNativEndian = true;
2195 pCursor->cbNativeAddr = 4;
2196 pCursor->rc = VINF_SUCCESS;
2197
2198 return VINF_SUCCESS;
2199}
2200
2201
2202/**
2203 * Initialize a section reader cursor with an offset.
2204 *
2205 * @returns IPRT status code.
2206 * @param pCursor The cursor.
2207 * @param pThis The dwarf module.
2208 * @param enmSect The name of the section to read.
2209 * @param offSect The offset into the section.
2210 */
2211static int rtDwarfCursor_InitWithOffset(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis,
2212 krtDbgModDwarfSect enmSect, uint32_t offSect)
2213{
2214 if (offSect > pThis->aSections[enmSect].cb)
2215 {
2216 Log(("rtDwarfCursor_InitWithOffset: offSect=%#x cb=%#x enmSect=%d\n", offSect, pThis->aSections[enmSect].cb, enmSect));
2217 return VERR_DWARF_BAD_POS;
2218 }
2219
2220 int rc = rtDwarfCursor_Init(pCursor, pThis, enmSect);
2221 if (RT_SUCCESS(rc))
2222 {
2223 pCursor->pbStart += offSect;
2224 pCursor->pb += offSect;
2225 pCursor->cbLeft -= offSect;
2226 pCursor->cbUnitLeft -= offSect;
2227 }
2228
2229 return rc;
2230}
2231
2232
2233/**
2234 * Initialize a cursor for a block (subsection) retrieved from the given cursor.
2235 *
2236 * The parent cursor will be advanced past the block.
2237 *
2238 * @returns IPRT status code.
2239 * @param pCursor The cursor.
2240 * @param pParent The parent cursor. Will be moved by @a cbBlock.
2241 * @param cbBlock The size of the block the new cursor should
2242 * cover.
2243 */
2244static int rtDwarfCursor_InitForBlock(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pParent, uint32_t cbBlock)
2245{
2246 if (RT_FAILURE(pParent->rc))
2247 return pParent->rc;
2248 if (pParent->cbUnitLeft < cbBlock)
2249 {
2250 Log(("rtDwarfCursor_InitForBlock: cbUnitLeft=%#x < cbBlock=%#x \n", pParent->cbUnitLeft, cbBlock));
2251 return VERR_DWARF_BAD_POS;
2252 }
2253
2254 *pCursor = *pParent;
2255 pCursor->cbLeft = cbBlock;
2256 pCursor->cbUnitLeft = cbBlock;
2257
2258 pParent->pb += cbBlock;
2259 pParent->cbLeft -= cbBlock;
2260 pParent->cbUnitLeft -= cbBlock;
2261
2262 return VINF_SUCCESS;
2263}
2264
2265
2266/**
2267 * Deletes a section reader initialized by rtDwarfCursor_Init.
2268 *
2269 * @returns @a rcOther or RTDWARCURSOR::rc.
2270 * @param pCursor The section reader.
2271 * @param rcOther Other error code to be returned if it indicates
2272 * error or if the cursor status is OK.
2273 */
2274static int rtDwarfCursor_Delete(PRTDWARFCURSOR pCursor, int rcOther)
2275{
2276 /* ... and a drop of poison. */
2277 pCursor->pb = NULL;
2278 pCursor->cbLeft = ~(size_t)0;
2279 pCursor->cbUnitLeft = ~(size_t)0;
2280 pCursor->pDwarfMod = NULL;
2281 if (RT_FAILURE(pCursor->rc) && RT_SUCCESS(rcOther))
2282 rcOther = pCursor->rc;
2283 pCursor->rc = VERR_INTERNAL_ERROR_4;
2284 return rcOther;
2285}
2286
2287
2288/*
2289 *
2290 * DWARF Line Numbers.
2291 * DWARF Line Numbers.
2292 * DWARF Line Numbers.
2293 *
2294 */
2295
2296
2297/**
2298 * Defines a file name.
2299 *
2300 * @returns IPRT status code.
2301 * @param pLnState The line number program state.
2302 * @param pszFilename The name of the file.
2303 * @param idxInc The include path index.
2304 */
2305static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc)
2306{
2307 /*
2308 * Resize the array if necessary.
2309 */
2310 uint32_t iFileName = pLnState->cFileNames;
2311 if ((iFileName % 2) == 0)
2312 {
2313 void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2));
2314 if (!pv)
2315 return VERR_NO_MEMORY;
2316 pLnState->papszFileNames = (char **)pv;
2317 }
2318
2319 /*
2320 * Add the file name.
2321 */
2322 if ( pszFilename[0] == '/'
2323 || pszFilename[0] == '\\'
2324 || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') )
2325 pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename);
2326 else if (idxInc < pLnState->cIncPaths)
2327 pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename);
2328 else
2329 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
2330 if (!pLnState->papszFileNames[iFileName])
2331 return VERR_NO_STR_MEMORY;
2332 pLnState->cFileNames = iFileName + 1;
2333
2334 /*
2335 * Sanitize the name.
2336 */
2337 int rc = rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]);
2338 Log((" File #%02u = '%s'\n", iFileName, pLnState->papszFileNames[iFileName]));
2339 return rc;
2340}
2341
2342
2343/**
2344 * Adds a line to the table and resets parts of the state (DW_LNS_copy).
2345 *
2346 * @returns IPRT status code
2347 * @param pLnState The line number program state.
2348 * @param offOpCode The opcode offset (for logging
2349 * purposes).
2350 */
2351static int rtDwarfLine_AddLine(PRTDWARFLINESTATE pLnState, uint32_t offOpCode)
2352{
2353 PRTDBGMODDWARF pThis = pLnState->pDwarfMod;
2354 int rc;
2355 if (pThis->iWatcomPass == 1)
2356 rc = rtDbgModDwarfRecordSegOffset(pThis, pLnState->Regs.uSegment, pLnState->Regs.uAddress + 1);
2357 else
2358 {
2359 const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames
2360 ? pLnState->papszFileNames[pLnState->Regs.iFile]
2361 : "<bad file name index>";
2362 NOREF(offOpCode);
2363
2364 RTDBGSEGIDX iSeg;
2365 RTUINTPTR offSeg;
2366 rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uSegment, pLnState->Regs.uAddress,
2367 &iSeg, &offSeg); /*AssertRC(rc);*/
2368 if (RT_SUCCESS(rc))
2369 {
2370 Log2(("rtDwarfLine_AddLine: %x:%08llx (%#llx) %s(%d) [offOpCode=%08x]\n", iSeg, offSeg, pLnState->Regs.uAddress, pszFile, pLnState->Regs.uLine, offOpCode));
2371 rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL);
2372
2373 /* Ignore address conflicts for now. */
2374 if (rc == VERR_DBG_ADDRESS_CONFLICT)
2375 rc = VINF_SUCCESS;
2376 }
2377 else
2378 rc = VINF_SUCCESS; /* ignore failure */
2379 }
2380
2381 pLnState->Regs.fBasicBlock = false;
2382 pLnState->Regs.fPrologueEnd = false;
2383 pLnState->Regs.fEpilogueBegin = false;
2384 pLnState->Regs.uDiscriminator = 0;
2385 return rc;
2386}
2387
2388
2389/**
2390 * Reset the program to the start-of-sequence state.
2391 *
2392 * @param pLnState The line number program state.
2393 */
2394static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState)
2395{
2396 pLnState->Regs.uAddress = 0;
2397 pLnState->Regs.idxOp = 0;
2398 pLnState->Regs.iFile = 1;
2399 pLnState->Regs.uLine = 1;
2400 pLnState->Regs.uColumn = 0;
2401 pLnState->Regs.fIsStatement = RT_BOOL(pLnState->Hdr.u8DefIsStmt);
2402 pLnState->Regs.fBasicBlock = false;
2403 pLnState->Regs.fEndSequence = false;
2404 pLnState->Regs.fPrologueEnd = false;
2405 pLnState->Regs.fEpilogueBegin = false;
2406 pLnState->Regs.uIsa = 0;
2407 pLnState->Regs.uDiscriminator = 0;
2408 pLnState->Regs.uSegment = 0;
2409}
2410
2411
2412/**
2413 * Runs the line number program.
2414 *
2415 * @returns IPRT status code.
2416 * @param pLnState The line number program state.
2417 * @param pCursor The cursor.
2418 */
2419static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
2420{
2421 LogFlow(("rtDwarfLine_RunProgram: cbUnitLeft=%zu\n", pCursor->cbUnitLeft));
2422
2423 int rc = VINF_SUCCESS;
2424 rtDwarfLine_ResetState(pLnState);
2425
2426 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
2427 {
2428#ifdef LOG_ENABLED
2429 uint32_t const offOpCode = rtDwarfCursor_CalcSectOffsetU32(pCursor);
2430#else
2431 uint32_t const offOpCode = 0;
2432#endif
2433 uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, DW_LNS_extended);
2434 if (bOpCode >= pLnState->Hdr.u8OpcodeBase)
2435 {
2436 /*
2437 * Special opcode.
2438 */
2439 uint8_t const bLogOpCode = bOpCode; NOREF(bLogOpCode);
2440 bOpCode -= pLnState->Hdr.u8OpcodeBase;
2441
2442 int32_t const cLineDelta = bOpCode % pLnState->Hdr.u8LineRange + (int32_t)pLnState->Hdr.s8LineBase;
2443 bOpCode /= pLnState->Hdr.u8LineRange;
2444
2445 uint64_t uTmp = bOpCode + pLnState->Regs.idxOp;
2446 uint64_t const cAddressDelta = uTmp / pLnState->Hdr.cMaxOpsPerInstr * pLnState->Hdr.cbMinInstr;
2447 uint64_t const cOpIndexDelta = uTmp % pLnState->Hdr.cMaxOpsPerInstr;
2448
2449 pLnState->Regs.uLine += cLineDelta;
2450 pLnState->Regs.uAddress += cAddressDelta;
2451 pLnState->Regs.idxOp += cOpIndexDelta;
2452 Log2(("%08x: DW Special Opcode %#04x: uLine + %d => %u; uAddress + %#llx => %#llx; idxOp + %#llx => %#llx\n",
2453 offOpCode, bLogOpCode, cLineDelta, pLnState->Regs.uLine, cAddressDelta, pLnState->Regs.uAddress,
2454 cOpIndexDelta, pLnState->Regs.idxOp));
2455
2456 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
2457 }
2458 else
2459 {
2460 switch (bOpCode)
2461 {
2462 /*
2463 * Standard opcode.
2464 */
2465 case DW_LNS_copy:
2466 Log2(("%08x: DW_LNS_copy\n", offOpCode));
2467 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
2468 break;
2469
2470 case DW_LNS_advance_pc:
2471 {
2472 uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0);
2473 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->Hdr.cMaxOpsPerInstr
2474 * pLnState->Hdr.cbMinInstr;
2475 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + u64Adv) % pLnState->Hdr.cMaxOpsPerInstr;
2476 Log2(("%08x: DW_LNS_advance_pc: u64Adv=%#llx (%lld) )\n", offOpCode, u64Adv, u64Adv));
2477 break;
2478 }
2479
2480 case DW_LNS_advance_line:
2481 {
2482 int32_t cLineDelta = rtDwarfCursor_GetSLeb128AsS32(pCursor, 0);
2483 pLnState->Regs.uLine += cLineDelta;
2484 Log2(("%08x: DW_LNS_advance_line: uLine + %d => %u\n", offOpCode, cLineDelta, pLnState->Regs.uLine));
2485 break;
2486 }
2487
2488 case DW_LNS_set_file:
2489 pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
2490 Log2(("%08x: DW_LNS_set_file: iFile=%u\n", offOpCode, pLnState->Regs.iFile));
2491 break;
2492
2493 case DW_LNS_set_column:
2494 pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
2495 Log2(("%08x: DW_LNS_set_column\n", offOpCode));
2496 break;
2497
2498 case DW_LNS_negate_stmt:
2499 pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement;
2500 Log2(("%08x: DW_LNS_negate_stmt\n", offOpCode));
2501 break;
2502
2503 case DW_LNS_set_basic_block:
2504 pLnState->Regs.fBasicBlock = true;
2505 Log2(("%08x: DW_LNS_set_basic_block\n", offOpCode));
2506 break;
2507
2508 case DW_LNS_const_add_pc:
2509 pLnState->Regs.uAddress += (pLnState->Regs.idxOp + 255) / pLnState->Hdr.cMaxOpsPerInstr
2510 * pLnState->Hdr.cbMinInstr;
2511 pLnState->Regs.idxOp += (pLnState->Regs.idxOp + 255) % pLnState->Hdr.cMaxOpsPerInstr;
2512 Log2(("%08x: DW_LNS_const_add_pc\n", offOpCode));
2513 break;
2514
2515 case DW_LNS_fixed_advance_pc:
2516 pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0);
2517 pLnState->Regs.idxOp = 0;
2518 Log2(("%08x: DW_LNS_fixed_advance_pc\n", offOpCode));
2519 break;
2520
2521 case DW_LNS_set_prologue_end:
2522 pLnState->Regs.fPrologueEnd = true;
2523 Log2(("%08x: DW_LNS_set_prologue_end\n", offOpCode));
2524 break;
2525
2526 case DW_LNS_set_epilogue_begin:
2527 pLnState->Regs.fEpilogueBegin = true;
2528 Log2(("%08x: DW_LNS_set_epilogue_begin\n", offOpCode));
2529 break;
2530
2531 case DW_LNS_set_isa:
2532 pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
2533 Log2(("%08x: DW_LNS_set_isa %#x\n", offOpCode, pLnState->Regs.uIsa));
2534 break;
2535
2536 default:
2537 {
2538 unsigned cOpsToSkip = pLnState->Hdr.pacStdOperands[bOpCode - 1];
2539 Log(("rtDwarfLine_RunProgram: Unknown standard opcode %#x, %#x operands, at %08x.\n", bOpCode, cOpsToSkip, offOpCode));
2540 while (cOpsToSkip-- > 0)
2541 rc = rtDwarfCursor_SkipLeb128(pCursor);
2542 break;
2543 }
2544
2545 /*
2546 * Extended opcode.
2547 */
2548 case DW_LNS_extended:
2549 {
2550 /* The instruction has a length prefix. */
2551 uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
2552 if (RT_FAILURE(pCursor->rc))
2553 return pCursor->rc;
2554 if (cbInstr > pCursor->cbUnitLeft)
2555 return VERR_DWARF_BAD_LNE;
2556 uint8_t const * const pbEndOfInstr = rtDwarfCursor_CalcPos(pCursor, cbInstr);
2557
2558 /* Get the opcode and deal with it if we know it. */
2559 bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
2560 switch (bOpCode)
2561 {
2562 case DW_LNE_end_sequence:
2563#if 0 /* No need for this, I think. */
2564 pLnState->Regs.fEndSequence = true;
2565 rc = rtDwarfLine_AddLine(pLnState, offOpCode);
2566#endif
2567 rtDwarfLine_ResetState(pLnState);
2568 Log2(("%08x: DW_LNE_end_sequence\n", offOpCode));
2569 break;
2570
2571 case DW_LNE_set_address:
2572 pLnState->Regs.uAddress = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
2573 pLnState->Regs.idxOp = 0;
2574 Log2(("%08x: DW_LNE_set_address: %#llx\n", offOpCode, pLnState->Regs.uAddress));
2575 break;
2576
2577 case DW_LNE_define_file:
2578 {
2579 const char *pszFilename = rtDwarfCursor_GetSZ(pCursor, NULL);
2580 uint32_t idxInc = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
2581 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
2582 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
2583 Log2(("%08x: DW_LNE_define_file: {%d}/%s\n", offOpCode, idxInc, pszFilename));
2584
2585 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
2586 if (RT_SUCCESS(rc))
2587 rc = rtDwarfLine_DefineFileName(pLnState, pszFilename, idxInc);
2588 break;
2589 }
2590
2591 /*
2592 * Note! Was defined in DWARF 4. But... Watcom used it
2593 * for setting the segment in DWARF 2, creating
2594 * an incompatibility with the newer standard.
2595 */
2596 case DW_LNE_set_descriminator:
2597 if (pLnState->Hdr.uVer != 2)
2598 {
2599 Assert(pLnState->Hdr.uVer >= 4);
2600 pLnState->Regs.uDiscriminator = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
2601 Log2(("%08x: DW_LNE_set_descriminator: %u\n", offOpCode, pLnState->Regs.uDiscriminator));
2602 }
2603 else
2604 {
2605 uint64_t uSeg = rtDwarfCursor_GetVarSizedU(pCursor, cbInstr - 1, UINT64_MAX);
2606 Log2(("%08x: DW_LNE_set_segment: %#llx, cbInstr=%#x - Watcom Extension\n", offOpCode, uSeg, cbInstr));
2607 pLnState->Regs.uSegment = (RTSEL)uSeg;
2608 AssertStmt(pLnState->Regs.uSegment == uSeg, rc = VERR_DWARF_BAD_INFO);
2609 }
2610 break;
2611
2612 default:
2613 Log(("rtDwarfLine_RunProgram: Unknown extended opcode %#x, length %#x at %08x\n", bOpCode, cbInstr, offOpCode));
2614 break;
2615 }
2616
2617 /* Advance the cursor to the end of the instruction . */
2618 rtDwarfCursor_AdvanceToPos(pCursor, pbEndOfInstr);
2619 break;
2620 }
2621 }
2622 }
2623
2624 /*
2625 * Check the status before looping.
2626 */
2627 if (RT_FAILURE(rc))
2628 return rc;
2629 if (RT_FAILURE(pCursor->rc))
2630 return pCursor->rc;
2631 }
2632 return rc;
2633}
2634
2635
2636/**
2637 * Reads the include directories for a line number unit.
2638 *
2639 * @returns IPRT status code
2640 * @param pLnState The line number program state.
2641 * @param pCursor The cursor.
2642 */
2643static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
2644{
2645 int rc = rtDwarfLine_DefineFileName(pLnState, "/<bad-zero-file-name-entry>", 0);
2646 if (RT_FAILURE(rc))
2647 return rc;
2648
2649 for (;;)
2650 {
2651 const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL);
2652 if (!*psz)
2653 break;
2654
2655 uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
2656 rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
2657 rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
2658
2659 rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc);
2660 if (RT_FAILURE(rc))
2661 return rc;
2662 }
2663 return pCursor->rc;
2664}
2665
2666
2667/**
2668 * Reads the include directories for a line number unit.
2669 *
2670 * @returns IPRT status code
2671 * @param pLnState The line number program state.
2672 * @param pCursor The cursor.
2673 */
2674static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
2675{
2676 const char *psz = ""; /* The zeroth is the unit dir. */
2677 for (;;)
2678 {
2679 if ((pLnState->cIncPaths % 2) == 0)
2680 {
2681 void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2));
2682 if (!pv)
2683 return VERR_NO_MEMORY;
2684 pLnState->papszIncPaths = (const char **)pv;
2685 }
2686 Log((" Path #%02u = '%s'\n", pLnState->cIncPaths, psz));
2687 pLnState->papszIncPaths[pLnState->cIncPaths] = psz;
2688 pLnState->cIncPaths++;
2689
2690 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
2691 if (!*psz)
2692 break;
2693 }
2694
2695 return pCursor->rc;
2696}
2697
2698
2699/**
2700 * Explodes the line number table for a compilation unit.
2701 *
2702 * @returns IPRT status code
2703 * @param pThis The DWARF instance.
2704 * @param pCursor The cursor to read the line number information
2705 * via.
2706 */
2707static int rtDwarfLine_ExplodeUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
2708{
2709 RTDWARFLINESTATE LnState;
2710 RT_ZERO(LnState);
2711 LnState.pDwarfMod = pThis;
2712
2713 /*
2714 * Parse the header.
2715 */
2716 rtDwarfCursor_GetInitalLength(pCursor);
2717 LnState.Hdr.uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
2718 if ( LnState.Hdr.uVer < 2
2719 || LnState.Hdr.uVer > 4)
2720 return rtDwarfCursor_SkipUnit(pCursor);
2721
2722 LnState.Hdr.offFirstOpcode = rtDwarfCursor_GetUOff(pCursor, 0);
2723 uint8_t const * const pbFirstOpcode = rtDwarfCursor_CalcPos(pCursor, LnState.Hdr.offFirstOpcode);
2724
2725 LnState.Hdr.cbMinInstr = rtDwarfCursor_GetUByte(pCursor, 0);
2726 if (LnState.Hdr.uVer >= 4)
2727 LnState.Hdr.cMaxOpsPerInstr = rtDwarfCursor_GetUByte(pCursor, 0);
2728 else
2729 LnState.Hdr.cMaxOpsPerInstr = 1;
2730 LnState.Hdr.u8DefIsStmt = rtDwarfCursor_GetUByte(pCursor, 0);
2731 LnState.Hdr.s8LineBase = rtDwarfCursor_GetSByte(pCursor, 0);
2732 LnState.Hdr.u8LineRange = rtDwarfCursor_GetUByte(pCursor, 0);
2733 LnState.Hdr.u8OpcodeBase = rtDwarfCursor_GetUByte(pCursor, 0);
2734
2735 if ( !LnState.Hdr.u8OpcodeBase
2736 || !LnState.Hdr.cMaxOpsPerInstr
2737 || !LnState.Hdr.u8LineRange
2738 || LnState.Hdr.u8DefIsStmt > 1)
2739 return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
2740 Log2(("DWARF Line number header:\n"
2741 " uVer %d\n"
2742 " offFirstOpcode %#llx\n"
2743 " cbMinInstr %u\n"
2744 " cMaxOpsPerInstr %u\n"
2745 " u8DefIsStmt %u\n"
2746 " s8LineBase %d\n"
2747 " u8LineRange %u\n"
2748 " u8OpcodeBase %u\n",
2749 LnState.Hdr.uVer, LnState.Hdr.offFirstOpcode, LnState.Hdr.cbMinInstr, LnState.Hdr.cMaxOpsPerInstr,
2750 LnState.Hdr.u8DefIsStmt, LnState.Hdr.s8LineBase, LnState.Hdr.u8LineRange, LnState.Hdr.u8OpcodeBase));
2751
2752 LnState.Hdr.pacStdOperands = pCursor->pb;
2753 for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.Hdr.u8OpcodeBase; iStdOpcode++)
2754 rtDwarfCursor_GetUByte(pCursor, 0);
2755
2756 int rc = pCursor->rc;
2757 if (RT_SUCCESS(rc))
2758 rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor);
2759 if (RT_SUCCESS(rc))
2760 rc = rtDwarfLine_ReadFileNames(&LnState, pCursor);
2761
2762 /*
2763 * Run the program....
2764 */
2765 if (RT_SUCCESS(rc))
2766 rc = rtDwarfCursor_AdvanceToPos(pCursor, pbFirstOpcode);
2767 if (RT_SUCCESS(rc))
2768 rc = rtDwarfLine_RunProgram(&LnState, pCursor);
2769
2770 /*
2771 * Clean up.
2772 */
2773 size_t i = LnState.cFileNames;
2774 while (i-- > 0)
2775 RTStrFree(LnState.papszFileNames[i]);
2776 RTMemFree(LnState.papszFileNames);
2777 RTMemFree(LnState.papszIncPaths);
2778
2779 Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc));
2780 return rc;
2781}
2782
2783
2784/**
2785 * Explodes the line number table.
2786 *
2787 * The line numbers are insered into the debug info container.
2788 *
2789 * @returns IPRT status code
2790 * @param pThis The DWARF instance.
2791 */
2792static int rtDwarfLine_ExplodeAll(PRTDBGMODDWARF pThis)
2793{
2794 if (!pThis->aSections[krtDbgModDwarfSect_line].fPresent)
2795 return VINF_SUCCESS;
2796
2797 RTDWARFCURSOR Cursor;
2798 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line);
2799 if (RT_FAILURE(rc))
2800 return rc;
2801
2802 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
2803 && RT_SUCCESS(rc))
2804 rc = rtDwarfLine_ExplodeUnit(pThis, &Cursor);
2805
2806 return rtDwarfCursor_Delete(&Cursor, rc);
2807}
2808
2809
2810/*
2811 *
2812 * DWARF Abbreviations.
2813 * DWARF Abbreviations.
2814 * DWARF Abbreviations.
2815 *
2816 */
2817
2818/**
2819 * Deals with a cache miss in rtDwarfAbbrev_Lookup.
2820 *
2821 * @returns Pointer to abbreviation cache entry (read only). May be rendered
2822 * invalid by subsequent calls to this function.
2823 * @param pThis The DWARF instance.
2824 * @param uCode The abbreviation code to lookup.
2825 */
2826static PCRTDWARFABBREV rtDwarfAbbrev_LookupMiss(PRTDBGMODDWARF pThis, uint32_t uCode)
2827{
2828 /*
2829 * There is no entry with code zero.
2830 */
2831 if (!uCode)
2832 return NULL;
2833
2834 /*
2835 * Resize the cache array if the code is considered cachable.
2836 */
2837 bool fFillCache = true;
2838 if (pThis->cCachedAbbrevsAlloced < uCode)
2839 {
2840 if (uCode > _64K)
2841 fFillCache = false;
2842 else
2843 {
2844 uint32_t cNew = RT_ALIGN(uCode, 64);
2845 void *pv = RTMemRealloc(pThis->paCachedAbbrevs, sizeof(pThis->paCachedAbbrevs[0]) * cNew);
2846 if (!pv)
2847 fFillCache = false;
2848 else
2849 {
2850 pThis->cCachedAbbrevsAlloced = cNew;
2851 pThis->paCachedAbbrevs = (PRTDWARFABBREV)pv;
2852 }
2853 }
2854 }
2855
2856 /*
2857 * Walk the abbreviations till we find the desired code.
2858 */
2859 RTDWARFCURSOR Cursor;
2860 int rc = rtDwarfCursor_InitWithOffset(&Cursor, pThis, krtDbgModDwarfSect_abbrev, pThis->offCachedAbbrev);
2861 if (RT_FAILURE(rc))
2862 return NULL;
2863
2864 PRTDWARFABBREV pRet = NULL;
2865 if (fFillCache)
2866 {
2867 /*
2868 * Search for the entry and fill the cache while doing so.
2869 */
2870 for (;;)
2871 {
2872 /* Read the 'header'. Skipping zero code bytes. */
2873 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2874 if (uCurCode != 0)
2875 {
2876 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2877 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
2878 if (RT_FAILURE(Cursor.rc))
2879 break;
2880 if ( uCurTag > 0xffff
2881 || uChildren > 1)
2882 {
2883 Cursor.rc = VERR_DWARF_BAD_ABBREV;
2884 break;
2885 }
2886
2887 /* Cache it? */
2888 if (uCurCode <= pThis->cCachedAbbrevsAlloced)
2889 {
2890 PRTDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
2891 while (pThis->cCachedAbbrevs < uCurCode)
2892 {
2893 pThis->paCachedAbbrevs[pThis->cCachedAbbrevs].fFilled = false;
2894 pThis->cCachedAbbrevs++;
2895 }
2896
2897 pEntry->fFilled = true;
2898 pEntry->fChildren = RT_BOOL(uChildren);
2899 pEntry->uTag = uCurTag;
2900 pEntry->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
2901
2902 if (uCurCode == uCode)
2903 {
2904 pRet = pEntry;
2905 if (uCurCode == pThis->cCachedAbbrevsAlloced)
2906 break;
2907 }
2908 }
2909
2910 /* Skip the specification. */
2911 uint32_t uAttr, uForm;
2912 do
2913 {
2914 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2915 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2916 } while (uAttr != 0);
2917 }
2918 if (RT_FAILURE(Cursor.rc))
2919 break;
2920
2921 /* Done? (Maximize cache filling.) */
2922 if ( pRet != NULL
2923 && uCurCode >= pThis->cCachedAbbrevsAlloced)
2924 break;
2925 }
2926 }
2927 else
2928 {
2929 /*
2930 * Search for the entry with the desired code, no cache filling.
2931 */
2932 for (;;)
2933 {
2934 /* Read the 'header'. */
2935 uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2936 uint32_t const uCurTag = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2937 uint8_t const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
2938 if (RT_FAILURE(Cursor.rc))
2939 break;
2940 if ( uCurTag > 0xffff
2941 || uChildren > 1)
2942 {
2943 Cursor.rc = VERR_DWARF_BAD_ABBREV;
2944 break;
2945 }
2946
2947 /* Do we have a match? */
2948 if (uCurCode == uCode)
2949 {
2950 pRet = &pThis->LookupAbbrev;
2951 pRet->fFilled = true;
2952 pRet->fChildren = RT_BOOL(uChildren);
2953 pRet->uTag = uCurTag;
2954 pRet->offSpec = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
2955 break;
2956 }
2957
2958 /* Skip the specification. */
2959 uint32_t uAttr, uForm;
2960 do
2961 {
2962 uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2963 uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
2964 } while (uAttr != 0);
2965 if (RT_FAILURE(Cursor.rc))
2966 break;
2967 }
2968 }
2969
2970 rtDwarfCursor_Delete(&Cursor, VINF_SUCCESS);
2971 return pRet;
2972}
2973
2974
2975/**
2976 * Looks up an abbreviation.
2977 *
2978 * @returns Pointer to abbreviation cache entry (read only). May be rendered
2979 * invalid by subsequent calls to this function.
2980 * @param pThis The DWARF instance.
2981 * @param uCode The abbreviation code to lookup.
2982 */
2983static PCRTDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
2984{
2985 if ( uCode - 1 >= pThis->cCachedAbbrevs
2986 || !pThis->paCachedAbbrevs[uCode - 1].fFilled)
2987 return rtDwarfAbbrev_LookupMiss(pThis, uCode);
2988 return &pThis->paCachedAbbrevs[uCode - 1];
2989}
2990
2991
2992/**
2993 * Sets the abbreviation offset of the current unit.
2994 *
2995 * This will flush the cached abbreviation entries if the offset differs from
2996 * the previous unit.
2997 *
2998 * @param pThis The DWARF instance.
2999 * @param offAbbrev The offset into the abbreviation section.
3000 */
3001static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
3002{
3003 if (pThis->offCachedAbbrev != offAbbrev)
3004 {
3005 pThis->offCachedAbbrev = offAbbrev;
3006 pThis->cCachedAbbrevs = 0;
3007 }
3008}
3009
3010
3011
3012/*
3013 *
3014 * DIE Attribute Parsers.
3015 * DIE Attribute Parsers.
3016 * DIE Attribute Parsers.
3017 *
3018 */
3019
3020/**
3021 * Gets the compilation unit a DIE belongs to.
3022 *
3023 * @returns The compilation unit DIE.
3024 * @param pDie Some DIE in the unit.
3025 */
3026static PRTDWARFDIECOMPILEUNIT rtDwarfDie_GetCompileUnit(PRTDWARFDIE pDie)
3027{
3028 while (pDie->pParent)
3029 pDie = pDie->pParent;
3030 AssertReturn( pDie->uTag == DW_TAG_compile_unit
3031 || pDie->uTag == DW_TAG_partial_unit,
3032 NULL);
3033 return (PRTDWARFDIECOMPILEUNIT)pDie;
3034}
3035
3036
3037/**
3038 * Resolves a string section (debug_str) reference.
3039 *
3040 * @returns Pointer to the string (inside the string section).
3041 * @param pThis The DWARF instance.
3042 * @param pCursor The cursor.
3043 * @param pszErrValue What to return on failure (@a
3044 * pCursor->rc is set).
3045 */
3046static const char *rtDwarfDecodeHlp_GetStrp(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, const char *pszErrValue)
3047{
3048 uint64_t offDebugStr = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
3049 if (RT_FAILURE(pCursor->rc))
3050 return pszErrValue;
3051
3052 if (offDebugStr >= pThis->aSections[krtDbgModDwarfSect_str].cb)
3053 {
3054 /* Ugly: Exploit the cursor status field for reporting errors. */
3055 pCursor->rc = VERR_DWARF_BAD_INFO;
3056 return pszErrValue;
3057 }
3058
3059 if (!pThis->aSections[krtDbgModDwarfSect_str].pv)
3060 {
3061 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_str);
3062 if (RT_FAILURE(rc))
3063 {
3064 /* Ugly: Exploit the cursor status field for reporting errors. */
3065 pCursor->rc = rc;
3066 return pszErrValue;
3067 }
3068 }
3069
3070 return (const char *)pThis->aSections[krtDbgModDwarfSect_str].pv + (size_t)offDebugStr;
3071}
3072
3073
3074/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3075static DECLCALLBACK(int) rtDwarfDecode_Address(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3076 uint32_t uForm, PRTDWARFCURSOR pCursor)
3077{
3078 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDR), VERR_INTERNAL_ERROR_3);
3079 NOREF(pDie);
3080
3081 uint64_t uAddr;
3082 switch (uForm)
3083 {
3084 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
3085 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
3086 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
3087 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
3088 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
3089 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
3090 default:
3091 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
3092 }
3093 if (RT_FAILURE(pCursor->rc))
3094 return pCursor->rc;
3095
3096 PRTDWARFADDR pAddr = (PRTDWARFADDR)pbMember;
3097 pAddr->uAddress = uAddr;
3098
3099 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
3100 return VINF_SUCCESS;
3101}
3102
3103
3104/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3105static DECLCALLBACK(int) rtDwarfDecode_Bool(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3106 uint32_t uForm, PRTDWARFCURSOR pCursor)
3107{
3108 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(bool), VERR_INTERNAL_ERROR_3);
3109 NOREF(pDie);
3110
3111 bool *pfMember = (bool *)pbMember;
3112 switch (uForm)
3113 {
3114 case DW_FORM_flag:
3115 {
3116 uint8_t b = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
3117 if (b > 1)
3118 {
3119 Log(("Unexpected boolean value %#x\n", b));
3120 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pCursor->rc = VERR_DWARF_BAD_INFO;
3121 }
3122 *pfMember = RT_BOOL(b);
3123 break;
3124 }
3125
3126 case DW_FORM_flag_present:
3127 *pfMember = true;
3128 break;
3129
3130 default:
3131 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3132 }
3133
3134 Log4((" %-20s %RTbool [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), *pfMember, rtDwarfLog_FormName(uForm)));
3135 return VINF_SUCCESS;
3136}
3137
3138
3139/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3140static DECLCALLBACK(int) rtDwarfDecode_LowHighPc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3141 uint32_t uForm, PRTDWARFCURSOR pCursor)
3142{
3143 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
3144 AssertReturn(pDesc->uAttr == DW_AT_low_pc || pDesc->uAttr == DW_AT_high_pc, VERR_INTERNAL_ERROR_3);
3145 NOREF(pDie);
3146
3147 uint64_t uAddr;
3148 switch (uForm)
3149 {
3150 case DW_FORM_addr: uAddr = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
3151 case DW_FORM_data1: uAddr = rtDwarfCursor_GetU8(pCursor, 0); break;
3152 case DW_FORM_data2: uAddr = rtDwarfCursor_GetU16(pCursor, 0); break;
3153 case DW_FORM_data4: uAddr = rtDwarfCursor_GetU32(pCursor, 0); break;
3154 case DW_FORM_data8: uAddr = rtDwarfCursor_GetU64(pCursor, 0); break;
3155 case DW_FORM_udata: uAddr = rtDwarfCursor_GetULeb128(pCursor, 0); break;
3156 default:
3157 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3158 }
3159 if (RT_FAILURE(pCursor->rc))
3160 return pCursor->rc;
3161
3162 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
3163 if (pDesc->uAttr == DW_AT_low_pc)
3164 {
3165 if (pRange->fHaveLowAddress)
3166 {
3167 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_low_pc\n"));
3168 return pCursor->rc = VERR_DWARF_BAD_INFO;
3169 }
3170 pRange->fHaveLowAddress = true;
3171 pRange->uLowAddress = uAddr;
3172 }
3173 else
3174 {
3175 if (pRange->fHaveHighAddress)
3176 {
3177 Log(("rtDwarfDecode_LowHighPc: Duplicate DW_AT_high_pc\n"));
3178 return pCursor->rc = VERR_DWARF_BAD_INFO;
3179 }
3180 pRange->fHaveHighAddress = true;
3181 pRange->uHighAddress = uAddr;
3182 }
3183 pRange->cAttrs++;
3184
3185 Log4((" %-20s %#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), uAddr, rtDwarfLog_FormName(uForm)));
3186 return VINF_SUCCESS;
3187}
3188
3189
3190/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3191static DECLCALLBACK(int) rtDwarfDecode_Ranges(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3192 uint32_t uForm, PRTDWARFCURSOR pCursor)
3193{
3194 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFADDRRANGE), VERR_INTERNAL_ERROR_3);
3195 AssertReturn(pDesc->uAttr == DW_AT_ranges, VERR_INTERNAL_ERROR_3);
3196 NOREF(pDie);
3197
3198 /* Decode it. */
3199 uint64_t off;
3200 switch (uForm)
3201 {
3202 case DW_FORM_addr: off = rtDwarfCursor_GetNativeUOff(pCursor, 0); break;
3203 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
3204 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
3205 default:
3206 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3207 }
3208 if (RT_FAILURE(pCursor->rc))
3209 return pCursor->rc;
3210
3211 /* Validate the offset and load the ranges. */
3212 PRTDBGMODDWARF pThis = pCursor->pDwarfMod;
3213 if (off >= pThis->aSections[krtDbgModDwarfSect_ranges].cb)
3214 {
3215 Log(("rtDwarfDecode_Ranges: bad ranges off=%#llx\n", off));
3216 return pCursor->rc = VERR_DWARF_BAD_POS;
3217 }
3218
3219 if (!pThis->aSections[krtDbgModDwarfSect_ranges].pv)
3220 {
3221 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_ranges);
3222 if (RT_FAILURE(rc))
3223 return pCursor->rc = rc;
3224 }
3225
3226 /* Store the result. */
3227 PRTDWARFADDRRANGE pRange = (PRTDWARFADDRRANGE)pbMember;
3228 if (pRange->fHaveRanges)
3229 {
3230 Log(("rtDwarfDecode_Ranges: Duplicate DW_AT_ranges\n"));
3231 return pCursor->rc = VERR_DWARF_BAD_INFO;
3232 }
3233 pRange->fHaveRanges = true;
3234 pRange->cAttrs++;
3235 pRange->pbRanges = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_ranges].pv + (size_t)off;
3236
3237 Log4((" %-20s TODO [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), rtDwarfLog_FormName(uForm)));
3238 return VINF_SUCCESS;
3239}
3240
3241
3242/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3243static DECLCALLBACK(int) rtDwarfDecode_Reference(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3244 uint32_t uForm, PRTDWARFCURSOR pCursor)
3245{
3246 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
3247
3248 /* Decode it. */
3249 uint64_t off;
3250 krtDwarfRef enmWrt = krtDwarfRef_SameUnit;
3251 switch (uForm)
3252 {
3253 case DW_FORM_ref1: off = rtDwarfCursor_GetU8(pCursor, 0); break;
3254 case DW_FORM_ref2: off = rtDwarfCursor_GetU16(pCursor, 0); break;
3255 case DW_FORM_ref4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
3256 case DW_FORM_ref8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
3257 case DW_FORM_ref_udata: off = rtDwarfCursor_GetULeb128(pCursor, 0); break;
3258
3259 case DW_FORM_ref_addr:
3260 enmWrt = krtDwarfRef_InfoSection;
3261 off = rtDwarfCursor_GetUOff(pCursor, 0);
3262 break;
3263
3264 case DW_FORM_ref_sig8:
3265 enmWrt = krtDwarfRef_TypeId64;
3266 off = rtDwarfCursor_GetU64(pCursor, 0);
3267 break;
3268
3269 default:
3270 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3271 }
3272 if (RT_FAILURE(pCursor->rc))
3273 return pCursor->rc;
3274
3275 /* Validate the offset and convert to debug_info relative offsets. */
3276 if (enmWrt == krtDwarfRef_InfoSection)
3277 {
3278 if (off >= pCursor->pDwarfMod->aSections[krtDbgModDwarfSect_info].cb)
3279 {
3280 Log(("rtDwarfDecode_Reference: bad info off=%#llx\n", off));
3281 return pCursor->rc = VERR_DWARF_BAD_POS;
3282 }
3283 }
3284 else if (enmWrt == krtDwarfRef_SameUnit)
3285 {
3286 PRTDWARFDIECOMPILEUNIT pUnit = rtDwarfDie_GetCompileUnit(pDie);
3287 if (off >= pUnit->cbUnit)
3288 {
3289 Log(("rtDwarfDecode_Reference: bad unit off=%#llx\n", off));
3290 return pCursor->rc = VERR_DWARF_BAD_POS;
3291 }
3292 off += pUnit->offUnit;
3293 enmWrt = krtDwarfRef_InfoSection;
3294 }
3295 /* else: not bother verifying/resolving the indirect type reference yet. */
3296
3297 /* Store it */
3298 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
3299 pRef->enmWrt = enmWrt;
3300 pRef->off = off;
3301
3302 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
3303 return VINF_SUCCESS;
3304}
3305
3306
3307/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3308static DECLCALLBACK(int) rtDwarfDecode_SectOff(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3309 uint32_t uForm, PRTDWARFCURSOR pCursor)
3310{
3311 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(RTDWARFREF), VERR_INTERNAL_ERROR_3);
3312 NOREF(pDie);
3313
3314 uint64_t off;
3315 switch (uForm)
3316 {
3317 case DW_FORM_data4: off = rtDwarfCursor_GetU32(pCursor, 0); break;
3318 case DW_FORM_data8: off = rtDwarfCursor_GetU64(pCursor, 0); break;
3319 case DW_FORM_sec_offset: off = rtDwarfCursor_GetUOff(pCursor, 0); break;
3320 default:
3321 AssertMsgFailedReturn(("%#x (%s)\n", uForm, rtDwarfLog_FormName(uForm)), VERR_DWARF_UNEXPECTED_FORM);
3322 }
3323 if (RT_FAILURE(pCursor->rc))
3324 return pCursor->rc;
3325
3326 krtDbgModDwarfSect enmSect;
3327 krtDwarfRef enmWrt;
3328 switch (pDesc->uAttr)
3329 {
3330 case DW_AT_stmt_list: enmSect = krtDbgModDwarfSect_line; enmWrt = krtDwarfRef_LineSection; break;
3331 case DW_AT_macro_info: enmSect = krtDbgModDwarfSect_loc; enmWrt = krtDwarfRef_LocSection; break;
3332 case DW_AT_ranges: enmSect = krtDbgModDwarfSect_ranges; enmWrt = krtDwarfRef_RangesSection; break;
3333 default:
3334 AssertMsgFailedReturn(("%u (%s)\n", pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr)), VERR_INTERNAL_ERROR_4);
3335 }
3336 size_t cbSect = pCursor->pDwarfMod->aSections[enmSect].cb;
3337 if (off >= cbSect)
3338 {
3339 /* Watcom generates offset past the end of the section, increasing the
3340 offset by one for each compile unit. So, just fudge it. */
3341 Log(("rtDwarfDecode_SectOff: bad off=%#llx, attr %#x (%s), enmSect=%d cb=%#llx; Assuming watcom/gcc.\n", off,
3342 pDesc->uAttr, rtDwarfLog_AttrName(pDesc->uAttr), enmSect, cbSect));
3343 off = cbSect;
3344 }
3345
3346 PRTDWARFREF pRef = (PRTDWARFREF)pbMember;
3347 pRef->enmWrt = enmWrt;
3348 pRef->off = off;
3349
3350 Log4((" %-20s %d:%#010llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), enmWrt, off, rtDwarfLog_FormName(uForm)));
3351 return VINF_SUCCESS;
3352}
3353
3354
3355/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3356static DECLCALLBACK(int) rtDwarfDecode_String(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3357 uint32_t uForm, PRTDWARFCURSOR pCursor)
3358{
3359 AssertReturn(ATTR_GET_SIZE(pDesc) == sizeof(const char *), VERR_INTERNAL_ERROR_3);
3360 NOREF(pDie);
3361
3362 const char *psz;
3363 switch (uForm)
3364 {
3365 case DW_FORM_string:
3366 psz = rtDwarfCursor_GetSZ(pCursor, NULL);
3367 break;
3368
3369 case DW_FORM_strp:
3370 psz = rtDwarfDecodeHlp_GetStrp(pCursor->pDwarfMod, pCursor, NULL);
3371 break;
3372
3373 default:
3374 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3375 }
3376
3377 *(const char **)pbMember = psz;
3378 Log4((" %-20s '%s' [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr), psz, rtDwarfLog_FormName(uForm)));
3379 return pCursor->rc;
3380}
3381
3382
3383/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3384static DECLCALLBACK(int) rtDwarfDecode_UnsignedInt(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3385 uint32_t uForm, PRTDWARFCURSOR pCursor)
3386{
3387 NOREF(pDie);
3388 uint64_t u64Val;
3389 switch (uForm)
3390 {
3391 case DW_FORM_udata: u64Val = rtDwarfCursor_GetULeb128(pCursor, 0); break;
3392 case DW_FORM_data1: u64Val = rtDwarfCursor_GetU8(pCursor, 0); break;
3393 case DW_FORM_data2: u64Val = rtDwarfCursor_GetU16(pCursor, 0); break;
3394 case DW_FORM_data4: u64Val = rtDwarfCursor_GetU32(pCursor, 0); break;
3395 case DW_FORM_data8: u64Val = rtDwarfCursor_GetU64(pCursor, 0); break;
3396 default:
3397 AssertMsgFailedReturn(("%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3398 }
3399 if (RT_FAILURE(pCursor->rc))
3400 return pCursor->rc;
3401
3402 switch (ATTR_GET_SIZE(pDesc))
3403 {
3404 case 1:
3405 *pbMember = (uint8_t)u64Val;
3406 if (*pbMember != u64Val)
3407 {
3408 AssertFailed();
3409 return VERR_OUT_OF_RANGE;
3410 }
3411 break;
3412
3413 case 2:
3414 *(uint16_t *)pbMember = (uint16_t)u64Val;
3415 if (*(uint16_t *)pbMember != u64Val)
3416 {
3417 AssertFailed();
3418 return VERR_OUT_OF_RANGE;
3419 }
3420 break;
3421
3422 case 4:
3423 *(uint32_t *)pbMember = (uint32_t)u64Val;
3424 if (*(uint32_t *)pbMember != u64Val)
3425 {
3426 AssertFailed();
3427 return VERR_OUT_OF_RANGE;
3428 }
3429 break;
3430
3431 case 8:
3432 *(uint64_t *)pbMember = (uint64_t)u64Val;
3433 if (*(uint64_t *)pbMember != u64Val)
3434 {
3435 AssertFailed();
3436 return VERR_OUT_OF_RANGE;
3437 }
3438 break;
3439
3440 default:
3441 AssertMsgFailedReturn(("%#x\n", ATTR_GET_SIZE(pDesc)), VERR_INTERNAL_ERROR_2);
3442 }
3443 return VINF_SUCCESS;
3444}
3445
3446
3447/**
3448 * Initialize location interpreter state from cursor & form.
3449 *
3450 * @returns IPRT status code.
3451 * @retval VERR_NOT_FOUND if no location information (i.e. there is source but
3452 * it resulted in no byte code).
3453 * @param pLoc The location state structure to initialize.
3454 * @param pCursor The cursor to read from.
3455 * @param uForm The attribute form.
3456 */
3457static int rtDwarfLoc_Init(PRTDWARFLOCST pLoc, PRTDWARFCURSOR pCursor, uint32_t uForm)
3458{
3459 uint32_t cbBlock;
3460 switch (uForm)
3461 {
3462 case DW_FORM_block1:
3463 cbBlock = rtDwarfCursor_GetU8(pCursor, 0);
3464 break;
3465
3466 case DW_FORM_block2:
3467 cbBlock = rtDwarfCursor_GetU16(pCursor, 0);
3468 break;
3469
3470 case DW_FORM_block4:
3471 cbBlock = rtDwarfCursor_GetU32(pCursor, 0);
3472 break;
3473
3474 case DW_FORM_block:
3475 cbBlock = rtDwarfCursor_GetULeb128(pCursor, 0);
3476 break;
3477
3478 default:
3479 AssertMsgFailedReturn(("uForm=%#x\n", uForm), VERR_DWARF_UNEXPECTED_FORM);
3480 }
3481 if (!cbBlock)
3482 return VERR_NOT_FOUND;
3483
3484 int rc = rtDwarfCursor_InitForBlock(&pLoc->Cursor, pCursor, cbBlock);
3485 if (RT_FAILURE(rc))
3486 return rc;
3487 pLoc->iTop = -1;
3488 return VINF_SUCCESS;
3489}
3490
3491
3492/**
3493 * Pushes a value onto the stack.
3494 *
3495 * @returns VINF_SUCCESS or VERR_DWARF_STACK_OVERFLOW.
3496 * @param pLoc The state.
3497 * @param uValue The value to push.
3498 */
3499static int rtDwarfLoc_Push(PRTDWARFLOCST pLoc, uint64_t uValue)
3500{
3501 int iTop = pLoc->iTop + 1;
3502 AssertReturn((unsigned)iTop < RT_ELEMENTS(pLoc->auStack), VERR_DWARF_STACK_OVERFLOW);
3503 pLoc->auStack[iTop] = uValue;
3504 pLoc->iTop = iTop;
3505 return VINF_SUCCESS;
3506}
3507
3508
3509static int rtDwarfLoc_Evaluate(PRTDWARFLOCST pLoc, void *pvLater, void *pvUser)
3510{
3511 while (!rtDwarfCursor_IsAtEndOfUnit(&pLoc->Cursor))
3512 {
3513 /* Read the next opcode.*/
3514 uint8_t const bOpcode = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
3515
3516 /* Get its operands. */
3517 uint64_t uOperand1 = 0;
3518 uint64_t uOperand2 = 0;
3519 switch (bOpcode)
3520 {
3521 case DW_OP_addr:
3522 uOperand1 = rtDwarfCursor_GetNativeUOff(&pLoc->Cursor, 0);
3523 break;
3524 case DW_OP_pick:
3525 case DW_OP_const1u:
3526 case DW_OP_deref_size:
3527 case DW_OP_xderef_size:
3528 uOperand1 = rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
3529 break;
3530 case DW_OP_const1s:
3531 uOperand1 = (int8_t)rtDwarfCursor_GetU8(&pLoc->Cursor, 0);
3532 break;
3533 case DW_OP_const2u:
3534 uOperand1 = rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
3535 break;
3536 case DW_OP_skip:
3537 case DW_OP_bra:
3538 case DW_OP_const2s:
3539 uOperand1 = (int16_t)rtDwarfCursor_GetU16(&pLoc->Cursor, 0);
3540 break;
3541 case DW_OP_const4u:
3542 uOperand1 = rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
3543 break;
3544 case DW_OP_const4s:
3545 uOperand1 = (int32_t)rtDwarfCursor_GetU32(&pLoc->Cursor, 0);
3546 break;
3547 case DW_OP_const8u:
3548 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
3549 break;
3550 case DW_OP_const8s:
3551 uOperand1 = rtDwarfCursor_GetU64(&pLoc->Cursor, 0);
3552 break;
3553 case DW_OP_regx:
3554 case DW_OP_piece:
3555 case DW_OP_plus_uconst:
3556 case DW_OP_constu:
3557 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
3558 break;
3559 case DW_OP_consts:
3560 case DW_OP_fbreg:
3561 case DW_OP_breg0+0: case DW_OP_breg0+1: case DW_OP_breg0+2: case DW_OP_breg0+3:
3562 case DW_OP_breg0+4: case DW_OP_breg0+5: case DW_OP_breg0+6: case DW_OP_breg0+7:
3563 case DW_OP_breg0+8: case DW_OP_breg0+9: case DW_OP_breg0+10: case DW_OP_breg0+11:
3564 case DW_OP_breg0+12: case DW_OP_breg0+13: case DW_OP_breg0+14: case DW_OP_breg0+15:
3565 case DW_OP_breg0+16: case DW_OP_breg0+17: case DW_OP_breg0+18: case DW_OP_breg0+19:
3566 case DW_OP_breg0+20: case DW_OP_breg0+21: case DW_OP_breg0+22: case DW_OP_breg0+23:
3567 case DW_OP_breg0+24: case DW_OP_breg0+25: case DW_OP_breg0+26: case DW_OP_breg0+27:
3568 case DW_OP_breg0+28: case DW_OP_breg0+29: case DW_OP_breg0+30: case DW_OP_breg0+31:
3569 uOperand1 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
3570 break;
3571 case DW_OP_bregx:
3572 uOperand1 = rtDwarfCursor_GetULeb128(&pLoc->Cursor, 0);
3573 uOperand2 = rtDwarfCursor_GetSLeb128(&pLoc->Cursor, 0);
3574 break;
3575 }
3576 if (RT_FAILURE(pLoc->Cursor.rc))
3577 break;
3578
3579 /* Interpret the opcode. */
3580 int rc;
3581 switch (bOpcode)
3582 {
3583 case DW_OP_const1u:
3584 case DW_OP_const1s:
3585 case DW_OP_const2u:
3586 case DW_OP_const2s:
3587 case DW_OP_const4u:
3588 case DW_OP_const4s:
3589 case DW_OP_const8u:
3590 case DW_OP_const8s:
3591 case DW_OP_constu:
3592 case DW_OP_consts:
3593 case DW_OP_addr:
3594 rc = rtDwarfLoc_Push(pLoc, uOperand1);
3595 break;
3596 case DW_OP_lit0 + 0: case DW_OP_lit0 + 1: case DW_OP_lit0 + 2: case DW_OP_lit0 + 3:
3597 case DW_OP_lit0 + 4: case DW_OP_lit0 + 5: case DW_OP_lit0 + 6: case DW_OP_lit0 + 7:
3598 case DW_OP_lit0 + 8: case DW_OP_lit0 + 9: case DW_OP_lit0 + 10: case DW_OP_lit0 + 11:
3599 case DW_OP_lit0 + 12: case DW_OP_lit0 + 13: case DW_OP_lit0 + 14: case DW_OP_lit0 + 15:
3600 case DW_OP_lit0 + 16: case DW_OP_lit0 + 17: case DW_OP_lit0 + 18: case DW_OP_lit0 + 19:
3601 case DW_OP_lit0 + 20: case DW_OP_lit0 + 21: case DW_OP_lit0 + 22: case DW_OP_lit0 + 23:
3602 case DW_OP_lit0 + 24: case DW_OP_lit0 + 25: case DW_OP_lit0 + 26: case DW_OP_lit0 + 27:
3603 case DW_OP_lit0 + 28: case DW_OP_lit0 + 29: case DW_OP_lit0 + 30: case DW_OP_lit0 + 31:
3604 rc = rtDwarfLoc_Push(pLoc, bOpcode - DW_OP_lit0);
3605 break;
3606 case DW_OP_nop:
3607 break;
3608 case DW_OP_dup: /** @todo 0 operands. */
3609 case DW_OP_drop: /** @todo 0 operands. */
3610 case DW_OP_over: /** @todo 0 operands. */
3611 case DW_OP_pick: /** @todo 1 operands, a 1-byte stack index. */
3612 case DW_OP_swap: /** @todo 0 operands. */
3613 case DW_OP_rot: /** @todo 0 operands. */
3614 case DW_OP_abs: /** @todo 0 operands. */
3615 case DW_OP_and: /** @todo 0 operands. */
3616 case DW_OP_div: /** @todo 0 operands. */
3617 case DW_OP_minus: /** @todo 0 operands. */
3618 case DW_OP_mod: /** @todo 0 operands. */
3619 case DW_OP_mul: /** @todo 0 operands. */
3620 case DW_OP_neg: /** @todo 0 operands. */
3621 case DW_OP_not: /** @todo 0 operands. */
3622 case DW_OP_or: /** @todo 0 operands. */
3623 case DW_OP_plus: /** @todo 0 operands. */
3624 case DW_OP_plus_uconst: /** @todo 1 operands, a ULEB128 addend. */
3625 case DW_OP_shl: /** @todo 0 operands. */
3626 case DW_OP_shr: /** @todo 0 operands. */
3627 case DW_OP_shra: /** @todo 0 operands. */
3628 case DW_OP_xor: /** @todo 0 operands. */
3629 case DW_OP_skip: /** @todo 1 signed 2-byte constant. */
3630 case DW_OP_bra: /** @todo 1 signed 2-byte constant. */
3631 case DW_OP_eq: /** @todo 0 operands. */
3632 case DW_OP_ge: /** @todo 0 operands. */
3633 case DW_OP_gt: /** @todo 0 operands. */
3634 case DW_OP_le: /** @todo 0 operands. */
3635 case DW_OP_lt: /** @todo 0 operands. */
3636 case DW_OP_ne: /** @todo 0 operands. */
3637 case DW_OP_reg0 + 0: case DW_OP_reg0 + 1: case DW_OP_reg0 + 2: case DW_OP_reg0 + 3: /** @todo 0 operands - reg 0..31. */
3638 case DW_OP_reg0 + 4: case DW_OP_reg0 + 5: case DW_OP_reg0 + 6: case DW_OP_reg0 + 7:
3639 case DW_OP_reg0 + 8: case DW_OP_reg0 + 9: case DW_OP_reg0 + 10: case DW_OP_reg0 + 11:
3640 case DW_OP_reg0 + 12: case DW_OP_reg0 + 13: case DW_OP_reg0 + 14: case DW_OP_reg0 + 15:
3641 case DW_OP_reg0 + 16: case DW_OP_reg0 + 17: case DW_OP_reg0 + 18: case DW_OP_reg0 + 19:
3642 case DW_OP_reg0 + 20: case DW_OP_reg0 + 21: case DW_OP_reg0 + 22: case DW_OP_reg0 + 23:
3643 case DW_OP_reg0 + 24: case DW_OP_reg0 + 25: case DW_OP_reg0 + 26: case DW_OP_reg0 + 27:
3644 case DW_OP_reg0 + 28: case DW_OP_reg0 + 29: case DW_OP_reg0 + 30: case DW_OP_reg0 + 31:
3645 case DW_OP_breg0+ 0: case DW_OP_breg0+ 1: case DW_OP_breg0+ 2: case DW_OP_breg0+ 3: /** @todo 1 operand, a SLEB128 offset. */
3646 case DW_OP_breg0+ 4: case DW_OP_breg0+ 5: case DW_OP_breg0+ 6: case DW_OP_breg0+ 7:
3647 case DW_OP_breg0+ 8: case DW_OP_breg0+ 9: case DW_OP_breg0+ 10: case DW_OP_breg0+ 11:
3648 case DW_OP_breg0+ 12: case DW_OP_breg0+ 13: case DW_OP_breg0+ 14: case DW_OP_breg0+ 15:
3649 case DW_OP_breg0+ 16: case DW_OP_breg0+ 17: case DW_OP_breg0+ 18: case DW_OP_breg0+ 19:
3650 case DW_OP_breg0+ 20: case DW_OP_breg0+ 21: case DW_OP_breg0+ 22: case DW_OP_breg0+ 23:
3651 case DW_OP_breg0+ 24: case DW_OP_breg0+ 25: case DW_OP_breg0+ 26: case DW_OP_breg0+ 27:
3652 case DW_OP_breg0+ 28: case DW_OP_breg0+ 29: case DW_OP_breg0+ 30: case DW_OP_breg0+ 31:
3653 case DW_OP_piece: /** @todo 1 operand, a ULEB128 size of piece addressed. */
3654 case DW_OP_regx: /** @todo 1 operand, a ULEB128 register. */
3655 case DW_OP_fbreg: /** @todo 1 operand, a SLEB128 offset. */
3656 case DW_OP_bregx: /** @todo 2 operands, a ULEB128 register followed by a SLEB128 offset. */
3657 case DW_OP_deref: /** @todo 0 operands. */
3658 case DW_OP_deref_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
3659 case DW_OP_xderef: /** @todo 0 operands. */
3660 case DW_OP_xderef_size: /** @todo 1 operand, a 1-byte size of data retrieved. */
3661 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_TODO);
3662 default:
3663 AssertMsgFailedReturn(("bOpcode=%#x\n", bOpcode), VERR_DWARF_UNKNOWN_LOC_OPCODE);
3664 }
3665 }
3666
3667 return pLoc->Cursor.rc;
3668}
3669
3670
3671/** @callback_method_impl{FNRTDWARFATTRDECODER} */
3672static DECLCALLBACK(int) rtDwarfDecode_SegmentLoc(PRTDWARFDIE pDie, uint8_t *pbMember, PCRTDWARFATTRDESC pDesc,
3673 uint32_t uForm, PRTDWARFCURSOR pCursor)
3674{
3675 NOREF(pDie);
3676 AssertReturn(ATTR_GET_SIZE(pDesc) == 2, VERR_DWARF_IPE);
3677
3678 RTDWARFLOCST LocSt;
3679 int rc = rtDwarfLoc_Init(&LocSt, pCursor, uForm);
3680 if (RT_SUCCESS(rc))
3681 {
3682 rc = rtDwarfLoc_Evaluate(&LocSt, NULL, NULL);
3683 if (RT_SUCCESS(rc))
3684 {
3685 if (LocSt.iTop >= 0)
3686 {
3687 *(uint16_t *)pbMember = LocSt.auStack[LocSt.iTop];
3688 Log4((" %-20s %#06llx [%s]\n", rtDwarfLog_AttrName(pDesc->uAttr),
3689 LocSt.auStack[LocSt.iTop], rtDwarfLog_FormName(uForm)));
3690 return VINF_SUCCESS;
3691 }
3692 rc = VERR_DWARF_STACK_UNDERFLOW;
3693 }
3694 }
3695 return rc;
3696}
3697
3698/*
3699 *
3700 * DWARF debug_info parser
3701 * DWARF debug_info parser
3702 * DWARF debug_info parser
3703 *
3704 */
3705
3706
3707/**
3708 * Special hack to get the name and/or linkage name for a subprogram via a
3709 * specification reference.
3710 *
3711 * Since this is a hack, we ignore failure.
3712 *
3713 * If we want to really make use of DWARF info, we'll have to create some kind
3714 * of lookup tree for handling this. But currently we don't, so a hack will
3715 * suffice.
3716 *
3717 * @param pThis The DWARF instance.
3718 * @param pSubProgram The subprogram which is short on names.
3719 */
3720static void rtDwarfInfo_TryGetSubProgramNameFromSpecRef(PRTDBGMODDWARF pThis, PRTDWARFDIESUBPROGRAM pSubProgram)
3721{
3722 /*
3723 * Must have a spec ref, and it must be in the info section.
3724 */
3725 if (pSubProgram->SpecRef.enmWrt != krtDwarfRef_InfoSection)
3726 return;
3727
3728 /*
3729 * Create a cursor for reading the info and then the abbrivation code
3730 * starting the off the DIE.
3731 */
3732 RTDWARFCURSOR InfoCursor;
3733 int rc = rtDwarfCursor_InitWithOffset(&InfoCursor, pThis, krtDbgModDwarfSect_info, pSubProgram->SpecRef.off);
3734 if (RT_FAILURE(rc))
3735 return;
3736
3737 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(&InfoCursor, UINT32_MAX);
3738 if (uAbbrCode)
3739 {
3740 /* Only references to subprogram tags are interesting here. */
3741 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
3742 if ( pAbbrev
3743 && pAbbrev->uTag == DW_TAG_subprogram)
3744 {
3745 /*
3746 * Use rtDwarfInfo_ParseDie to do the parsing, but with a different
3747 * attribute spec than usual.
3748 */
3749 rtDwarfInfo_ParseDie(pThis, &pSubProgram->Core, &g_SubProgramSpecHackDesc, &InfoCursor,
3750 pAbbrev, false /*fInitDie*/);
3751 }
3752 }
3753
3754 rtDwarfCursor_Delete(&InfoCursor, VINF_SUCCESS);
3755}
3756
3757
3758/**
3759 * Select which name to use.
3760 *
3761 * @returns One of the names.
3762 * @param pszName The DWARF name, may exclude namespace and class.
3763 * Can also be NULL.
3764 * @param pszLinkageName The linkage name. Can be NULL.
3765 */
3766static const char *rtDwarfInfo_SelectName(const char *pszName, const char *pszLinkageName)
3767{
3768 if (!pszName || !pszLinkageName)
3769 return pszName ? pszName : pszLinkageName;
3770
3771 /*
3772 * Some heuristics for selecting the link name if the normal name is missing
3773 * namespace or class prefixes.
3774 */
3775 size_t cchName = strlen(pszName);
3776 size_t cchLinkageName = strlen(pszLinkageName);
3777 if (cchLinkageName <= cchName + 1)
3778 return pszName;
3779
3780 const char *psz = strstr(pszLinkageName, pszName);
3781 if (!psz || psz - pszLinkageName < 4)
3782 return pszName;
3783
3784 return pszLinkageName;
3785}
3786
3787
3788/**
3789 * Parse the attributes of a DIE.
3790 *
3791 * @returns IPRT status code.
3792 * @param pThis The DWARF instance.
3793 * @param pDie The internal DIE structure to fill.
3794 */
3795static int rtDwarfInfo_SnoopSymbols(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
3796{
3797 int rc = VINF_SUCCESS;
3798 switch (pDie->uTag)
3799 {
3800 case DW_TAG_subprogram:
3801 {
3802 PRTDWARFDIESUBPROGRAM pSubProgram = (PRTDWARFDIESUBPROGRAM)pDie;
3803
3804 /* Obtain referenced specification there is only partial info. */
3805 if ( pSubProgram->PcRange.cAttrs
3806 && !pSubProgram->pszName)
3807 rtDwarfInfo_TryGetSubProgramNameFromSpecRef(pThis, pSubProgram);
3808
3809 if (pSubProgram->PcRange.cAttrs)
3810 {
3811 if (pSubProgram->PcRange.fHaveRanges)
3812 Log5(("subprogram %s (%s) <implement ranges>\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
3813 else
3814 {
3815 Log5(("subprogram %s (%s) %#llx-%#llx%s\n", pSubProgram->pszName, pSubProgram->pszLinkageName,
3816 pSubProgram->PcRange.uLowAddress, pSubProgram->PcRange.uHighAddress,
3817 pSubProgram->PcRange.cAttrs == 2 ? "" : " !bad!"));
3818 if ( ( pSubProgram->pszName || pSubProgram->pszLinkageName)
3819 && pSubProgram->PcRange.cAttrs == 2)
3820 {
3821 if (pThis->iWatcomPass == 1)
3822 rc = rtDbgModDwarfRecordSegOffset(pThis, pSubProgram->uSegment, pSubProgram->PcRange.uHighAddress);
3823 else
3824 {
3825 RTDBGSEGIDX iSeg;
3826 RTUINTPTR offSeg;
3827 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pSubProgram->uSegment,
3828 pSubProgram->PcRange.uLowAddress,
3829 &iSeg, &offSeg);
3830 if (RT_SUCCESS(rc))
3831 {
3832 rc = RTDbgModSymbolAdd(pThis->hCnt,
3833 rtDwarfInfo_SelectName(pSubProgram->pszName, pSubProgram->pszLinkageName),
3834 iSeg, offSeg,
3835 pSubProgram->PcRange.uHighAddress - pSubProgram->PcRange.uLowAddress,
3836 0 /*fFlags*/, NULL /*piOrdinal*/);
3837 AssertMsg(RT_SUCCESS(rc) || rc == VERR_DBG_DUPLICATE_SYMBOL, ("%Rrc\n", rc));
3838 }
3839 else if ( pSubProgram->PcRange.uLowAddress == 0 /* see with vmlinux */
3840 && pSubProgram->PcRange.uHighAddress == 0)
3841 {
3842 Log5(("rtDbgModDwarfLinkAddressToSegOffset: Ignoring empty range.\n"));
3843 rc = VINF_SUCCESS; /* ignore */
3844 }
3845 else
3846 {
3847 AssertRC(rc);
3848 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
3849 }
3850 }
3851 }
3852 }
3853 }
3854 else
3855 Log5(("subprogram %s (%s) external\n", pSubProgram->pszName, pSubProgram->pszLinkageName));
3856 break;
3857 }
3858
3859 case DW_TAG_label:
3860 {
3861 PCRTDWARFDIELABEL pLabel = (PCRTDWARFDIELABEL)pDie;
3862 if (pLabel->fExternal)
3863 {
3864 Log5(("label %s %#x:%#llx\n", pLabel->pszName, pLabel->uSegment, pLabel->Address.uAddress));
3865 if (pThis->iWatcomPass == 1)
3866 rc = rtDbgModDwarfRecordSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress);
3867 else
3868 {
3869 RTDBGSEGIDX iSeg;
3870 RTUINTPTR offSeg;
3871 rc = rtDbgModDwarfLinkAddressToSegOffset(pThis, pLabel->uSegment, pLabel->Address.uAddress,
3872 &iSeg, &offSeg);
3873 AssertRC(rc);
3874 if (RT_SUCCESS(rc))
3875 {
3876 rc = RTDbgModSymbolAdd(pThis->hCnt, pLabel->pszName, iSeg, offSeg, 0 /*cb*/,
3877 0 /*fFlags*/, NULL /*piOrdinal*/);
3878 AssertRC(rc);
3879 }
3880 else
3881 Log5(("rtDbgModDwarfLinkAddressToSegOffset failed: %Rrc\n", rc));
3882 }
3883
3884 }
3885 break;
3886 }
3887
3888 }
3889 return rc;
3890}
3891
3892
3893/**
3894 * Initializes the non-core fields of an internal DIE structure.
3895 *
3896 * @param pDie The DIE structure.
3897 * @param pDieDesc The DIE descriptor.
3898 */
3899static void rtDwarfInfo_InitDie(PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc)
3900{
3901 size_t i = pDieDesc->cAttributes;
3902 while (i-- > 0)
3903 {
3904 switch (pDieDesc->paAttributes[i].cbInit & ATTR_INIT_MASK)
3905 {
3906 case ATTR_INIT_ZERO:
3907 /* Nothing to do (RTMemAllocZ). */
3908 break;
3909
3910 case ATTR_INIT_FFFS:
3911 switch (pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK)
3912 {
3913 case 1:
3914 *(uint8_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT8_MAX;
3915 break;
3916 case 2:
3917 *(uint16_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT16_MAX;
3918 break;
3919 case 4:
3920 *(uint32_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT32_MAX;
3921 break;
3922 case 8:
3923 *(uint64_t *)((uintptr_t)pDie + pDieDesc->paAttributes[i].off) = UINT64_MAX;
3924 break;
3925 default:
3926 AssertFailed();
3927 memset((uint8_t *)pDie + pDieDesc->paAttributes[i].off, 0xff,
3928 pDieDesc->paAttributes[i].cbInit & ATTR_SIZE_MASK);
3929 break;
3930 }
3931 break;
3932
3933 default:
3934 AssertFailed();
3935 }
3936 }
3937}
3938
3939
3940/**
3941 * Creates a new internal DIE structure and links it up.
3942 *
3943 * @returns Pointer to the new DIE structure.
3944 * @param pThis The DWARF instance.
3945 * @param pDieDesc The DIE descriptor (for size and init).
3946 * @param pAbbrev The abbreviation cache entry.
3947 * @param pParent The parent DIE (NULL if unit).
3948 */
3949static PRTDWARFDIE rtDwarfInfo_NewDie(PRTDBGMODDWARF pThis, PCRTDWARFDIEDESC pDieDesc,
3950 PCRTDWARFABBREV pAbbrev, PRTDWARFDIE pParent)
3951{
3952 NOREF(pThis);
3953 Assert(pDieDesc->cbDie >= sizeof(RTDWARFDIE));
3954#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
3955 uint32_t iAllocator = pDieDesc->cbDie > pThis->aDieAllocators[0].cbMax;
3956 Assert(pDieDesc->cbDie <= pThis->aDieAllocators[iAllocator].cbMax);
3957 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemCacheAlloc(pThis->aDieAllocators[iAllocator].hMemCache);
3958#else
3959 PRTDWARFDIE pDie = (PRTDWARFDIE)RTMemAllocZ(pDieDesc->cbDie);
3960#endif
3961 if (pDie)
3962 {
3963#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
3964 RT_BZERO(pDie, pDieDesc->cbDie);
3965 pDie->iAllocator = iAllocator;
3966#endif
3967 rtDwarfInfo_InitDie(pDie, pDieDesc);
3968
3969 pDie->uTag = pAbbrev->uTag;
3970 pDie->offSpec = pAbbrev->offSpec;
3971 pDie->pParent = pParent;
3972 if (pParent)
3973 RTListAppend(&pParent->ChildList, &pDie->SiblingNode);
3974 else
3975 RTListInit(&pDie->SiblingNode);
3976 RTListInit(&pDie->ChildList);
3977
3978 }
3979 return pDie;
3980}
3981
3982
3983/**
3984 * Free all children of a DIE.
3985 *
3986 * @param pThis The DWARF instance.
3987 * @param pParent The parent DIE.
3988 */
3989static void rtDwarfInfo_FreeChildren(PRTDBGMODDWARF pThis, PRTDWARFDIE pParentDie)
3990{
3991 PRTDWARFDIE pChild, pNextChild;
3992 RTListForEachSafe(&pParentDie->ChildList, pChild, pNextChild, RTDWARFDIE, SiblingNode)
3993 {
3994 if (!RTListIsEmpty(&pChild->ChildList))
3995 rtDwarfInfo_FreeChildren(pThis, pChild);
3996 RTListNodeRemove(&pChild->SiblingNode);
3997#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
3998 RTMemCacheFree(pThis->aDieAllocators[pChild->iAllocator].hMemCache, pChild);
3999#else
4000 RTMemFree(pChild);
4001#endif
4002 }
4003}
4004
4005
4006/**
4007 * Free a DIE an all its children.
4008 *
4009 * @param pThis The DWARF instance.
4010 * @param pDie The DIE to free.
4011 */
4012static void rtDwarfInfo_FreeDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie)
4013{
4014 rtDwarfInfo_FreeChildren(pThis, pDie);
4015 RTListNodeRemove(&pDie->SiblingNode);
4016#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
4017 RTMemCacheFree(pThis->aDieAllocators[pDie->iAllocator].hMemCache, pDie);
4018#else
4019 RTMemFree(pChild);
4020#endif
4021}
4022
4023
4024/**
4025 * Skips a form.
4026 * @returns IPRT status code
4027 * @param pCursor The cursor.
4028 * @param uForm The form to skip.
4029 */
4030static int rtDwarfInfo_SkipForm(PRTDWARFCURSOR pCursor, uint32_t uForm)
4031{
4032 switch (uForm)
4033 {
4034 case DW_FORM_addr:
4035 return rtDwarfCursor_SkipBytes(pCursor, pCursor->cbNativeAddr);
4036
4037 case DW_FORM_block:
4038 case DW_FORM_exprloc:
4039 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetULeb128(pCursor, 0));
4040
4041 case DW_FORM_block1:
4042 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU8(pCursor, 0));
4043
4044 case DW_FORM_block2:
4045 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU16(pCursor, 0));
4046
4047 case DW_FORM_block4:
4048 return rtDwarfCursor_SkipBytes(pCursor, rtDwarfCursor_GetU32(pCursor, 0));
4049
4050 case DW_FORM_data1:
4051 case DW_FORM_ref1:
4052 case DW_FORM_flag:
4053 return rtDwarfCursor_SkipBytes(pCursor, 1);
4054
4055 case DW_FORM_data2:
4056 case DW_FORM_ref2:
4057 return rtDwarfCursor_SkipBytes(pCursor, 2);
4058
4059 case DW_FORM_data4:
4060 case DW_FORM_ref4:
4061 return rtDwarfCursor_SkipBytes(pCursor, 4);
4062
4063 case DW_FORM_data8:
4064 case DW_FORM_ref8:
4065 case DW_FORM_ref_sig8:
4066 return rtDwarfCursor_SkipBytes(pCursor, 8);
4067
4068 case DW_FORM_udata:
4069 case DW_FORM_sdata:
4070 case DW_FORM_ref_udata:
4071 return rtDwarfCursor_SkipLeb128(pCursor);
4072
4073 case DW_FORM_string:
4074 rtDwarfCursor_GetSZ(pCursor, NULL);
4075 return pCursor->rc;
4076
4077 case DW_FORM_indirect:
4078 return rtDwarfInfo_SkipForm(pCursor, rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX));
4079
4080 case DW_FORM_strp:
4081 case DW_FORM_ref_addr:
4082 case DW_FORM_sec_offset:
4083 return rtDwarfCursor_SkipBytes(pCursor, pCursor->f64bitDwarf ? 8 : 4);
4084
4085 case DW_FORM_flag_present:
4086 return pCursor->rc; /* no data */
4087
4088 default:
4089 return VERR_DWARF_UNKNOWN_FORM;
4090 }
4091}
4092
4093
4094
4095#ifdef SOME_UNUSED_FUNCTION
4096/**
4097 * Skips a DIE.
4098 *
4099 * @returns IPRT status code.
4100 * @param pCursor The cursor.
4101 * @param pAbbrevCursor The abbreviation cursor.
4102 */
4103static int rtDwarfInfo_SkipDie(PRTDWARFCURSOR pCursor, PRTDWARFCURSOR pAbbrevCursor)
4104{
4105 for (;;)
4106 {
4107 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
4108 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(pAbbrevCursor, 0);
4109 if (uAttr == 0 && uForm == 0)
4110 break;
4111
4112 int rc = rtDwarfInfo_SkipForm(pCursor, uForm);
4113 if (RT_FAILURE(rc))
4114 return rc;
4115 }
4116 return RT_FAILURE(pCursor->rc) ? pCursor->rc : pAbbrevCursor->rc;
4117}
4118#endif
4119
4120
4121/**
4122 * Parse the attributes of a DIE.
4123 *
4124 * @returns IPRT status code.
4125 * @param pThis The DWARF instance.
4126 * @param pDie The internal DIE structure to fill.
4127 * @param pDieDesc The DIE descriptor.
4128 * @param pCursor The debug_info cursor.
4129 * @param pAbbrev The abbreviation cache entry.
4130 * @param fInitDie Whether to initialize the DIE first. If not (@c
4131 * false) it's safe to assume we're following a
4132 * DW_AT_specification or DW_AT_abstract_origin,
4133 * and that we shouldn't be snooping any symbols.
4134 */
4135static int rtDwarfInfo_ParseDie(PRTDBGMODDWARF pThis, PRTDWARFDIE pDie, PCRTDWARFDIEDESC pDieDesc,
4136 PRTDWARFCURSOR pCursor, PCRTDWARFABBREV pAbbrev, bool fInitDie)
4137{
4138 RTDWARFCURSOR AbbrevCursor;
4139 int rc = rtDwarfCursor_InitWithOffset(&AbbrevCursor, pThis, krtDbgModDwarfSect_abbrev, pAbbrev->offSpec);
4140 if (RT_FAILURE(rc))
4141 return rc;
4142
4143 if (fInitDie)
4144 rtDwarfInfo_InitDie(pDie, pDieDesc);
4145 for (;;)
4146 {
4147 uint32_t uAttr = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
4148 uint32_t uForm = rtDwarfCursor_GetULeb128AsU32(&AbbrevCursor, 0);
4149 if (uAttr == 0)
4150 break;
4151 if (uForm == DW_FORM_indirect)
4152 uForm = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
4153
4154 /* Look up the attribute in the descriptor and invoke the decoder. */
4155 PCRTDWARFATTRDESC pAttr = NULL;
4156 size_t i = pDieDesc->cAttributes;
4157 while (i-- > 0)
4158 if (pDieDesc->paAttributes[i].uAttr == uAttr)
4159 {
4160 pAttr = &pDieDesc->paAttributes[i];
4161 rc = pAttr->pfnDecoder(pDie, (uint8_t *)pDie + pAttr->off, pAttr, uForm, pCursor);
4162 break;
4163 }
4164
4165 /* Some house keeping. */
4166 if (pAttr)
4167 pDie->cDecodedAttrs++;
4168 else
4169 {
4170 pDie->cUnhandledAttrs++;
4171 rc = rtDwarfInfo_SkipForm(pCursor, uForm);
4172 Log4((" %-20s [%s]\n", rtDwarfLog_AttrName(uAttr), rtDwarfLog_FormName(uForm)));
4173 }
4174 if (RT_FAILURE(rc))
4175 break;
4176 }
4177
4178 rc = rtDwarfCursor_Delete(&AbbrevCursor, rc);
4179 if (RT_SUCCESS(rc))
4180 rc = pCursor->rc;
4181
4182 /*
4183 * Snoop up symbols on the way out.
4184 */
4185 if (RT_SUCCESS(rc) && fInitDie)
4186 {
4187 rc = rtDwarfInfo_SnoopSymbols(pThis, pDie);
4188 /* Ignore duplicates, get work done instead. */
4189 /** @todo clean up global/static symbol mess. */
4190 if (rc == VERR_DBG_DUPLICATE_SYMBOL)
4191 rc = VINF_SUCCESS;
4192 }
4193
4194 return rc;
4195}
4196
4197
4198/**
4199 * Load the debug information of a unit.
4200 *
4201 * @returns IPRT status code.
4202 * @param pThis The DWARF instance.
4203 * @param pCursor The debug_info cursor.
4204 * @param fKeepDies Whether to keep the DIEs or discard them as soon
4205 * as possible.
4206 */
4207static int rtDwarfInfo_LoadUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor, bool fKeepDies)
4208{
4209 Log(("rtDwarfInfo_LoadUnit: %#x\n", rtDwarfCursor_CalcSectOffsetU32(pCursor)));
4210
4211 /*
4212 * Read the compilation unit header.
4213 */
4214 uint64_t offUnit = rtDwarfCursor_CalcSectOffsetU32(pCursor);
4215 uint64_t cbUnit = rtDwarfCursor_GetInitalLength(pCursor);
4216 cbUnit += rtDwarfCursor_CalcSectOffsetU32(pCursor) - offUnit;
4217 uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
4218 if ( uVer < 2
4219 || uVer > 4)
4220 return rtDwarfCursor_SkipUnit(pCursor);
4221 uint64_t const offAbbrev = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
4222 uint8_t const cbNativeAddr = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
4223 if (RT_FAILURE(pCursor->rc))
4224 return pCursor->rc;
4225 Log((" uVer=%d offAbbrev=%#llx cbNativeAddr=%d\n", uVer, offAbbrev, cbNativeAddr));
4226
4227 /*
4228 * Set up the abbreviation cache and store the native address size in the cursor.
4229 */
4230 if (offAbbrev > UINT32_MAX)
4231 {
4232 Log(("Unexpected abbrviation code offset of %#llx\n", offAbbrev));
4233 return VERR_DWARF_BAD_INFO;
4234 }
4235 rtDwarfAbbrev_SetUnitOffset(pThis, (uint32_t)offAbbrev);
4236 pCursor->cbNativeAddr = cbNativeAddr;
4237
4238 /*
4239 * The first DIE is a compile or partial unit, parse it here.
4240 */
4241 uint32_t uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
4242 if (!uAbbrCode)
4243 {
4244 Log(("Unexpected abbrviation code of zero\n"));
4245 return VERR_DWARF_BAD_INFO;
4246 }
4247 PCRTDWARFABBREV pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
4248 if (!pAbbrev)
4249 return VERR_DWARF_ABBREV_NOT_FOUND;
4250 if ( pAbbrev->uTag != DW_TAG_compile_unit
4251 && pAbbrev->uTag != DW_TAG_partial_unit)
4252 {
4253 Log(("Unexpected compile/partial unit tag %#x\n", pAbbrev->uTag));
4254 return VERR_DWARF_BAD_INFO;
4255 }
4256
4257 PRTDWARFDIECOMPILEUNIT pUnit;
4258 pUnit = (PRTDWARFDIECOMPILEUNIT)rtDwarfInfo_NewDie(pThis, &g_CompileUnitDesc, pAbbrev, NULL /*pParent*/);
4259 if (!pUnit)
4260 return VERR_NO_MEMORY;
4261 pUnit->offUnit = offUnit;
4262 pUnit->cbUnit = cbUnit;
4263 pUnit->offAbbrev = offAbbrev;
4264 pUnit->cbNativeAddr = cbNativeAddr;
4265 pUnit->uDwarfVer = (uint8_t)uVer;
4266 RTListAppend(&pThis->CompileUnitList, &pUnit->Core.SiblingNode);
4267
4268 int rc = rtDwarfInfo_ParseDie(pThis, &pUnit->Core, &g_CompileUnitDesc, pCursor, pAbbrev, true /*fInitDie*/);
4269 if (RT_FAILURE(rc))
4270 return rc;
4271
4272 /*
4273 * Parse DIEs.
4274 */
4275 uint32_t cDepth = 0;
4276 PRTDWARFDIE pParentDie = &pUnit->Core;
4277 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
4278 {
4279#ifdef LOG_ENABLED
4280 uint32_t offLog = rtDwarfCursor_CalcSectOffsetU32(pCursor);
4281#endif
4282 uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
4283 if (!uAbbrCode)
4284 {
4285 /* End of siblings, up one level. (Is this correct?) */
4286 pParentDie = pParentDie->pParent;
4287 if (!pParentDie)
4288 {
4289 /* Padding. */
4290 while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
4291 {
4292 uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
4293 if (uAbbrCode)
4294 {
4295 Log(("%08x: End of DIE stack, but still more info to parse: uAbbrCode=%#x (+%u bytes).\n",
4296 offLog, uAbbrCode, pCursor->cbUnitLeft));
4297 return VERR_DWARF_BAD_INFO;
4298 }
4299 }
4300 break;
4301 }
4302 cDepth--;
4303 if (!fKeepDies && pParentDie->pParent)
4304 rtDwarfInfo_FreeChildren(pThis, pParentDie);
4305 }
4306 else
4307 {
4308 /*
4309 * Look up the abbreviation and match the tag up with a descriptor.
4310 */
4311 pAbbrev = rtDwarfAbbrev_Lookup(pThis, uAbbrCode);
4312 if (!pAbbrev)
4313 return VERR_DWARF_ABBREV_NOT_FOUND;
4314
4315 PCRTDWARFDIEDESC pDieDesc;
4316 const char *pszName;
4317 if (pAbbrev->uTag < RT_ELEMENTS(g_aTagDescs))
4318 {
4319 Assert(g_aTagDescs[pAbbrev->uTag].uTag == pAbbrev->uTag || g_aTagDescs[pAbbrev->uTag].uTag == 0);
4320 pszName = g_aTagDescs[pAbbrev->uTag].pszName;
4321 pDieDesc = g_aTagDescs[pAbbrev->uTag].pDesc;
4322 }
4323 else
4324 {
4325 pszName = "<unknown>";
4326 pDieDesc = g_aTagDescs[0].pDesc;
4327 }
4328 Log4(("%08x: %*stag=%s (%#x)%s\n", offLog, cDepth * 2, "", pszName,
4329 pAbbrev->uTag, pAbbrev->fChildren ? " has children" : ""));
4330
4331 /*
4332 * Create a new internal DIE structure and parse the
4333 * attributes.
4334 */
4335 PRTDWARFDIE pNewDie = rtDwarfInfo_NewDie(pThis, pDieDesc, pAbbrev, pParentDie);
4336 if (!pNewDie)
4337 return VERR_NO_MEMORY;
4338
4339 if (pAbbrev->fChildren)
4340 {
4341 pParentDie = pNewDie;
4342 cDepth++;
4343 }
4344
4345 rc = rtDwarfInfo_ParseDie(pThis, pNewDie, pDieDesc, pCursor, pAbbrev, true /*fInitDie*/);
4346 if (RT_FAILURE(rc))
4347 return rc;
4348
4349 if (!fKeepDies && !pAbbrev->fChildren)
4350 rtDwarfInfo_FreeDie(pThis, pNewDie);
4351 }
4352 } /* while more DIEs */
4353
4354
4355 /* Unlink and free child DIEs if told to do so. */
4356 if (!fKeepDies)
4357 rtDwarfInfo_FreeChildren(pThis, &pUnit->Core);
4358
4359 return RT_SUCCESS(rc) ? pCursor->rc : rc;
4360}
4361
4362
4363/**
4364 * Extracts the symbols.
4365 *
4366 * The symbols are insered into the debug info container.
4367 *
4368 * @returns IPRT status code
4369 * @param pThis The DWARF instance.
4370 */
4371static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis)
4372{
4373 RTDWARFCURSOR Cursor;
4374 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
4375 if (RT_SUCCESS(rc))
4376 {
4377 while ( !rtDwarfCursor_IsAtEnd(&Cursor)
4378 && RT_SUCCESS(rc))
4379 rc = rtDwarfInfo_LoadUnit(pThis, &Cursor, false /* fKeepDies */);
4380
4381 rc = rtDwarfCursor_Delete(&Cursor, rc);
4382 }
4383 return rc;
4384}
4385
4386
4387
4388
4389/*
4390 *
4391 * DWARF Debug module implementation.
4392 * DWARF Debug module implementation.
4393 * DWARF Debug module implementation.
4394 *
4395 */
4396
4397
4398/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByAddr} */
4399static DECLCALLBACK(int) rtDbgModDwarf_LineByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off,
4400 PRTINTPTR poffDisp, PRTDBGLINE pLineInfo)
4401{
4402 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4403 return RTDbgModLineByAddr(pThis->hCnt, iSeg, off, poffDisp, pLineInfo);
4404}
4405
4406
4407/** @interface_method_impl{RTDBGMODVTDBG,pfnLineByOrdinal} */
4408static DECLCALLBACK(int) rtDbgModDwarf_LineByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo)
4409{
4410 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4411 return RTDbgModLineByOrdinal(pThis->hCnt, iOrdinal, pLineInfo);
4412}
4413
4414
4415/** @interface_method_impl{RTDBGMODVTDBG,pfnLineCount} */
4416static DECLCALLBACK(uint32_t) rtDbgModDwarf_LineCount(PRTDBGMODINT pMod)
4417{
4418 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4419 return RTDbgModLineCount(pThis->hCnt);
4420}
4421
4422
4423/** @interface_method_impl{RTDBGMODVTDBG,pfnLineAdd} */
4424static DECLCALLBACK(int) rtDbgModDwarf_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
4425 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
4426{
4427 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4428 Assert(!pszFile[cchFile]); NOREF(cchFile);
4429 return RTDbgModLineAdd(pThis->hCnt, pszFile, uLineNo, iSeg, off, piOrdinal);
4430}
4431
4432
4433/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByAddr} */
4434static DECLCALLBACK(int) rtDbgModDwarf_SymbolByAddr(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
4435 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo)
4436{
4437 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4438 return RTDbgModSymbolByAddr(pThis->hCnt, iSeg, off, fFlags, poffDisp, pSymInfo);
4439}
4440
4441
4442/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByName} */
4443static DECLCALLBACK(int) rtDbgModDwarf_SymbolByName(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
4444 PRTDBGSYMBOL pSymInfo)
4445{
4446 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4447 Assert(!pszSymbol[cchSymbol]);
4448 return RTDbgModSymbolByName(pThis->hCnt, pszSymbol/*, cchSymbol*/, pSymInfo);
4449}
4450
4451
4452/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolByOrdinal} */
4453static DECLCALLBACK(int) rtDbgModDwarf_SymbolByOrdinal(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo)
4454{
4455 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4456 return RTDbgModSymbolByOrdinal(pThis->hCnt, iOrdinal, pSymInfo);
4457}
4458
4459
4460/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolCount} */
4461static DECLCALLBACK(uint32_t) rtDbgModDwarf_SymbolCount(PRTDBGMODINT pMod)
4462{
4463 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4464 return RTDbgModSymbolCount(pThis->hCnt);
4465}
4466
4467
4468/** @interface_method_impl{RTDBGMODVTDBG,pfnSymbolAdd} */
4469static DECLCALLBACK(int) rtDbgModDwarf_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
4470 RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
4471 uint32_t *piOrdinal)
4472{
4473 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4474 Assert(!pszSymbol[cchSymbol]); NOREF(cchSymbol);
4475 return RTDbgModSymbolAdd(pThis->hCnt, pszSymbol, iSeg, off, cb, fFlags, piOrdinal);
4476}
4477
4478
4479/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentByIndex} */
4480static DECLCALLBACK(int) rtDbgModDwarf_SegmentByIndex(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo)
4481{
4482 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4483 return RTDbgModSegmentByIndex(pThis->hCnt, iSeg, pSegInfo);
4484}
4485
4486
4487/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentCount} */
4488static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_SegmentCount(PRTDBGMODINT pMod)
4489{
4490 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4491 return RTDbgModSegmentCount(pThis->hCnt);
4492}
4493
4494
4495/** @interface_method_impl{RTDBGMODVTDBG,pfnSegmentAdd} */
4496static DECLCALLBACK(int) rtDbgModDwarf_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
4497 uint32_t fFlags, PRTDBGSEGIDX piSeg)
4498{
4499 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4500 Assert(!pszName[cchName]); NOREF(cchName);
4501 return RTDbgModSegmentAdd(pThis->hCnt, uRva, cb, pszName, fFlags, piSeg);
4502}
4503
4504
4505/** @interface_method_impl{RTDBGMODVTDBG,pfnImageSize} */
4506static DECLCALLBACK(RTUINTPTR) rtDbgModDwarf_ImageSize(PRTDBGMODINT pMod)
4507{
4508 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4509 RTUINTPTR cb1 = RTDbgModImageSize(pThis->hCnt);
4510 RTUINTPTR cb2 = pThis->pImgMod->pImgVt->pfnImageSize(pMod);
4511 return RT_MAX(cb1, cb2);
4512}
4513
4514
4515/** @interface_method_impl{RTDBGMODVTDBG,pfnRvaToSegOff} */
4516static DECLCALLBACK(RTDBGSEGIDX) rtDbgModDwarf_RvaToSegOff(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg)
4517{
4518 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4519 return RTDbgModRvaToSegOff(pThis->hCnt, uRva, poffSeg);
4520}
4521
4522
4523/** @interface_method_impl{RTDBGMODVTDBG,pfnClose} */
4524static DECLCALLBACK(int) rtDbgModDwarf_Close(PRTDBGMODINT pMod)
4525{
4526 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pMod->pvDbgPriv;
4527
4528 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
4529 if (pThis->aSections[iSect].pv)
4530 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb, &pThis->aSections[iSect].pv);
4531
4532 RTDbgModRelease(pThis->hCnt);
4533 RTMemFree(pThis->paCachedAbbrevs);
4534 if (pThis->pNestedMod)
4535 {
4536 pThis->pNestedMod->pImgVt->pfnClose(pThis->pNestedMod);
4537 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszName);
4538 RTStrCacheRelease(g_hDbgModStrCache, pThis->pNestedMod->pszDbgFile);
4539 RTMemFree(pThis->pNestedMod);
4540 pThis->pNestedMod = NULL;
4541 }
4542
4543#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
4544 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
4545 while (i-- > 0)
4546 {
4547 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
4548 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
4549 }
4550#endif
4551
4552 RTMemFree(pThis);
4553
4554 return VINF_SUCCESS;
4555}
4556
4557
4558/** @callback_method_impl{FNRTLDRENUMDBG} */
4559static DECLCALLBACK(int) rtDbgModDwarfEnumCallback(RTLDRMOD hLdrMod, PCRTLDRDBGINFO pDbgInfo, void *pvUser)
4560{
4561 /*
4562 * Skip stuff we can't handle.
4563 */
4564 if (pDbgInfo->enmType != RTLDRDBGINFOTYPE_DWARF)
4565 return VINF_SUCCESS;
4566 const char *pszSection = pDbgInfo->u.Dwarf.pszSection;
4567 if (!pszSection || !*pszSection)
4568 return VINF_SUCCESS;
4569 Assert(!pDbgInfo->pszExtFile);
4570
4571 /*
4572 * Must have a part name starting with debug_ and possibly prefixed by dots
4573 * or underscores.
4574 */
4575 if (!strncmp(pszSection, RT_STR_TUPLE(".debug_"))) /* ELF */
4576 pszSection += sizeof(".debug_") - 1;
4577 else if (!strncmp(pszSection, RT_STR_TUPLE("__debug_"))) /* Mach-O */
4578 pszSection += sizeof("__debug_") - 1;
4579 else if (!strcmp(pszSection, ".WATCOM_references"))
4580 return VINF_SUCCESS; /* Ignore special watcom section for now.*/
4581 else
4582 AssertMsgFailedReturn(("%s\n", pszSection), VINF_SUCCESS /*ignore*/);
4583
4584 /*
4585 * Figure out which part we're talking about.
4586 */
4587 krtDbgModDwarfSect enmSect;
4588 if (0) { /* dummy */ }
4589#define ELSE_IF_STRCMP_SET(a_Name) else if (!strcmp(pszSection, #a_Name)) enmSect = krtDbgModDwarfSect_ ## a_Name
4590 ELSE_IF_STRCMP_SET(abbrev);
4591 ELSE_IF_STRCMP_SET(aranges);
4592 ELSE_IF_STRCMP_SET(frame);
4593 ELSE_IF_STRCMP_SET(info);
4594 ELSE_IF_STRCMP_SET(inlined);
4595 ELSE_IF_STRCMP_SET(line);
4596 ELSE_IF_STRCMP_SET(loc);
4597 ELSE_IF_STRCMP_SET(macinfo);
4598 ELSE_IF_STRCMP_SET(pubnames);
4599 ELSE_IF_STRCMP_SET(pubtypes);
4600 ELSE_IF_STRCMP_SET(ranges);
4601 ELSE_IF_STRCMP_SET(str);
4602 ELSE_IF_STRCMP_SET(types);
4603#undef ELSE_IF_STRCMP_SET
4604 else
4605 {
4606 AssertMsgFailed(("%s\n", pszSection));
4607 return VINF_SUCCESS;
4608 }
4609
4610 /*
4611 * Record the section.
4612 */
4613 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)pvUser;
4614 AssertMsgReturn(!pThis->aSections[enmSect].fPresent, ("duplicate %s\n", pszSection), VINF_SUCCESS /*ignore*/);
4615
4616 pThis->aSections[enmSect].fPresent = true;
4617 pThis->aSections[enmSect].offFile = pDbgInfo->offFile;
4618 pThis->aSections[enmSect].pv = NULL;
4619 pThis->aSections[enmSect].cb = (size_t)pDbgInfo->cb;
4620 pThis->aSections[enmSect].iDbgInfo = pDbgInfo->iDbgInfo;
4621 if (pThis->aSections[enmSect].cb != pDbgInfo->cb)
4622 pThis->aSections[enmSect].cb = ~(size_t)0;
4623
4624 return VINF_SUCCESS;
4625}
4626
4627
4628static int rtDbgModDwarfTryOpenDbgFile(PRTDBGMODINT pDbgMod, PRTDBGMODDWARF pThis, RTLDRARCH enmArch)
4629{
4630 if ( !pDbgMod->pszDbgFile
4631 || RTPathIsSame(pDbgMod->pszDbgFile, pDbgMod->pszImgFile) == (int)true /* returns VERR too */)
4632 return VERR_DBG_NO_MATCHING_INTERPRETER;
4633
4634 /*
4635 * Only open the image.
4636 */
4637 PRTDBGMODINT pDbgInfoMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgInfoMod));
4638 if (!pDbgInfoMod)
4639 return VERR_NO_MEMORY;
4640
4641 int rc;
4642 pDbgInfoMod->u32Magic = RTDBGMOD_MAGIC;
4643 pDbgInfoMod->cRefs = 1;
4644 if (RTStrCacheRetain(pDbgMod->pszDbgFile) != UINT32_MAX)
4645 {
4646 pDbgInfoMod->pszImgFile = pDbgMod->pszDbgFile;
4647 if (RTStrCacheRetain(pDbgMod->pszName) != UINT32_MAX)
4648 {
4649 pDbgInfoMod->pszName = pDbgMod->pszName;
4650 pDbgInfoMod->pImgVt = &g_rtDbgModVtImgLdr;
4651 rc = pDbgInfoMod->pImgVt->pfnTryOpen(pDbgInfoMod, enmArch);
4652 if (RT_SUCCESS(rc))
4653 {
4654 pThis->pDbgInfoMod = pDbgInfoMod;
4655 pThis->pNestedMod = pDbgInfoMod;
4656 return VINF_SUCCESS;
4657 }
4658
4659 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszName);
4660 }
4661 else
4662 rc = VERR_NO_STR_MEMORY;
4663 RTStrCacheRelease(g_hDbgModStrCache, pDbgInfoMod->pszImgFile);
4664 }
4665 else
4666 rc = VERR_NO_STR_MEMORY;
4667 RTMemFree(pDbgInfoMod);
4668 return rc;
4669}
4670
4671
4672/** @interface_method_impl{RTDBGMODVTDBG,pfnTryOpen} */
4673static DECLCALLBACK(int) rtDbgModDwarf_TryOpen(PRTDBGMODINT pMod, RTLDRARCH enmArch)
4674{
4675 /*
4676 * DWARF is only supported when part of an image.
4677 */
4678 if (!pMod->pImgVt)
4679 return VERR_DBG_NO_MATCHING_INTERPRETER;
4680
4681 /*
4682 * Create the module instance data.
4683 */
4684 PRTDBGMODDWARF pThis = (PRTDBGMODDWARF)RTMemAllocZ(sizeof(*pThis));
4685 if (!pThis)
4686 return VERR_NO_MEMORY;
4687 pThis->pDbgInfoMod = pMod;
4688 pThis->pImgMod = pMod;
4689 RTListInit(&pThis->CompileUnitList);
4690
4691#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
4692 AssertCompile(RT_ELEMENTS(pThis->aDieAllocators) == 2);
4693 pThis->aDieAllocators[0].cbMax = sizeof(RTDWARFDIE);
4694 pThis->aDieAllocators[1].cbMax = sizeof(RTDWARFDIECOMPILEUNIT);
4695 for (uint32_t i = 0; i < RT_ELEMENTS(g_aTagDescs); i++)
4696 if (g_aTagDescs[i].pDesc && g_aTagDescs[i].pDesc->cbDie > pThis->aDieAllocators[1].cbMax)
4697 pThis->aDieAllocators[1].cbMax = (uint32_t)g_aTagDescs[i].pDesc->cbDie;
4698 pThis->aDieAllocators[1].cbMax = RT_ALIGN_32(pThis->aDieAllocators[1].cbMax, sizeof(uint64_t));
4699
4700 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aDieAllocators); i++)
4701 {
4702 int rc = RTMemCacheCreate(&pThis->aDieAllocators[i].hMemCache, pThis->aDieAllocators[i].cbMax, sizeof(uint64_t),
4703 UINT32_MAX, NULL /*pfnCtor*/, NULL /*pfnDtor*/, NULL /*pvUser*/, 0 /*fFlags*/);
4704 if (RT_FAILURE(rc))
4705 {
4706 while (i-- > 0)
4707 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
4708 RTMemFree(pThis);
4709 return rc;
4710 }
4711 }
4712#endif
4713
4714 /*
4715 * If the debug file name is set, let's see if it's an ELF image with DWARF
4716 * inside it. In that case we'll have to deal with two image modules, one
4717 * for segments and address translation and one for the debug information.
4718 */
4719 if (pMod->pszDbgFile != NULL)
4720 rtDbgModDwarfTryOpenDbgFile(pMod, pThis, enmArch);
4721
4722 /*
4723 * Enumerate the debug info in the module, looking for DWARF bits.
4724 */
4725 int rc = pThis->pDbgInfoMod->pImgVt->pfnEnumDbgInfo(pThis->pDbgInfoMod, rtDbgModDwarfEnumCallback, pThis);
4726 if (RT_SUCCESS(rc))
4727 {
4728 if (pThis->aSections[krtDbgModDwarfSect_info].fPresent)
4729 {
4730 /*
4731 * Extract / explode the data we want (symbols and line numbers)
4732 * storing them in a container module.
4733 */
4734 rc = RTDbgModCreate(&pThis->hCnt, pMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
4735 if (RT_SUCCESS(rc))
4736 {
4737 pMod->pvDbgPriv = pThis;
4738
4739 rc = rtDbgModDwarfAddSegmentsFromImage(pThis);
4740 if (RT_SUCCESS(rc))
4741 rc = rtDwarfInfo_LoadAll(pThis);
4742 if (RT_SUCCESS(rc))
4743 rc = rtDwarfLine_ExplodeAll(pThis);
4744 if (RT_SUCCESS(rc) && pThis->iWatcomPass == 1)
4745 {
4746 rc = rtDbgModDwarfAddSegmentsFromPass1(pThis);
4747 pThis->iWatcomPass = 2;
4748 if (RT_SUCCESS(rc))
4749 rc = rtDwarfInfo_LoadAll(pThis);
4750 if (RT_SUCCESS(rc))
4751 rc = rtDwarfLine_ExplodeAll(pThis);
4752 }
4753 if (RT_SUCCESS(rc))
4754 {
4755 /*
4756 * Free the cached abbreviations and unload all sections.
4757 */
4758 pThis->cCachedAbbrevs = pThis->cCachedAbbrevsAlloced = 0;
4759 RTMemFree(pThis->paCachedAbbrevs);
4760
4761 for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
4762 if (pThis->aSections[iSect].pv)
4763 pThis->pDbgInfoMod->pImgVt->pfnUnmapPart(pThis->pDbgInfoMod, pThis->aSections[iSect].cb,
4764 &pThis->aSections[iSect].pv);
4765
4766 /** @todo Kill pThis->CompileUnitList and the alloc caches. */
4767 return VINF_SUCCESS;
4768 }
4769
4770 /* bail out. */
4771 RTDbgModRelease(pThis->hCnt);
4772 pMod->pvDbgPriv = NULL;
4773 }
4774 }
4775 else
4776 rc = VERR_DBG_NO_MATCHING_INTERPRETER;
4777 }
4778
4779 RTMemFree(pThis->paCachedAbbrevs);
4780
4781#ifdef RTDBGMODDWARF_WITH_MEM_CACHE
4782 uint32_t i = RT_ELEMENTS(pThis->aDieAllocators);
4783 while (i-- > 0)
4784 {
4785 RTMemCacheDestroy(pThis->aDieAllocators[i].hMemCache);
4786 pThis->aDieAllocators[i].hMemCache = NIL_RTMEMCACHE;
4787 }
4788#endif
4789
4790 RTMemFree(pThis);
4791
4792 return rc;
4793}
4794
4795
4796
4797/** Virtual function table for the DWARF debug info reader. */
4798DECL_HIDDEN_CONST(RTDBGMODVTDBG) const g_rtDbgModVtDbgDwarf =
4799{
4800 /*.u32Magic = */ RTDBGMODVTDBG_MAGIC,
4801 /*.fSupports = */ RT_DBGTYPE_DWARF,
4802 /*.pszName = */ "dwarf",
4803 /*.pfnTryOpen = */ rtDbgModDwarf_TryOpen,
4804 /*.pfnClose = */ rtDbgModDwarf_Close,
4805
4806 /*.pfnRvaToSegOff = */ rtDbgModDwarf_RvaToSegOff,
4807 /*.pfnImageSize = */ rtDbgModDwarf_ImageSize,
4808
4809 /*.pfnSegmentAdd = */ rtDbgModDwarf_SegmentAdd,
4810 /*.pfnSegmentCount = */ rtDbgModDwarf_SegmentCount,
4811 /*.pfnSegmentByIndex = */ rtDbgModDwarf_SegmentByIndex,
4812
4813 /*.pfnSymbolAdd = */ rtDbgModDwarf_SymbolAdd,
4814 /*.pfnSymbolCount = */ rtDbgModDwarf_SymbolCount,
4815 /*.pfnSymbolByOrdinal = */ rtDbgModDwarf_SymbolByOrdinal,
4816 /*.pfnSymbolByName = */ rtDbgModDwarf_SymbolByName,
4817 /*.pfnSymbolByAddr = */ rtDbgModDwarf_SymbolByAddr,
4818
4819 /*.pfnLineAdd = */ rtDbgModDwarf_LineAdd,
4820 /*.pfnLineCount = */ rtDbgModDwarf_LineCount,
4821 /*.pfnLineByOrdinal = */ rtDbgModDwarf_LineByOrdinal,
4822 /*.pfnLineByAddr = */ rtDbgModDwarf_LineByAddr,
4823
4824 /*.u32EndMagic = */ RTDBGMODVTDBG_MAGIC
4825};
4826
Note: See TracBrowser for help on using the repository browser.

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