VirtualBox

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

Last change on this file since 73895 was 73537, checked in by vboxsync, 6 years ago

IPRT: Some more work on stack unwinding using dwarf info. bugref:3897

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