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, &regs);
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, &regs, 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