VirtualBox

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

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

DWARF: Watcom segment detection and wasm/wlink labels.

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