VirtualBox

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

Last change on this file since 47332 was 47332, checked in by vboxsync, 12 years ago

Runtime/dbgmoddwarf: Ignore a few more sections emitted by apple llvm-clang

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