Rizin
unix-like reverse engineering framework and cli tools
dwarf.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2012-2018 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2012-2018 Fedor Sakharov <fedor.sakharov@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #define D0 if (1)
6 #define D1 if (1)
7 
8 #include <errno.h>
9 
10 #define DWARF_DUMP 0
11 
12 #if DWARF_DUMP
13 #define DBGFD stdout
14 #else
15 #define DBGFD NULL
16 #endif
17 
18 #include <rz_bin.h>
19 #include <rz_bin_dwarf.h>
20 #include <rz_core.h>
21 
22 #define STANDARD_OPERAND_COUNT_DWARF2 9
23 #define STANDARD_OPERAND_COUNT_DWARF3 12
24 #define RZ_BIN_DWARF_INFO 1
25 
26 #define READ8(buf) \
27  (((buf) + 1 < buf_end) ? *((ut8 *)(buf)) : 0); \
28  (buf)++
29 #define READ16(buf) \
30  (((buf) + sizeof(ut16) < buf_end) ? rz_read_ble16(buf, big_endian) : 0); \
31  (buf) += sizeof(ut16)
32 #define READ32(buf) \
33  (((buf) + sizeof(ut32) < buf_end) ? rz_read_ble32(buf, big_endian) : 0); \
34  (buf) += sizeof(ut32)
35 #define READ64(buf) \
36  (((buf) + sizeof(ut64) < buf_end) ? rz_read_ble64(buf, big_endian) : 0); \
37  (buf) += sizeof(ut64)
38 
39 static const char *dwarf_tag_name_encodings[] = {
40  [DW_TAG_null_entry] = "DW_TAG_null_entry",
41  [DW_TAG_array_type] = "DW_TAG_array_type",
42  [DW_TAG_class_type] = "DW_TAG_class_type",
43  [DW_TAG_entry_point] = "DW_TAG_entry_point",
44  [DW_TAG_enumeration_type] = "DW_TAG_enumeration_type",
45  [DW_TAG_formal_parameter] = "DW_TAG_formal_parameter",
46  [DW_TAG_imported_declaration] = "DW_TAG_imported_declaration",
47  [DW_TAG_label] = "DW_TAG_label",
48  [DW_TAG_lexical_block] = "DW_TAG_lexical_block",
49  [DW_TAG_member] = "DW_TAG_member",
50  [DW_TAG_pointer_type] = "DW_TAG_pointer_type",
51  [DW_TAG_reference_type] = "DW_TAG_reference_type",
52  [DW_TAG_compile_unit] = "DW_TAG_compile_unit",
53  [DW_TAG_string_type] = "DW_TAG_string_type",
54  [DW_TAG_structure_type] = "DW_TAG_structure_type",
55  [DW_TAG_subroutine_type] = "DW_TAG_subroutine_type",
56  [DW_TAG_typedef] = "DW_TAG_typedef",
57  [DW_TAG_union_type] = "DW_TAG_union_type",
58  [DW_TAG_unspecified_parameters] = "DW_TAG_unspecified_parameters",
59  [DW_TAG_variant] = "DW_TAG_variant",
60  [DW_TAG_common_block] = "DW_TAG_common_block",
61  [DW_TAG_common_inclusion] = "DW_TAG_common_inclusion",
62  [DW_TAG_inheritance] = "DW_TAG_inheritance",
63  [DW_TAG_inlined_subroutine] = "DW_TAG_inlined_subroutine",
64  [DW_TAG_module] = "DW_TAG_module",
65  [DW_TAG_ptr_to_member_type] = "DW_TAG_ptr_to_member_type",
66  [DW_TAG_set_type] = "DW_TAG_set_type",
67  [DW_TAG_subrange_type] = "DW_TAG_subrange_type",
68  [DW_TAG_with_stmt] = "DW_TAG_with_stmt",
69  [DW_TAG_access_declaration] = "DW_TAG_access_declaration",
70  [DW_TAG_base_type] = "DW_TAG_base_type",
71  [DW_TAG_catch_block] = "DW_TAG_catch_block",
72  [DW_TAG_const_type] = "DW_TAG_const_type",
73  [DW_TAG_constant] = "DW_TAG_constant",
74  [DW_TAG_enumerator] = "DW_TAG_enumerator",
75  [DW_TAG_file_type] = "DW_TAG_file_type",
76  [DW_TAG_friend] = "DW_TAG_friend",
77  [DW_TAG_namelist] = "DW_TAG_namelist",
78  [DW_TAG_namelist_item] = "DW_TAG_namelist_item",
79  [DW_TAG_packed_type] = "DW_TAG_packed_type",
80  [DW_TAG_subprogram] = "DW_TAG_subprogram",
81  [DW_TAG_template_type_param] = "DW_TAG_template_type_param",
82  [DW_TAG_template_value_param] = "DW_TAG_template_value_param",
83  [DW_TAG_thrown_type] = "DW_TAG_thrown_type",
84  [DW_TAG_try_block] = "DW_TAG_try_block",
85  [DW_TAG_variant_part] = "DW_TAG_variant_part",
86  [DW_TAG_variable] = "DW_TAG_variable",
87  [DW_TAG_volatile_type] = "DW_TAG_volatile_type",
88  [DW_TAG_dwarf_procedure] = "DW_TAG_dwarf_procedure",
89  [DW_TAG_restrict_type] = "DW_TAG_restrict_type",
90  [DW_TAG_interface_type] = "DW_TAG_interface_type",
91  [DW_TAG_namespace] = "DW_TAG_namespace",
92  [DW_TAG_imported_module] = "DW_TAG_imported_module",
93  [DW_TAG_unspecified_type] = "DW_TAG_unspecified_type",
94  [DW_TAG_partial_unit] = "DW_TAG_partial_unit",
95  [DW_TAG_imported_unit] = "DW_TAG_imported_unit",
96  [DW_TAG_mutable_type] = "DW_TAG_mutable_type",
97  [DW_TAG_condition] = "DW_TAG_condition",
98  [DW_TAG_shared_type] = "DW_TAG_shared_type",
99  [DW_TAG_type_unit] = "DW_TAG_type_unit",
100  [DW_TAG_rvalue_reference_type] = "DW_TAG_rvalue_reference_type",
101  [DW_TAG_template_alias] = "DW_TAG_template_alias",
102  [DW_TAG_LAST] = "DW_TAG_LAST",
103 };
104 
105 static const char *dwarf_attr_encodings[] = {
106  [DW_AT_sibling] = "DW_AT_siblings",
107  [DW_AT_location] = "DW_AT_location",
108  [DW_AT_name] = "DW_AT_name",
109  [DW_AT_ordering] = "DW_AT_ordering",
110  [DW_AT_byte_size] = "DW_AT_byte_size",
111  [DW_AT_bit_size] = "DW_AT_bit_size",
112  [DW_AT_stmt_list] = "DW_AT_stmt_list",
113  [DW_AT_low_pc] = "DW_AT_low_pc",
114  [DW_AT_high_pc] = "DW_AT_high_pc",
115  [DW_AT_language] = "DW_AT_language",
116  [DW_AT_discr] = "DW_AT_discr",
117  [DW_AT_discr_value] = "DW_AT_discr_value",
118  [DW_AT_visibility] = "DW_AT_visibility",
119  [DW_AT_import] = "DW_AT_import",
120  [DW_AT_string_length] = "DW_AT_string_length",
121  [DW_AT_common_reference] = "DW_AT_common_reference",
122  [DW_AT_comp_dir] = "DW_AT_comp_dir",
123  [DW_AT_const_value] = "DW_AT_const_value",
124  [DW_AT_containing_type] = "DW_AT_containing_type",
125  [DW_AT_default_value] = "DW_AT_default_value",
126  [DW_AT_inline] = "DW_AT_inline",
127  [DW_AT_is_optional] = "DW_AT_is_optional",
128  [DW_AT_lower_bound] = "DW_AT_lower_bound",
129  [DW_AT_producer] = "DW_AT_producer",
130  [DW_AT_prototyped] = "DW_AT_prototyped",
131  [DW_AT_return_addr] = "DW_AT_return_addr",
132  [DW_AT_start_scope] = "DW_AT_start_scope",
133  [DW_AT_stride_size] = "DW_AT_stride_size",
134  [DW_AT_upper_bound] = "DW_AT_upper_bound",
135  [DW_AT_abstract_origin] = "DW_AT_abstract_origin",
136  [DW_AT_accessibility] = "DW_AT_accessibility",
137  [DW_AT_address_class] = "DW_AT_address_class",
138  [DW_AT_artificial] = "DW_AT_artificial",
139  [DW_AT_base_types] = "DW_AT_base_types",
140  [DW_AT_calling_convention] = "DW_AT_calling_convention",
141  [DW_AT_count] = "DW_AT_count",
142  [DW_AT_data_member_location] = "DW_AT_data_member_location",
143  [DW_AT_decl_column] = "DW_AT_decl_column",
144  [DW_AT_decl_file] = "DW_AT_decl_file",
145  [DW_AT_decl_line] = "DW_AT_decl_line",
146  [DW_AT_declaration] = "DW_AT_declaration",
147  [DW_AT_discr_list] = "DW_AT_discr_list",
148  [DW_AT_encoding] = "DW_AT_encoding",
149  [DW_AT_external] = "DW_AT_external",
150  [DW_AT_frame_base] = "DW_AT_frame_base",
151  [DW_AT_friend] = "DW_AT_friend",
152  [DW_AT_identifier_case] = "DW_AT_identifier_case",
153  [DW_AT_macro_info] = "DW_AT_macro_info",
154  [DW_AT_namelist_item] = "DW_AT_namelist_item",
155  [DW_AT_priority] = "DW_AT_priority",
156  [DW_AT_segment] = "DW_AT_segment",
157  [DW_AT_specification] = "DW_AT_specification",
158  [DW_AT_static_link] = "DW_AT_static_link",
159  [DW_AT_type] = "DW_AT_type",
160  [DW_AT_use_location] = "DW_AT_use_location",
161  [DW_AT_variable_parameter] = "DW_AT_variable_parameter",
162  [DW_AT_virtuality] = "DW_AT_virtuality",
163  [DW_AT_vtable_elem_location] = "DW_AT_vtable_elem_location",
164  [DW_AT_allocated] = "DW_AT_allocated",
165  [DW_AT_associated] = "DW_AT_associated",
166  [DW_AT_data_location] = "DW_AT_data_location",
167  [DW_AT_byte_stride] = "DW_AT_byte_stride",
168  [DW_AT_entry_pc] = "DW_AT_entry_pc",
169  [DW_AT_use_UTF8] = "DW_AT_use_UTF8",
170  [DW_AT_extension] = "DW_AT_extension",
171  [DW_AT_ranges] = "DW_AT_ranges",
172  [DW_AT_trampoline] = "DW_AT_trampoline",
173  [DW_AT_call_column] = "DW_AT_call_column",
174  [DW_AT_call_file] = "DW_AT_call_file",
175  [DW_AT_call_line] = "DW_AT_call_line",
176  [DW_AT_description] = "DW_AT_description",
177  [DW_AT_binary_scale] = "DW_AT_binary_scale",
178  [DW_AT_decimal_scale] = "DW_AT_decimal_scale",
179  [DW_AT_small] = "DW_AT_small",
180  [DW_AT_decimal_sign] = "DW_AT_decimal_sign",
181  [DW_AT_digit_count] = "DW_AT_digit_count",
182  [DW_AT_picture_string] = "DW_AT_picture_string",
183  [DW_AT_mutable] = "DW_AT_mutable",
184  [DW_AT_threads_scaled] = "DW_AT_threads_scaled",
185  [DW_AT_explicit] = "DW_AT_explicit",
186  [DW_AT_object_pointer] = "DW_AT_object_pointer",
187  [DW_AT_endianity] = "DW_AT_endianity",
188  [DW_AT_elemental] = "DW_AT_elemental",
189  [DW_AT_pure] = "DW_AT_pure",
190  [DW_AT_recursive] = "DW_AT_recursive",
191  [DW_AT_signature] = "DW_AT_signature",
192  [DW_AT_main_subprogram] = "DW_AT_main_subprogram",
193  [DW_AT_data_bit_offset] = "DW_AT_data_big_offset",
194  [DW_AT_const_expr] = "DW_AT_const_expr",
195  [DW_AT_enum_class] = "DW_AT_enum_class",
196  [DW_AT_linkage_name] = "DW_AT_linkage_name",
197  [DW_AT_string_length_bit_size] = "DW_AT_string_length_bit_size",
198  [DW_AT_string_length_byte_size] = "DW_AT_string_length_byte_size",
199  [DW_AT_rank] = "DW_AT_rank",
200  [DW_AT_str_offsets_base] = "DW_AT_str_offsets_base",
201  [DW_AT_addr_base] = "DW_AT_addr_base",
202  [DW_AT_rnglists_base] = "DW_AT_rnglists_base",
203  [DW_AT_dwo_name] = "DW_AT_dwo_name",
204  [DW_AT_reference] = "DW_AT_reference",
205  [DW_AT_rvalue_reference] = "DW_AT_rvalue_reference",
206  [DW_AT_macros] = "DW_AT_macros",
207  [DW_AT_call_all_calls] = "DW_AT_call_all_calls",
208  [DW_AT_call_all_source_calls] = "DW_AT_call_all_source_calls",
209  [DW_AT_call_all_tail_calls] = "DW_AT_call_all_tail_calls",
210  [DW_AT_call_return_pc] = "DW_AT_call_return_pc",
211  [DW_AT_call_value] = "DW_AT_call_value",
212  [DW_AT_call_origin] = "DW_AT_call_origin",
213  [DW_AT_call_parameter] = "DW_AT_call_parameter",
214  [DW_AT_call_pc] = "DW_AT_call_pc",
215  [DW_AT_call_tail_call] = "DW_AT_call_tail_call",
216  [DW_AT_call_target] = "DW_AT_call_target",
217  [DW_AT_call_target_clobbered] = "DW_AT_call_target_clobbered",
218  [DW_AT_call_data_location] = "DW_AT_call_data_location",
219  [DW_AT_call_data_value] = "DW_AT_call_data_value",
220  [DW_AT_noreturn] = "DW_AT_noreturn",
221  [DW_AT_alignment] = "DW_AT_alignment",
222  [DW_AT_export_symbols] = "DW_AT_export_symbols",
223  [DW_AT_deleted] = "DW_AT_deleted",
224  [DW_AT_defaulted] = "DW_AT_defaulted",
225  [DW_AT_loclists_base] = "DW_AT_loclists_base"
226 };
227 
228 static const char *dwarf_attr_form_encodings[] = {
229  [DW_FORM_addr] = "DW_FORM_addr",
230  [DW_FORM_block2] = "DW_FORM_block2",
231  [DW_FORM_block4] = "DW_FORM_block4",
232  [DW_FORM_data2] = "DW_FORM_data2",
233  [DW_FORM_data4] = "DW_FORM_data4",
234  [DW_FORM_data8] = "DW_FORM_data8",
235  [DW_FORM_string] = "DW_FORM_string",
236  [DW_FORM_block] = "DW_FORM_block",
237  [DW_FORM_block1] = "DW_FORM_block1",
238  [DW_FORM_data1] = "DW_FORM_data1",
239  [DW_FORM_flag] = "DW_FORM_flag",
240  [DW_FORM_sdata] = "DW_FORM_sdata",
241  [DW_FORM_strp] = "DW_FORM_strp",
242  [DW_FORM_udata] = "DW_FORM_udata",
243  [DW_FORM_ref_addr] = "DW_FORM_ref_addr",
244  [DW_FORM_ref1] = "DW_FORM_ref1",
245  [DW_FORM_ref2] = "DW_FORM_ref2",
246  [DW_FORM_ref4] = "DW_FORM_ref4",
247  [DW_FORM_ref8] = "DW_FORM_ref8",
248  [DW_FORM_ref_udata] = "DW_FORM_ref_udata",
249  [DW_FORM_indirect] = "DW_FORM_indirect",
250  [DW_FORM_sec_offset] = "DW_FORM_sec_offset",
251  [DW_FORM_exprloc] = "DW_FORM_exprloc",
252  [DW_FORM_flag_present] = "DW_FORM_flag_present",
253  [DW_FORM_strx] = "DW_FORM_strx",
254  [DW_FORM_addrx] = "DW_FORM_addrx",
255  [DW_FORM_ref_sup4] = "DW_FORM_ref_sup4",
256  [DW_FORM_strp_sup] = "DW_FORM_strp_sup",
257  [DW_FORM_data16] = "DW_FORM_data16",
258  [DW_FORM_line_ptr] = "DW_FORM_line_ptr",
259  [DW_FORM_ref_sig8] = "DW_FORM_ref_sig8",
260  [DW_FORM_implicit_const] = "DW_FORM_implicit_const",
261  [DW_FORM_loclistx] = "DW_FORM_loclistx",
262  [DW_FORM_rnglistx] = "DW_FORM_rnglistx",
263  [DW_FORM_ref_sup8] = "DW_FORM_ref_sup8",
264  [DW_FORM_strx1] = "DW_FORM_strx1",
265  [DW_FORM_strx2] = "DW_FORM_strx2",
266  [DW_FORM_strx3] = "DW_FORM_strx3",
267  [DW_FORM_strx4] = "DW_FORM_strx4",
268  [DW_FORM_addrx1] = "DW_FORM_addrx1",
269  [DW_FORM_addrx2] = "DW_FORM_addrx2",
270  [DW_FORM_addrx3] = "DW_FORM_addrx3",
271  [DW_FORM_addrx4] = "DW_FORM_addrx4",
272 };
273 
274 static const char *dwarf_langs[] = {
275  [DW_LANG_C89] = "C89",
276  [DW_LANG_C] = "C",
277  [DW_LANG_Ada83] = "Ada83",
278  [DW_LANG_C_plus_plus] = "C++",
279  [DW_LANG_Cobol74] = "Cobol74",
280  [DW_LANG_Cobol85] = "Cobol85",
281  [DW_LANG_Fortran77] = "Fortran77",
282  [DW_LANG_Fortran90] = "Fortran90",
283  [DW_LANG_Pascal83] = "Pascal83",
284  [DW_LANG_Modula2] = "Modula2",
285  [DW_LANG_Java] = "Java",
286  [DW_LANG_C99] = "C99",
287  [DW_LANG_Ada95] = "Ada95",
288  [DW_LANG_Fortran95] = "Fortran95",
289  [DW_LANG_PLI] = "PLI",
290  [DW_LANG_ObjC] = "ObjC",
291  [DW_LANG_ObjC_plus_plus] = "ObjC_plus_plus",
292  [DW_LANG_UPC] = "UPC",
293  [DW_LANG_D] = "D",
294  [DW_LANG_Python] = "Python",
295  [DW_LANG_Rust] = "Rust",
296  [DW_LANG_C11] = "C11",
297  [DW_LANG_Swift] = "Swift",
298  [DW_LANG_Julia] = "Julia",
299  [DW_LANG_Dylan] = "Dylan",
300  [DW_LANG_C_plus_plus_14] = "C++14",
301  [DW_LANG_Fortran03] = "Fortran03",
302  [DW_LANG_Fortran08] = "Fortran08"
303 };
304 
305 static const char *dwarf_unit_types[] = {
306  [DW_UT_compile] = "DW_UT_compile",
307  [DW_UT_type] = "DW_UT_type",
308  [DW_UT_partial] = "DW_UT_partial",
309  [DW_UT_skeleton] = "DW_UT_skeleton",
310  [DW_UT_split_compile] = "DW_UT_split_compile",
311  [DW_UT_split_type] = "DW_UT_split_type",
312  [DW_UT_lo_user] = "DW_UT_lo_user",
313  [DW_UT_hi_user] = "DW_UT_hi_user",
314 };
315 
317  if (tag >= DW_TAG_LAST) {
318  return NULL;
319  }
321 }
322 
323 RZ_API const char *rz_bin_dwarf_get_attr_name(ut64 attr_code) {
324  if (attr_code < RZ_ARRAY_SIZE(dwarf_attr_encodings)) {
325  return dwarf_attr_encodings[attr_code];
326  }
327  // the below codes are much sparser, so putting them in an array would require a lot of
328  // unused memory
329  switch (attr_code) {
330  case DW_AT_lo_user:
331  return "DW_AT_lo_user";
333  return "DW_AT_MIPS_linkage_name";
335  return "DW_AT_GNU_call_site_value";
337  return "DW_AT_GNU_call_site_data_value";
339  return "DW_AT_GNU_call_site_target";
341  return "DW_AT_GNU_call_site_target_clobbered";
342  case DW_AT_GNU_tail_call:
343  return "DW_AT_GNU_tail_call";
345  return "DW_AT_GNU_all_tail_call_sites";
347  return "DW_AT_GNU_all_call_sites";
349  return "DW_AT_GNU_all_source_call_sites";
350  case DW_AT_GNU_macros:
351  return "DW_AT_GNU_macros";
352  case DW_AT_GNU_deleted:
353  return "DW_AT_GNU_deleted";
354  case DW_AT_GNU_dwo_name:
355  return "DW_AT_GNU_dwo_name";
356  case DW_AT_GNU_dwo_id:
357  return "DW_AT_GNU_dwo_id";
359  return "DW_AT_GNU_ranges_base";
360  case DW_AT_GNU_addr_base:
361  return "DW_AT_GNU_addr_base";
362  case DW_AT_GNU_pubnames:
363  return "DW_AT_GNU_pubnames";
364  case DW_AT_GNU_pubtypes:
365  return "DW_AT_GNU_pubtypes";
366  case DW_AT_hi_user:
367  return "DW_AT_hi_user";
368  default:
369  return NULL;
370  }
371 }
372 
374  if (form_code < DW_FORM_addr || form_code > DW_FORM_addrx4) {
375  return NULL;
376  }
377  return dwarf_attr_form_encodings[form_code];
378 }
379 
381  if (!unit_type || unit_type > DW_UT_split_type) {
382  return NULL;
383  }
384  return dwarf_unit_types[unit_type];
385 }
386 
388  if (lang >= RZ_ARRAY_SIZE(dwarf_langs)) {
389  return NULL;
390  }
391  return dwarf_langs[lang];
392 }
393 
394 static int abbrev_cmp(const void *a, const void *b) {
395  const RzBinDwarfAbbrevDecl *first = a;
396  const RzBinDwarfAbbrevDecl *second = b;
397 
398  if (first->offset > second->offset) {
399  return 1;
400  } else if (first->offset < second->offset) {
401  return -1;
402  } else {
403  return 0;
404  }
405 }
406 
411 static inline ut64 dwarf_read_initial_length(RZ_OUT bool *is_64bit, bool big_endian, const ut8 **buf, const ut8 *buf_end) {
412  ut64 r = READ32(*buf);
413  if (r == DWARF_INIT_LEN_64) {
414  r = READ64(*buf);
415  *is_64bit = true;
416  } else {
417  *is_64bit = false;
418  }
419  return r;
420 }
421 
430 static inline ut64 dwarf_read_offset(bool is_64bit, bool big_endian, const ut8 **buf, const ut8 *buf_end) {
431  ut64 result;
432  if (is_64bit) {
433  result = READ64(*buf);
434  } else {
435  result = READ32(*buf);
436  }
437  return result;
438 }
439 
440 static inline ut64 dwarf_read_address(size_t size, bool big_endian, const ut8 **buf, const ut8 *buf_end) {
441  ut64 result;
442  switch (size) {
443  case 2:
444  result = READ16(*buf);
445  break;
446  case 4:
447  result = READ32(*buf);
448  break;
449  case 8:
450  result = READ64(*buf);
451  break;
452  default:
453  result = 0;
454  *buf += size;
455  RZ_LOG_WARN("Weird dwarf address size: %zu.", size);
456  }
457  return result;
458 }
459 
461  if (hdr) {
462  for (size_t i = 0; i < hdr->file_names_count; i++) {
463  free(hdr->file_names[i].name);
464  }
465 
466  free(hdr->std_opcode_lengths);
467  free(hdr->file_names);
468 
469  if (hdr->include_dirs) {
470  for (size_t i = 0; i < hdr->include_dirs_count; i++) {
471  free(hdr->include_dirs[i]);
472  }
473  free(hdr->include_dirs);
474  }
475  }
476 }
477 
478 // Parses source file header of DWARF version <= 4
479 static const ut8 *parse_line_header_source(RzBinFile *bf, const ut8 *buf, const ut8 *buf_end, RzBinDwarfLineHeader *hdr) {
480  RzPVector incdirs;
481  rz_pvector_init(&incdirs, free);
482  while (buf + 1 < buf_end) {
483  size_t maxlen = RZ_MIN((size_t)(buf_end - buf) - 1, 0xfff);
484  size_t len = rz_str_nlen((const char *)buf, maxlen);
485  char *str = rz_str_ndup((const char *)buf, len);
486  if (len < 1 || len >= 0xfff || !str) {
487  buf += 1;
488  free(str);
489  break;
490  }
491  rz_pvector_push(&incdirs, str);
492  buf += len + 1;
493  }
494  hdr->include_dirs_count = rz_pvector_len(&incdirs);
495  hdr->include_dirs = (char **)rz_pvector_flush(&incdirs);
496  rz_pvector_fini(&incdirs);
497 
498  RzVector file_names;
499  rz_vector_init(&file_names, sizeof(RzBinDwarfLineFileEntry), NULL, NULL);
500  while (buf + 1 < buf_end) {
501  const char *filename = (const char *)buf;
502  size_t maxlen = RZ_MIN((size_t)(buf_end - buf - 1), 0xfff);
503  ut64 id_idx, mod_time, file_len;
504  size_t len = rz_str_nlen(filename, maxlen);
505 
506  if (!len) {
507  buf++;
508  break;
509  }
510  buf += len + 1;
511  if (buf >= buf_end) {
512  buf = NULL;
513  goto beach;
514  }
515  buf = rz_uleb128(buf, buf_end - buf, &id_idx, NULL);
516  if (buf >= buf_end) {
517  buf = NULL;
518  goto beach;
519  }
520  buf = rz_uleb128(buf, buf_end - buf, &mod_time, NULL);
521  if (buf >= buf_end) {
522  buf = NULL;
523  goto beach;
524  }
525  buf = rz_uleb128(buf, buf_end - buf, &file_len, NULL);
526  if (buf >= buf_end) {
527  buf = NULL;
528  goto beach;
529  }
532  entry->id_idx = id_idx;
533  entry->mod_time = mod_time;
534  entry->file_len = file_len;
535  }
536  hdr->file_names_count = rz_vector_len(&file_names);
537  hdr->file_names = rz_vector_flush(&file_names);
538  rz_vector_fini(&file_names);
539 
540 beach:
541  return buf;
542 }
543 
549  if (file_index >= header->file_names_count) {
550  return NULL;
551  }
552  RzBinDwarfLineFileEntry *file = &header->file_names[file_index];
553  if (!file->name) {
554  return NULL;
555  }
556 
557  /*
558  * Dwarf standard does not seem to specify the exact separator (slash/backslash) of paths
559  * so apparently it is target-dependent. However we have yet to see a Windows binary that
560  * also contains dwarf and contains backslashes. The ones we have seen from MinGW have regular
561  * slashes.
562  * And since there seems to be no way to reliable check whether the target uses slashes
563  * or backslashes anyway, we will simply use slashes always here.
564  */
565 
566  const char *comp_dir = info ? ht_up_find(info->line_info_offset_comp_dir, header->offset, NULL) : NULL;
567  const char *include_dir = NULL;
568  char *own_str = NULL;
569  if (file->id_idx > 0 && file->id_idx - 1 < header->include_dirs_count) {
570  include_dir = header->include_dirs[file->id_idx - 1];
571  if (include_dir && include_dir[0] != '/' && comp_dir) {
572  include_dir = own_str = rz_str_newf("%s/%s/", comp_dir, include_dir);
573  }
574  } else {
575  include_dir = comp_dir;
576  }
577  if (!include_dir) {
578  include_dir = "./";
579  }
580  char *r = rz_str_newf("%s/%s", include_dir, file->name);
581  free(own_str);
582  return r;
583 }
584 
586  return RZ_NEWS0(char *, hdr->file_names_count);
587 }
588 
590  if (!fnc) {
591  return;
592  }
593  for (size_t i = 0; i < hdr->file_names_count; i++) {
594  free(fnc[i]);
595  }
596  free(fnc);
597 }
598 
600  RZ_NULLABLE RzBinDwarfLineFileCache cache, ut64 file_index) {
601  if (file_index >= header->file_names_count) {
602  return NULL;
603  }
604  if (!cache) {
605  return header->file_names[file_index].name;
606  }
607  if (!cache[file_index]) {
608  cache[file_index] = rz_bin_dwarf_line_header_get_full_file_path(info, header, file_index);
609  }
610  return cache[file_index];
611 }
612 
615  return opcode - header->opcode_base;
616 }
617 
620  if (!header->line_range) {
621  // to dodge division by zero
622  return 0;
623  }
624  ut8 adj_opcode = rz_bin_dwarf_line_header_get_adj_opcode(header, opcode);
625  return (adj_opcode / header->line_range) * header->min_inst_len;
626 }
627 
630  if (!header->line_range) {
631  // to dodge division by zero
632  return 0;
633  }
634  ut8 adj_opcode = rz_bin_dwarf_line_header_get_adj_opcode(header, opcode);
635  return header->line_base + (adj_opcode % header->line_range);
636 }
637 
638 static const ut8 *parse_line_header(
639  RzBinFile *bf, const ut8 *buf, const ut8 *buf_end,
640  RzBinDwarfLineHeader *hdr, ut64 offset_cur, bool big_endian) {
641  rz_return_val_if_fail(hdr && bf && buf && buf_end, NULL);
642 
643  hdr->offset = offset_cur;
644  hdr->is_64bit = false;
645  hdr->unit_length = dwarf_read_initial_length(&hdr->is_64bit, big_endian, &buf, buf_end);
646  hdr->version = READ16(buf);
647 
648  if (hdr->version == 5) {
649  hdr->address_size = READ8(buf);
651  }
652 
653  hdr->header_length = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
654 
655  const ut8 *tmp_buf = buf; // So I can skip parsing DWARF 5 headers for now
656 
657  if (buf_end - buf < 8) {
658  return NULL;
659  }
660  hdr->min_inst_len = READ8(buf);
661  if (hdr->version >= 4) {
662  hdr->max_ops_per_inst = READ8(buf);
663  }
664  hdr->default_is_stmt = READ8(buf);
665  hdr->line_base = (st8)READ8(buf);
666  hdr->line_range = READ8(buf);
667  hdr->opcode_base = READ8(buf);
668 
669  hdr->file_names = NULL;
670 
671  if (hdr->opcode_base > 1) {
672  hdr->std_opcode_lengths = calloc(sizeof(ut8), hdr->opcode_base - 1);
673  for (size_t i = 1; i < hdr->opcode_base; i++) {
674  if (buf + 2 > buf_end) {
675  hdr->opcode_base = i;
676  break;
677  }
678  hdr->std_opcode_lengths[i - 1] = READ8(buf);
679  }
680  } else {
681  hdr->std_opcode_lengths = NULL;
682  }
683  // TODO finish parsing of source files out of DWARF 5 header
684  // for now we skip
685  if (hdr->version == 5) {
686  tmp_buf += hdr->header_length;
687  return tmp_buf;
688  }
689 
690  if (hdr->version <= 4) {
691  buf = parse_line_header_source(bf, buf, buf_end, hdr);
692  } else {
693  buf = NULL;
694  }
695 
696  return buf;
697 }
698 
701  if (op->type == RZ_BIN_DWARF_LINE_OP_TYPE_EXT && op->opcode == DW_LNE_define_file) {
702  free(op->args.define_file.filename);
703  }
704 }
705 
706 static const ut8 *parse_ext_opcode(RzBinDwarfLineOp *op, const RzBinDwarfLineHeader *hdr, const ut8 *obuf, size_t len,
707  bool big_endian, ut8 target_addr_size) {
708  rz_return_val_if_fail(op && hdr && obuf, NULL);
709  const ut8 *buf = obuf;
710  const ut8 *buf_end = obuf + len;
711 
712  ut64 op_len;
713  buf = rz_uleb128(buf, len, &op_len, NULL);
714  // op_len must fit and be at least 1 (for the opcode byte)
715  if (!buf || buf >= buf_end || !op_len || buf_end - buf < op_len) {
716  return NULL;
717  }
718 
719  ut8 opcode = *buf++;
721  op->opcode = opcode;
722 
723  switch (opcode) {
724  case DW_LNE_set_address: {
725  ut8 addr_size = hdr->address_size;
726  if (hdr->version < 5) { // address_size in header only starting with Dwarf 5
727  addr_size = target_addr_size;
728  }
729  op->args.set_address = dwarf_read_address(addr_size, big_endian, &buf, buf_end);
730  break;
731  }
732  case DW_LNE_define_file: {
733  size_t fn_len = rz_str_nlen((const char *)buf, buf_end - buf);
734  char *fn = malloc(fn_len + 1);
735  if (!fn) {
736  return NULL;
737  }
738  memcpy(fn, buf, fn_len);
739  fn[fn_len] = 0;
740  op->args.define_file.filename = fn;
741  buf += fn_len + 1;
742  if (buf + 1 < buf_end) {
743  buf = rz_uleb128(buf, buf_end - buf, &op->args.define_file.dir_index, NULL);
744  }
745  if (buf && buf + 1 < buf_end) {
746  buf = rz_uleb128(buf, buf_end - buf, NULL, NULL);
747  }
748  if (buf && buf + 1 < buf_end) {
749  buf = rz_uleb128(buf, buf_end - buf, NULL, NULL);
750  }
751  break;
752  }
754  buf = rz_uleb128(buf, buf_end - buf, &op->args.set_discriminator, NULL);
755  break;
756  case DW_LNE_end_sequence:
757  default:
758  buf += op_len - 1;
759  break;
760  }
761  return buf;
762 }
763 
767 static size_t std_opcode_args_count(const RzBinDwarfLineHeader *hdr, ut8 opcode) {
768  if (!opcode || opcode > hdr->opcode_base - 1 || !hdr->std_opcode_lengths) {
769  return 0;
770  }
771  return hdr->std_opcode_lengths[opcode - 1];
772 }
773 
774 static const ut8 *parse_std_opcode(RzBinDwarfLineOp *op, const RzBinDwarfLineHeader *hdr, const ut8 *obuf, size_t len, ut8 opcode, bool big_endian) {
775  rz_return_val_if_fail(op && hdr && obuf, NULL);
776  const ut8 *buf = obuf;
777  const ut8 *buf_end = obuf + len;
778 
780  op->opcode = opcode;
781  switch (opcode) {
782  case DW_LNS_advance_pc:
783  buf = rz_uleb128(buf, buf_end - buf, &op->args.advance_pc, NULL);
784  break;
785  case DW_LNS_advance_line:
786  buf = rz_leb128(buf, buf_end - buf, &op->args.advance_line);
787  break;
788  case DW_LNS_set_file:
789  buf = rz_uleb128(buf, buf_end - buf, &op->args.set_file, NULL);
790  break;
791  case DW_LNS_set_column:
792  buf = rz_uleb128(buf, buf_end - buf, &op->args.set_column, NULL);
793  break;
795  op->args.fixed_advance_pc = READ16(buf);
796  break;
797  case DW_LNS_set_isa:
798  buf = rz_uleb128(buf, buf_end - buf, &op->args.set_isa, NULL);
799  break;
800 
801  // known opcodes that take no args
802  case DW_LNS_copy:
803  case DW_LNS_negate_stmt:
805  case DW_LNS_const_add_pc:
808  break;
809 
810  // unknown operands, skip the number of args given in the header.
811  default: {
812  size_t args_count = std_opcode_args_count(hdr, opcode);
813  for (size_t i = 0; i < args_count; i++) {
814  buf = rz_uleb128(buf, buf_end - buf, &op->args.advance_pc, NULL);
815  if (!buf) {
816  break;
817  }
818  }
819  }
820  }
821  return buf;
822 }
823 
825  rz_return_if_fail(hdr && regs);
826  regs->address = 0;
827  regs->file = 1;
828  regs->line = 1;
829  regs->column = 0;
830  regs->is_stmt = hdr->default_is_stmt;
831  regs->basic_block = DWARF_FALSE;
832  regs->end_sequence = DWARF_FALSE;
833  regs->prologue_end = DWARF_FALSE;
834  regs->epilogue_begin = DWARF_FALSE;
835  regs->isa = 0;
836 }
837 
840  const char *file = NULL;
841  if (regs->file) {
842  file = get_full_file_path(info, hdr, fnc, regs->file - 1);
843  }
844  rz_bin_source_line_info_builder_push_sample(bob, regs->address, (ut32)regs->line, (ut32)regs->column, file);
845 }
846 
853  rz_return_val_if_fail(hdr && regs && op, false);
854  switch (op->type) {
856  switch (op->opcode) {
857  case DW_LNS_copy:
858  if (bob) {
859  store_line_sample(bob, hdr, regs, info, fnc);
860  }
861  regs->basic_block = DWARF_FALSE;
862  break;
863  case DW_LNS_advance_pc:
864  regs->address += op->args.advance_pc * hdr->min_inst_len;
865  break;
866  case DW_LNS_advance_line:
867  regs->line += op->args.advance_line;
868  break;
869  case DW_LNS_set_file:
870  regs->file = op->args.set_file;
871  break;
872  case DW_LNS_set_column:
873  regs->column = op->args.set_column;
874  break;
875  case DW_LNS_negate_stmt:
876  regs->is_stmt = regs->is_stmt ? DWARF_FALSE : DWARF_TRUE;
877  break;
879  regs->basic_block = DWARF_TRUE;
880  break;
881  case DW_LNS_const_add_pc:
883  break;
885  regs->address += op->args.fixed_advance_pc;
886  break;
888  regs->prologue_end = ~0;
889  break;
891  regs->epilogue_begin = ~0;
892  break;
893  case DW_LNS_set_isa:
894  regs->isa = op->args.set_isa;
895  break;
896  default:
897  return false;
898  }
899  break;
901  switch (op->opcode) {
902  case DW_LNE_end_sequence:
903  regs->end_sequence = DWARF_TRUE;
904  if (bob) {
905  // closing entry
907  }
909  break;
910  case DW_LNE_set_address:
911  regs->address = op->args.set_address;
912  break;
913  case DW_LNE_define_file:
914  break;
916  regs->discriminator = op->args.set_discriminator;
917  break;
918  default:
919  return false;
920  }
921  break;
923  regs->address += rz_bin_dwarf_line_header_get_spec_op_advance_pc(hdr, op->opcode);
925  if (bob) {
926  store_line_sample(bob, hdr, regs, info, fnc);
927  }
928  regs->basic_block = DWARF_FALSE;
929  regs->prologue_end = DWARF_FALSE;
930  regs->epilogue_begin = DWARF_FALSE;
931  regs->discriminator = 0;
932  break;
933  default:
934  return false;
935  }
936  return true;
937 }
938 
939 static size_t parse_opcodes(const ut8 *obuf,
940  size_t len, const RzBinDwarfLineHeader *hdr, RzVector *ops_out,
942  RZ_NULLABLE RzBinDwarfLineFileCache fnc, bool big_endian, ut8 target_addr_size) {
943  const ut8 *buf, *buf_end;
944  ut8 opcode;
945 
946  if (!obuf || !len) {
947  return 0;
948  }
949  buf = obuf;
950  buf_end = obuf + len;
951 
952  while (buf < buf_end) {
953  opcode = *buf++;
954  RzBinDwarfLineOp op = { 0 };
955  if (!opcode) {
956  buf = parse_ext_opcode(&op, hdr, buf, (buf_end - buf), big_endian, target_addr_size);
957  } else if (opcode >= hdr->opcode_base) {
958  // special opcode without args, no further parsing needed
960  op.opcode = opcode;
961  } else {
962  buf = parse_std_opcode(&op, hdr, buf, (buf_end - buf), opcode, big_endian);
963  }
964  if (!buf) {
965  break;
966  }
967  if (bob) {
968  rz_bin_dwarf_line_op_run(hdr, regs, &op, bob, info, fnc);
969  }
970  if (ops_out) {
971  rz_vector_push(ops_out, &op);
972  } else {
974  }
975  }
976  if (!buf) {
977  return 0;
978  }
979  return (size_t)(buf - obuf); // number of bytes we've moved by
980 }
981 
982 static void line_unit_free(RzBinDwarfLineUnit *unit) {
983  if (!unit) {
984  return;
985  }
986  line_header_fini(&unit->header);
987  if (unit->ops) {
988  for (size_t i = 0; i < unit->ops_count; i++) {
990  }
991  free(unit->ops);
992  }
993  free(unit);
994 }
995 
998  // Dwarf 3 Standard 6.2 Line Number Information
999  rz_return_val_if_fail(binfile && obuf, NULL);
1000 
1001  const ut8 *buf = obuf;
1002  const ut8 *buf_start = buf;
1003  const ut8 *buf_end = obuf + len;
1004  const ut8 *tmpbuf = NULL;
1005  ut64 buf_size;
1006 
1007  // Dwarf < 5 needs this size to be supplied from outside
1008  RzBinObject *o = binfile->o;
1009  ut8 target_addr_size = o && o->info && o->info->bits ? o->info->bits / 8 : 4;
1010 
1012  if (!li) {
1013  return NULL;
1014  }
1016  if (!li->units) {
1017  free(li);
1018  return NULL;
1019  }
1020 
1024  }
1025 
1026  // each iteration we read one header AKA comp. unit
1027  while (buf <= buf_end) {
1029  if (!unit) {
1030  break;
1031  }
1032 
1033  // How much did we read from the compilation unit
1034  size_t bytes_read = 0;
1035  // calculate how much we've read by parsing header
1036  // because header unit_length includes itself
1037  buf_size = buf_end - buf;
1038 
1039  tmpbuf = buf;
1040  buf = parse_line_header(binfile, buf, buf_end, &unit->header, buf - buf_start, big_endian);
1041  if (!buf) {
1042  line_unit_free(unit);
1043  break;
1044  }
1045 
1046  bytes_read = buf - tmpbuf;
1047 
1050 
1051  // If there is more bytes in the buffer than size of the header
1052  // It means that there has to be another header/comp.unit
1053  buf_size = RZ_MIN(buf_size, unit->header.unit_length + (unit->header.is_64bit * 8 + 4)); // length field + rest of the unit
1054  if (buf_size <= bytes_read) {
1055  // no info or truncated
1056  line_unit_free(unit);
1057  continue;
1058  }
1059  if (buf_size > (buf_end - buf) + bytes_read || buf > buf_end) {
1060  line_unit_free(unit);
1061  break;
1062  }
1063  size_t tmp_read = 0;
1064 
1065  RzVector ops;
1068  }
1069 
1073  }
1074 
1075  // we read the whole compilation unit (that might be composed of more sequences)
1076  do {
1077  // reads one whole sequence
1078  tmp_read = parse_opcodes(buf, buf_size - bytes_read, &unit->header,
1081  info, fnc, big_endian, target_addr_size);
1082  bytes_read += tmp_read;
1083  buf += tmp_read; // Move in the buffer forward
1084  } while (bytes_read < buf_size && tmp_read != 0); // if nothing is read -> error, exit
1085 
1087 
1089  unit->ops_count = rz_vector_len(&ops);
1090  unit->ops = rz_vector_flush(&ops);
1091  rz_vector_fini(&ops);
1092  }
1093 
1094  if (!tmp_read) {
1095  line_unit_free(unit);
1096  break;
1097  }
1098  rz_list_push(li->units, unit);
1099  }
1102  }
1103  return li;
1104 }
1105 
1107  if (!set) {
1108  return;
1109  }
1110  free(set->aranges);
1111  free(set);
1112 }
1113 
1114 static RzList /*<RzBinDwarfARangeSet *>*/ *parse_aranges_raw(const ut8 *obuf, size_t obuf_sz, bool big_endian) {
1116  const ut8 *buf = obuf;
1117  const ut8 *buf_end = buf + obuf_sz;
1118 
1120  if (!r) {
1121  return NULL;
1122  }
1123 
1124  // DWARF 3 Standard Section 6.1.2 Lookup by Address
1125  // also useful to grep for display_debug_aranges in binutils
1126  while (buf < buf_end) {
1127  const ut8 *start = buf;
1128  bool is_64bit;
1129  ut64 unit_length = dwarf_read_initial_length(&is_64bit, big_endian, &buf, buf_end);
1130  // Sanity check: length must be at least the minimal size of the remaining header fields
1131  // and at maximum the remaining buffer size.
1132  size_t header_rest_size = 2 + (is_64bit ? 8 : 4) + 1 + 1;
1133  if (unit_length < header_rest_size || unit_length > buf_end - buf) {
1134  break;
1135  }
1136  const ut8 *next_set_buf = buf + unit_length;
1138  if (!set) {
1139  break;
1140  }
1141  set->unit_length = unit_length;
1142  set->is_64bit = is_64bit;
1143  set->version = READ16(buf);
1144  set->debug_info_offset = dwarf_read_offset(set->is_64bit, big_endian, &buf, buf_end);
1145  set->address_size = READ8(buf);
1146  set->segment_size = READ8(buf);
1147  unit_length -= header_rest_size;
1148  if (!set->address_size) {
1149  free(set);
1150  break;
1151  }
1152 
1153  // align to 2*addr_size
1154  size_t off = buf - start;
1155  size_t pad = rz_num_align_delta(off, 2 * set->address_size);
1156  if (pad > unit_length || pad > buf_end - buf) {
1157  free(set);
1158  break;
1159  }
1160  buf += pad;
1161  unit_length -= pad;
1162 
1163  size_t arange_size = 2 * set->address_size;
1164  set->aranges_count = unit_length / arange_size;
1165  if (!set->aranges_count) {
1166  free(set);
1167  break;
1168  }
1170  if (!set->aranges) {
1171  free(set);
1172  break;
1173  }
1174  size_t i;
1175  for (i = 0; i < set->aranges_count; i++) {
1176  set->aranges[i].addr = dwarf_read_address(set->address_size, big_endian, &buf, buf_end);
1177  set->aranges[i].length = dwarf_read_address(set->address_size, big_endian, &buf, buf_end);
1178  if (!set->aranges[i].addr && !set->aranges[i].length) {
1179  // last entry has two 0s
1180  i++; // so i will be the total count of read entries
1181  break;
1182  }
1183  }
1184  set->aranges_count = i;
1185  buf = next_set_buf;
1186  rz_list_push(r, set);
1187  }
1188 
1189  return r;
1190 }
1191 
1192 static void free_ht_comp_dir(HtUPKv *kv) {
1193  free(kv->value);
1194 }
1195 
1198  if (!inf->comp_units) {
1199  return false;
1200  }
1201  inf->line_info_offset_comp_dir = ht_up_new(NULL, free_ht_comp_dir, NULL);
1202  if (!inf->line_info_offset_comp_dir) {
1203  goto wurzelbert_comp_units;
1204  }
1205  inf->capacity = DEBUG_INFO_CAPACITY;
1206  inf->count = 0;
1207  return true;
1208 wurzelbert_comp_units:
1209  RZ_FREE(inf->comp_units);
1210  return false;
1211 }
1212 
1213 static int init_die(RzBinDwarfDie *die, ut64 abbr_code, ut64 attr_count) {
1214  if (!die) {
1215  return -1;
1216  }
1217  if (attr_count) {
1218  die->attr_values = calloc(sizeof(RzBinDwarfAttrValue), attr_count);
1219  if (!die->attr_values) {
1220  return -1;
1221  }
1222  } else {
1223  die->attr_values = NULL;
1224  }
1225  die->abbrev_code = abbr_code;
1226  die->capacity = attr_count;
1227  die->count = 0;
1228  return 0;
1229 }
1230 
1232  if (!cu) {
1233  return -EINVAL;
1234  }
1235  cu->dies = calloc(sizeof(RzBinDwarfDie), COMP_UNIT_CAPACITY);
1236  if (!cu->dies) {
1237  return -ENOMEM;
1238  }
1240  cu->count = 0;
1241  return 0;
1242 }
1243 
1245  RzBinDwarfDie *tmp;
1246 
1247  if (!cu || cu->capacity == 0 || cu->capacity != cu->count) {
1248  return -EINVAL;
1249  }
1250 
1251  tmp = (RzBinDwarfDie *)realloc(cu->dies,
1252  cu->capacity * 2 * sizeof(RzBinDwarfDie));
1253  if (!tmp) {
1254  return -ENOMEM;
1255  }
1256 
1257  memset((ut8 *)tmp + cu->capacity * sizeof(RzBinDwarfDie),
1258  0, cu->capacity * sizeof(RzBinDwarfDie));
1259  cu->dies = tmp;
1260  cu->capacity *= 2;
1261 
1262  return 0;
1263 }
1264 
1266  if (!ad) {
1267  return -EINVAL;
1268  }
1269  ad->defs = calloc(sizeof(RzBinDwarfAttrDef), ABBREV_DECL_CAP);
1270 
1271  if (!ad->defs) {
1272  return -ENOMEM;
1273  }
1274 
1275  ad->capacity = ABBREV_DECL_CAP;
1276  ad->count = 0;
1277 
1278  return 0;
1279 }
1280 
1283 
1284  if (!ad || !ad->capacity || ad->capacity != ad->count) {
1285  return -EINVAL;
1286  }
1287 
1288  tmp = (RzBinDwarfAttrDef *)realloc(ad->defs,
1289  ad->capacity * 2 * sizeof(RzBinDwarfAttrDef));
1290 
1291  if (!tmp) {
1292  return -ENOMEM;
1293  }
1294 
1295  // Set the area in the buffer past the length to 0
1296  memset((ut8 *)tmp + ad->capacity * sizeof(RzBinDwarfAttrDef),
1297  0, ad->capacity * sizeof(RzBinDwarfAttrDef));
1298  ad->defs = tmp;
1299  ad->capacity *= 2;
1300 
1301  return 0;
1302 }
1303 
1305  if (!da) {
1306  return -EINVAL;
1307  }
1309  if (!da->decls) {
1310  return -ENOMEM;
1311  }
1312  da->capacity = DEBUG_ABBREV_CAP;
1313  da->count = 0;
1314 
1315  return 0;
1316 }
1317 
1320 
1321  if (!da || da->capacity == 0 || da->capacity != da->count) {
1322  return -EINVAL;
1323  }
1324 
1326  da->capacity * 2 * sizeof(RzBinDwarfAbbrevDecl));
1327 
1328  if (!tmp) {
1329  return -ENOMEM;
1330  }
1331  memset((ut8 *)tmp + da->capacity * sizeof(RzBinDwarfAbbrevDecl),
1332  0, da->capacity * sizeof(RzBinDwarfAbbrevDecl));
1333 
1334  da->decls = tmp;
1335  da->capacity *= 2;
1336 
1337  return 0;
1338 }
1339 
1341  size_t i;
1342  if (!da) {
1343  return;
1344  }
1345  for (i = 0; i < da->count; i++) {
1346  RZ_FREE(da->decls[i].defs);
1347  }
1348  RZ_FREE(da->decls);
1349  free(da);
1350 }
1351 
1353  if (!li) {
1354  return;
1355  }
1356  rz_list_free(li->units);
1358  free(li);
1359 }
1360 
1362  // TODO adjust to new forms, now we're leaking
1363  if (!val) {
1364  return;
1365  }
1366  switch (val->attr_form) {
1367  case DW_FORM_strp:
1368  case DW_FORM_string:
1369  RZ_FREE(val->string.content);
1370  break;
1371  case DW_FORM_exprloc:
1372  case DW_FORM_block:
1373  case DW_FORM_block1:
1374  case DW_FORM_block2:
1375  case DW_FORM_block4:
1376  RZ_FREE(val->block.data);
1377  break;
1378  default:
1379  break;
1380  };
1381 }
1382 
1383 static void free_die(RzBinDwarfDie *die) {
1384  size_t i;
1385  if (!die) {
1386  return;
1387  }
1388  for (i = 0; i < die->count; i++) {
1389  free_attr_value(&die->attr_values[i]);
1390  }
1391  RZ_FREE(die->attr_values);
1392 }
1393 
1395  size_t i;
1396  if (!cu) {
1397  return;
1398  }
1399  for (i = 0; i < cu->count; i++) {
1400  if (cu->dies) {
1401  free_die(&cu->dies[i]);
1402  }
1403  }
1404  RZ_FREE(cu->dies);
1405 }
1406 
1408  if (!inf) {
1409  return;
1410  }
1411  for (size_t i = 0; i < inf->count; i++) {
1412  free_comp_unit(&inf->comp_units[i]);
1413  }
1414  ht_up_free(inf->line_info_offset_comp_dir);
1415  ht_up_free(inf->lookup_table);
1416  free(inf->comp_units);
1417  free(inf);
1418 }
1419 
1420 static const ut8 *fill_block_data(const ut8 *buf, const ut8 *buf_end, RzBinDwarfBlock *block) {
1421  block->data = calloc(sizeof(ut8), block->length);
1422  if (!block->data) {
1423  return NULL;
1424  }
1425  /* Maybe unroll this as an optimization in future? */
1426  if (block->data) {
1427  size_t j = 0;
1428  for (j = 0; j < block->length; j++) {
1429  block->data[j] = READ8(buf);
1430  }
1431  }
1432  return buf;
1433 }
1434 
1450 static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
1452  const RzBinDwarfCompUnitHdr *hdr,
1453  const ut8 *debug_str, size_t debug_str_len,
1454  bool big_endian) {
1455 
1456  const ut8 *buf = obuf;
1457  const ut8 *buf_end = obuf + obuf_len;
1458  size_t j;
1459 
1460  rz_return_val_if_fail(def && value && hdr && obuf && obuf_len >= 1, NULL);
1461 
1462  value->attr_form = def->attr_form;
1463  value->attr_name = def->attr_name;
1464  value->block.data = NULL;
1465  value->string.content = NULL;
1466  value->string.offset = 0;
1467 
1468  // http://www.dwarfstd.org/doc/DWARF4.pdf#page=161&zoom=100,0,560
1469  switch (def->attr_form) {
1470  case DW_FORM_addr:
1471  value->kind = DW_AT_KIND_ADDRESS;
1472  switch (hdr->address_size) {
1473  case 1:
1474  value->address = READ8(buf);
1475  break;
1476  case 2:
1477  value->address = READ16(buf);
1478  break;
1479  case 4:
1480  value->address = READ32(buf);
1481  break;
1482  case 8:
1483  value->address = READ64(buf);
1484  break;
1485  default:
1486  RZ_LOG_ERROR("DWARF: Unexpected pointer size: %u\n", (unsigned)hdr->address_size);
1487  return NULL;
1488  }
1489  break;
1490  case DW_FORM_data1:
1491  value->kind = DW_AT_KIND_CONSTANT;
1492  value->uconstant = READ8(buf);
1493  break;
1494  case DW_FORM_data2:
1495  value->kind = DW_AT_KIND_CONSTANT;
1496  value->uconstant = READ16(buf);
1497  break;
1498  case DW_FORM_data4:
1499  value->kind = DW_AT_KIND_CONSTANT;
1500  value->uconstant = READ32(buf);
1501  break;
1502  case DW_FORM_data8:
1503  value->kind = DW_AT_KIND_CONSTANT;
1504  value->uconstant = READ64(buf);
1505  break;
1506  case DW_FORM_data16: // TODO Fix this, right now I just read the data, but I need to make storage for it
1507  value->kind = DW_AT_KIND_CONSTANT;
1508  value->uconstant = READ64(buf);
1509  value->uconstant = READ64(buf);
1510  break;
1511  case DW_FORM_sdata:
1512  value->kind = DW_AT_KIND_CONSTANT;
1513  buf = rz_leb128(buf, buf_end - buf, &value->sconstant);
1514  break;
1515  case DW_FORM_udata:
1516  value->kind = DW_AT_KIND_CONSTANT;
1517  buf = rz_uleb128(buf, buf_end - buf, &value->uconstant, NULL);
1518  break;
1519  case DW_FORM_string:
1520  value->kind = DW_AT_KIND_STRING;
1521  value->string.content = *buf ? rz_str_ndup((char *)buf, buf_end - buf) : NULL;
1522  buf += value->string.content ? strlen(value->string.content) + 1 : 1;
1523  break;
1524  case DW_FORM_block1:
1525  value->kind = DW_AT_KIND_BLOCK;
1526  value->block.length = READ8(buf);
1527  buf = fill_block_data(buf, buf_end, &value->block);
1528  break;
1529  case DW_FORM_block2:
1530  value->kind = DW_AT_KIND_BLOCK;
1531  value->block.length = READ16(buf);
1532  if (value->block.length > 0) {
1533  value->block.data = calloc(sizeof(ut8), value->block.length);
1534  if (!value->block.data) {
1535  return NULL;
1536  }
1537  for (j = 0; j < value->block.length; j++) {
1538  value->block.data[j] = READ8(buf);
1539  }
1540  }
1541  break;
1542  case DW_FORM_block4:
1543  value->kind = DW_AT_KIND_BLOCK;
1544  value->block.length = READ32(buf);
1545  buf = fill_block_data(buf, buf_end, &value->block);
1546  break;
1547  case DW_FORM_block: // variable length ULEB128
1548  value->kind = DW_AT_KIND_BLOCK;
1549  buf = rz_uleb128(buf, buf_end - buf, &value->block.length, NULL);
1550  if (!buf || buf >= buf_end) {
1551  return NULL;
1552  }
1553  buf = fill_block_data(buf, buf_end, &value->block);
1554  break;
1555  case DW_FORM_flag:
1556  value->kind = DW_AT_KIND_FLAG;
1557  value->flag = READ8(buf);
1558  break;
1559  // offset in .debug_str
1560  case DW_FORM_strp:
1561  value->kind = DW_AT_KIND_STRING;
1562  value->string.offset = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1563  if (debug_str && value->string.offset < debug_str_len) {
1564  value->string.content =
1565  rz_str_ndup((char *)debug_str + value->string.offset, debug_str_len - value->string.offset);
1566  } else {
1567  value->string.content = NULL; // Means malformed DWARF, should we print error message?
1568  }
1569  break;
1570  // offset in .debug_info
1571  case DW_FORM_ref_addr:
1572  value->kind = DW_AT_KIND_REFERENCE;
1573  value->reference = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1574  break;
1575  // This type of reference is an offset from the first byte of the compilation
1576  // header for the compilation unit containing the reference
1577  case DW_FORM_ref1:
1578  value->kind = DW_AT_KIND_REFERENCE;
1579  value->reference = hdr->unit_offset + READ8(buf);
1580  break;
1581  case DW_FORM_ref2:
1582  value->kind = DW_AT_KIND_REFERENCE;
1583  value->reference = hdr->unit_offset + READ16(buf);
1584  break;
1585  case DW_FORM_ref4:
1586  value->kind = DW_AT_KIND_REFERENCE;
1587  value->reference = hdr->unit_offset + READ32(buf);
1588  break;
1589  case DW_FORM_ref8:
1590  value->kind = DW_AT_KIND_REFERENCE;
1591  value->reference = hdr->unit_offset + READ64(buf);
1592  break;
1593  case DW_FORM_ref_udata:
1594  value->kind = DW_AT_KIND_REFERENCE;
1595  // uleb128 is enough to fit into ut64?
1596  buf = rz_uleb128(buf, buf_end - buf, &value->reference, NULL);
1597  value->reference += hdr->unit_offset;
1598  break;
1599  // offset in a section other than .debug_info or .debug_str
1600  case DW_FORM_sec_offset:
1601  value->kind = DW_AT_KIND_REFERENCE;
1602  value->reference = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1603  break;
1604  case DW_FORM_exprloc:
1605  value->kind = DW_AT_KIND_BLOCK;
1606  buf = rz_uleb128(buf, buf_end - buf, &value->block.length, NULL);
1607  if (!buf || buf >= buf_end) {
1608  return NULL;
1609  }
1610  buf = fill_block_data(buf, buf_end, &value->block);
1611  break;
1612  // this means that the flag is present, nothing is read
1613  case DW_FORM_flag_present:
1614  value->kind = DW_AT_KIND_FLAG;
1615  value->flag = true;
1616  break;
1617  case DW_FORM_ref_sig8:
1618  value->kind = DW_AT_KIND_REFERENCE;
1619  value->reference = READ64(buf);
1620  break;
1621  // offset into .debug_line_str section, can't parse the section now, so we just skip
1622  case DW_FORM_strx:
1623  value->kind = DW_AT_KIND_STRING;
1624  // value->string.offset = dwarf_read_offset (hdr->is_64bit, big_endian, &buf, buf_end);
1625  // if (debug_str && value->string.offset < debug_str_len) {
1626  // value->string.content =
1627  // rz_str_ndup ((const char *)(debug_str + value->string.offset), debug_str_len - value->string.offset);
1628  // } else {
1629  // value->string.content = NULL; // Means malformed DWARF, should we print error message?
1630  // }
1631  break;
1632  case DW_FORM_strx1:
1633  value->kind = DW_AT_KIND_STRING;
1634  value->string.offset = READ8(buf);
1635  break;
1636  case DW_FORM_strx2:
1637  value->kind = DW_AT_KIND_STRING;
1638  value->string.offset = READ16(buf);
1639  break;
1640  case DW_FORM_strx3: // TODO Add 3 byte int read
1641  value->kind = DW_AT_KIND_STRING;
1642  buf += 3;
1643  break;
1644  case DW_FORM_strx4:
1645  value->kind = DW_AT_KIND_STRING;
1646  value->string.offset = READ32(buf);
1647  break;
1649  value->kind = DW_AT_KIND_CONSTANT;
1650  value->uconstant = def->special;
1651  break;
1652  /* addrx* forms : The index is relative to the value of the
1653  DW_AT_addr_base attribute of the associated compilation unit.
1654  index into an array of addresses in the .debug_addr section.*/
1655  case DW_FORM_addrx:
1656  value->kind = DW_AT_KIND_ADDRESS;
1657  buf = rz_uleb128(buf, buf_end - buf, &value->address, NULL);
1658  break;
1659  case DW_FORM_addrx1:
1660  value->kind = DW_AT_KIND_ADDRESS;
1661  value->address = READ8(buf);
1662  break;
1663  case DW_FORM_addrx2:
1664  value->kind = DW_AT_KIND_ADDRESS;
1665  value->address = READ16(buf);
1666  break;
1667  case DW_FORM_addrx3:
1668  // I need to add 3byte endianess free read here TODO
1669  value->kind = DW_AT_KIND_ADDRESS;
1670  buf += 3;
1671  break;
1672  case DW_FORM_addrx4:
1673  value->kind = DW_AT_KIND_ADDRESS;
1674  value->address = READ32(buf);
1675  break;
1676  case DW_FORM_line_ptr: // offset in a section .debug_line_str
1677  case DW_FORM_strp_sup: // offset in a section .debug_line_str
1678  value->kind = DW_AT_KIND_STRING;
1679  value->string.offset = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1680  // if (debug_str && value->string.offset < debug_line_str_len) {
1681  // value->string.content =
1682  // rz_str_ndup
1683  break;
1684  // offset in the supplementary object file
1685  case DW_FORM_ref_sup4:
1686  value->kind = DW_AT_KIND_REFERENCE;
1687  value->reference = READ32(buf);
1688  break;
1689  case DW_FORM_ref_sup8:
1690  value->kind = DW_AT_KIND_REFERENCE;
1691  value->reference = READ64(buf);
1692  break;
1693  // An index into the .debug_loc
1694  case DW_FORM_loclistx:
1695  value->kind = DW_AT_KIND_LOCLISTPTR;
1696  value->reference = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1697  break;
1698  // An index into the .debug_rnglists
1699  case DW_FORM_rnglistx:
1700  value->kind = DW_AT_KIND_ADDRESS;
1701  buf = rz_uleb128(buf, buf_end - buf, &value->address, NULL);
1702  break;
1703  default:
1704  RZ_LOG_ERROR("Unknown DW_FORM 0x%02" PFMT64x "\n", def->attr_form);
1705  value->uconstant = 0;
1706  return NULL;
1707  }
1708  return buf;
1709 }
1710 
1722 static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RzBinDwarfDebugInfo *info, RzBinDwarfAbbrevDecl *abbrev,
1723  RzBinDwarfCompUnitHdr *hdr, RzBinDwarfDie *die, const ut8 *debug_str, size_t debug_str_len, bool big_endian) {
1724  size_t i;
1725  const char *comp_dir = NULL;
1726  ut64 line_info_offset = UT64_MAX;
1727  if (abbrev->count) {
1728  for (i = 0; i < abbrev->count - 1; i++) {
1729  memset(&die->attr_values[i], 0, sizeof(die->attr_values[i]));
1730 
1731  buf = parse_attr_value(buf, buf_end - buf, &abbrev->defs[i],
1732  &die->attr_values[i], hdr, debug_str, debug_str_len, big_endian);
1733 
1734  RzBinDwarfAttrValue *attribute = &die->attr_values[i];
1735 
1736  if (attribute->attr_name == DW_AT_comp_dir && (attribute->attr_form == DW_FORM_strp || attribute->attr_form == DW_FORM_string) && attribute->string.content) {
1737  comp_dir = attribute->string.content;
1738  }
1739  if (attribute->attr_name == DW_AT_stmt_list) {
1740  if (attribute->kind == DW_AT_KIND_CONSTANT) {
1741  line_info_offset = attribute->uconstant;
1742  } else if (attribute->kind == DW_AT_KIND_REFERENCE) {
1743  line_info_offset = attribute->reference;
1744  }
1745  }
1746  die->count++;
1747  }
1748  }
1749 
1750  // If this is a compilation unit dir attribute, we want to cache it so the line info parsing
1751  // which will need this info can quickly look it up.
1752  if (comp_dir && line_info_offset != UT64_MAX) {
1753  char *name = strdup(comp_dir);
1754  if (name) {
1755  if (!ht_up_insert(info->line_info_offset_comp_dir, line_info_offset, name)) {
1756  free(name);
1757  }
1758  }
1759  }
1760 
1761  return buf;
1762 }
1763 
1776 static const ut8 *parse_comp_unit(RzBinDwarfDebugInfo *info, const ut8 *buf_start,
1777  RzBinDwarfCompUnit *unit, const RzBinDwarfDebugAbbrev *abbrevs,
1778  size_t first_abbr_idx, const ut8 *debug_str, size_t debug_str_len, bool big_endian) {
1779 
1780  const ut8 *buf = buf_start;
1781  const ut8 *buf_end = buf_start + unit->hdr.length - unit->hdr.header_size;
1782 
1783  while (buf && buf < buf_end && buf >= buf_start) {
1784  if (unit->count && unit->capacity == unit->count) {
1785  expand_cu(unit);
1786  }
1787  RzBinDwarfDie *die = &unit->dies[unit->count];
1788  // add header size to the offset;
1789  die->offset = buf - buf_start + unit->hdr.header_size + unit->offset;
1790  die->offset += unit->hdr.is_64bit ? 12 : 4;
1791 
1792  // DIE starts with ULEB128 with the abbreviation code
1793  ut64 abbr_code;
1794  buf = rz_uleb128(buf, buf_end - buf, &abbr_code, NULL);
1795 
1796  if (abbr_code > abbrevs->count || !buf) { // something invalid
1797  return NULL;
1798  }
1799 
1800  if (buf >= buf_end) {
1801  unit->count++; // we wanna store this entry too, usually the last one is null_entry
1802  return buf; // return the buffer to parse next compilation units
1803  }
1804  // there can be "null" entries that have abbr_code == 0
1805  if (!abbr_code) {
1806  unit->count++;
1807  continue;
1808  }
1809  ut64 abbr_idx = first_abbr_idx + abbr_code;
1810 
1811  if (abbrevs->count < abbr_idx) {
1812  return NULL;
1813  }
1814  RzBinDwarfAbbrevDecl *abbrev = &abbrevs->decls[abbr_idx - 1];
1815 
1816  if (init_die(die, abbr_code, abbrev->count)) {
1817  return NULL; // error
1818  }
1819  die->tag = abbrev->tag;
1820  die->has_children = abbrev->has_children;
1821 
1822  buf = parse_die(buf, buf_end, info, abbrev, &unit->hdr, die, debug_str, debug_str_len, big_endian);
1823  if (!buf) {
1824  return NULL;
1825  }
1826 
1827  unit->count++;
1828  }
1829  return buf;
1830 }
1831 
1840 static const ut8 *info_comp_unit_read_hdr(const ut8 *buf, const ut8 *buf_end, RzBinDwarfCompUnitHdr *hdr, bool big_endian) {
1841  // 32-bit vs 64-bit dwarf formats
1842  // http://www.dwarfstd.org/doc/Dwarf3.pdf section 7.4
1843  hdr->length = READ32(buf);
1844  if (hdr->length == (ut32)DWARF_INIT_LEN_64) { // then its 64bit
1845  hdr->length = READ64(buf);
1846  hdr->is_64bit = true;
1847  }
1848  const ut8 *tmp = buf; // to calculate header size
1849  hdr->version = READ16(buf);
1850  if (hdr->version == 5) {
1851  hdr->unit_type = READ8(buf);
1852  hdr->address_size = READ8(buf);
1853  hdr->abbrev_offset = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1854 
1855  if (hdr->unit_type == DW_UT_skeleton || hdr->unit_type == DW_UT_split_compile) {
1856  hdr->dwo_id = READ8(buf);
1857  } else if (hdr->unit_type == DW_UT_type || hdr->unit_type == DW_UT_split_type) {
1858  hdr->type_sig = READ64(buf);
1859  hdr->type_offset = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1860  }
1861  } else {
1862  hdr->abbrev_offset = dwarf_read_offset(hdr->is_64bit, big_endian, &buf, buf_end);
1863  hdr->address_size = READ8(buf);
1864  }
1865  hdr->header_size = buf - tmp; // header size excluding length field
1866  return buf;
1867 }
1869  rz_return_val_if_fail(info && info->capacity == info->count, -1);
1870 
1871  RzBinDwarfCompUnit *tmp = realloc(info->comp_units,
1872  info->capacity * 2 * sizeof(RzBinDwarfCompUnit));
1873  if (!tmp) {
1874  return -1;
1875  }
1876 
1877  memset((ut8 *)tmp + info->capacity * sizeof(RzBinDwarfCompUnit),
1878  0, info->capacity * sizeof(RzBinDwarfCompUnit));
1879 
1880  info->comp_units = tmp;
1881  info->capacity *= 2;
1882 
1883  return 0;
1884 }
1885 
1898  const ut8 *obuf, size_t len,
1899  const ut8 *debug_str, size_t debug_str_len, bool big_endian) {
1900 
1901  rz_return_val_if_fail(da && obuf, false);
1902 
1903  const ut8 *buf = obuf;
1904  const ut8 *buf_end = obuf + len;
1905 
1907  if (!info) {
1908  return NULL;
1909  }
1910  if (!init_debug_info(info)) {
1911  goto cleanup;
1912  }
1913  int unit_idx = 0;
1914 
1915  while (buf < buf_end) {
1916  if (info->count >= info->capacity) {
1917  if (expand_info(info)) {
1918  break;
1919  }
1920  }
1921 
1922  RzBinDwarfCompUnit *unit = &info->comp_units[unit_idx];
1923  if (init_comp_unit(unit) < 0) {
1924  unit_idx--;
1925  goto cleanup;
1926  }
1927  info->count++;
1928 
1929  unit->offset = buf - obuf;
1930  // small redundancy, because it was easiest solution at a time
1931  unit->hdr.unit_offset = buf - obuf;
1932 
1933  buf = info_comp_unit_read_hdr(buf, buf_end, &unit->hdr, big_endian);
1934 
1935  if (unit->hdr.length > len) {
1936  goto cleanup;
1937  }
1938 
1939  if (da->decls->count >= da->capacity) {
1940  RZ_LOG_WARN("malformed dwarf have not enough buckets for decls.\n");
1941  }
1942  rz_warn_if_fail(da->count <= da->capacity);
1943 
1944  // find abbrev start for current comp unit
1945  // we could also do naive, ((char *)da->decls) + abbrev_offset,
1946  // but this is more bulletproof to invalid DWARF
1947  RzBinDwarfAbbrevDecl key = { .offset = unit->hdr.abbrev_offset };
1948  RzBinDwarfAbbrevDecl *abbrev_start = bsearch(&key, da->decls, da->count, sizeof(key), abbrev_cmp);
1949  if (!abbrev_start) {
1950  goto cleanup;
1951  }
1952  // They point to the same array object, so should be def. behaviour
1953  size_t first_abbr_idx = abbrev_start - da->decls;
1954 
1955  buf = parse_comp_unit(info, buf, unit, da, first_abbr_idx, debug_str, debug_str_len, big_endian);
1956 
1957  if (!buf) {
1958  goto cleanup;
1959  }
1960 
1961  info->n_dwarf_dies += unit->count;
1962 
1963  unit_idx++;
1964  }
1965 
1966  return info;
1967 
1968 cleanup:
1970  return NULL;
1971 }
1972 
1974  const ut8 *buf = obuf, *buf_end = obuf + len;
1975  ut64 tmp, attr_code, attr_form, offset;
1976  st64 special;
1977  ut8 has_children;
1978  RzBinDwarfAbbrevDecl *tmpdecl;
1979 
1980  // XXX - Set a suitable value here.
1981  if (!obuf || len < 3) {
1982  return NULL;
1983  }
1985 
1986  init_debug_abbrev(da);
1987 
1988  while (buf && buf + 1 < buf_end) {
1989  offset = buf - obuf;
1990  buf = rz_uleb128(buf, (size_t)(buf_end - buf), &tmp, NULL);
1991  if (!buf || !tmp || buf >= buf_end) {
1992  continue;
1993  }
1994  if (da->count == da->capacity) {
1995  expand_debug_abbrev(da);
1996  }
1997  tmpdecl = &da->decls[da->count];
1998  init_abbrev_decl(tmpdecl);
1999 
2000  tmpdecl->code = tmp;
2001  buf = rz_uleb128(buf, (size_t)(buf_end - buf), &tmp, NULL);
2002  tmpdecl->tag = tmp;
2003 
2004  tmpdecl->offset = offset;
2005  if (buf >= buf_end) {
2006  break;
2007  }
2008  has_children = READ8(buf);
2009  tmpdecl->has_children = has_children;
2010  do {
2011  if (tmpdecl->count == tmpdecl->capacity) {
2012  expand_abbrev_decl(tmpdecl);
2013  }
2014  buf = rz_uleb128(buf, (size_t)(buf_end - buf), &attr_code, NULL);
2015  if (buf >= buf_end) {
2016  break;
2017  }
2018  buf = rz_uleb128(buf, (size_t)(buf_end - buf), &attr_form, NULL);
2019  // http://www.dwarfstd.org/doc/DWARF5.pdf#page=225
2020  if (attr_form == DW_FORM_implicit_const) {
2021  buf = rz_leb128(buf, (size_t)(buf_end - buf), &special);
2022  tmpdecl->defs[tmpdecl->count].special = special;
2023  }
2024  tmpdecl->defs[tmpdecl->count].attr_name = attr_code;
2025  tmpdecl->defs[tmpdecl->count].attr_form = attr_form;
2026  tmpdecl->count++;
2027  } while (attr_code && attr_form);
2028 
2029  da->count++;
2030  }
2031  return da;
2032 }
2033 
2034 static RzBinSection *getsection(RzBinFile *binfile, const char *sn) {
2035  rz_return_val_if_fail(binfile && sn, NULL);
2036  RzListIter *iter;
2038  RzBinObject *o = binfile->o;
2039  if (!o || !o->sections) {
2040  return NULL;
2041  }
2042  rz_list_foreach (o->sections, iter, section) {
2043  if (!section->name) {
2044  continue;
2045  }
2046  if (strstr(section->name, sn)) {
2047  return section;
2048  }
2049  }
2050  return NULL;
2051 }
2052 
2053 static ut8 *get_section_bytes(RzBinFile *binfile, const char *sect_name, size_t *len) {
2054  rz_return_val_if_fail(binfile && sect_name && len, NULL);
2055  RzBinSection *section = getsection(binfile, sect_name);
2056  if (!section) {
2057  return NULL;
2058  }
2059  if (section->paddr >= binfile->size) {
2060  return NULL;
2061  }
2062  *len = RZ_MIN(section->size, binfile->size - section->paddr);
2063  ut8 *buf = calloc(1, *len);
2064  rz_buf_read_at(binfile->buf, section->paddr, buf, *len);
2065  return buf;
2066 }
2067 
2076  rz_return_val_if_fail(binfile && da, NULL);
2078 
2079  size_t debug_str_len = 0;
2080  ut8 *debug_str_buf = get_section_bytes(binfile, "debug_str", &debug_str_len);
2081 
2082  size_t len;
2083  ut8 *buf = get_section_bytes(binfile, "debug_info", &len);
2084  if (!buf) {
2085  goto cave_debug_str_buf;
2086  }
2087  info = parse_info_raw(da, buf, len, debug_str_buf, debug_str_len,
2088  binfile->o && binfile->o->info && binfile->o->info->big_endian);
2089  if (!info) {
2090  goto cave_buf;
2091  }
2092  info->lookup_table = ht_up_new_size(info->n_dwarf_dies, NULL, NULL, NULL);
2093  if (!info->lookup_table) {
2095  info = NULL;
2096  goto cave_buf;
2097  }
2098  // build hashtable after whole parsing because of possible relocations
2099  if (info) {
2100  size_t i, j;
2101  for (i = 0; i < info->count; i++) {
2102  RzBinDwarfCompUnit *unit = &info->comp_units[i];
2103  for (j = 0; j < unit->count; j++) {
2104  RzBinDwarfDie *die = &unit->dies[j];
2105  ht_up_insert(info->lookup_table, die->offset, die); // optimization for further processing}
2106  }
2107  }
2108  }
2109 cave_buf:
2110  free(buf);
2111 cave_debug_str_buf:
2112  free(debug_str_buf);
2113  return info;
2114 }
2115 
2120  rz_return_val_if_fail(binfile, NULL);
2121  size_t len;
2122  ut8 *buf = get_section_bytes(binfile, "debug_line", &len);
2123  if (!buf) {
2124  return NULL;
2125  }
2126  // Actually parse the section
2127  RzBinDwarfLineInfo *r = parse_line_raw(binfile, buf, len, mask, binfile->o && binfile->o->info && binfile->o->info->big_endian, info);
2128  free(buf);
2129  return r;
2130 }
2131 
2132 RZ_API RzList /*<RzBinDwarfARangeSet *>*/ *rz_bin_dwarf_parse_aranges(RzBinFile *binfile) {
2133  rz_return_val_if_fail(binfile, NULL);
2134  size_t len;
2135  ut8 *buf = get_section_bytes(binfile, "debug_aranges", &len);
2136  if (!buf) {
2137  return NULL;
2138  }
2139  RzList *r = parse_aranges_raw(buf, len, binfile->o && binfile->o->info && binfile->o->info->big_endian);
2140  free(buf);
2141  return r;
2142 }
2143 
2145  rz_return_val_if_fail(binfile, NULL);
2146  size_t len = 0;
2147  ut8 *buf = get_section_bytes(binfile, "debug_abbrev", &len);
2148  if (!buf) {
2149  return NULL;
2150  }
2152  free(buf);
2153  return abbrevs;
2154 }
2155 
2156 static inline ut64 get_max_offset(size_t addr_size) {
2157  switch (addr_size) {
2158  case 2:
2159  return UT16_MAX;
2160  case 4:
2161  return UT32_MAX;
2162  case 8:
2163  return UT64_MAX;
2164  }
2165  return 0;
2166 }
2167 
2170  if (list) {
2171  list->list = rz_list_new();
2172  list->offset = offset;
2173  }
2174  return list;
2175 }
2176 
2179  if (range) {
2180  range->start = start;
2181  range->end = end;
2182  range->expression = block;
2183  }
2184  return range;
2185 }
2186 
2187 static void free_loc_table_list(RzBinDwarfLocList *loc_list) {
2188  RzListIter *iter;
2190  rz_list_foreach (loc_list->list, iter, range) {
2191  free(range->expression->data);
2192  free(range->expression);
2193  free(range);
2194  }
2195  rz_list_free(loc_list->list);
2196  free(loc_list);
2197 }
2198 
2199 static HtUP *parse_loc_raw(HtUP /*<offset, List *<LocListEntry>*/ *loc_table, const ut8 *buf, size_t len, size_t addr_size,
2200  bool big_endian) {
2201  /* GNU has their own extensions GNU locviews that we can't parse */
2202  const ut8 *const buf_start = buf;
2203  const ut8 *buf_end = buf + len;
2204  /* for recognizing Base address entry */
2205  ut64 max_offset = get_max_offset(addr_size);
2206 
2207  ut64 address_base = 0; /* remember base of the loclist */
2208  ut64 list_offset = 0;
2209 
2210  RzBinDwarfLocList *loc_list = NULL;
2212  while (buf && buf < buf_end) {
2213  ut64 start_addr = dwarf_read_address(addr_size, big_endian, &buf, buf_end);
2214  ut64 end_addr = dwarf_read_address(addr_size, big_endian, &buf, buf_end);
2215 
2216  if (start_addr == 0 && end_addr == 0) { /* end of list entry: 0, 0 */
2217  if (loc_list) {
2218  ht_up_insert(loc_table, loc_list->offset, loc_list);
2219  list_offset = buf - buf_start;
2220  loc_list = NULL;
2221  }
2222  address_base = 0;
2223  continue;
2224  } else if (start_addr == max_offset && end_addr != max_offset) {
2225  /* base address, DWARF2 doesn't have this type of entry, these entries shouldn't
2226  be in the list, they are just informational entries for further parsing (address_base) */
2227  address_base = end_addr;
2228  } else { /* location list entry: */
2229  if (!loc_list) {
2230  loc_list = create_loc_list(list_offset);
2231  }
2232  /* TODO in future parse expressions to better structure in dwarf.c and not in dwarf_process.c */
2234  block->length = READ16(buf);
2235  buf = fill_block_data(buf, buf_end, block);
2236  range = create_loc_range(start_addr + address_base, end_addr + address_base, block);
2237  if (!range) {
2238  free(block);
2239  }
2240  rz_list_append(loc_list->list, range);
2241  range = NULL;
2242  }
2243  }
2244  /* if for some reason end of list is missing, then loc_list would leak */
2245  if (loc_list) {
2246  free_loc_table_list(loc_list);
2247  }
2248  return loc_table;
2249 }
2250 
2259 RZ_API HtUP /*<offset, RzBinDwarfLocList *>*/ *rz_bin_dwarf_parse_loc(RzBinFile *binfile, int addr_size) {
2260  rz_return_val_if_fail(binfile, NULL);
2261  /* The standarparse_loc_raw_frame, not sure why is that */
2262  size_t len = 0;
2263  ut8 *buf = get_section_bytes(binfile, "debug_loc", &len);
2264  if (!buf) {
2265  return NULL;
2266  }
2267  HtUP /*<offset, RzBinDwarfLocList*/ *loc_table = ht_up_new0();
2268  if (!loc_table) {
2269  free(buf);
2270  return NULL;
2271  }
2272  loc_table = parse_loc_raw(loc_table, buf, len, addr_size, binfile->o && binfile->o->info && binfile->o->info->big_endian);
2273  free(buf);
2274  return loc_table;
2275 }
2276 
2277 static void free_loc_table_entry(HtUPKv *kv) {
2278  if (kv) {
2279  free_loc_table_list(kv->value);
2280  }
2281 }
2282 
2283 RZ_API void rz_bin_dwarf_loc_free(HtUP /*<offset, RzBinDwarfLocList *>*/ *loc_table) {
2284  rz_return_if_fail(loc_table);
2285  loc_table->opt.freefn = free_loc_table_entry;
2286  ht_up_free(loc_table);
2287 }
size_t len
Definition: 6502dis.c:15
static struct @29 ops[]
#define mask()
static char * regs[]
Definition: analysis_sh.c:203
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
RZ_API void rz_bin_source_line_info_free(RzBinSourceLineInfo *sli)
Definition: dbginfo.c:137
RZ_API void rz_bin_source_line_info_builder_init(RzBinSourceLineInfoBuilder *builder)
Definition: dbginfo.c:9
RZ_API RzBinSourceLineInfo * rz_bin_source_line_info_builder_build_and_fini(RzBinSourceLineInfoBuilder *builder)
Definition: dbginfo.c:87
RZ_API void rz_bin_source_line_info_builder_push_sample(RzBinSourceLineInfoBuilder *builder, ut64 address, ut32 line, ut32 column, const char *file)
Push a new sample into the builder.
Definition: dbginfo.c:28
static int buf_size
Definition: debug_qnx.c:35
uint32_t ut32
static int init_debug_abbrev(RzBinDwarfDebugAbbrev *da)
Definition: dwarf.c:1304
static void free_die(RzBinDwarfDie *die)
Definition: dwarf.c:1383
static void free_attr_value(RzBinDwarfAttrValue *val)
Definition: dwarf.c:1361
#define READ16(buf)
Definition: dwarf.c:29
static const ut8 * parse_attr_value(const ut8 *obuf, int obuf_len, RzBinDwarfAttrDef *def, RzBinDwarfAttrValue *value, const RzBinDwarfCompUnitHdr *hdr, const ut8 *debug_str, size_t debug_str_len, bool big_endian)
Parses attribute value based on its definition and stores it into value
Definition: dwarf.c:1450
RZ_API const char * rz_bin_dwarf_get_attr_name(ut64 attr_code)
Definition: dwarf.c:323
RZ_API RzBinDwarfDebugAbbrev * rz_bin_dwarf_parse_abbrev(RzBinFile *binfile)
Definition: dwarf.c:2144
RZ_API const char * rz_bin_dwarf_get_lang_name(ut64 lang)
Definition: dwarf.c:387
RZ_API void rz_bin_dwarf_debug_abbrev_free(RzBinDwarfDebugAbbrev *da)
Definition: dwarf.c:1340
static RzBinDwarfDebugAbbrev * parse_abbrev_raw(const ut8 *obuf, size_t len)
Definition: dwarf.c:1973
static const char * dwarf_attr_form_encodings[]
Definition: dwarf.c:228
RZ_API st64 rz_bin_dwarf_line_header_get_spec_op_advance_line(const RzBinDwarfLineHeader *header, ut8 opcode)
Definition: dwarf.c:628
static ut64 dwarf_read_offset(bool is_64bit, bool big_endian, const ut8 **buf, const ut8 *buf_end)
Reads 64/32 bit unsigned based on format.
Definition: dwarf.c:430
static const char * dwarf_tag_name_encodings[]
Definition: dwarf.c:39
RZ_API void rz_bin_dwarf_line_header_free_file_cache(const RzBinDwarfLineHeader *hdr, RzBinDwarfLineFileCache fnc)
Definition: dwarf.c:589
RZ_API void rz_bin_dwarf_line_info_free(RzBinDwarfLineInfo *li)
Definition: dwarf.c:1352
static const char * dwarf_attr_encodings[]
Definition: dwarf.c:105
RZ_API void rz_bin_dwarf_loc_free(HtUP *loc_table)
Definition: dwarf.c:2283
static RzBinDwarfLocList * create_loc_list(ut64 offset)
Definition: dwarf.c:2168
RZ_API void rz_bin_dwarf_line_op_fini(RzBinDwarfLineOp *op)
Definition: dwarf.c:699
RZ_API bool rz_bin_dwarf_line_op_run(const RzBinDwarfLineHeader *hdr, RzBinDwarfSMRegisters *regs, RzBinDwarfLineOp *op, RZ_NULLABLE RzBinSourceLineInfoBuilder *bob, RZ_NULLABLE RzBinDwarfDebugInfo *info, RZ_NULLABLE RzBinDwarfLineFileCache fnc)
Execute a single line op on regs and optionally store the resulting line info in bob.
Definition: dwarf.c:851
static void free_loc_table_entry(HtUPKv *kv)
Definition: dwarf.c:2277
RZ_API const char * rz_bin_dwarf_get_attr_form_name(ut64 form_code)
Definition: dwarf.c:373
static const ut8 * parse_die(const ut8 *buf, const ut8 *buf_end, RzBinDwarfDebugInfo *info, RzBinDwarfAbbrevDecl *abbrev, RzBinDwarfCompUnitHdr *hdr, RzBinDwarfDie *die, const ut8 *debug_str, size_t debug_str_len, bool big_endian)
Definition: dwarf.c:1722
static const ut8 * fill_block_data(const ut8 *buf, const ut8 *buf_end, RzBinDwarfBlock *block)
Definition: dwarf.c:1420
static void free_comp_unit(RzBinDwarfCompUnit *cu)
Definition: dwarf.c:1394
static RzBinDwarfLineInfo * parse_line_raw(RzBinFile *binfile, const ut8 *obuf, ut64 len, RzBinDwarfLineInfoMask mask, bool big_endian, RZ_NULLABLE RzBinDwarfDebugInfo *info)
Definition: dwarf.c:996
RZ_API ut64 rz_bin_dwarf_line_header_get_spec_op_advance_pc(const RzBinDwarfLineHeader *header, ut8 opcode)
Definition: dwarf.c:618
static ut64 dwarf_read_address(size_t size, bool big_endian, const ut8 **buf, const ut8 *buf_end)
Definition: dwarf.c:440
static const ut8 * parse_ext_opcode(RzBinDwarfLineOp *op, const RzBinDwarfLineHeader *hdr, const ut8 *obuf, size_t len, bool big_endian, ut8 target_addr_size)
Definition: dwarf.c:706
static size_t std_opcode_args_count(const RzBinDwarfLineHeader *hdr, ut8 opcode)
Definition: dwarf.c:767
static RzBinSection * getsection(RzBinFile *binfile, const char *sn)
Definition: dwarf.c:2034
static int init_abbrev_decl(RzBinDwarfAbbrevDecl *ad)
Definition: dwarf.c:1265
static int expand_info(RzBinDwarfDebugInfo *info)
Definition: dwarf.c:1868
RZ_API void rz_bin_dwarf_line_header_reset_regs(const RzBinDwarfLineHeader *hdr, RzBinDwarfSMRegisters *regs)
Definition: dwarf.c:824
static void free_loc_table_list(RzBinDwarfLocList *loc_list)
Definition: dwarf.c:2187
RZ_API char * rz_bin_dwarf_line_header_get_full_file_path(RZ_NULLABLE const RzBinDwarfDebugInfo *info, const RzBinDwarfLineHeader *header, ut64 file_index)
Definition: dwarf.c:547
static const char * dwarf_langs[]
Definition: dwarf.c:274
#define READ64(buf)
Definition: dwarf.c:35
RZ_API const char * rz_bin_dwarf_get_tag_name(ut64 tag)
Definition: dwarf.c:316
static const ut8 * parse_line_header(RzBinFile *bf, const ut8 *buf, const ut8 *buf_end, RzBinDwarfLineHeader *hdr, ut64 offset_cur, bool big_endian)
Definition: dwarf.c:638
static void free_ht_comp_dir(HtUPKv *kv)
Definition: dwarf.c:1192
static int expand_cu(RzBinDwarfCompUnit *cu)
Definition: dwarf.c:1244
RZ_API RzList * rz_bin_dwarf_parse_aranges(RzBinFile *binfile)
Definition: dwarf.c:2132
static RzBinDwarfDebugInfo * parse_info_raw(RzBinDwarfDebugAbbrev *da, const ut8 *obuf, size_t len, const ut8 *debug_str, size_t debug_str_len, bool big_endian)
Parses whole .debug_info section.
Definition: dwarf.c:1897
static int abbrev_cmp(const void *a, const void *b)
Definition: dwarf.c:394
static int expand_debug_abbrev(RzBinDwarfDebugAbbrev *da)
Definition: dwarf.c:1318
static size_t parse_opcodes(const ut8 *obuf, size_t len, const RzBinDwarfLineHeader *hdr, RzVector *ops_out, RzBinDwarfSMRegisters *regs, RZ_NULLABLE RzBinSourceLineInfoBuilder *bob, RZ_NULLABLE RzBinDwarfDebugInfo *info, RZ_NULLABLE RzBinDwarfLineFileCache fnc, bool big_endian, ut8 target_addr_size)
Definition: dwarf.c:939
RZ_API void rz_bin_dwarf_arange_set_free(RzBinDwarfARangeSet *set)
Definition: dwarf.c:1106
static bool init_debug_info(RzBinDwarfDebugInfo *inf)
Definition: dwarf.c:1196
static ut64 get_max_offset(size_t addr_size)
Definition: dwarf.c:2156
RZ_API RzBinDwarfDebugInfo * rz_bin_dwarf_parse_info(RzBinFile *binfile, RzBinDwarfDebugAbbrev *da)
Parses .debug_info section.
Definition: dwarf.c:2075
static int expand_abbrev_decl(RzBinDwarfAbbrevDecl *ad)
Definition: dwarf.c:1281
static const ut8 * info_comp_unit_read_hdr(const ut8 *buf, const ut8 *buf_end, RzBinDwarfCompUnitHdr *hdr, bool big_endian)
Reads all information about compilation unit header.
Definition: dwarf.c:1840
static void store_line_sample(RzBinSourceLineInfoBuilder *bob, const RzBinDwarfLineHeader *hdr, RzBinDwarfSMRegisters *regs, RZ_NULLABLE RzBinDwarfDebugInfo *info, RZ_NULLABLE RzBinDwarfLineFileCache fnc)
Definition: dwarf.c:838
static int init_comp_unit(RzBinDwarfCompUnit *cu)
Definition: dwarf.c:1231
static const char * get_full_file_path(const RzBinDwarfDebugInfo *info, const RzBinDwarfLineHeader *header, RZ_NULLABLE RzBinDwarfLineFileCache cache, ut64 file_index)
Definition: dwarf.c:599
RZ_API const char * rz_bin_dwarf_get_unit_type_name(ut64 unit_type)
Definition: dwarf.c:380
static HtUP * parse_loc_raw(HtUP *loc_table, const ut8 *buf, size_t len, size_t addr_size, bool big_endian)
Definition: dwarf.c:2199
static RzList * parse_aranges_raw(const ut8 *obuf, size_t obuf_sz, bool big_endian)
Definition: dwarf.c:1114
static RzBinDwarfLocRange * create_loc_range(ut64 start, ut64 end, RzBinDwarfBlock *block)
Definition: dwarf.c:2177
RZ_API HtUP * rz_bin_dwarf_parse_loc(RzBinFile *binfile, int addr_size)
Parses out the .debug_loc section into a table that maps each list as offset of a list -> LocationLis...
Definition: dwarf.c:2259
#define READ8(buf)
Definition: dwarf.c:26
static int init_die(RzBinDwarfDie *die, ut64 abbr_code, ut64 attr_count)
Definition: dwarf.c:1213
RZ_API RzBinDwarfLineFileCache rz_bin_dwarf_line_header_new_file_cache(const RzBinDwarfLineHeader *hdr)
Definition: dwarf.c:585
static void line_unit_free(RzBinDwarfLineUnit *unit)
Definition: dwarf.c:982
RZ_API void rz_bin_dwarf_debug_info_free(RzBinDwarfDebugInfo *inf)
Definition: dwarf.c:1407
static const ut8 * parse_line_header_source(RzBinFile *bf, const ut8 *buf, const ut8 *buf_end, RzBinDwarfLineHeader *hdr)
Definition: dwarf.c:479
static void line_header_fini(RzBinDwarfLineHeader *hdr)
Definition: dwarf.c:460
#define READ32(buf)
Definition: dwarf.c:32
static const ut8 * parse_std_opcode(RzBinDwarfLineOp *op, const RzBinDwarfLineHeader *hdr, const ut8 *obuf, size_t len, ut8 opcode, bool big_endian)
Definition: dwarf.c:774
static ut64 dwarf_read_initial_length(RZ_OUT bool *is_64bit, bool big_endian, const ut8 **buf, const ut8 *buf_end)
Read an "initial length" value, as specified by dwarf. This also determines whether it is 64bit or 32...
Definition: dwarf.c:411
RZ_API ut64 rz_bin_dwarf_line_header_get_adj_opcode(const RzBinDwarfLineHeader *header, ut8 opcode)
Definition: dwarf.c:613
static ut8 * get_section_bytes(RzBinFile *binfile, const char *sect_name, size_t *len)
Definition: dwarf.c:2053
RZ_API RzBinDwarfLineInfo * rz_bin_dwarf_parse_line(RzBinFile *binfile, RZ_NULLABLE RzBinDwarfDebugInfo *info, RzBinDwarfLineInfoMask mask)
Definition: dwarf.c:2119
static const char * dwarf_unit_types[]
Definition: dwarf.c:305
static const ut8 * parse_comp_unit(RzBinDwarfDebugInfo *info, const ut8 *buf_start, RzBinDwarfCompUnit *unit, const RzBinDwarfDebugAbbrev *abbrevs, size_t first_abbr_idx, const ut8 *debug_str, size_t debug_str_len, bool big_endian)
Reads throught comp_unit buffer and parses all its DIEntries.
Definition: dwarf.c:1776
void cleanup(void)
Definition: enough.c:244
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static const char struct stat static buf struct stat static buf static idle const char static path static fd const char static len const void static prot const char struct module static image struct kernel_sym static table unsigned char static buf static fsuid unsigned struct dirent unsigned static count const struct iovec static count static pid const void static len static flags const struct sched_param static p static pid static policy struct timespec static tp static suid unsigned fn
Definition: sflib.h:186
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define header(is_bt, len_min, ret_op)
int off
Definition: pal.c:13
static void pad(RzStrBuf *sb, ut32 count)
Definition: protobuf.c:36
static void special(struct parse *, int)
Definition: regcomp.c:1076
#define rz_warn_if_fail(expr)
Definition: rz_assert.h:35
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define DW_FORM_strx4
Definition: rz_bin_dwarf.h:317
#define DW_FORM_strx3
Definition: rz_bin_dwarf.h:316
#define DW_FORM_exprloc
Definition: rz_bin_dwarf.h:301
#define DW_AT_hi_user
Definition: rz_bin_dwarf.h:277
#define DW_AT_high_pc
Definition: rz_bin_dwarf.h:142
#define DW_TAG_friend
Definition: rz_bin_dwarf.h:90
#define DW_AT_trampoline
Definition: rz_bin_dwarf.h:200
#define DW_AT_segment
Definition: rz_bin_dwarf.h:184
#define DW_TAG_variable
Definition: rz_bin_dwarf.h:107
#define DW_AT_addr_base
Definition: rz_bin_dwarf.h:230
#define DW_AT_specification
Definition: rz_bin_dwarf.h:185
#define DW_AT_binary_scale
Definition: rz_bin_dwarf.h:205
#define DW_AT_picture_string
Definition: rz_bin_dwarf.h:210
#define DEBUG_ABBREV_CAP
Definition: rz_bin_dwarf.h:796
#define DW_AT_producer
Definition: rz_bin_dwarf.h:157
#define DW_AT_call_data_value
Definition: rz_bin_dwarf.h:249
#define DW_AT_endianity
Definition: rz_bin_dwarf.h:215
#define DW_LANG_Rust
Definition: rz_bin_dwarf.h:549
#define DW_AT_comp_dir
Definition: rz_bin_dwarf.h:150
#define DW_TAG_access_declaration
Definition: rz_bin_dwarf.h:83
#define DW_TAG_catch_block
Definition: rz_bin_dwarf.h:85
#define DW_FORM_sdata
Definition: rz_bin_dwarf.h:290
#define DW_TAG_thrown_type
Definition: rz_bin_dwarf.h:104
#define DW_LANG_C89
Definition: rz_bin_dwarf.h:529
#define DW_AT_rank
Definition: rz_bin_dwarf.h:228
#define DW_FORM_addrx4
Definition: rz_bin_dwarf.h:321
#define DW_AT_count
Definition: rz_bin_dwarf.h:169
#define DW_AT_data_location
Definition: rz_bin_dwarf.h:194
#define DW_AT_threads_scaled
Definition: rz_bin_dwarf.h:212
#define DW_FORM_udata
Definition: rz_bin_dwarf.h:292
#define DW_AT_alignment
Definition: rz_bin_dwarf.h:251
#define DW_AT_enum_class
Definition: rz_bin_dwarf.h:223
#define DW_TAG_constant
Definition: rz_bin_dwarf.h:87
#define DW_LNE_set_address
Definition: rz_bin_dwarf.h:33
#define DW_TAG_subrange_type
Definition: rz_bin_dwarf.h:81
#define DW_FORM_ref_sup8
Definition: rz_bin_dwarf.h:313
#define DW_TAG_label
Definition: rz_bin_dwarf.h:61
#define DW_TAG_ptr_to_member_type
Definition: rz_bin_dwarf.h:79
#define DW_LANG_Swift
Definition: rz_bin_dwarf.h:551
#define DW_LANG_Julia
Definition: rz_bin_dwarf.h:552
#define DW_LNS_set_column
Definition: rz_bin_dwarf.h:23
#define DW_TAG_subprogram
Definition: rz_bin_dwarf.h:97
#define DW_AT_artificial
Definition: rz_bin_dwarf.h:166
#define DW_AT_GNU_pubtypes
Definition: rz_bin_dwarf.h:276
#define DW_LNS_advance_pc
Definition: rz_bin_dwarf.h:20
#define DW_AT_GNU_all_call_sites
Definition: rz_bin_dwarf.h:267
#define DW_AT_encoding
Definition: rz_bin_dwarf.h:176
#define DW_FORM_strx
Definition: rz_bin_dwarf.h:303
#define DW_FORM_addrx3
Definition: rz_bin_dwarf.h:320
#define DW_TAG_volatile_type
Definition: rz_bin_dwarf.h:108
#define DW_AT_data_member_location
Definition: rz_bin_dwarf.h:170
#define DW_LANG_ObjC
Definition: rz_bin_dwarf.h:544
#define DW_AT_inline
Definition: rz_bin_dwarf.h:154
#define DW_UT_split_type
Definition: rz_bin_dwarf.h:623
#define DW_AT_visibility
Definition: rz_bin_dwarf.h:146
#define DW_AT_language
Definition: rz_bin_dwarf.h:143
#define DW_TAG_interface_type
Definition: rz_bin_dwarf.h:111
#define DW_AT_calling_convention
Definition: rz_bin_dwarf.h:168
#define DW_TAG_inlined_subroutine
Definition: rz_bin_dwarf.h:77
#define DW_AT_decl_file
Definition: rz_bin_dwarf.h:172
#define DW_FORM_ref_udata
Definition: rz_bin_dwarf.h:298
#define DW_LNS_advance_line
Definition: rz_bin_dwarf.h:21
#define DW_AT_use_UTF8
Definition: rz_bin_dwarf.h:197
#define DW_LNS_set_file
Definition: rz_bin_dwarf.h:22
RzBinDwarfLineInfoMask
Definition: rz_bin_dwarf.h:906
@ RZ_BIN_DWARF_LINE_INFO_MASK_OPS
Definition: rz_bin_dwarf.h:908
@ RZ_BIN_DWARF_LINE_INFO_MASK_LINES
Definition: rz_bin_dwarf.h:909
#define DW_AT_GNU_call_site_target_clobbered
Definition: rz_bin_dwarf.h:264
#define DW_TAG_partial_unit
Definition: rz_bin_dwarf.h:115
#define DW_AT_default_value
Definition: rz_bin_dwarf.h:153
#define DW_TAG_variant_part
Definition: rz_bin_dwarf.h:106
#define DW_AT_virtuality
Definition: rz_bin_dwarf.h:190
#define DW_TAG_formal_parameter
Definition: rz_bin_dwarf.h:59
#define COMP_UNIT_CAPACITY
Definition: rz_bin_dwarf.h:767
#define DW_AT_discr_value
Definition: rz_bin_dwarf.h:145
#define DW_LANG_Java
Definition: rz_bin_dwarf.h:539
#define DW_AT_loclists_base
Definition: rz_bin_dwarf.h:255
@ DW_AT_KIND_STRING
Definition: rz_bin_dwarf.h:698
@ DW_AT_KIND_REFERENCE
Definition: rz_bin_dwarf.h:697
@ DW_AT_KIND_BLOCK
Definition: rz_bin_dwarf.h:689
@ DW_AT_KIND_CONSTANT
Definition: rz_bin_dwarf.h:690
@ DW_AT_KIND_ADDRESS
Definition: rz_bin_dwarf.h:688
@ DW_AT_KIND_FLAG
Definition: rz_bin_dwarf.h:692
@ DW_AT_KIND_LOCLISTPTR
Definition: rz_bin_dwarf.h:694
#define DW_AT_GNU_all_source_call_sites
Definition: rz_bin_dwarf.h:268
#define DW_FORM_block2
Definition: rz_bin_dwarf.h:280
#define DW_FORM_addr
Definition: rz_bin_dwarf.h:279
#define DW_FORM_data16
Definition: rz_bin_dwarf.h:307
#define DW_TAG_imported_unit
Definition: rz_bin_dwarf.h:116
#define DW_AT_GNU_deleted
Definition: rz_bin_dwarf.h:270
#define DW_AT_recursive
Definition: rz_bin_dwarf.h:218
#define DW_TAG_class_type
Definition: rz_bin_dwarf.h:56
#define DW_LANG_Dylan
Definition: rz_bin_dwarf.h:553
#define DW_AT_description
Definition: rz_bin_dwarf.h:204
#define DW_TAG_unspecified_type
Definition: rz_bin_dwarf.h:114
#define DW_AT_name
Definition: rz_bin_dwarf.h:135
#define DW_LANG_Modula2
Definition: rz_bin_dwarf.h:538
#define DW_LNS_copy
Definition: rz_bin_dwarf.h:19
#define DW_FORM_line_ptr
Definition: rz_bin_dwarf.h:308
#define DW_AT_call_all_tail_calls
Definition: rz_bin_dwarf.h:239
#define DW_LNS_set_isa
Definition: rz_bin_dwarf.h:30
#define DW_TAG_typedef
Definition: rz_bin_dwarf.h:70
#define DW_TAG_template_type_param
Definition: rz_bin_dwarf.h:101
#define DW_AT_friend
Definition: rz_bin_dwarf.h:179
#define DW_AT_allocated
Definition: rz_bin_dwarf.h:192
#define DW_AT_export_symbols
Definition: rz_bin_dwarf.h:252
#define DW_TAG_inheritance
Definition: rz_bin_dwarf.h:76
#define DW_AT_call_parameter
Definition: rz_bin_dwarf.h:243
#define DW_TAG_namelist
Definition: rz_bin_dwarf.h:91
#define DW_AT_discr_list
Definition: rz_bin_dwarf.h:175
#define DW_AT_reference
Definition: rz_bin_dwarf.h:234
#define DW_LANG_PLI
Definition: rz_bin_dwarf.h:543
#define DW_AT_byte_stride
Definition: rz_bin_dwarf.h:195
#define DW_TAG_structure_type
Definition: rz_bin_dwarf.h:68
#define DW_FORM_ref_sup4
Definition: rz_bin_dwarf.h:305
#define DW_LANG_Python
Definition: rz_bin_dwarf.h:548
#define DW_LANG_C_plus_plus
Definition: rz_bin_dwarf.h:532
#define DW_LNS_negate_stmt
Definition: rz_bin_dwarf.h:24
#define DW_AT_decl_column
Definition: rz_bin_dwarf.h:171
#define DW_LANG_Cobol85
Definition: rz_bin_dwarf.h:534
#define DW_TAG_template_alias
Definition: rz_bin_dwarf.h:123
#define DW_AT_location
Definition: rz_bin_dwarf.h:134
#define DW_AT_call_data_location
Definition: rz_bin_dwarf.h:248
#define DW_AT_upper_bound
Definition: rz_bin_dwarf.h:162
#define DW_AT_priority
Definition: rz_bin_dwarf.h:183
#define DW_TAG_array_type
Definition: rz_bin_dwarf.h:55
#define DW_AT_GNU_call_site_data_value
Definition: rz_bin_dwarf.h:262
#define DWARF_INIT_LEN_64
Definition: rz_bin_dwarf.h:652
#define DW_AT_call_line
Definition: rz_bin_dwarf.h:203
#define DW_AT_accessibility
Definition: rz_bin_dwarf.h:164
#define DW_AT_digit_count
Definition: rz_bin_dwarf.h:209
#define DW_AT_extension
Definition: rz_bin_dwarf.h:198
#define DW_TAG_shared_type
Definition: rz_bin_dwarf.h:120
#define DW_AT_small
Definition: rz_bin_dwarf.h:207
#define DW_TAG_module
Definition: rz_bin_dwarf.h:78
#define DW_FORM_ref_sig8
Definition: rz_bin_dwarf.h:309
#define DW_TAG_mutable_type
Definition: rz_bin_dwarf.h:118
#define DW_AT_GNU_addr_base
Definition: rz_bin_dwarf.h:274
#define DW_AT_data_bit_offset
Definition: rz_bin_dwarf.h:221
#define DW_LANG_C
Definition: rz_bin_dwarf.h:530
#define DW_AT_decimal_scale
Definition: rz_bin_dwarf.h:206
#define DW_TAG_set_type
Definition: rz_bin_dwarf.h:80
#define DW_TAG_pointer_type
Definition: rz_bin_dwarf.h:64
#define DW_AT_signature
Definition: rz_bin_dwarf.h:219
#define DW_AT_call_all_source_calls
Definition: rz_bin_dwarf.h:238
#define DW_AT_mutable
Definition: rz_bin_dwarf.h:211
#define DW_AT_macro_info
Definition: rz_bin_dwarf.h:181
#define DW_AT_rnglists_base
Definition: rz_bin_dwarf.h:231
#define DW_FORM_implicit_const
Definition: rz_bin_dwarf.h:310
#define DW_AT_call_tail_call
Definition: rz_bin_dwarf.h:245
#define DW_AT_vtable_elem_location
Definition: rz_bin_dwarf.h:191
#define DW_AT_const_expr
Definition: rz_bin_dwarf.h:222
#define DW_AT_MIPS_linkage_name
Definition: rz_bin_dwarf.h:260
#define DW_LANG_Fortran03
Definition: rz_bin_dwarf.h:555
#define DW_AT_noreturn
Definition: rz_bin_dwarf.h:250
#define DW_AT_decimal_sign
Definition: rz_bin_dwarf.h:208
#define DW_UT_compile
Definition: rz_bin_dwarf.h:618
#define DW_AT_pure
Definition: rz_bin_dwarf.h:217
#define DW_AT_abstract_origin
Definition: rz_bin_dwarf.h:163
#define DW_FORM_block1
Definition: rz_bin_dwarf.h:287
#define DW_AT_call_origin
Definition: rz_bin_dwarf.h:242
#define DW_TAG_null_entry
Definition: rz_bin_dwarf.h:54
#define DW_AT_containing_type
Definition: rz_bin_dwarf.h:152
#define DW_LNE_set_discriminator
Definition: rz_bin_dwarf.h:35
#define DW_AT_bit_size
Definition: rz_bin_dwarf.h:139
#define DW_TAG_subroutine_type
Definition: rz_bin_dwarf.h:69
#define DW_FORM_block
Definition: rz_bin_dwarf.h:286
#define DW_TAG_const_type
Definition: rz_bin_dwarf.h:86
#define DW_AT_base_types
Definition: rz_bin_dwarf.h:167
#define DW_AT_use_location
Definition: rz_bin_dwarf.h:188
#define DW_FORM_strx1
Definition: rz_bin_dwarf.h:314
#define DW_AT_GNU_call_site_value
Definition: rz_bin_dwarf.h:261
#define DW_LANG_C_plus_plus_14
Definition: rz_bin_dwarf.h:554
#define DW_AT_declaration
Definition: rz_bin_dwarf.h:174
#define DW_TAG_compile_unit
Definition: rz_bin_dwarf.h:66
#define DW_AT_entry_pc
Definition: rz_bin_dwarf.h:196
#define DW_LANG_C99
Definition: rz_bin_dwarf.h:540
#define DW_AT_start_scope
Definition: rz_bin_dwarf.h:160
#define DW_AT_GNU_macros
Definition: rz_bin_dwarf.h:269
#define DW_AT_macros
Definition: rz_bin_dwarf.h:236
#define DW_FORM_ref_addr
Definition: rz_bin_dwarf.h:293
#define DW_AT_string_length_byte_size
Definition: rz_bin_dwarf.h:227
#define DW_AT_sibling
Definition: rz_bin_dwarf.h:133
#define DW_TAG_file_type
Definition: rz_bin_dwarf.h:89
#define DW_LANG_Fortran08
Definition: rz_bin_dwarf.h:556
#define DW_FORM_strx2
Definition: rz_bin_dwarf.h:315
#define DW_AT_byte_size
Definition: rz_bin_dwarf.h:137
#define DW_AT_associated
Definition: rz_bin_dwarf.h:193
#define DW_TAG_unspecified_parameters
Definition: rz_bin_dwarf.h:72
#define DW_FORM_string
Definition: rz_bin_dwarf.h:285
#define DW_AT_call_column
Definition: rz_bin_dwarf.h:201
#define DW_LANG_ObjC_plus_plus
Definition: rz_bin_dwarf.h:545
#define DW_TAG_common_inclusion
Definition: rz_bin_dwarf.h:75
#define DW_LNS_set_epilogue_begin
Definition: rz_bin_dwarf.h:29
@ RZ_BIN_DWARF_LINE_OP_TYPE_SPEC
Definition: rz_bin_dwarf.h:859
@ RZ_BIN_DWARF_LINE_OP_TYPE_EXT
Definition: rz_bin_dwarf.h:861
@ RZ_BIN_DWARF_LINE_OP_TYPE_STD
Definition: rz_bin_dwarf.h:860
#define DW_LANG_Pascal83
Definition: rz_bin_dwarf.h:537
#define DW_FORM_block4
Definition: rz_bin_dwarf.h:281
char ** RzBinDwarfLineFileCache
Opaque cache for fully resolved filenames during Dwarf Line Info Generation This cache stores full fi...
Definition: rz_bin_dwarf.h:965
#define DW_FORM_addrx2
Definition: rz_bin_dwarf.h:319
#define DW_AT_external
Definition: rz_bin_dwarf.h:177
#define DW_TAG_with_stmt
Definition: rz_bin_dwarf.h:82
#define DW_AT_call_value
Definition: rz_bin_dwarf.h:241
#define DW_UT_partial
Definition: rz_bin_dwarf.h:620
#define DW_LNS_fixed_advance_pc
Definition: rz_bin_dwarf.h:27
#define DW_TAG_dwarf_procedure
Definition: rz_bin_dwarf.h:109
#define DW_FORM_addrx1
Definition: rz_bin_dwarf.h:318
#define DW_AT_rvalue_reference
Definition: rz_bin_dwarf.h:235
#define DW_FORM_data2
Definition: rz_bin_dwarf.h:282
#define DW_AT_lo_user
Definition: rz_bin_dwarf.h:258
#define DW_TAG_base_type
Definition: rz_bin_dwarf.h:84
#define ABBREV_DECL_CAP
Definition: rz_bin_dwarf.h:784
#define DW_TAG_LAST
Definition: rz_bin_dwarf.h:125
#define DW_TAG_member
Definition: rz_bin_dwarf.h:63
#define DW_TAG_restrict_type
Definition: rz_bin_dwarf.h:110
#define DW_AT_elemental
Definition: rz_bin_dwarf.h:216
#define DW_FORM_flag_present
Definition: rz_bin_dwarf.h:302
#define DW_AT_stmt_list
Definition: rz_bin_dwarf.h:140
#define DW_LNE_define_file
Definition: rz_bin_dwarf.h:34
#define DW_FORM_flag
Definition: rz_bin_dwarf.h:289
#define DW_LANG_Fortran77
Definition: rz_bin_dwarf.h:535
#define DW_AT_call_all_calls
Definition: rz_bin_dwarf.h:237
#define DW_AT_call_return_pc
Definition: rz_bin_dwarf.h:240
#define DW_AT_dwo_name
Definition: rz_bin_dwarf.h:233
#define DW_LNS_set_basic_block
Definition: rz_bin_dwarf.h:25
#define DW_LANG_Ada95
Definition: rz_bin_dwarf.h:541
#define DW_AT_frame_base
Definition: rz_bin_dwarf.h:178
#define DW_TAG_entry_point
Definition: rz_bin_dwarf.h:57
#define DW_FORM_data4
Definition: rz_bin_dwarf.h:283
#define DW_AT_address_class
Definition: rz_bin_dwarf.h:165
#define DW_AT_ranges
Definition: rz_bin_dwarf.h:199
#define DW_FORM_data1
Definition: rz_bin_dwarf.h:288
#define DW_TAG_string_type
Definition: rz_bin_dwarf.h:67
#define DW_AT_static_link
Definition: rz_bin_dwarf.h:186
#define DW_FORM_strp_sup
Definition: rz_bin_dwarf.h:306
#define DW_LANG_D
Definition: rz_bin_dwarf.h:547
#define DW_AT_const_value
Definition: rz_bin_dwarf.h:151
#define DW_AT_call_pc
Definition: rz_bin_dwarf.h:244
#define DW_UT_lo_user
Definition: rz_bin_dwarf.h:624
#define DW_FORM_data8
Definition: rz_bin_dwarf.h:284
#define DW_TAG_enumeration_type
Definition: rz_bin_dwarf.h:58
#define DW_FORM_ref2
Definition: rz_bin_dwarf.h:295
#define DW_TAG_imported_declaration
Definition: rz_bin_dwarf.h:60
#define DW_TAG_imported_module
Definition: rz_bin_dwarf.h:113
#define DWARF_TRUE
Definition: rz_bin_dwarf.h:805
#define DW_TAG_rvalue_reference_type
Definition: rz_bin_dwarf.h:122
#define DW_TAG_enumerator
Definition: rz_bin_dwarf.h:88
#define DW_AT_object_pointer
Definition: rz_bin_dwarf.h:214
#define DW_AT_common_reference
Definition: rz_bin_dwarf.h:149
#define DW_FORM_ref8
Definition: rz_bin_dwarf.h:297
#define DW_AT_deleted
Definition: rz_bin_dwarf.h:253
#define DW_FORM_addrx
Definition: rz_bin_dwarf.h:304
#define DW_AT_str_offsets_base
Definition: rz_bin_dwarf.h:229
#define DW_AT_string_length
Definition: rz_bin_dwarf.h:148
#define DW_AT_GNU_ranges_base
Definition: rz_bin_dwarf.h:273
#define DW_AT_stride_size
Definition: rz_bin_dwarf.h:161
#define DW_TAG_reference_type
Definition: rz_bin_dwarf.h:65
#define DW_LANG_Cobol74
Definition: rz_bin_dwarf.h:533
#define DW_AT_prototyped
Definition: rz_bin_dwarf.h:158
#define DW_AT_lower_bound
Definition: rz_bin_dwarf.h:156
#define DW_TAG_template_value_param
Definition: rz_bin_dwarf.h:103
#define DW_TAG_variant
Definition: rz_bin_dwarf.h:73
#define DW_FORM_rnglistx
Definition: rz_bin_dwarf.h:312
#define DW_TAG_union_type
Definition: rz_bin_dwarf.h:71
#define DW_AT_call_target
Definition: rz_bin_dwarf.h:246
#define DW_LANG_Fortran95
Definition: rz_bin_dwarf.h:542
#define DW_LANG_Ada83
Definition: rz_bin_dwarf.h:531
#define DW_AT_variable_parameter
Definition: rz_bin_dwarf.h:189
#define DW_FORM_strp
Definition: rz_bin_dwarf.h:291
#define DW_TAG_namespace
Definition: rz_bin_dwarf.h:112
#define DW_UT_split_compile
Definition: rz_bin_dwarf.h:622
#define DW_TAG_condition
Definition: rz_bin_dwarf.h:119
#define DW_AT_linkage_name
Definition: rz_bin_dwarf.h:224
#define DW_AT_namelist_item
Definition: rz_bin_dwarf.h:182
#define DW_FORM_ref1
Definition: rz_bin_dwarf.h:294
#define DW_AT_call_target_clobbered
Definition: rz_bin_dwarf.h:247
#define DW_FORM_loclistx
Definition: rz_bin_dwarf.h:311
#define DW_AT_decl_line
Definition: rz_bin_dwarf.h:173
#define DW_AT_low_pc
Definition: rz_bin_dwarf.h:141
#define DW_AT_main_subprogram
Definition: rz_bin_dwarf.h:220
#define DW_LANG_C11
Definition: rz_bin_dwarf.h:550
#define DW_LNS_set_prologue_end
Definition: rz_bin_dwarf.h:28
#define DW_AT_type
Definition: rz_bin_dwarf.h:187
#define DW_AT_GNU_dwo_name
Definition: rz_bin_dwarf.h:271
#define DW_FORM_ref4
Definition: rz_bin_dwarf.h:296
#define DW_TAG_type_unit
Definition: rz_bin_dwarf.h:121
#define DW_LNE_end_sequence
Definition: rz_bin_dwarf.h:32
#define DW_FORM_sec_offset
Definition: rz_bin_dwarf.h:300
#define DW_AT_is_optional
Definition: rz_bin_dwarf.h:155
#define DW_AT_GNU_pubnames
Definition: rz_bin_dwarf.h:275
#define DW_AT_import
Definition: rz_bin_dwarf.h:147
#define DW_AT_GNU_dwo_id
Definition: rz_bin_dwarf.h:272
#define DW_AT_GNU_tail_call
Definition: rz_bin_dwarf.h:265
#define DEBUG_INFO_CAPACITY
Definition: rz_bin_dwarf.h:768
#define DW_LANG_Fortran90
Definition: rz_bin_dwarf.h:536
#define DW_UT_hi_user
Definition: rz_bin_dwarf.h:625
#define DW_AT_GNU_call_site_target
Definition: rz_bin_dwarf.h:263
#define DW_LNS_const_add_pc
Definition: rz_bin_dwarf.h:26
#define DW_TAG_packed_type
Definition: rz_bin_dwarf.h:96
#define DW_TAG_namelist_item
Definition: rz_bin_dwarf.h:94
#define DW_AT_ordering
Definition: rz_bin_dwarf.h:136
#define DW_FORM_indirect
Definition: rz_bin_dwarf.h:299
#define DW_AT_discr
Definition: rz_bin_dwarf.h:144
#define DW_AT_GNU_all_tail_call_sites
Definition: rz_bin_dwarf.h:266
#define DW_LANG_UPC
Definition: rz_bin_dwarf.h:546
#define DW_TAG_lexical_block
Definition: rz_bin_dwarf.h:62
#define DW_UT_type
Definition: rz_bin_dwarf.h:619
#define DW_AT_explicit
Definition: rz_bin_dwarf.h:213
#define DW_AT_string_length_bit_size
Definition: rz_bin_dwarf.h:226
#define DW_AT_call_file
Definition: rz_bin_dwarf.h:202
#define DW_TAG_try_block
Definition: rz_bin_dwarf.h:105
#define DW_TAG_common_block
Definition: rz_bin_dwarf.h:74
#define DW_UT_skeleton
Definition: rz_bin_dwarf.h:621
#define DW_AT_return_addr
Definition: rz_bin_dwarf.h:159
#define DW_AT_identifier_case
Definition: rz_bin_dwarf.h:180
#define DW_AT_defaulted
Definition: rz_bin_dwarf.h:254
#define DWARF_FALSE
Definition: rz_bin_dwarf.h:804
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
static ut64 rz_num_align_delta(ut64 v, ut64 alignment)
Padding to align v to the next alignment-boundary.
Definition: rz_num.h:116
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API size_t rz_str_nlen(const char *s, size_t n)
Definition: str.c:1949
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_OUT
Definition: rz_types.h:51
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define st8
Definition: rz_types_base.h:16
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT64_MAX
Definition: rz_types_base.h:86
#define UT16_MAX
RZ_API const ut8 * rz_uleb128(const ut8 *data, int datalen, RZ_NULLABLE ut64 *v, const char **error)
Definition: uleb128.c:9
RZ_API const ut8 * rz_leb128(const ut8 *data, int datalen, st64 *v)
Definition: uleb128.c:117
RZ_API void * rz_vector_flush(RzVector *vec)
Turn the vector into a fixed-size array. This will clear the vector and return an array of its origin...
Definition: vector.c:230
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
RZ_API void rz_pvector_fini(RzPVector *vec)
Definition: vector.c:331
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
static void ** rz_pvector_flush(RzPVector *vec)
Definition: rz_vector.h:320
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
#define EINVAL
Definition: sftypes.h:132
#define ENOMEM
Definition: sftypes.h:122
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
RzBinDwarfAttrDef * defs
Definition: rz_bin_dwarf.h:793
RzBinDwarfDie * dies
Definition: rz_bin_dwarf.h:764
RzBinDwarfCompUnitHdr hdr
Definition: rz_bin_dwarf.h:760
RzBinDwarfAbbrevDecl * decls
Definition: rz_bin_dwarf.h:801
RzBinDwarfAttrValue * attr_values
Definition: rz_bin_dwarf.h:756
ut8 * std_opcode_lengths
The number of LEB128 operands for each of the standard opcodes From standard_opcode_lengths in DWARF ...
Definition: rz_bin_dwarf.h:850
RzBinDwarfLineFileEntry * file_names
Definition: rz_bin_dwarf.h:854
Line info of all compilation units from the entire debug_line section.
Definition: rz_bin_dwarf.h:901
struct rz_bin_source_line_info_t * lines
Definition: rz_bin_dwarf.h:903
DWARF 3 Standard Section 6.2 Line Number Information This contains the entire raw line info for one c...
Definition: rz_bin_dwarf.h:891
RzBinDwarfLineHeader header
Definition: rz_bin_dwarf.h:892
RzBinDwarfLineOp * ops
Definition: rz_bin_dwarf.h:895
RzBinDwarfAttrKind kind
Definition: rz_bin_dwarf.h:704
struct dwarf_attr_kind::@251::@253 string
Definition: zipcmp.c:77
char * name
Definition: zipcmp.c:78
Definition: gzappend.c:170
char * name
Definition: gzappend.c:176
Definition: z80asm.h:102
DWARF 3 Standard Section 6.1.2 Lookup by Address.
Definition: rz_bin_dwarf.h:931
RzBinDwarfARange * aranges
Definition: rz_bin_dwarf.h:939
Definition: rz_bin_dwarf.h:822
char * name
Definition: rz_bin_dwarf.h:824
Definition: rz_bin_dwarf.h:912
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
RzBuffer * buf
Definition: rz_bin.h:303
int big_endian
Definition: rz_bin.h:235
RzBinInfo * info
Definition: rz_bin.h:287
RzList * sections
Definition: rz_bin.h:267
uint32_t size
ut64 maxlen
Definition: core.c:76
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static unsigned char * obuf
Definition: z80asm.c:36
int inf(FILE *source, FILE *dest)
Definition: zpipe.c:92
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36