1 /* radare - LGPL - Copyright 2012-2018 - pancake, Fedor Sakharov */
2
3 #define D0 if(1)
4 #define D1 if(1)
5
6 #include <errno.h>
7
8 #define DWARF_DUMP 0
9
10 #if DWARF_DUMP
11 #define DBGFD stdout
12 #else
13 #define DBGFD NULL
14 #endif
15
16 #include <r_bin.h>
17 #include <r_bin_dwarf.h>
18 #include <r_core.h>
19
20 #define STANDARD_OPERAND_COUNT_DWARF2 9
21 #define STANDARD_OPERAND_COUNT_DWARF3 12
22 #define R_BIN_DWARF_INFO 1
23
24 // endianness setting global
25 static bool big_end = false;
26
27 /* This macro seems bad regarding to endianess XXX, use only for single byte */
28 #define READ(buf, type) \
29 (((buf) + sizeof (type) < buf_end) ? *((type *)(buf)) : 0); \
30 (buf) += sizeof (type)
31 #define READ8(buf) \
32 (((buf) + sizeof (ut8) < buf_end) ? ((ut8 *)buf)[0] : 0); \
33 (buf) += sizeof (ut8)
34 #define READ16(buf) \
35 (((buf) + sizeof (ut16) < buf_end) ? r_read_ble16 (buf, big_end) : 0); \
36 (buf) += sizeof (ut16)
37 #define READ32(buf) \
38 (((buf) + sizeof (ut32) < buf_end) ? r_read_ble32 (buf, big_end) : 0); \
39 (buf) += sizeof (ut32)
40 #define READ64(buf) \
41 (((buf) + sizeof (ut64) < buf_end) ? r_read_ble64 (buf, big_end) : 0); \
42 (buf) += sizeof (ut64)
43
44 static const char *dwarf_tag_name_encodings[] = {
45 [DW_TAG_null_entry] = "DW_TAG_null_entry",
46 [DW_TAG_array_type] = "DW_TAG_array_type",
47 [DW_TAG_class_type] = "DW_TAG_class_type",
48 [DW_TAG_entry_point] = "DW_TAG_entry_point",
49 [DW_TAG_enumeration_type] = "DW_TAG_enumeration_type",
50 [DW_TAG_formal_parameter] = "DW_TAG_formal_parameter",
51 [DW_TAG_imported_declaration] = "DW_TAG_imported_declaration",
52 [DW_TAG_label] = "DW_TAG_label",
53 [DW_TAG_lexical_block] = "DW_TAG_lexical_block",
54 [DW_TAG_member] = "DW_TAG_member",
55 [DW_TAG_pointer_type] = "DW_TAG_pointer_type",
56 [DW_TAG_reference_type] = "DW_TAG_reference_type",
57 [DW_TAG_compile_unit] = "DW_TAG_compile_unit",
58 [DW_TAG_string_type] = "DW_TAG_string_type",
59 [DW_TAG_structure_type] = "DW_TAG_structure_type",
60 [DW_TAG_subroutine_type] = "DW_TAG_subroutine_type",
61 [DW_TAG_typedef] = "DW_TAG_typedef",
62 [DW_TAG_union_type] = "DW_TAG_union_type",
63 [DW_TAG_unspecified_parameters] = "DW_TAG_unspecified_parameters",
64 [DW_TAG_variant] = "DW_TAG_variant",
65 [DW_TAG_common_block] = "DW_TAG_common_block",
66 [DW_TAG_common_inclusion] = "DW_TAG_common_inclusion",
67 [DW_TAG_inheritance] = "DW_TAG_inheritance",
68 [DW_TAG_inlined_subroutine] = "DW_TAG_inlined_subroutine",
69 [DW_TAG_module] = "DW_TAG_module",
70 [DW_TAG_ptr_to_member_type] = "DW_TAG_ptr_to_member_type",
71 [DW_TAG_set_type] = "DW_TAG_set_type",
72 [DW_TAG_subrange_type] = "DW_TAG_subrange_type",
73 [DW_TAG_with_stmt] = "DW_TAG_with_stmt",
74 [DW_TAG_access_declaration] = "DW_TAG_access_declaration",
75 [DW_TAG_base_type] = "DW_TAG_base_type",
76 [DW_TAG_catch_block] = "DW_TAG_catch_block",
77 [DW_TAG_const_type] = "DW_TAG_const_type",
78 [DW_TAG_constant] = "DW_TAG_constant",
79 [DW_TAG_enumerator] = "DW_TAG_enumerator",
80 [DW_TAG_file_type] = "DW_TAG_file_type",
81 [DW_TAG_friend] = "DW_TAG_friend",
82 [DW_TAG_namelist] = "DW_TAG_namelist",
83 [DW_TAG_namelist_item] = "DW_TAG_namelist_item",
84 [DW_TAG_packed_type] = "DW_TAG_packed_type",
85 [DW_TAG_subprogram] = "DW_TAG_subprogram",
86 [DW_TAG_template_type_param] = "DW_TAG_template_type_param",
87 [DW_TAG_template_value_param] = "DW_TAG_template_value_param",
88 [DW_TAG_thrown_type] = "DW_TAG_thrown_type",
89 [DW_TAG_try_block] = "DW_TAG_try_block",
90 [DW_TAG_variant_part] = "DW_TAG_variant_part",
91 [DW_TAG_variable] = "DW_TAG_variable",
92 [DW_TAG_volatile_type] = "DW_TAG_volatile_type",
93 [DW_TAG_dwarf_procedure] = "DW_TAG_dwarf_procedure",
94 [DW_TAG_restrict_type] = "DW_TAG_restrict_type",
95 [DW_TAG_interface_type] = "DW_TAG_interface_type",
96 [DW_TAG_namespace] = "DW_TAG_namespace",
97 [DW_TAG_imported_module] = "DW_TAG_imported_module",
98 [DW_TAG_unspecified_type] = "DW_TAG_unspecified_type",
99 [DW_TAG_partial_unit] = "DW_TAG_partial_unit",
100 [DW_TAG_imported_unit] = "DW_TAG_imported_unit",
101 [DW_TAG_mutable_type] = "DW_TAG_mutable_type",
102 [DW_TAG_condition] = "DW_TAG_condition",
103 [DW_TAG_shared_type] = "DW_TAG_shared_type",
104 [DW_TAG_type_unit] = "DW_TAG_type_unit",
105 [DW_TAG_rvalue_reference_type] = "DW_TAG_rvalue_reference_type",
106 [DW_TAG_template_alias] = "DW_TAG_template_alias",
107 [DW_TAG_LAST] = "DW_TAG_LAST",
108 };
109
110 static const char *dwarf_attr_encodings[] = {
111 [DW_AT_sibling] = "DW_AT_siblings",
112 [DW_AT_location] = "DW_AT_location",
113 [DW_AT_name] = "DW_AT_name",
114 [DW_AT_ordering] = "DW_AT_ordering",
115 [DW_AT_byte_size] = "DW_AT_byte_size",
116 [DW_AT_bit_size] = "DW_AT_bit_size",
117 [DW_AT_stmt_list] = "DW_AT_stmt_list",
118 [DW_AT_low_pc] = "DW_AT_low_pc",
119 [DW_AT_high_pc] = "DW_AT_high_pc",
120 [DW_AT_language] = "DW_AT_language",
121 [DW_AT_discr] = "DW_AT_discr",
122 [DW_AT_discr_value] = "DW_AT_discr_value",
123 [DW_AT_visibility] = "DW_AT_visibility",
124 [DW_AT_import] = "DW_AT_import",
125 [DW_AT_string_length] = "DW_AT_string_length",
126 [DW_AT_common_reference] = "DW_AT_common_reference",
127 [DW_AT_comp_dir] = "DW_AT_comp_dir",
128 [DW_AT_const_value] = "DW_AT_const_value",
129 [DW_AT_containing_type] = "DW_AT_containing_type",
130 [DW_AT_default_value] = "DW_AT_default_value",
131 [DW_AT_inline] = "DW_AT_inline",
132 [DW_AT_is_optional] = "DW_AT_is_optional",
133 [DW_AT_lower_bound] = "DW_AT_lower_bound",
134 [DW_AT_producer] = "DW_AT_producer",
135 [DW_AT_prototyped] = "DW_AT_prototyped",
136 [DW_AT_return_addr] = "DW_AT_return_addr",
137 [DW_AT_start_scope] = "DW_AT_start_scope",
138 [DW_AT_stride_size] = "DW_AT_stride_size",
139 [DW_AT_upper_bound] = "DW_AT_upper_bound",
140 [DW_AT_abstract_origin] = "DW_AT_abstract_origin",
141 [DW_AT_accessibility] = "DW_AT_accessibility",
142 [DW_AT_address_class] = "DW_AT_address_class",
143 [DW_AT_artificial] = "DW_AT_artificial",
144 [DW_AT_base_types] = "DW_AT_base_types",
145 [DW_AT_calling_convention] = "DW_AT_calling_convention",
146 [DW_AT_count] = "DW_AT_count",
147 [DW_AT_data_member_location] = "DW_AT_data_member_location",
148 [DW_AT_decl_column] = "DW_AT_decl_column",
149 [DW_AT_decl_file] = "DW_AT_decl_file",
150 [DW_AT_decl_line] = "DW_AT_decl_line",
151 [DW_AT_declaration] = "DW_AT_declaration",
152 [DW_AT_discr_list] = "DW_AT_discr_list",
153 [DW_AT_encoding] = "DW_AT_encoding",
154 [DW_AT_external] = "DW_AT_external",
155 [DW_AT_frame_base] = "DW_AT_frame_base",
156 [DW_AT_friend] = "DW_AT_friend",
157 [DW_AT_identifier_case] = "DW_AT_identifier_case",
158 [DW_AT_macro_info] = "DW_AT_macro_info",
159 [DW_AT_namelist_item] = "DW_AT_namelist_item",
160 [DW_AT_priority] = "DW_AT_priority",
161 [DW_AT_segment] = "DW_AT_segment",
162 [DW_AT_specification] = "DW_AT_specification",
163 [DW_AT_static_link] = "DW_AT_static_link",
164 [DW_AT_type] = "DW_AT_type",
165 [DW_AT_use_location] = "DW_AT_use_location",
166 [DW_AT_variable_parameter] = "DW_AT_variable_parameter",
167 [DW_AT_virtuality] = "DW_AT_virtuality",
168 [DW_AT_vtable_elem_location] = "DW_AT_vtable_elem_location",
169 [DW_AT_allocated] = "DW_AT_allocated",
170 [DW_AT_associated] = "DW_AT_associated",
171 [DW_AT_data_location] = "DW_AT_data_location",
172 [DW_AT_byte_stride] = "DW_AT_byte_stride",
173 [DW_AT_entry_pc] = "DW_AT_entry_pc",
174 [DW_AT_use_UTF8] = "DW_AT_use_UTF8",
175 [DW_AT_extension] = "DW_AT_extension",
176 [DW_AT_ranges] = "DW_AT_ranges",
177 [DW_AT_trampoline] = "DW_AT_trampoline",
178 [DW_AT_call_column] = "DW_AT_call_column",
179 [DW_AT_call_file] = "DW_AT_call_file",
180 [DW_AT_call_line] = "DW_AT_call_line",
181 [DW_AT_description] = "DW_AT_description",
182 [DW_AT_binary_scale] = "DW_AT_binary_scale",
183 [DW_AT_decimal_scale] = "DW_AT_decimal_scale",
184 [DW_AT_small] = "DW_AT_small",
185 [DW_AT_decimal_sign] = "DW_AT_decimal_sign",
186 [DW_AT_digit_count] = "DW_AT_digit_count",
187 [DW_AT_picture_string] = "DW_AT_picture_string",
188 [DW_AT_mutable] = "DW_AT_mutable",
189 [DW_AT_threads_scaled] = "DW_AT_threads_scaled",
190 [DW_AT_explicit] = "DW_AT_explicit",
191 [DW_AT_object_pointer] = "DW_AT_object_pointer",
192 [DW_AT_endianity] = "DW_AT_endianity",
193 [DW_AT_elemental] = "DW_AT_elemental",
194 [DW_AT_pure] = "DW_AT_pure",
195 [DW_AT_recursive] = "DW_AT_recursive",
196 [DW_AT_signature] = "DW_AT_signature",
197 [DW_AT_main_subprogram] = "DW_AT_main_subprogram",
198 [DW_AT_data_bit_offset] = "DW_AT_data_big_offset",
199 [DW_AT_const_expr] = "DW_AT_const_expr",
200 [DW_AT_enum_class] = "DW_AT_enum_class",
201 [DW_AT_linkage_name] = "DW_AT_linkage_name",
202 [DW_AT_string_length_bit_size] = "DW_AT_string_length_bit_size",
203 [DW_AT_string_length_byte_size] = "DW_AT_string_length_byte_size",
204 [DW_AT_rank] = "DW_AT_rank",
205 [DW_AT_str_offsets_base] = "DW_AT_str_offsets_base",
206 [DW_AT_addr_base] = "DW_AT_addr_base",
207 [DW_AT_rnglists_base] = "DW_AT_rnglists_base",
208 [DW_AT_dwo_name] = "DW_AT_dwo_name",
209 [DW_AT_reference] = "DW_AT_reference",
210 [DW_AT_rvalue_reference] = "DW_AT_rvalue_reference",
211 [DW_AT_macros] = "DW_AT_macros",
212 [DW_AT_call_all_calls] = "DW_AT_call_all_calls",
213 [DW_AT_call_all_source_calls] = "DW_AT_call_all_source_calls",
214 [DW_AT_call_all_tail_calls] = "DW_AT_call_all_tail_calls",
215 [DW_AT_call_return_pc] = "DW_AT_call_return_pc",
216 [DW_AT_call_value] = "DW_AT_call_value",
217 [DW_AT_call_origin] = "DW_AT_call_origin",
218 [DW_AT_call_parameter] = "DW_AT_call_parameter",
219 [DW_AT_call_pc] = "DW_AT_call_pc",
220 [DW_AT_call_tail_call] = "DW_AT_call_tail_call",
221 [DW_AT_call_target] = "DW_AT_call_target",
222 [DW_AT_call_target_clobbered] = "DW_AT_call_target_clobbered",
223 [DW_AT_call_data_location] = "DW_AT_call_data_location",
224 [DW_AT_call_data_value] = "DW_AT_call_data_value",
225 [DW_AT_noreturn] = "DW_AT_noreturn",
226 [DW_AT_alignment] = "DW_AT_alignment",
227 [DW_AT_export_symbols] = "DW_AT_export_symbols",
228 [DW_AT_deleted] = "DW_AT_deleted",
229 [DW_AT_defaulted] = "DW_AT_defaulted",
230 [DW_AT_loclists_base] = "DW_AT_loclists_base",
231
232 [DW_AT_lo_user] = "DW_AT_lo_user",
233 [DW_AT_MIPS_linkage_name] = "DW_AT_MIPS_linkage_name",
234 [DW_AT_GNU_call_site_value] = "DW_AT_GNU_call_site_value",
235 [DW_AT_GNU_call_site_data_value] = "DW_AT_GNU_call_site_data_value",
236 [DW_AT_GNU_call_site_target] = "DW_AT_GNU_call_site_target",
237 [DW_AT_GNU_call_site_target_clobbered] = "DW_AT_GNU_call_site_target_clobbered",
238 [DW_AT_GNU_tail_call] = "DW_AT_GNU_tail_call",
239 [DW_AT_GNU_all_tail_call_sites] = "DW_AT_GNU_all_tail_call_sites",
240 [DW_AT_GNU_all_call_sites] = "DW_AT_GNU_all_call_sites",
241 [DW_AT_GNU_all_source_call_sites] = "DW_AT_GNU_all_source_call_sites",
242 [DW_AT_GNU_macros] = "DW_AT_GNU_macros",
243 [DW_AT_GNU_deleted] = "DW_AT_GNU_deleted",
244 [DW_AT_GNU_dwo_name] = "DW_AT_GNU_dwo_name",
245 [DW_AT_GNU_dwo_id] = "DW_AT_GNU_dwo_id",
246 [DW_AT_GNU_ranges_base] = "DW_AT_GNU_ranges_base",
247 [DW_AT_GNU_addr_base] = "DW_AT_GNU_addr_base",
248 [DW_AT_GNU_pubnames] = "DW_AT_GNU_pubnames",
249 [DW_AT_GNU_pubtypes] = "DW_AT_GNU_pubtypes",
250 [DW_AT_hi_user] = "DW_AT_hi_user",
251 };
252
253 static const char *dwarf_attr_form_encodings[] = {
254 [DW_FORM_addr] = "DW_FORM_addr",
255 [DW_FORM_block2] = "DW_FORM_block2",
256 [DW_FORM_block4] = "DW_FORM_block4",
257 [DW_FORM_data2] = "DW_FORM_data2",
258 [DW_FORM_data4] = "DW_FORM_data4",
259 [DW_FORM_data8] = "DW_FORM_data8",
260 [DW_FORM_string] = "DW_FORM_string",
261 [DW_FORM_block] = "DW_FORM_block",
262 [DW_FORM_block1] = "DW_FORM_block1",
263 [DW_FORM_data1] = "DW_FORM_data1",
264 [DW_FORM_flag] = "DW_FORM_flag",
265 [DW_FORM_sdata] = "DW_FORM_sdata",
266 [DW_FORM_strp] = "DW_FORM_strp",
267 [DW_FORM_udata] = "DW_FORM_udata",
268 [DW_FORM_ref_addr] = "DW_FORM_ref_addr",
269 [DW_FORM_ref1] = "DW_FORM_ref1",
270 [DW_FORM_ref2] = "DW_FORM_ref2",
271 [DW_FORM_ref4] = "DW_FORM_ref4",
272 [DW_FORM_ref8] = "DW_FORM_ref8",
273 [DW_FORM_ref_udata] = "DW_FORM_ref_udata",
274 [DW_FORM_indirect] = "DW_FORM_indirect",
275 [DW_FORM_sec_offset] = "DW_FORM_sec_offset",
276 [DW_FORM_exprloc] = "DW_FORM_exprloc",
277 [DW_FORM_flag_present] = "DW_FORM_flag_present",
278 [DW_FORM_strx] = "DW_FORM_strx",
279 [DW_FORM_addrx] = "DW_FORM_addrx",
280 [DW_FORM_ref_sup4] = "DW_FORM_ref_sup4",
281 [DW_FORM_strp_sup] = "DW_FORM_strp_sup",
282 [DW_FORM_data16] = "DW_FORM_data16",
283 [DW_FORM_line_ptr] = "DW_FORM_line_ptr",
284 [DW_FORM_ref_sig8] = "DW_FORM_ref_sig8",
285 [DW_FORM_implicit_const] = "DW_FORM_implicit_const",
286 [DW_FORM_loclistx] = "DW_FORM_loclistx",
287 [DW_FORM_rnglistx] = "DW_FORM_rnglistx",
288 [DW_FORM_ref_sup8] = "DW_FORM_ref_sup8",
289 [DW_FORM_strx1] = "DW_FORM_strx1",
290 [DW_FORM_strx2] = "DW_FORM_strx2",
291 [DW_FORM_strx3] = "DW_FORM_strx3",
292 [DW_FORM_strx4] = "DW_FORM_strx4",
293 [DW_FORM_addrx1] = "DW_FORM_addrx1",
294 [DW_FORM_addrx2] = "DW_FORM_addrx2",
295 [DW_FORM_addrx3] = "DW_FORM_addrx3",
296 [DW_FORM_addrx4] = "DW_FORM_addrx4",
297 };
298
299 static const char *dwarf_langs[] = {
300 [DW_LANG_C89] = "C89",
301 [DW_LANG_C] = "C",
302 [DW_LANG_Ada83] = "Ada83",
303 [DW_LANG_C_plus_plus] = "C++",
304 [DW_LANG_Cobol74] = "Cobol74",
305 [DW_LANG_Cobol85] = "Cobol85",
306 [DW_LANG_Fortran77] = "Fortran77",
307 [DW_LANG_Fortran90] = "Fortran90",
308 [DW_LANG_Pascal83] = "Pascal83",
309 [DW_LANG_Modula2] = "Modula2",
310 [DW_LANG_Java] = "Java",
311 [DW_LANG_C99] = "C99",
312 [DW_LANG_Ada95] = "Ada95",
313 [DW_LANG_Fortran95] = "Fortran95",
314 [DW_LANG_PLI] = "PLI",
315 [DW_LANG_ObjC] = "ObjC",
316 [DW_LANG_ObjC_plus_plus] = "ObjC_plus_plus",
317 [DW_LANG_UPC] = "UPC",
318 [DW_LANG_D] = "D",
319 [DW_LANG_Python] = "Python",
320 [DW_LANG_Rust] = "Rust",
321 [DW_LANG_C11] = "C11",
322 [DW_LANG_Swift] = "Swift",
323 [DW_LANG_Julia] = "Julia",
324 [DW_LANG_Dylan] = "Dylan",
325 [DW_LANG_C_plus_plus_14] = "C++14",
326 [DW_LANG_Fortran03] = "Fortran03",
327 [DW_LANG_Fortran08] = "Fortran08"
328 };
329
330 static const char *dwarf_unit_types[] = {
331 [DW_UT_compile] = "DW_UT_compile",
332 [DW_UT_type] = "DW_UT_type",
333 [DW_UT_partial] = "DW_UT_partial",
334 [DW_UT_skeleton] = "DW_UT_skeleton",
335 [DW_UT_split_compile] = "DW_UT_split_compile",
336 [DW_UT_split_type] = "DW_UT_split_type",
337 [DW_UT_lo_user] = "DW_UT_lo_user",
338 [DW_UT_hi_user] = "DW_UT_hi_user",
339 };
340
abbrev_cmp(const void * a,const void * b)341 static int abbrev_cmp(const void *a, const void *b) {
342 const RBinDwarfAbbrevDecl *first = a;
343 const RBinDwarfAbbrevDecl *second = b;
344
345 if (first->offset > second->offset) {
346 return 1;
347 } else if (first->offset < second->offset) {
348 return -1;
349 } else {
350 return 0;
351 }
352 }
353
is_printable_attr(ut64 attr_code)354 static inline bool is_printable_attr(ut64 attr_code) {
355 return (attr_code >= DW_AT_sibling && attr_code <= DW_AT_loclists_base) ||
356 attr_code == DW_AT_MIPS_linkage_name ||
357 (attr_code >= DW_AT_GNU_call_site_value && attr_code <= DW_AT_GNU_deleted) ||
358 (attr_code >= DW_AT_GNU_dwo_name && attr_code <= DW_AT_GNU_pubtypes);
359 }
360
is_printable_form(ut64 form_code)361 static inline bool is_printable_form(ut64 form_code) {
362 return form_code >= DW_FORM_addr && form_code <= DW_FORM_addrx4;
363 }
364
is_printable_tag(ut64 attr_code)365 static inline bool is_printable_tag(ut64 attr_code) {
366 return attr_code <= DW_TAG_LAST;
367 }
368
is_printable_unit_type(ut64 unit_type)369 static inline bool is_printable_unit_type(ut64 unit_type) {
370 return unit_type > 0 && unit_type <= DW_UT_split_type;
371 }
372
373 /**
374 * @brief Reads 64/32 bit unsigned based on format
375 *
376 * @param is_64bit Format of the comp unit
377 * @param buf Pointer to the buffer to read from, to update after read
378 * @param buf_end To check the boundary /for READ macro/
379 * @return ut64 Read value
380 */
dwarf_read_offset(bool is_64bit,const ut8 ** buf,const ut8 * buf_end)381 static inline ut64 dwarf_read_offset(bool is_64bit, const ut8 **buf, const ut8 *buf_end) {
382 ut64 result;
383 if (is_64bit) {
384 result = READ64 (*buf);
385 } else {
386 result = READ32 (*buf);
387 }
388 return result;
389 }
390
dwarf_read_address(size_t size,const ut8 ** buf,const ut8 * buf_end)391 static inline ut64 dwarf_read_address(size_t size, const ut8 **buf, const ut8 *buf_end) {
392 ut64 result;
393 switch (size) {
394 case 2:
395 result = READ16 (*buf); break;
396 case 4:
397 result = READ32 (*buf); break;
398 case 8:
399 result = READ64 (*buf); break;
400 default:
401 result = 0;
402 *buf += size;
403 eprintf ("Weird dwarf address size: %zu.", size);
404 }
405 return result;
406 }
407
add_sdb_include_dir(Sdb * s,const char * incl,int idx)408 static int add_sdb_include_dir(Sdb *s, const char *incl, int idx) {
409 if (!s || !incl) {
410 return false;
411 }
412 return sdb_array_set (s, "includedirs", idx, incl, 0);
413 }
414
line_header_fini(RBinDwarfLineHeader * hdr)415 static void line_header_fini(RBinDwarfLineHeader *hdr) {
416 if (hdr) {
417 size_t i;
418
419 for (i = 0; i < hdr->file_names_count; i ++) {
420 free (hdr->file_names[i].name);
421 }
422
423 free (hdr->std_opcode_lengths);
424 free (hdr->file_names);
425 }
426 }
427
428 // Parses source file header of DWARF version <= 4
parse_line_header_source(RBinFile * bf,const ut8 * buf,const ut8 * buf_end,RBinDwarfLineHeader * hdr,Sdb * sdb,int mode,PrintfCallback print)429 static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const ut8 *buf_end,
430 RBinDwarfLineHeader *hdr, Sdb *sdb, int mode, PrintfCallback print) {
431 int i = 0;
432 size_t count;
433 const ut8 *tmp_buf = NULL;
434
435 if (mode == R_MODE_PRINT) {
436 print (" The Directory Table:\n");
437 }
438 while (buf + 1 < buf_end) {
439 size_t maxlen = R_MIN ((size_t) (buf_end - buf) - 1, 0xfff);
440 size_t len = r_str_nlen ((const char *)buf, maxlen);
441 char *str = r_str_ndup ((const char *)buf, len);
442 if (len < 1 || len >= 0xfff || !str) {
443 buf += 1;
444 free (str);
445 break;
446 }
447 if (mode == R_MODE_PRINT) {
448 print (" %d %s\n", i + 1, str);
449 }
450 add_sdb_include_dir (sdb, str, i);
451 free (str);
452 i++;
453 buf += len + 1;
454 }
455
456 tmp_buf = buf;
457 count = 0;
458 if (mode == R_MODE_PRINT) {
459 print ("\n");
460 print (" The File Name Table:\n");
461 print (" Entry Dir Time Size Name\n");
462 }
463 int entry_index = 1; // used for printing information
464
465 for (i = 0; i < 2; i++) {
466 while (buf + 1 < buf_end) {
467 const char *filename = (const char *)buf;
468 size_t maxlen = R_MIN ((size_t) (buf_end - buf - 1), 0xfff);
469 ut64 id_idx, mod_time, file_len;
470 size_t len = r_str_nlen (filename, maxlen);
471
472 if (!len) {
473 buf++;
474 break;
475 }
476 buf += len + 1;
477 if (buf >= buf_end) {
478 buf = NULL;
479 goto beach;
480 }
481 buf = r_uleb128 (buf, buf_end - buf, &id_idx, NULL);
482 if (buf >= buf_end) {
483 buf = NULL;
484 goto beach;
485 }
486 buf = r_uleb128 (buf, buf_end - buf, &mod_time, NULL);
487 if (buf >= buf_end) {
488 buf = NULL;
489 goto beach;
490 }
491 buf = r_uleb128 (buf, buf_end - buf, &file_len, NULL);
492 if (buf >= buf_end) {
493 buf = NULL;
494 goto beach;
495 }
496
497 if (i) {
498 char *include_dir = NULL, *comp_dir = NULL, *pinclude_dir = NULL;
499 if (id_idx > 0) {
500 include_dir = pinclude_dir = sdb_array_get (sdb, "includedirs", id_idx - 1, 0);
501 if (include_dir && include_dir[0] != '/') {
502 comp_dir = sdb_get (bf->sdb_addrinfo, "DW_AT_comp_dir", 0);
503 if (comp_dir) {
504 include_dir = r_str_newf("%s/%s/", comp_dir, include_dir);
505 }
506 }
507 } else {
508 include_dir = pinclude_dir = sdb_get (bf->sdb_addrinfo, "DW_AT_comp_dir", 0);
509 if (!include_dir) {
510 include_dir = "./";
511 }
512 }
513
514 if (hdr->file_names) {
515 hdr->file_names[count].name = r_str_newf("%s/%s", r_str_get (include_dir), filename);
516 hdr->file_names[count].id_idx = id_idx;
517 hdr->file_names[count].mod_time = mod_time;
518 hdr->file_names[count].file_len = file_len;
519 }
520 if (comp_dir) {
521 R_FREE (include_dir);
522 R_FREE (comp_dir);
523 }
524 R_FREE (pinclude_dir);
525 }
526 count++;
527 if (mode == R_MODE_PRINT && i) {
528 print (" %d %" PFMT64d " %" PFMT64d " %" PFMT64d " %s\n", entry_index++, id_idx, mod_time, file_len, filename);
529 }
530 }
531 if (i == 0) {
532 if (count > 0) {
533 hdr->file_names = calloc (sizeof (file_entry), count);
534 } else {
535 hdr->file_names = NULL;
536 }
537 hdr->file_names_count = count;
538 buf = tmp_buf;
539 count = 0;
540 }
541 }
542 if (mode == R_MODE_PRINT) {
543 print ("\n");
544 }
545
546 beach:
547 sdb_free (sdb);
548
549 return buf;
550 }
551 // TODO DWARF 5 line header parsing, very different from ver. 4
552 // Because this function needs ability to parse a lot of FORMS just like debug info
553 // I'll complete this function after completing debug_info parsing and merging
554 // for the meanwhile I am skipping the space.
parse_line_header_source_dwarf5(RBinFile * bf,const ut8 * buf,const ut8 * buf_end,RBinDwarfLineHeader * hdr,Sdb * sdb,int mode)555 static const ut8 *parse_line_header_source_dwarf5(RBinFile *bf, const ut8 *buf, const ut8 *buf_end,
556 RBinDwarfLineHeader *hdr, Sdb *sdb, int mode) {
557 // int i = 0;
558 // size_t count;
559 // const ut8 *tmp_buf = NULL;
560
561 // ut8 dir_entry_count = READ8 (buf);
562 // // uleb128 pairs
563 // ut8 dir_count = READ8 (buf);
564
565 // // dirs
566
567 // ut8 file_entry_count = READ8 (buf);
568 // // uleb128 pairs
569 // ut8 file_count = READ8 (buf);
570 // // file names
571
572 // beach:
573 // sdb_free (sdb);
574
575 return NULL;
576 }
577
parse_line_header(RBinFile * bf,const ut8 * buf,const ut8 * buf_end,RBinDwarfLineHeader * hdr,int mode,PrintfCallback print)578 static const ut8 *parse_line_header (
579 RBinFile *bf, const ut8 *buf, const ut8 *buf_end,
580 RBinDwarfLineHeader *hdr, int mode, PrintfCallback print) {
581
582 r_return_val_if_fail(hdr && bf && buf, NULL);
583
584 hdr->is_64bit = false;
585 hdr->unit_length = READ32 (buf);
586
587 if (hdr->unit_length == DWARF_INIT_LEN_64) {
588 hdr->unit_length = READ64 (buf);
589 hdr->is_64bit = true;
590 }
591
592 hdr->version = READ16 (buf);
593
594 if (hdr->version == 5) {
595 hdr->address_size = READ8 (buf);
596 hdr->segment_selector_size = READ8 (buf);
597 }
598
599 hdr->header_length = dwarf_read_offset(hdr->is_64bit, &buf, buf_end);
600
601 const ut8 *tmp_buf = buf; // So I can skip parsing DWARF 5 headers for now
602
603 if (buf_end - buf < 8) {
604 return NULL;
605 }
606 hdr->min_inst_len = READ8 (buf);
607 if (hdr->version >= 4) {
608 hdr->max_ops_per_inst = READ8 (buf);
609 }
610 hdr->default_is_stmt = READ8 (buf);
611 hdr->line_base = READ (buf, int8_t); // signed
612 hdr->line_range = READ8 (buf);
613 hdr->opcode_base = READ8 (buf);
614
615 hdr->file_names = NULL;
616
617 if (mode == R_MODE_PRINT) {
618 print (" Header information:\n");
619 print (" Length: %" PFMT64u "\n", hdr->unit_length);
620 print (" DWARF Version: %d\n", hdr->version);
621 print (" Header Length: %" PFMT64d "\n", hdr->header_length);
622 print (" Minimum Instruction Length: %d\n", hdr->min_inst_len);
623 print (" Maximum Operations per Instruction: %d\n", hdr->max_ops_per_inst);
624 print (" Initial value of 'is_stmt': %d\n", hdr->default_is_stmt);
625 print (" Line Base: %d\n", hdr->line_base);
626 print (" Line Range: %d\n", hdr->line_range);
627 print (" Opcode Base: %d\n\n", hdr->opcode_base);
628 }
629
630 if (hdr->opcode_base > 0) {
631 hdr->std_opcode_lengths = calloc (sizeof (ut8), hdr->opcode_base);
632
633 if (mode == R_MODE_PRINT) {
634 print (" Opcodes:\n");
635 }
636 size_t i;
637 for (i = 1; i < hdr->opcode_base; i++) {
638 if (buf + 2 > buf_end) {
639 break;
640 }
641 hdr->std_opcode_lengths[i] = READ (buf, ut8);
642 if (mode == R_MODE_PRINT) {
643 print (" Opcode %zu has %d arg\n", i, hdr->std_opcode_lengths[i]);
644 }
645 }
646 if (mode == R_MODE_PRINT) {
647 print ("\n");
648 }
649 } else {
650 hdr->std_opcode_lengths = NULL;
651 }
652 // TODO finish parsing of source files out of DWARF 5 header
653 // for now we skip
654 if (hdr->version == 5) {
655 tmp_buf += hdr->header_length;
656 return tmp_buf;
657 }
658
659 Sdb *sdb = sdb_new (NULL, NULL, 0);
660 if (!sdb) {
661 return NULL;
662 }
663
664 if (hdr->version <= 4) {
665 buf = parse_line_header_source (bf, buf, buf_end, hdr, sdb, mode, print);
666 } else { // because Version 5 source files are very different
667 buf = parse_line_header_source_dwarf5 (bf, buf, buf_end, hdr, sdb, mode);
668 }
669
670 return buf;
671 }
672
add_sdb_addrline(Sdb * s,ut64 addr,const char * file,ut64 line,int mode,PrintfCallback print)673 static inline void add_sdb_addrline(Sdb *s, ut64 addr, const char *file, ut64 line, int mode, PrintfCallback print) {
674 const char *p;
675 char *fileline;
676 char offset[64];
677 char *offset_ptr;
678
679 if (!s || !file) {
680 return;
681 }
682 p = r_str_rchr (file, NULL, '/');
683 if (p) {
684 p++;
685 } else {
686 p = file;
687 }
688 // includedirs and properly check full paths
689 switch (mode) {
690 case 1:
691 case 'r':
692 case '*':
693 print ("CL %s:%d 0x%08"PFMT64x"\n", p, (int)line, addr);
694 break;
695 }
696 #if 0
697 /* THIS IS TOO SLOW */
698 if (r_file_exists (file)) {
699 p = file;
700 }
701 #else
702 p = file;
703 #endif
704 fileline = r_str_newf ("%s|%"PFMT64d, p, line);
705 offset_ptr = sdb_itoa (addr, offset, 16);
706 sdb_add (s, offset_ptr, fileline, 0);
707 sdb_add (s, fileline, offset_ptr, 0);
708 free (fileline);
709 }
710
parse_ext_opcode(const RBin * bin,const ut8 * obuf,size_t len,const RBinDwarfLineHeader * hdr,RBinDwarfSMRegisters * regs,int mode)711 static const ut8 *parse_ext_opcode(const RBin *bin, const ut8 *obuf,
712 size_t len, const RBinDwarfLineHeader *hdr,
713 RBinDwarfSMRegisters *regs, int mode) {
714
715 r_return_val_if_fail (bin && bin->cur && obuf && hdr && regs, NULL);
716
717 PrintfCallback print = bin->cb_printf;
718 const ut8 *buf;
719 const ut8 *buf_end;
720 ut8 opcode;
721 ut64 addr;
722 buf = obuf;
723 st64 op_len;
724 RBinFile *binfile = bin->cur;
725 RBinObject *o = binfile->o;
726 ut32 addr_size = o && o->info && o->info->bits ? o->info->bits / 8 : 4;
727 const char *filename;
728
729 buf_end = buf + len;
730 buf = r_leb128 (buf, len, &op_len);
731 if (buf >= buf_end) {
732 return NULL;
733 }
734
735 opcode = *buf++;
736
737 if (mode == R_MODE_PRINT) {
738 print (" Extended opcode %d: ", opcode);
739 }
740
741 switch (opcode) {
742 case DW_LNE_end_sequence:
743 regs->end_sequence = DWARF_TRUE;
744
745 if (binfile && binfile->sdb_addrinfo && hdr->file_names) {
746 int fnidx = regs->file - 1;
747 if (fnidx >= 0 && fnidx < hdr->file_names_count) {
748 add_sdb_addrline(binfile->sdb_addrinfo, regs->address,
749 hdr->file_names[fnidx].name, regs->line, mode, print);
750 }
751 }
752
753 if (mode == R_MODE_PRINT) {
754 print ("End of Sequence\n");
755 }
756 break;
757 case DW_LNE_set_address:
758 if (addr_size == 8) {
759 addr = READ64 (buf);
760 } else {
761 addr = READ32 (buf);
762 }
763 regs->address = addr;
764 if (mode == R_MODE_PRINT) {
765 print ("set Address to 0x%"PFMT64x"\n", addr);
766 }
767 break;
768 case DW_LNE_define_file:
769 filename = (const char*)buf;
770
771 if (mode == R_MODE_PRINT) {
772 print ("define_file\n");
773 print ("filename %s\n", filename);
774 }
775
776 buf += (strlen (filename) + 1);
777 ut64 dir_idx;
778 ut64 ignore;
779 if (buf + 1 < buf_end) {
780 buf = r_uleb128 (buf, buf_end - buf, &dir_idx, NULL);
781 }
782 if (buf + 1 < buf_end) {
783 buf = r_uleb128 (buf, buf_end - buf, &ignore, NULL);
784 }
785 if (buf + 1 < buf_end) {
786 buf = r_uleb128 (buf, buf_end - buf, &ignore, NULL);
787 }
788 break;
789 case DW_LNE_set_discriminator:
790 buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
791 if (mode == R_MODE_PRINT) {
792 print ("set Discriminator to %"PFMT64d"\n", addr);
793 }
794 regs->discriminator = addr;
795 break;
796 default:
797 if (mode == R_MODE_PRINT) {
798 print ("Unexpected ext opcode %d\n", opcode);
799 }
800 buf = NULL;
801 break;
802 }
803
804 return buf;
805 }
806
parse_spec_opcode(const RBin * bin,const ut8 * obuf,size_t len,const RBinDwarfLineHeader * hdr,RBinDwarfSMRegisters * regs,ut8 opcode,int mode)807 static const ut8 *parse_spec_opcode(
808 const RBin *bin, const ut8 *obuf, size_t len,
809 const RBinDwarfLineHeader *hdr,
810 RBinDwarfSMRegisters *regs,
811 ut8 opcode, int mode) {
812
813 r_return_val_if_fail (bin && obuf && hdr && regs, NULL);
814
815 PrintfCallback print = bin->cb_printf;
816 RBinFile *binfile = bin->cur;
817 const ut8 *buf = obuf;
818 ut8 adj_opcode = 0;
819 ut64 advance_adr;
820
821 adj_opcode = opcode - hdr->opcode_base;
822 if (!hdr->line_range) {
823 // line line-range information. move away
824 return NULL;
825 }
826 advance_adr = (adj_opcode / hdr->line_range) * hdr->min_inst_len;
827 regs->address += advance_adr;
828 int line_increment = hdr->line_base + (adj_opcode % hdr->line_range);
829 regs->line += line_increment;
830 if (mode == R_MODE_PRINT) {
831 print (" Special opcode %d: ", adj_opcode);
832 print ("advance Address by %"PFMT64d" to 0x%"PFMT64x" and Line by %d to %"PFMT64d"\n",
833 advance_adr, regs->address, line_increment, regs->line);
834 }
835 if (binfile && binfile->sdb_addrinfo && hdr->file_names) {
836 int idx = regs->file -1;
837 if (idx >= 0 && idx < hdr->file_names_count) {
838 add_sdb_addrline (binfile->sdb_addrinfo, regs->address,
839 hdr->file_names[idx].name,
840 regs->line, mode, print);
841 }
842 }
843 regs->basic_block = DWARF_FALSE;
844 regs->prologue_end = DWARF_FALSE;
845 regs->epilogue_begin = DWARF_FALSE;
846 regs->discriminator = 0;
847
848 return buf;
849 }
850
parse_std_opcode(const RBin * bin,const ut8 * obuf,size_t len,const RBinDwarfLineHeader * hdr,RBinDwarfSMRegisters * regs,ut8 opcode,int mode)851 static const ut8 *parse_std_opcode(
852 const RBin *bin, const ut8 *obuf, size_t len,
853 const RBinDwarfLineHeader *hdr, RBinDwarfSMRegisters *regs,
854 ut8 opcode, int mode) {
855
856 r_return_val_if_fail (bin && bin->cur && obuf && hdr && regs, NULL);
857
858 PrintfCallback print = bin->cb_printf;
859 RBinFile *binfile = bin->cur;
860 const ut8* buf = obuf;
861 const ut8* buf_end = obuf + len;
862 ut64 addr = 0LL;
863 st64 sbuf;
864 ut8 adj_opcode;
865 ut64 op_advance;
866 ut16 operand;
867
868 if (mode == R_MODE_PRINT) {
869 print (" "); // formatting
870 }
871 switch (opcode) {
872 case DW_LNS_copy:
873 if (mode == R_MODE_PRINT) {
874 print ("Copy\n");
875 }
876 if (binfile && binfile->sdb_addrinfo && hdr->file_names) {
877 int fnidx = regs->file - 1;
878 if (fnidx >= 0 && fnidx < hdr->file_names_count) {
879 add_sdb_addrline (binfile->sdb_addrinfo,
880 regs->address,
881 hdr->file_names[fnidx].name,
882 regs->line, mode, print);
883 }
884 }
885 regs->basic_block = DWARF_FALSE;
886 break;
887 case DW_LNS_advance_pc:
888 buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
889 regs->address += addr * hdr->min_inst_len;
890 if (mode == R_MODE_PRINT) {
891 print ("Advance PC by %"PFMT64d" to 0x%"PFMT64x"\n",
892 addr * hdr->min_inst_len, regs->address);
893 }
894 break;
895 case DW_LNS_advance_line:
896 buf = r_leb128(buf, buf_end - buf, &sbuf);
897 regs->line += sbuf;
898 if (mode == R_MODE_PRINT) {
899 print ("Advance line by %"PFMT64d", to %"PFMT64d"\n", sbuf, regs->line);
900 }
901 break;
902 case DW_LNS_set_file:
903 buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
904 if (mode == R_MODE_PRINT) {
905 print ("Set file to %"PFMT64d"\n", addr);
906 }
907 regs->file = addr;
908 break;
909 case DW_LNS_set_column:
910 buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
911 if (mode == R_MODE_PRINT) {
912 print ("Set column to %"PFMT64d"\n", addr);
913 }
914 regs->column = addr;
915 break;
916 case DW_LNS_negate_stmt:
917 regs->is_stmt = regs->is_stmt ? DWARF_FALSE : DWARF_TRUE;
918 if (mode == R_MODE_PRINT) {
919 print ("Set is_stmt to %d\n", regs->is_stmt);
920 }
921 break;
922 case DW_LNS_set_basic_block:
923 if (mode == R_MODE_PRINT) {
924 print ("set_basic_block\n");
925 }
926 regs->basic_block = DWARF_TRUE;
927 break;
928 case DW_LNS_const_add_pc:
929 adj_opcode = 255 - hdr->opcode_base;
930 if (hdr->line_range > 0) { // to dodge division by zero
931 op_advance = (adj_opcode / hdr->line_range) * hdr->min_inst_len;
932 } else {
933 op_advance = 0;
934 }
935 regs->address += op_advance;
936 if (mode == R_MODE_PRINT) {
937 print ("Advance PC by constant %"PFMT64d" to 0x%"PFMT64x"\n",
938 op_advance, regs->address);
939 }
940 break;
941 case DW_LNS_fixed_advance_pc:
942 operand = READ16 (buf);
943 regs->address += operand;
944 if (mode == R_MODE_PRINT) {
945 print ("Fixed advance pc to %"PFMT64d"\n", regs->address);
946 }
947 break;
948 case DW_LNS_set_prologue_end:
949 regs->prologue_end = ~0;
950 if (mode == R_MODE_PRINT) {
951 print ("set_prologue_end\n");
952 }
953 break;
954 case DW_LNS_set_epilogue_begin:
955 regs->epilogue_begin = ~0;
956 if (mode == R_MODE_PRINT) {
957 print ("set_epilogue_begin\n");
958 }
959 break;
960 case DW_LNS_set_isa:
961 buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
962 regs->isa = addr;
963 if (mode == R_MODE_PRINT) {
964 print ("set_isa\n");
965 }
966 break;
967 default:
968 if (mode == R_MODE_PRINT) {
969 print ("Unexpected std opcode %d\n", opcode);
970 }
971 break;
972 }
973 return buf;
974 }
975
set_regs_default(const RBinDwarfLineHeader * hdr,RBinDwarfSMRegisters * regs)976 static void set_regs_default(const RBinDwarfLineHeader *hdr, RBinDwarfSMRegisters *regs) {
977 regs->address = 0;
978 regs->file = 1;
979 regs->line = 1;
980 regs->column = 0;
981 regs->is_stmt = hdr->default_is_stmt;
982 regs->basic_block = DWARF_FALSE;
983 regs->end_sequence = DWARF_FALSE;
984 regs->prologue_end = DWARF_FALSE;
985 regs->epilogue_begin = DWARF_FALSE;
986 regs->isa = 0;
987 }
988
989 // Passing bin should be unnecessary (after we stop printing inside bin_dwarf)
parse_opcodes(const RBin * bin,const ut8 * obuf,size_t len,const RBinDwarfLineHeader * hdr,RBinDwarfSMRegisters * regs,int mode)990 static size_t parse_opcodes(const RBin *bin, const ut8 *obuf,
991 size_t len, const RBinDwarfLineHeader *hdr,
992 RBinDwarfSMRegisters *regs, int mode) {
993 const ut8 *buf, *buf_end;
994 ut8 opcode, ext_opcode;
995
996 if (!bin || !obuf || len < 8) {
997 return 0;
998 }
999 buf = obuf;
1000 buf_end = obuf + len;
1001
1002 while (buf && buf + 1 < buf_end) {
1003 opcode = *buf++;
1004 len--;
1005 if (!opcode) {
1006 ext_opcode = *buf;
1007 buf = parse_ext_opcode (bin, buf, len, hdr, regs, mode);
1008 if (!buf || ext_opcode == DW_LNE_end_sequence) {
1009 set_regs_default (hdr, regs); // end_sequence should reset regs to default
1010 break;
1011 }
1012 } else if (opcode >= hdr->opcode_base) {
1013 buf = parse_spec_opcode (bin, buf, len, hdr, regs, opcode, mode);
1014 } else {
1015 buf = parse_std_opcode (bin, buf, len, hdr, regs, opcode, mode);
1016 }
1017 len = (size_t)(buf_end - buf);
1018 }
1019 if (mode == R_MODE_PRINT) {
1020 bin->cb_printf ("\n"); // formatting of the output
1021 }
1022 if (!buf) {
1023 return 0;
1024 }
1025 return (size_t) (buf - obuf); // number of bytes we've moved by
1026 }
1027
parse_line_raw(const RBin * a,const ut8 * obuf,ut64 len,int mode)1028 static int parse_line_raw(const RBin *a, const ut8 *obuf,
1029 ut64 len, int mode) {
1030
1031 RBinFile *binfile = a ? a->cur : NULL;
1032 r_return_val_if_fail(binfile && obuf, false);
1033 PrintfCallback print = a->cb_printf;
1034
1035 if (mode == R_MODE_PRINT) {
1036 print ("Raw dump of debug contents of section .debug_line:\n\n");
1037 }
1038 const ut8 *buf = obuf;
1039 const ut8 *buf_end = obuf + len;
1040 const ut8 *tmpbuf = NULL;
1041
1042 RBinDwarfLineHeader hdr = { 0 };
1043 ut64 buf_size;
1044
1045 // each iteration we read one header AKA comp. unit
1046 while (buf <= buf_end) {
1047 // How much did we read from the compilation unit
1048 size_t bytes_read = 0;
1049 // calculate how much we've read by parsing header
1050 // because header unit_length includes itself
1051 buf_size = buf_end - buf;
1052
1053 tmpbuf = buf;
1054 buf = parse_line_header (a->cur, buf, buf_end, &hdr, mode, print);
1055 if (!buf) {
1056 return false;
1057 }
1058
1059 if (mode == R_MODE_PRINT) {
1060 print (" Line Number Statements:\n");
1061 }
1062 bytes_read = buf - tmpbuf;
1063
1064 RBinDwarfSMRegisters regs;
1065 set_regs_default (&hdr, ®s);
1066
1067 // If there is more bytes in the buffer than size of the header
1068 // It means that there has to be another header/comp.unit
1069 if (buf_size > hdr.unit_length) {
1070 buf_size = hdr.unit_length + (hdr.is_64bit * 8 + 4); // we dif against bytes_read, but
1071 // unit_length doesn't account unit_length field
1072 }
1073 // this deals with a case that there is compilation unit with any line information
1074 if (buf_size == bytes_read) {
1075 if (mode == R_MODE_PRINT) {
1076 print (" Line table is present, but no lines present\n");
1077 }
1078 line_header_fini (&hdr);
1079 continue;
1080 }
1081 if (buf_size > (buf_end - buf) + bytes_read || buf > buf_end) {
1082 line_header_fini (&hdr);
1083 return false;
1084 }
1085 size_t tmp_read = 0;
1086 // we read the whole compilation unit (that might be composed of more sequences)
1087 do {
1088 // reads one whole sequence
1089 tmp_read = parse_opcodes (a, buf, buf_end - buf, &hdr, ®s, mode);
1090 bytes_read += tmp_read;
1091 buf += tmp_read; // Move in the buffer forward
1092 } while (bytes_read < buf_size && tmp_read != 0); // if nothing is read -> error, exit
1093
1094 line_header_fini (&hdr);
1095 if (!tmp_read) {
1096 return false;
1097 }
1098 }
1099 return true;
1100 }
1101
1102 #define READ_BUF(x,y) if (idx+sizeof(y)>=len) { return false;} \
1103 (x)=*(y*)buf; idx+=sizeof(y);buf+=sizeof(y)
1104
1105 #define READ_BUF64(x) if (idx+sizeof(ut64)>=len) { return false;} \
1106 (x)=r_read_ble64(buf, big_end); idx+=sizeof(ut64);buf+=sizeof(ut64)
1107 #define READ_BUF32(x) if (idx+sizeof(ut32)>=len) { return false;} \
1108 (x)=r_read_ble32(buf, big_end); idx+=sizeof(ut32);buf+=sizeof(ut32)
1109 #define READ_BUF16(x) if (idx+sizeof(ut16)>=len) { return false;} \
1110 (x)=r_read_ble16(buf, big_end); idx+=sizeof(ut16);buf+=sizeof(ut16)
1111
parse_aranges_raw(const ut8 * obuf,int len,int mode,PrintfCallback print)1112 static int parse_aranges_raw(const ut8 *obuf, int len, int mode, PrintfCallback print) {
1113 ut32 length, offset;
1114 ut16 version;
1115 ut32 debug_info_offset;
1116 ut8 address_size, segment_size;
1117 const ut8 *buf = obuf;
1118 int idx = 0;
1119
1120 if (!buf || len< 4) {
1121 return false;
1122 }
1123
1124 READ_BUF32 (length);
1125 if (mode == R_MODE_PRINT) {
1126 print ("parse_aranges\n");
1127 print ("length 0x%x\n", length);
1128 }
1129
1130 if (idx + 12 >= len) {
1131 return false;
1132 }
1133
1134 READ_BUF16 (version);
1135 if (mode == R_MODE_PRINT) {
1136 print("Version %d\n", version);
1137 }
1138
1139 READ_BUF32 (debug_info_offset);
1140 if (mode == R_MODE_PRINT) {
1141 print ("Debug info offset %d\n", debug_info_offset);
1142 }
1143
1144 READ_BUF (address_size, ut8);
1145 if (mode == R_MODE_PRINT) {
1146 print ("address size %d\n", (int)address_size);
1147 }
1148
1149 READ_BUF (segment_size, ut8);
1150 if (mode == R_MODE_PRINT) {
1151 print ("segment size %d\n", (int)segment_size);
1152 }
1153
1154 offset = segment_size + address_size * 2;
1155
1156 if (offset) {
1157 ut64 n = (((ut64) (size_t)buf / offset) + 1) * offset - ((ut64)(size_t)buf);
1158 if (idx+n>=len) {
1159 return false;
1160 }
1161 buf += n;
1162 idx += n;
1163 }
1164
1165 while ((buf - obuf) < len) {
1166 ut64 adr, length;
1167 if ((idx+8)>=len) {
1168 break;
1169 }
1170 READ_BUF64 (adr);
1171 READ_BUF64 (length);
1172 if (mode == R_MODE_PRINT) {
1173 print ("length 0x%" PFMT64x " address 0x%" PFMT64x "\n", length, adr);
1174 }
1175 }
1176
1177 return 0;
1178 }
1179
init_debug_info(RBinDwarfDebugInfo * inf)1180 static int init_debug_info(RBinDwarfDebugInfo *inf) {
1181 if (!inf) {
1182 return -1;
1183 }
1184 inf->comp_units = calloc (sizeof (RBinDwarfCompUnit), DEBUG_INFO_CAPACITY);
1185
1186 inf->lookup_table = ht_up_new0 ();
1187
1188 if (!inf->comp_units) {
1189 return -1;
1190 }
1191
1192 inf->capacity = DEBUG_INFO_CAPACITY;
1193 inf->count = 0;
1194 return true;
1195 }
1196
init_die(RBinDwarfDie * die,ut64 abbr_code,ut64 attr_count)1197 static int init_die(RBinDwarfDie *die, ut64 abbr_code, ut64 attr_count) {
1198 if (!die) {
1199 return -1;
1200 }
1201 die->attr_values = calloc (sizeof (RBinDwarfAttrValue), attr_count);
1202 if (!die->attr_values) {
1203 return -1;
1204 }
1205 die->abbrev_code = abbr_code;
1206 die->capacity = attr_count;
1207 die->count = 0;
1208 return 0;
1209 }
1210
init_comp_unit(RBinDwarfCompUnit * cu)1211 static int init_comp_unit(RBinDwarfCompUnit *cu) {
1212 if (!cu) {
1213 return -EINVAL;
1214 }
1215 cu->dies = calloc (sizeof (RBinDwarfDie), COMP_UNIT_CAPACITY);
1216 if (!cu->dies) {
1217 return -ENOMEM;
1218 }
1219 cu->capacity = COMP_UNIT_CAPACITY;
1220 cu->count = 0;
1221 return 0;
1222 }
1223
expand_cu(RBinDwarfCompUnit * cu)1224 static int expand_cu(RBinDwarfCompUnit *cu) {
1225 RBinDwarfDie *tmp;
1226
1227 if (!cu || cu->capacity == 0 || cu->capacity != cu->count) {
1228 return -EINVAL;
1229 }
1230
1231 tmp = (RBinDwarfDie *)realloc (cu->dies,
1232 cu->capacity * 2 * sizeof (RBinDwarfDie));
1233 if (!tmp) {
1234 return -ENOMEM;
1235 }
1236
1237 memset ((ut8 *)tmp + cu->capacity * sizeof (RBinDwarfDie),
1238 0, cu->capacity * sizeof (RBinDwarfDie));
1239 cu->dies = tmp;
1240 cu->capacity *= 2;
1241
1242 return 0;
1243 }
1244
init_abbrev_decl(RBinDwarfAbbrevDecl * ad)1245 static int init_abbrev_decl(RBinDwarfAbbrevDecl *ad) {
1246 if (!ad) {
1247 return -EINVAL;
1248 }
1249 ad->defs = calloc (sizeof (RBinDwarfAttrDef), ABBREV_DECL_CAP);
1250
1251 if (!ad->defs) {
1252 return -ENOMEM;
1253 }
1254
1255 ad->capacity = ABBREV_DECL_CAP;
1256 ad->count = 0;
1257
1258 return 0;
1259 }
1260
expand_abbrev_decl(RBinDwarfAbbrevDecl * ad)1261 static int expand_abbrev_decl(RBinDwarfAbbrevDecl *ad) {
1262 RBinDwarfAttrDef *tmp;
1263
1264 if (!ad || !ad->capacity || ad->capacity != ad->count) {
1265 return -EINVAL;
1266 }
1267
1268 tmp = (RBinDwarfAttrDef *)realloc (ad->defs,
1269 ad->capacity * 2 * sizeof (RBinDwarfAttrDef));
1270
1271 if (!tmp) {
1272 return -ENOMEM;
1273 }
1274
1275 // Set the area in the buffer past the length to 0
1276 memset ((ut8 *)tmp + ad->capacity * sizeof (RBinDwarfAttrDef),
1277 0, ad->capacity * sizeof (RBinDwarfAttrDef));
1278 ad->defs = tmp;
1279 ad->capacity *= 2;
1280
1281 return 0;
1282 }
1283
init_debug_abbrev(RBinDwarfDebugAbbrev * da)1284 static int init_debug_abbrev(RBinDwarfDebugAbbrev *da) {
1285 if (!da) {
1286 return -EINVAL;
1287 }
1288 da->decls = calloc (sizeof (RBinDwarfAbbrevDecl), DEBUG_ABBREV_CAP);
1289 if (!da->decls) {
1290 return -ENOMEM;
1291 }
1292 da->capacity = DEBUG_ABBREV_CAP;
1293 da->count = 0;
1294
1295 return 0;
1296 }
1297
expand_debug_abbrev(RBinDwarfDebugAbbrev * da)1298 static int expand_debug_abbrev(RBinDwarfDebugAbbrev *da) {
1299 RBinDwarfAbbrevDecl *tmp;
1300
1301 if (!da || da->capacity == 0 || da->capacity != da->count) {
1302 return -EINVAL;
1303 }
1304
1305 tmp = (RBinDwarfAbbrevDecl *)realloc (da->decls,
1306 da->capacity * 2 * sizeof (RBinDwarfAbbrevDecl));
1307
1308 if (!tmp) {
1309 return -ENOMEM;
1310 }
1311 memset ((ut8 *)tmp + da->capacity * sizeof (RBinDwarfAbbrevDecl),
1312 0, da->capacity * sizeof (RBinDwarfAbbrevDecl));
1313
1314 da->decls = tmp;
1315 da->capacity *= 2;
1316
1317 return 0;
1318 }
1319
print_abbrev_section(RBinDwarfDebugAbbrev * da,PrintfCallback print)1320 static void print_abbrev_section(RBinDwarfDebugAbbrev *da, PrintfCallback print) {
1321 size_t i, j;
1322 ut64 attr_name, attr_form;
1323
1324 if (!da) {
1325 return;
1326 }
1327 for (i = 0; i < da->count; i++) {
1328 int declstag = da->decls[i].tag;
1329 print (" %-4"PFMT64d" ", da->decls[i].code);
1330 if (declstag>=0 && declstag < DW_TAG_LAST) {
1331 print (" %-25s ", dwarf_tag_name_encodings[declstag]);
1332 }
1333 print ("[%s]", da->decls[i].has_children ?
1334 "has children" : "no children");
1335 print (" (0x%"PFMT64x")\n", da->decls[i].offset);
1336
1337 if (da->decls[i].defs) {
1338 for (j = 0; j < da->decls[i].count; j++) {
1339 attr_name = da->decls[i].defs[j].attr_name;
1340 attr_form = da->decls[i].defs[j].attr_form;
1341 if (is_printable_attr(attr_name) && is_printable_form(attr_form)) {
1342 print (" %-30s %-30s\n",
1343 dwarf_attr_encodings[attr_name],
1344 dwarf_attr_form_encodings[attr_form]);
1345 }
1346 }
1347 }
1348 }
1349 }
1350
r_bin_dwarf_free_debug_abbrev(RBinDwarfDebugAbbrev * da)1351 R_API void r_bin_dwarf_free_debug_abbrev(RBinDwarfDebugAbbrev *da) {
1352 size_t i;
1353 if (!da) {
1354 return;
1355 }
1356 for (i = 0; i < da->count; i++) {
1357 R_FREE (da->decls[i].defs);
1358 }
1359 R_FREE (da->decls);
1360 free (da);
1361 }
1362
free_attr_value(RBinDwarfAttrValue * val)1363 static void free_attr_value(RBinDwarfAttrValue *val) {
1364 // TODO adjust to new forms, now we're leaking
1365 if (!val) {
1366 return;
1367 }
1368 switch (val->attr_form) {
1369 case DW_FORM_strp:
1370 case DW_FORM_string:
1371 R_FREE (val->string.content);
1372 break;
1373 case DW_FORM_exprloc:
1374 case DW_FORM_block:
1375 case DW_FORM_block1:
1376 case DW_FORM_block2:
1377 case DW_FORM_block4:
1378 R_FREE (val->block.data);
1379 break;
1380 default:
1381 break;
1382 };
1383 }
1384
free_die(RBinDwarfDie * die)1385 static void free_die(RBinDwarfDie *die) {
1386 size_t i;
1387 if (!die) {
1388 return;
1389 }
1390 for (i = 0; i < die->count; i++) {
1391 free_attr_value (&die->attr_values[i]);
1392 }
1393 R_FREE (die->attr_values);
1394 }
1395
free_comp_unit(RBinDwarfCompUnit * cu)1396 static void free_comp_unit(RBinDwarfCompUnit *cu) {
1397 size_t i;
1398 if (!cu) {
1399 return;
1400 }
1401 for (i = 0; i < cu->count; i++) {
1402 if (cu->dies) {
1403 free_die (&cu->dies[i]);
1404 }
1405 }
1406 R_FREE (cu->dies);
1407 }
1408
r_bin_dwarf_free_debug_info(RBinDwarfDebugInfo * inf)1409 R_API void r_bin_dwarf_free_debug_info(RBinDwarfDebugInfo *inf) {
1410 size_t i;
1411 if (!inf) {
1412 return;
1413 }
1414 for (i = 0; i < inf->count; i++) {
1415 free_comp_unit (&inf->comp_units[i]);
1416 }
1417 ht_up_free (inf->lookup_table);
1418 free (inf->comp_units);
1419 free(inf);
1420 }
1421
print_attr_value(const RBinDwarfAttrValue * val,PrintfCallback print)1422 static void print_attr_value(const RBinDwarfAttrValue *val, PrintfCallback print) {
1423 size_t i;
1424 r_return_if_fail(val);
1425
1426 switch (val->attr_form) {
1427 case DW_FORM_block:
1428 case DW_FORM_block1:
1429 case DW_FORM_block2:
1430 case DW_FORM_block4:
1431 case DW_FORM_exprloc:
1432 print ("%"PFMT64u" byte block:", val->block.length);
1433 for (i = 0; i < val->block.length; i++) {
1434 print (" 0x%02x", val->block.data[i]);
1435 }
1436 break;
1437 case DW_FORM_data1:
1438 case DW_FORM_data2:
1439 case DW_FORM_data4:
1440 case DW_FORM_data8:
1441 case DW_FORM_data16:
1442 print ("%"PFMT64u"", val->uconstant);
1443 if (val->attr_name == DW_AT_language) {
1444 print (" (%s)", dwarf_langs[val->uconstant]);
1445 }
1446 break;
1447 case DW_FORM_string:
1448 if (val->string.content) {
1449 print ("%s", val->string.content);
1450 } else {
1451 print ("No string found");
1452 }
1453 break;
1454 case DW_FORM_flag:
1455 print ("%u", val->flag);
1456 break;
1457 case DW_FORM_sdata:
1458 print ("%"PFMT64d"", val->sconstant);
1459 break;
1460 case DW_FORM_udata:
1461 print ("%"PFMT64u"", val->uconstant);
1462 break;
1463 case DW_FORM_ref_addr:
1464 case DW_FORM_ref1:
1465 case DW_FORM_ref2:
1466 case DW_FORM_ref4:
1467 case DW_FORM_ref8:
1468 case DW_FORM_ref_sig8:
1469 case DW_FORM_ref_udata:
1470 case DW_FORM_ref_sup4:
1471 case DW_FORM_ref_sup8:
1472 case DW_FORM_sec_offset:
1473 print ("<0x%"PFMT64x">", val->reference);
1474 break;
1475 case DW_FORM_flag_present:
1476 print ("1");
1477 break;
1478 case DW_FORM_strx:
1479 case DW_FORM_strx1:
1480 case DW_FORM_strx2:
1481 case DW_FORM_strx3:
1482 case DW_FORM_strx4:
1483 case DW_FORM_line_ptr:
1484 case DW_FORM_strp_sup:
1485 case DW_FORM_strp:
1486 print ("(indirect string, offset: 0x%"PFMT64x"): %s",
1487 val->string.offset, val->string.content);
1488 break;
1489 case DW_FORM_addr:
1490 case DW_FORM_addrx:
1491 case DW_FORM_addrx1:
1492 case DW_FORM_addrx2:
1493 case DW_FORM_addrx3:
1494 case DW_FORM_addrx4:
1495 case DW_FORM_loclistx:
1496 case DW_FORM_rnglistx:
1497 print ("0x%"PFMT64x"", val->address);
1498 break;
1499 case DW_FORM_implicit_const:
1500 print ("0x%"PFMT64d"", val->uconstant);
1501 break;
1502 default:
1503 print ("Unknown attr value form %"PFMT64d"\n", val->attr_form);
1504 break;
1505 };
1506 }
1507
print_debug_info(const RBinDwarfDebugInfo * inf,PrintfCallback print)1508 static void print_debug_info(const RBinDwarfDebugInfo *inf, PrintfCallback print) {
1509 size_t i, j, k;
1510 RBinDwarfDie *dies;
1511 RBinDwarfAttrValue *values;
1512
1513 r_return_if_fail(inf);
1514
1515 for (i = 0; i < inf->count; i++) {
1516 print ("\n");
1517 print (" Compilation Unit @ offset 0x%" PFMT64x ":\n", inf->comp_units[i].offset);
1518 print (" Length: 0x%" PFMT64x "\n", inf->comp_units[i].hdr.length);
1519 print (" Version: %d\n", inf->comp_units[i].hdr.version);
1520 print (" Abbrev Offset: 0x%" PFMT64x "\n", inf->comp_units[i].hdr.abbrev_offset);
1521 print (" Pointer Size: %d\n", inf->comp_units[i].hdr.address_size);
1522 if (is_printable_unit_type(inf->comp_units[i].hdr.unit_type)) {
1523 print (" Unit Type: %s\n", dwarf_unit_types[inf->comp_units[i].hdr.unit_type]);
1524 }
1525 print ("\n");
1526
1527 dies = inf->comp_units[i].dies;
1528
1529 for (j = 0; j < inf->comp_units[i].count; j++) {
1530 print ("<0x%"PFMT64x">: Abbrev Number: %-4" PFMT64u " ", dies[j].offset,dies[j].abbrev_code);
1531
1532 if (is_printable_tag (dies[j].tag)) {
1533 print ("(%s)\n", dwarf_tag_name_encodings[dies[j].tag]);
1534 } else {
1535 print ("(Unknown abbrev tag)\n");
1536 }
1537
1538 if (!dies[j].abbrev_code) {
1539 continue;
1540 }
1541 values = dies[j].attr_values;
1542
1543 for (k = 0; k < dies[j].count; k++) {
1544 if (!values[k].attr_name) {
1545 continue;
1546 }
1547 if (is_printable_attr (values[k].attr_name)) {
1548 print (" %-25s : ", dwarf_attr_encodings[values[k].attr_name]);
1549 } else {
1550 print (" AT_UNKWN [0x%-3" PFMT64x "]\t : ", values[k].attr_name);
1551 }
1552 print_attr_value (&values[k], print);
1553 print ("\n");
1554 }
1555 }
1556 }
1557 }
1558
fill_block_data(const ut8 * buf,const ut8 * buf_end,RBinDwarfBlock * block)1559 static const ut8 *fill_block_data(const ut8 *buf, const ut8 *buf_end, RBinDwarfBlock *block) {
1560 block->data = calloc (sizeof (ut8), block->length);
1561 if (!block->data) {
1562 return NULL;
1563 }
1564 /* Maybe unroll this as an optimization in future? */
1565 if (block->data) {
1566 size_t j = 0;
1567 for (j = 0; j < block->length; j++) {
1568 block->data[j] = READ (buf, ut8);
1569 }
1570 }
1571 return buf;
1572 }
1573
1574 /**
1575 * This function is quite incomplete and requires lot of work
1576 * With parsing various new FORM values
1577 * @brief Parses attribute value based on its definition
1578 * and stores it into `value`
1579 *
1580 * @param obuf
1581 * @param obuf_len Buffer max capacity
1582 * @param def Attribute definition
1583 * @param value Parsed value storage
1584 * @param hdr Current unit header
1585 * @param debug_str Ptr to string section start
1586 * @param debug_str_len Length of the string section
1587 * @return const ut8* Updated buffer
1588 */
parse_attr_value(const ut8 * obuf,int obuf_len,RBinDwarfAttrDef * def,RBinDwarfAttrValue * value,const RBinDwarfCompUnitHdr * hdr,const ut8 * debug_str,size_t debug_str_len)1589 static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
1590 RBinDwarfAttrDef *def, RBinDwarfAttrValue *value,
1591 const RBinDwarfCompUnitHdr *hdr,
1592 const ut8 *debug_str, size_t debug_str_len) {
1593
1594 const ut8 *buf = obuf;
1595 const ut8 *buf_end = obuf + obuf_len;
1596 size_t j;
1597
1598 r_return_val_if_fail(def && value && hdr && obuf && obuf_len >= 1, NULL);
1599
1600 value->attr_form = def->attr_form;
1601 value->attr_name = def->attr_name;
1602 value->block.data = NULL;
1603 value->string.content = NULL;
1604 value->string.offset = 0;
1605
1606 // http://www.dwarfstd.org/doc/DWARF4.pdf#page=161&zoom=100,0,560
1607 switch (def->attr_form) {
1608 case DW_FORM_addr:
1609 value->kind = DW_AT_KIND_ADDRESS;
1610 switch (hdr->address_size) {
1611 case 1:
1612 value->address = READ8 (buf);
1613 break;
1614 case 2:
1615 value->address = READ16 (buf);
1616 break;
1617 case 4:
1618 value->address = READ32 (buf);
1619 break;
1620 case 8:
1621 value->address = READ64 (buf);
1622 break;
1623 default:
1624 eprintf ("DWARF: Unexpected pointer size: %u\n", (unsigned)hdr->address_size);
1625 return NULL;
1626 }
1627 break;
1628 case DW_FORM_data1:
1629 value->kind = DW_AT_KIND_CONSTANT;
1630 value->uconstant = READ8 (buf);
1631 break;
1632 case DW_FORM_data2:
1633 value->kind = DW_AT_KIND_CONSTANT;
1634 value->uconstant = READ16 (buf);
1635 break;
1636 case DW_FORM_data4:
1637 value->kind = DW_AT_KIND_CONSTANT;
1638 value->uconstant = READ32 (buf);
1639 break;
1640 case DW_FORM_data8:
1641 value->kind = DW_AT_KIND_CONSTANT;
1642 value->uconstant = READ64 (buf);
1643 break;
1644 case DW_FORM_data16: // TODO Fix this, right now I just read the data, but I need to make storage for it
1645 value->kind = DW_AT_KIND_CONSTANT;
1646 value->uconstant = READ64 (buf);
1647 value->uconstant = READ64 (buf);
1648 break;
1649 case DW_FORM_sdata:
1650 value->kind = DW_AT_KIND_CONSTANT;
1651 buf = r_leb128 (buf, buf_end - buf, &value->sconstant);
1652 break;
1653 case DW_FORM_udata:
1654 value->kind = DW_AT_KIND_CONSTANT;
1655 buf = r_uleb128 (buf, buf_end - buf, &value->uconstant, NULL);
1656 break;
1657 case DW_FORM_string:
1658 value->kind = DW_AT_KIND_STRING;
1659 value->string.content = *buf ? strdup ((const char *)buf) : NULL;
1660 buf += (strlen ((const char *)buf) + 1);
1661 break;
1662 case DW_FORM_block1:
1663 value->kind = DW_AT_KIND_BLOCK;
1664 value->block.length = READ8 (buf);
1665 buf = fill_block_data (buf, buf_end, &value->block);
1666 break;
1667 case DW_FORM_block2:
1668 value->kind = DW_AT_KIND_BLOCK;
1669 value->block.length = READ16 (buf);
1670 if (value->block.length > 0) {
1671 value->block.data = calloc (sizeof (ut8), value->block.length);
1672 if (!value->block.data) {
1673 return NULL;
1674 }
1675 for (j = 0; j < value->block.length; j++) {
1676 value->block.data[j] = READ (buf, ut8);
1677 }
1678 }
1679 break;
1680 case DW_FORM_block4:
1681 value->kind = DW_AT_KIND_BLOCK;
1682 value->block.length = READ32 (buf);
1683 buf = fill_block_data (buf, buf_end, &value->block);
1684 break;
1685 case DW_FORM_block: // variable length ULEB128
1686 value->kind = DW_AT_KIND_BLOCK;
1687 buf = r_uleb128 (buf, buf_end - buf, &value->block.length, NULL);
1688 if (!buf || buf >= buf_end) {
1689 return NULL;
1690 }
1691 buf = fill_block_data (buf, buf_end, &value->block);
1692 break;
1693 case DW_FORM_flag:
1694 value->kind = DW_AT_KIND_FLAG;
1695 value->flag = READ (buf, ut8);
1696 break;
1697 // offset in .debug_str
1698 case DW_FORM_strp:
1699 value->kind = DW_AT_KIND_STRING;
1700 value->string.offset = dwarf_read_offset(hdr->is_64bit, &buf, buf_end);
1701 if (debug_str && value->string.offset < debug_str_len) {
1702 value->string.content =
1703 strdup ((const char *)(debug_str + value->string.offset));
1704 } else {
1705 value->string.content = NULL; // Means malformed DWARF, should we print error message?
1706 }
1707 break;
1708 // offset in .debug_info
1709 case DW_FORM_ref_addr:
1710 value->kind = DW_AT_KIND_REFERENCE;
1711 value->reference = dwarf_read_offset(hdr->is_64bit, &buf, buf_end);
1712 break;
1713 // This type of reference is an offset from the first byte of the compilation
1714 // header for the compilation unit containing the reference
1715 case DW_FORM_ref1:
1716 value->kind = DW_AT_KIND_REFERENCE;
1717 value->reference = hdr->unit_offset + READ8 (buf);
1718 break;
1719 case DW_FORM_ref2:
1720 value->kind = DW_AT_KIND_REFERENCE;
1721 value->reference = hdr->unit_offset + READ16 (buf);
1722 break;
1723 case DW_FORM_ref4:
1724 value->kind = DW_AT_KIND_REFERENCE;
1725 value->reference = hdr->unit_offset + READ32 (buf);
1726 break;
1727 case DW_FORM_ref8:
1728 value->kind = DW_AT_KIND_REFERENCE;
1729 value->reference = hdr->unit_offset + READ64 (buf);
1730 break;
1731 case DW_FORM_ref_udata:
1732 value->kind = DW_AT_KIND_REFERENCE;
1733 // uleb128 is enough to fit into ut64?
1734 buf = r_uleb128 (buf, buf_end - buf, &value->reference, NULL);
1735 value->reference += hdr->unit_offset;
1736 break;
1737 // offset in a section other than .debug_info or .debug_str
1738 case DW_FORM_sec_offset:
1739 value->kind = DW_AT_KIND_REFERENCE;
1740 value->reference = dwarf_read_offset(hdr->is_64bit, &buf, buf_end);
1741 break;
1742 case DW_FORM_exprloc:
1743 value->kind = DW_AT_KIND_BLOCK;
1744 buf = r_uleb128 (buf, buf_end - buf, &value->block.length, NULL);
1745 if (!buf || buf >= buf_end) {
1746 return NULL;
1747 }
1748 buf = fill_block_data (buf, buf_end, &value->block);
1749 break;
1750 // this means that the flag is present, nothing is read
1751 case DW_FORM_flag_present:
1752 value->kind = DW_AT_KIND_FLAG;
1753 value->flag = true;
1754 break;
1755 case DW_FORM_ref_sig8:
1756 value->kind = DW_AT_KIND_REFERENCE;
1757 value->reference = READ64 (buf);
1758 break;
1759 // offset into .debug_line_str section, can't parse the section now, so we just skip
1760 case DW_FORM_strx:
1761 value->kind = DW_AT_KIND_STRING;
1762 // value->string.offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1763 // if (debug_str && value->string.offset < debug_line_str_len) {
1764 // value->string.content =
1765 // strdup ((const char *)(debug_str + value->string.offset));
1766 // } else {
1767 // value->string.content = NULL; // Means malformed DWARF, should we print error message?
1768 // }
1769 break;
1770 case DW_FORM_strx1:
1771 value->kind = DW_AT_KIND_STRING;
1772 value->string.offset = READ8 (buf);
1773 break;
1774 case DW_FORM_strx2:
1775 value->kind = DW_AT_KIND_STRING;
1776 value->string.offset = READ16 (buf);
1777 break;
1778 case DW_FORM_strx3: // TODO Add 3 byte int read
1779 value->kind = DW_AT_KIND_STRING;
1780 buf += 3;
1781 break;
1782 case DW_FORM_strx4:
1783 value->kind = DW_AT_KIND_STRING;
1784 value->string.offset = READ32 (buf);
1785 break;
1786 case DW_FORM_implicit_const:
1787 value->kind = DW_AT_KIND_CONSTANT;
1788 value->uconstant = def->special;
1789 break;
1790 /* addrx* forms : The index is relative to the value of the
1791 DW_AT_addr_base attribute of the associated compilation unit.
1792 index into an array of addresses in the .debug_addr section.*/
1793 case DW_FORM_addrx:
1794 value->kind = DW_AT_KIND_ADDRESS;
1795 buf = r_uleb128 (buf, buf_end - buf, &value->address, NULL);
1796 break;
1797 case DW_FORM_addrx1:
1798 value->kind = DW_AT_KIND_ADDRESS;
1799 value->address = READ8 (buf);
1800 break;
1801 case DW_FORM_addrx2:
1802 value->kind = DW_AT_KIND_ADDRESS;
1803 value->address = READ16 (buf);
1804 break;
1805 case DW_FORM_addrx3:
1806 // I need to add 3byte endianess free read here TODO
1807 value->kind = DW_AT_KIND_ADDRESS;
1808 buf += 3;
1809 break;
1810 case DW_FORM_addrx4:
1811 value->kind = DW_AT_KIND_ADDRESS;
1812 value->address = READ32 (buf);
1813 break;
1814 case DW_FORM_line_ptr: // offset in a section .debug_line_str
1815 case DW_FORM_strp_sup: // offset in a section .debug_line_str
1816 value->kind = DW_AT_KIND_STRING;
1817 value->string.offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1818 // if (debug_str && value->string.offset < debug_line_str_len) {
1819 // value->string.content =
1820 // strdupsts
1821 break;
1822 // offset in the supplementary object file
1823 case DW_FORM_ref_sup4:
1824 value->kind = DW_AT_KIND_REFERENCE;
1825 value->reference = READ32 (buf);
1826 break;
1827 case DW_FORM_ref_sup8:
1828 value->kind = DW_AT_KIND_REFERENCE;
1829 value->reference = READ64 (buf);
1830 break;
1831 // An index into the .debug_loc
1832 case DW_FORM_loclistx:
1833 value->kind = DW_AT_KIND_LOCLISTPTR;
1834 value->reference = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1835 break;
1836 // An index into the .debug_rnglists
1837 case DW_FORM_rnglistx:
1838 value->kind = DW_AT_KIND_ADDRESS;
1839 buf = r_uleb128 (buf, buf_end - buf, &value->address, NULL);
1840 break;
1841 default:
1842 eprintf ("Unknown DW_FORM 0x%02" PFMT64x "\n", def->attr_form);
1843 value->uconstant = 0;
1844 return NULL;
1845 }
1846 return buf;
1847 }
1848
1849 /**
1850 * @brief
1851 *
1852 * @param buf Start of the DIE data
1853 * @param buf_end
1854 * @param abbrev Abbreviation of the DIE
1855 * @param hdr Unit header
1856 * @param die DIE to store the parsed info into
1857 * @param debug_str Ptr to string section start
1858 * @param debug_str_len Length of the string section
1859 * @param sdb
1860 * @return const ut8* Updated buffer
1861 */
parse_die(const ut8 * buf,const ut8 * buf_end,RBinDwarfAbbrevDecl * abbrev,RBinDwarfCompUnitHdr * hdr,RBinDwarfDie * die,const ut8 * debug_str,size_t debug_str_len,Sdb * sdb)1862 static const ut8 *parse_die(const ut8 *buf, const ut8 *buf_end, RBinDwarfAbbrevDecl *abbrev,
1863 RBinDwarfCompUnitHdr *hdr, RBinDwarfDie *die, const ut8 *debug_str, size_t debug_str_len, Sdb *sdb) {
1864 size_t i;
1865 for (i = 0; i < abbrev->count - 1; i++) {
1866 memset (&die->attr_values[i], 0, sizeof (die->attr_values[i]));
1867
1868 buf = parse_attr_value (buf, buf_end - buf, &abbrev->defs[i],
1869 &die->attr_values[i], hdr, debug_str, debug_str_len);
1870
1871 RBinDwarfAttrValue *attribute = &die->attr_values[i];
1872
1873 bool is_valid_string_form = (attribute->attr_form == DW_FORM_strp ||
1874 attribute->attr_form == DW_FORM_string) &&
1875 attribute->string.content;
1876 // TODO does this have a purpose anymore?
1877 // Or atleast it needs to rework becase there will be
1878 // more comp units -> more comp dirs and only the last one will be kept
1879 if (attribute->attr_name == DW_AT_comp_dir && is_valid_string_form) {
1880 const char *name = attribute->string.content;
1881 sdb_set (sdb, "DW_AT_comp_dir", name, 0);
1882 }
1883 die->count++;
1884 }
1885
1886 return buf;
1887 }
1888
1889 /**
1890 * @brief Reads throught comp_unit buffer and parses all its DIEntries
1891 *
1892 * @param sdb
1893 * @param buf_start Start of the compilation unit data
1894 * @param unit Unit to store the newly parsed information
1895 * @param abbrevs Parsed abbrev section info of *all* abbreviations
1896 * @param first_abbr_idx index for first abbrev of the current comp unit in abbrev array
1897 * @param debug_str Ptr to string section start
1898 * @param debug_str_len Length of the string section
1899 *
1900 * @return const ut8* Update buffer
1901 */
parse_comp_unit(RBinDwarfDebugInfo * info,Sdb * sdb,const ut8 * buf_start,RBinDwarfCompUnit * unit,const RBinDwarfDebugAbbrev * abbrevs,size_t first_abbr_idx,const ut8 * debug_str,size_t debug_str_len)1902 static const ut8 *parse_comp_unit(RBinDwarfDebugInfo *info, Sdb *sdb, const ut8 *buf_start,
1903 RBinDwarfCompUnit *unit, const RBinDwarfDebugAbbrev *abbrevs,
1904 size_t first_abbr_idx, const ut8 *debug_str, size_t debug_str_len) {
1905
1906 const ut8 *buf = buf_start;
1907 const ut8 *buf_end = buf_start + unit->hdr.length - unit->hdr.header_size;
1908
1909 while (buf && buf < buf_end && buf >= buf_start) {
1910 if (unit->count && unit->capacity == unit->count) {
1911 expand_cu (unit);
1912 }
1913 RBinDwarfDie *die = &unit->dies[unit->count];
1914 // add header size to the offset;
1915 die->offset = buf - buf_start + unit->hdr.header_size + unit->offset;
1916 die->offset += unit->hdr.is_64bit ? 12 : 4;
1917
1918 // DIE starts with ULEB128 with the abbreviation code
1919 ut64 abbr_code;
1920 buf = r_uleb128 (buf, buf_end - buf, &abbr_code, NULL);
1921
1922 if (abbr_code > abbrevs->count || !buf) { // something invalid
1923 return NULL;
1924 }
1925
1926 if (buf >= buf_end) {
1927 unit->count++; // we wanna store this entry too, usually the last one is null_entry
1928 return buf; // return the buffer to parse next compilation units
1929 }
1930 // there can be "null" entries that have abbr_code == 0
1931 if (!abbr_code) {
1932 unit->count++;
1933 continue;
1934 }
1935 ut64 abbr_idx = first_abbr_idx + abbr_code;
1936
1937 if (abbrevs->count < abbr_idx) {
1938 return NULL;
1939 }
1940 RBinDwarfAbbrevDecl *abbrev = &abbrevs->decls[abbr_idx - 1];
1941
1942 if (init_die (die, abbr_code, abbrev->count)) {
1943 return NULL; // error
1944 }
1945 die->tag = abbrev->tag;
1946 die->has_children = abbrev->has_children;
1947
1948 buf = parse_die (buf, buf_end, abbrev, &unit->hdr, die, debug_str, debug_str_len, sdb);
1949 if (!buf) {
1950 return NULL;
1951 }
1952
1953 unit->count++;
1954 }
1955 return buf;
1956 }
1957
1958 /**
1959 * @brief Reads all information about compilation unit header
1960 *
1961 * @param buf Start of the buffer
1962 * @param buf_end Upper bound of the buffer
1963 * @param unit Unit to read information into
1964 * @return ut8* Advanced position in a buffer
1965 */
info_comp_unit_read_hdr(const ut8 * buf,const ut8 * buf_end,RBinDwarfCompUnitHdr * hdr)1966 static const ut8 *info_comp_unit_read_hdr(const ut8 *buf, const ut8 *buf_end, RBinDwarfCompUnitHdr *hdr) {
1967 // 32-bit vs 64-bit dwarf formats
1968 // http://www.dwarfstd.org/doc/Dwarf3.pdf section 7.4
1969 hdr->length = READ32 (buf);
1970 if (hdr->length == (ut32)DWARF_INIT_LEN_64) { // then its 64bit
1971 hdr->length = READ64 (buf);
1972 hdr->is_64bit = true;
1973 }
1974 const ut8 *tmp = buf; // to calculate header size
1975 hdr->version = READ16 (buf);
1976 if (hdr->version == 5) {
1977 hdr->unit_type = READ8 (buf);
1978 hdr->address_size = READ8 (buf);
1979 hdr->abbrev_offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1980
1981 if (hdr->unit_type == DW_UT_skeleton || hdr->unit_type == DW_UT_split_compile) {
1982 hdr->dwo_id = READ8 (buf);
1983 } else if (hdr->unit_type == DW_UT_type || hdr->unit_type == DW_UT_split_type) {
1984 hdr->type_sig = READ64 (buf);
1985 hdr->type_offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1986 }
1987 } else {
1988 hdr->abbrev_offset = dwarf_read_offset (hdr->is_64bit, &buf, buf_end);
1989 hdr->address_size = READ8 (buf);
1990 }
1991 hdr->header_size = buf - tmp; // header size excluding length field
1992 return buf;
1993 }
expand_info(RBinDwarfDebugInfo * info)1994 static int expand_info(RBinDwarfDebugInfo *info) {
1995 r_return_val_if_fail (info && info->capacity == info->count, -1);
1996
1997 RBinDwarfCompUnit *tmp = realloc (info->comp_units,
1998 info->capacity * 2 * sizeof (RBinDwarfCompUnit));
1999 if (!tmp) {
2000 return -1;
2001 }
2002
2003 memset ((ut8 *)tmp + info->capacity * sizeof (RBinDwarfCompUnit),
2004 0, info->capacity * sizeof (RBinDwarfCompUnit));
2005
2006 info->comp_units = tmp;
2007 info->capacity *= 2;
2008
2009 return 0;
2010 }
2011
2012 /**
2013 * @brief Parses whole .debug_info section
2014 *
2015 * @param sdb Sdb to store line related information into
2016 * @param da Parsed Abbreviations
2017 * @param obuf .debug_info section buffer start
2018 * @param len length of the section buffer
2019 * @param debug_str start of the .debug_str section
2020 * @param debug_str_len length of the debug_str section
2021 * @param mode
2022 * @return R_API* parse_info_raw Parsed information
2023 */
parse_info_raw(Sdb * sdb,RBinDwarfDebugAbbrev * da,const ut8 * obuf,size_t len,const ut8 * debug_str,size_t debug_str_len)2024 static RBinDwarfDebugInfo *parse_info_raw(Sdb *sdb, RBinDwarfDebugAbbrev *da,
2025 const ut8 *obuf, size_t len,
2026 const ut8 *debug_str, size_t debug_str_len) {
2027
2028 r_return_val_if_fail (da && sdb && obuf, false);
2029
2030 const ut8 *buf = obuf;
2031 const ut8 *buf_end = obuf + len;
2032
2033 RBinDwarfDebugInfo *info = R_NEW0 (RBinDwarfDebugInfo);
2034 if (!info) {
2035 return NULL;
2036 }
2037 if (init_debug_info (info) < 0) {
2038 goto cleanup;
2039 }
2040 int unit_idx = 0;
2041
2042 while (buf < buf_end) {
2043 if (info->count >= info->capacity) {
2044 if (expand_info (info)) {
2045 break;
2046 }
2047 }
2048
2049 RBinDwarfCompUnit *unit = &info->comp_units[unit_idx];
2050 if (init_comp_unit (unit) < 0) {
2051 unit_idx--;
2052 goto cleanup;
2053 }
2054 info->count++;
2055
2056 unit->offset = buf - obuf;
2057 // small redundancy, because it was easiest solution at a time
2058 unit->hdr.unit_offset = buf - obuf;
2059
2060 buf = info_comp_unit_read_hdr (buf, buf_end, &unit->hdr);
2061
2062 if (unit->hdr.length > len) {
2063 goto cleanup;
2064 }
2065
2066 if (da->decls->count >= da->capacity) {
2067 eprintf ("WARNING: malformed dwarf have not enough buckets for decls.\n");
2068 }
2069 r_warn_if_fail (da->count <= da->capacity);
2070
2071 // find abbrev start for current comp unit
2072 // we could also do naive, ((char *)da->decls) + abbrev_offset,
2073 // but this is more bulletproof to invalid DWARF
2074 RBinDwarfAbbrevDecl key = { .offset = unit->hdr.abbrev_offset };
2075 RBinDwarfAbbrevDecl *abbrev_start = bsearch (&key, da->decls, da->count, sizeof (key), abbrev_cmp);
2076 if (!abbrev_start) {
2077 goto cleanup;
2078 }
2079 // They point to the same array object, so should be def. behaviour
2080 size_t first_abbr_idx = abbrev_start - da->decls;
2081
2082 buf = parse_comp_unit (info, sdb, buf, unit, da, first_abbr_idx, debug_str, debug_str_len);
2083
2084 if (!buf) {
2085 goto cleanup;
2086 }
2087
2088 unit_idx++;
2089 }
2090
2091 return info;
2092
2093 cleanup:
2094 r_bin_dwarf_free_debug_info (info);
2095 return NULL;
2096 }
2097
parse_abbrev_raw(const ut8 * obuf,size_t len)2098 static RBinDwarfDebugAbbrev *parse_abbrev_raw(const ut8 *obuf, size_t len) {
2099 const ut8 *buf = obuf, *buf_end = obuf + len;
2100 ut64 tmp, attr_code, attr_form, offset;
2101 st64 special;
2102 ut8 has_children;
2103 RBinDwarfAbbrevDecl *tmpdecl;
2104
2105 // XXX - Set a suitable value here.
2106 if (!obuf || len < 3) {
2107 return NULL;
2108 }
2109 RBinDwarfDebugAbbrev *da = R_NEW0 (RBinDwarfDebugAbbrev);
2110
2111 init_debug_abbrev (da);
2112
2113 while (buf && buf+1 < buf_end) {
2114 offset = buf - obuf;
2115 buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp, NULL);
2116 if (!buf || !tmp || buf >= buf_end) {
2117 continue;
2118 }
2119 if (da->count == da->capacity) {
2120 expand_debug_abbrev(da);
2121 }
2122 tmpdecl = &da->decls[da->count];
2123 init_abbrev_decl (tmpdecl);
2124
2125 tmpdecl->code = tmp;
2126 buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp, NULL);
2127 tmpdecl->tag = tmp;
2128
2129 tmpdecl->offset = offset;
2130 if (buf >= buf_end) {
2131 break;
2132 }
2133 has_children = READ (buf, ut8);
2134 tmpdecl->has_children = has_children;
2135 do {
2136 if (tmpdecl->count == tmpdecl->capacity) {
2137 expand_abbrev_decl (tmpdecl);
2138 }
2139 buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_code, NULL);
2140 if (buf >= buf_end) {
2141 break;
2142 }
2143 buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_form, NULL);
2144 // http://www.dwarfstd.org/doc/DWARF5.pdf#page=225
2145 if (attr_form == DW_FORM_implicit_const) {
2146 buf = r_leb128 (buf, (size_t)(buf_end - buf), &special);
2147 tmpdecl->defs[tmpdecl->count].special = special;
2148 }
2149 tmpdecl->defs[tmpdecl->count].attr_name = attr_code;
2150 tmpdecl->defs[tmpdecl->count].attr_form = attr_form;
2151 tmpdecl->count++;
2152 } while (attr_code && attr_form);
2153
2154 da->count++;
2155 }
2156 return da;
2157 }
2158
getsection(RBin * a,const char * sn)2159 RBinSection *getsection(RBin *a, const char *sn) {
2160 RListIter *iter;
2161 RBinSection *section = NULL;
2162 RBinFile *binfile = a ? a->cur: NULL;
2163 RBinObject *o = binfile ? binfile->o : NULL;
2164
2165 if ( o && o->sections) {
2166 r_list_foreach (o->sections, iter, section) {
2167 if (strstr (section->name, sn)) {
2168 return section;
2169 }
2170 }
2171 }
2172 return NULL;
2173 }
2174
get_section_bytes(RBin * bin,const char * sect_name,size_t * len)2175 static ut8 *get_section_bytes(RBin *bin, const char *sect_name, size_t *len) {
2176 RBinSection *section = getsection (bin, sect_name);
2177 RBinFile *binfile = bin ? bin->cur: NULL;
2178 if (!section || !binfile) {
2179 return NULL;
2180 }
2181 if (section->size > binfile->size) {
2182 return NULL;
2183 }
2184 *len = section->size;
2185 ut8 *buf = calloc (1,*len);
2186 r_buf_read_at (binfile->buf, section->paddr, buf, *len);
2187 return buf;
2188 }
2189
2190 /**
2191 * @brief Parses .debug_info section
2192 *
2193 * @param da Parsed abbreviations
2194 * @param bin
2195 * @param mode R_MODE_PRINT to print
2196 * @return RBinDwarfDebugInfo* Parsed information, NULL if error
2197 */
r_bin_dwarf_parse_info(RBinDwarfDebugAbbrev * da,RBin * bin,int mode)2198 R_API RBinDwarfDebugInfo *r_bin_dwarf_parse_info(RBinDwarfDebugAbbrev *da, RBin *bin, int mode) {
2199 RBinDwarfDebugInfo *info = NULL;
2200 RBinSection *debug_str;
2201 RBinSection *section = getsection (bin, "debug_info");
2202 RBinFile *binfile = bin ? bin->cur : NULL;
2203
2204 ut64 debug_str_len = 0;
2205 ut8 *debug_str_buf = NULL;
2206
2207 if (binfile && section) {
2208 debug_str = getsection (bin, "debug_str");
2209 if (debug_str) {
2210 debug_str_len = debug_str->size;
2211 debug_str_buf = calloc (1, debug_str_len + 1);
2212 if (!debug_str_buf) {
2213 goto cleanup;
2214 }
2215 st64 ret = r_buf_read_at (binfile->buf, debug_str->paddr,
2216 debug_str_buf, debug_str_len);
2217 if (!ret) {
2218 goto cleanup;
2219 }
2220 }
2221
2222 ut64 len = section->size;
2223 // what is this checking for?
2224 if (len > (UT32_MAX >> 1) || len < 1) {
2225 goto cleanup;
2226 }
2227 ut8 *buf = calloc (1, len);
2228 if (!buf) {
2229 goto cleanup;
2230 }
2231 if (!r_buf_read_at (binfile->buf, section->paddr, buf, len)) {
2232 free (buf);
2233 goto cleanup;
2234 }
2235 /* set the endianity global [HOTFIX] */
2236 big_end = r_bin_is_big_endian (bin);
2237 info = parse_info_raw (binfile->sdb_addrinfo, da, buf, len,
2238 debug_str_buf, debug_str_len);
2239
2240 if (mode == R_MODE_PRINT && info) {
2241 print_debug_info (info, bin->cb_printf);
2242 }
2243 // build hashtable after whole parsing because of possible relocations
2244 if (info) {
2245 size_t i, j;
2246 for (i = 0; i < info->count; i++) {
2247 RBinDwarfCompUnit *unit = &info->comp_units[i];
2248 for (j = 0; j < unit->count; j++) {
2249 RBinDwarfDie *die = &unit->dies[j];
2250 ht_up_insert (info->lookup_table, die->offset, die); // optimization for further processing}
2251 }
2252 }
2253 }
2254 free (debug_str_buf);
2255 free (buf);
2256 return info;
2257 }
2258 cleanup:
2259 free (debug_str_buf);
2260 return NULL;
2261 }
2262
row_new(ut64 addr,const char * file,int line,int col)2263 static RBinDwarfRow *row_new(ut64 addr, const char *file, int line, int col) {
2264 RBinDwarfRow *row = R_NEW0 (RBinDwarfRow);
2265 if (!row) {
2266 return NULL;
2267 }
2268 row->file = strdup (file);
2269 row->address = addr;
2270 row->line = line;
2271 row->column = 0;
2272 return row;
2273 }
2274
row_free(void * p)2275 static void row_free(void *p) {
2276 RBinDwarfRow *row = (RBinDwarfRow*)p;
2277 free (row->file);
2278 free (row);
2279 }
2280
r_bin_dwarf_parse_line(RBin * bin,int mode)2281 R_API RList *r_bin_dwarf_parse_line(RBin *bin, int mode) {
2282 ut8 *buf;
2283 RList *list = NULL;
2284 int len, ret;
2285 RBinSection *section = getsection (bin, "debug_line");
2286 RBinFile *binfile = bin ? bin->cur: NULL;
2287 if (binfile && section) {
2288 len = section->size;
2289 if (len < 1) {
2290 return NULL;
2291 }
2292 buf = calloc (1, len + 1);
2293 if (!buf) {
2294 return NULL;
2295 }
2296 ret = r_buf_read_at (binfile->buf, section->paddr, buf, len);
2297 if (ret != len) {
2298 free (buf);
2299 return NULL;
2300 }
2301 list = r_list_newf (row_free);
2302 if (!list) {
2303 free (buf);
2304 return NULL;
2305 }
2306 /* set the endianity global [HOTFIX] */
2307 big_end = r_bin_is_big_endian (bin);
2308 // Actually parse the section
2309 parse_line_raw (bin, buf, len, mode);
2310 // k bin/cur/addrinfo/*
2311 SdbListIter *iter;
2312 SdbKv *kv;
2313 SdbList *ls = sdb_foreach_list (binfile->sdb_addrinfo, false);
2314 // Use the parsed information from _raw and transform it to more useful format
2315 ls_foreach (ls, iter, kv) {
2316 if (!strncmp (sdbkv_key (kv), "0x", 2)) {
2317 ut64 addr;
2318 RBinDwarfRow *row;
2319 int line;
2320 char *file = strdup (sdbkv_value (kv));
2321 if (!file) {
2322 free (buf);
2323 ls_free (ls);
2324 r_list_free (list);
2325 return NULL;
2326 }
2327 char *tok = strchr (file, '|');
2328 if (tok) {
2329 *tok++ = 0;
2330 line = atoi (tok);
2331 addr = r_num_math (NULL, sdbkv_key (kv));
2332 row = row_new (addr, file, line, 0);
2333 r_list_append (list, row);
2334 }
2335 free (file);
2336 }
2337 }
2338 ls_free (ls);
2339 free (buf);
2340 }
2341 return list;
2342 }
2343
r_bin_dwarf_parse_aranges(RBin * bin,int mode)2344 R_API RList *r_bin_dwarf_parse_aranges(RBin *bin, int mode) {
2345 ut8 *buf;
2346 int ret;
2347 size_t len;
2348 RBinSection *section = getsection (bin, "debug_aranges");
2349 RBinFile *binfile = bin ? bin->cur: NULL;
2350
2351 if (binfile && section) {
2352 len = section->size;
2353 if (len < 1 || len > ST32_MAX) {
2354 return NULL;
2355 }
2356 buf = calloc (1, len);
2357 ret = r_buf_read_at (binfile->buf, section->paddr, buf, len);
2358 if (!ret) {
2359 free (buf);
2360 return NULL;
2361 }
2362 /* set the endianity global [HOTFIX] */
2363 big_end = r_bin_is_big_endian (bin);
2364 parse_aranges_raw (buf, len, mode, bin->cb_printf);
2365
2366 free (buf);
2367 }
2368 return NULL;
2369 }
2370
r_bin_dwarf_parse_abbrev(RBin * bin,int mode)2371 R_API RBinDwarfDebugAbbrev *r_bin_dwarf_parse_abbrev(RBin *bin, int mode) {
2372 size_t len = 0;
2373 ut8 *buf = get_section_bytes (bin, "debug_abbrev", &len);
2374 if (!buf) {
2375 return NULL;
2376 }
2377 RBinDwarfDebugAbbrev *abbrevs = parse_abbrev_raw (buf, len);
2378
2379 if (mode == R_MODE_PRINT && abbrevs) {
2380 print_abbrev_section (abbrevs, bin->cb_printf);
2381 }
2382 free (buf);
2383 return abbrevs;
2384 }
2385
get_max_offset(size_t addr_size)2386 static inline ut64 get_max_offset(size_t addr_size) {
2387 switch (addr_size) {
2388 case 2:
2389 return UT16_MAX;
2390 case 4:
2391 return UT32_MAX;
2392 case 8:
2393 return UT64_MAX;
2394 }
2395 return 0;
2396 }
2397
create_loc_list(ut64 offset)2398 static inline RBinDwarfLocList *create_loc_list(ut64 offset) {
2399 RBinDwarfLocList *list = R_NEW0 (RBinDwarfLocList);
2400 if (list) {
2401 list->list = r_list_new ();
2402 list->offset = offset;
2403 }
2404 return list;
2405 }
2406
create_loc_range(ut64 start,ut64 end,RBinDwarfBlock * block)2407 static inline RBinDwarfLocRange *create_loc_range(ut64 start, ut64 end, RBinDwarfBlock *block) {
2408 RBinDwarfLocRange *range = R_NEW0 (RBinDwarfLocRange);
2409 if (range) {
2410 range->start = start;
2411 range->end = end;
2412 range->expression = block;
2413 }
2414 return range;
2415 }
2416
free_loc_table_list(RBinDwarfLocList * loc_list)2417 static void free_loc_table_list(RBinDwarfLocList *loc_list) {
2418 RListIter *iter;
2419 RBinDwarfLocRange *range;
2420 r_list_foreach (loc_list->list, iter, range) {
2421 free (range->expression->data);
2422 free (range->expression);
2423 free (range);
2424 }
2425 r_list_free (loc_list->list);
2426 free (loc_list);
2427 }
2428
parse_loc_raw(HtUP * loc_table,const ut8 * buf,size_t len,size_t addr_size)2429 static HtUP *parse_loc_raw(HtUP/*<offset, List *<LocListEntry>*/ *loc_table, const ut8 *buf, size_t len, size_t addr_size) {
2430 /* GNU has their own extensions GNU locviews that we can't parse */
2431 const ut8 *const buf_start = buf;
2432 const ut8 *buf_end = buf + len;
2433 /* for recognizing Base address entry */
2434 ut64 max_offset = get_max_offset (addr_size);
2435
2436 ut64 address_base = 0; /* remember base of the loclist */
2437 ut64 list_offset = 0;
2438
2439 RBinDwarfLocList *loc_list = NULL;
2440 RBinDwarfLocRange *range = NULL;
2441 while (buf && buf < buf_end) {
2442 ut64 start_addr = dwarf_read_address (addr_size, &buf, buf_end);
2443 ut64 end_addr = dwarf_read_address (addr_size, &buf, buf_end);
2444
2445 if (start_addr == 0 && end_addr == 0) { /* end of list entry: 0, 0 */
2446 if (loc_list) {
2447 ht_up_insert (loc_table, loc_list->offset, loc_list);
2448 list_offset = buf - buf_start;
2449 loc_list = NULL;
2450 }
2451 address_base = 0;
2452 continue;
2453 } else if (start_addr == max_offset && end_addr != max_offset) {
2454 /* base address, DWARF2 doesn't have this type of entry, these entries shouldn't
2455 be in the list, they are just informational entries for further parsing (address_base) */
2456 address_base = end_addr;
2457 } else { /* location list entry: */
2458 if (!loc_list) {
2459 loc_list = create_loc_list (list_offset);
2460 }
2461 /* TODO in future parse expressions to better structure in dwarf.c and not in dwarf_process.c */
2462 RBinDwarfBlock *block = R_NEW0 (RBinDwarfBlock);
2463 block->length = READ16 (buf);
2464 buf = fill_block_data (buf, buf_end, block);
2465 range = create_loc_range (start_addr + address_base, end_addr + address_base, block);
2466 r_list_append (loc_list->list, range);
2467 range = NULL;
2468 }
2469 }
2470 /* if for some reason end of list is missing, then loc_list would leak */
2471 if (loc_list) {
2472 free_loc_table_list (loc_list);
2473 }
2474 return loc_table;
2475 }
2476
2477 /**
2478 * @brief Parses out the .debug_loc section into a table that maps each list as
2479 * offset of a list -> LocationList
2480 *
2481 * @param bin
2482 * @param addr_size machine address size used in executable (necessary for parsing)
2483 * @return R_API*
2484 */
r_bin_dwarf_parse_loc(RBin * bin,int addr_size)2485 R_API HtUP/*<offset, RBinDwarfLocList*/ *r_bin_dwarf_parse_loc(RBin *bin, int addr_size) {
2486 r_return_val_if_fail (bin, NULL);
2487 /* The standarparse_loc_raw_frame, not sure why is that */
2488 size_t len = 0;
2489 ut8 *buf = get_section_bytes (bin, "debug_loc", &len);
2490 if (!buf) {
2491 return NULL;
2492 }
2493 /* set the endianity global [HOTFIX] */
2494 big_end = r_bin_is_big_endian (bin);
2495 HtUP /*<offset, RBinDwarfLocList*/ *loc_table = ht_up_new0 ();
2496 if (!loc_table) {
2497 free (buf);
2498 return NULL;
2499 }
2500 loc_table = parse_loc_raw (loc_table, buf, len, addr_size);
2501 free (buf);
2502 return loc_table;
2503 }
2504
offset_comp(const void * a,const void * b)2505 static int offset_comp(const void *a, const void *b) {
2506 const RBinDwarfLocList *f = a;
2507 const RBinDwarfLocList *s = b;
2508 ut64 first = f->offset;
2509 ut64 second = s->offset;
2510 if (first < second) {
2511 return -1;
2512 }
2513 if (first > second) {
2514 return 1;
2515 }
2516 return 0;
2517 }
2518
sort_loclists(void * user,const ut64 key,const void * value)2519 static bool sort_loclists(void *user, const ut64 key, const void *value) {
2520 RBinDwarfLocList *loc_list = (RBinDwarfLocList *)value;
2521 RList *sort_list = user;
2522 r_list_add_sorted (sort_list, loc_list, offset_comp);
2523 return true;
2524 }
2525
r_bin_dwarf_print_loc(HtUP * loc_table,int addr_size,PrintfCallback print)2526 R_API void r_bin_dwarf_print_loc(HtUP /*<offset, RBinDwarfLocList*/ *loc_table, int addr_size, PrintfCallback print) {
2527 r_return_if_fail (loc_table && print);
2528 print ("\nContents of the .debug_loc section:\n");
2529 RList /*<RBinDwarfLocList *>*/ *sort_list = r_list_new ();
2530 /* sort the table contents by offset and print sorted
2531 a bit ugly, but I wanted to decouple the parsing and printing */
2532 ht_up_foreach (loc_table, sort_loclists, sort_list);
2533 RListIter *i;
2534 RBinDwarfLocList *loc_list;
2535 r_list_foreach (sort_list, i, loc_list) {
2536 RListIter *j;
2537 RBinDwarfLocRange *range;
2538 ut64 base_offset = loc_list->offset;
2539 r_list_foreach (loc_list->list, j, range) {
2540 print ("0x%" PFMT64x " 0x%" PFMT64x " 0x%" PFMT64x "\n", base_offset, range->start, range->end);
2541 base_offset += addr_size * 2;
2542 if (range->expression) {
2543 base_offset += 2 + range->expression->length; /* 2 bytes for expr length */
2544 }
2545 }
2546 print ("0x%" PFMT64x " <End of list>\n", base_offset);
2547 }
2548 print ("\n");
2549 r_list_free (sort_list);
2550 }
2551
free_loc_table_entry(HtUPKv * kv)2552 static void free_loc_table_entry(HtUPKv *kv) {
2553 if (kv) {
2554 free_loc_table_list (kv->value);
2555 }
2556 }
2557
r_bin_dwarf_free_loc(HtUP * loc_table)2558 R_API void r_bin_dwarf_free_loc(HtUP /*<offset, RBinDwarfLocList*>*/ *loc_table) {
2559 r_return_if_fail (loc_table);
2560 loc_table->opt.freefn = free_loc_table_entry;
2561 ht_up_free (loc_table);
2562 }
2563