1179187Sjb/*-
2179187Sjb * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3179187Sjb * All rights reserved.
4179187Sjb *
5179187Sjb * Redistribution and use in source and binary forms, with or without
6179187Sjb * modification, are permitted provided that the following conditions
7179187Sjb * are met:
8179187Sjb * 1. Redistributions of source code must retain the above copyright
9179187Sjb *    notice, this list of conditions and the following disclaimer.
10179187Sjb * 2. Redistributions in binary form must reproduce the above copyright
11179187Sjb *    notice, this list of conditions and the following disclaimer in the
12179187Sjb *    documentation and/or other materials provided with the distribution.
13179187Sjb *
14179187Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15179187Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16179187Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17179187Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18179187Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19179187Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20179187Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21179187Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22179187Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23179187Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24179187Sjb * SUCH DAMAGE.
25179187Sjb *
26179187Sjb * $FreeBSD$
27179187Sjb */
28179187Sjb
29179187Sjb#include <stdlib.h>
30179187Sjb#include <string.h>
31179187Sjb#include "_libdwarf.h"
32179187Sjb
33179187Sjbconst char *
34179187Sjbget_sht_desc(uint32_t sh_type)
35179187Sjb{
36179187Sjb	switch (sh_type) {
37179187Sjb	case SHT_NULL:
38179187Sjb		return "inactive";
39179187Sjb	case SHT_PROGBITS:
40179187Sjb		return "program defined information";
41179187Sjb	case SHT_SYMTAB:
42179187Sjb		return "symbol table section";
43179187Sjb	case SHT_STRTAB:
44179187Sjb		return "string table section";
45179187Sjb	case SHT_RELA:
46179187Sjb		return "relocation section with addends";
47179187Sjb	case SHT_HASH:
48179187Sjb		return "symbol hash table section";
49179187Sjb	case SHT_DYNAMIC:
50179187Sjb		return "dynamic section";
51179187Sjb	case SHT_NOTE:
52179187Sjb		return "note section";
53179187Sjb	case SHT_NOBITS:
54179187Sjb		return "no space section";
55179187Sjb	case SHT_REL:
56179187Sjb		return "relocation section - no addends";
57179187Sjb	case SHT_SHLIB:
58179187Sjb		return "reserved - purpose unknown";
59179187Sjb	case SHT_DYNSYM:
60179187Sjb		return "dynamic symbol table section";
61179187Sjb	case SHT_INIT_ARRAY:
62179187Sjb		return "Initialization function pointers.";
63179187Sjb	case SHT_FINI_ARRAY:
64179187Sjb		return "Termination function pointers.";
65179187Sjb	case SHT_PREINIT_ARRAY:
66179187Sjb		return "Pre-initialization function ptrs.";
67179187Sjb	case SHT_GROUP:
68179187Sjb		return "Section group.";
69179187Sjb	case SHT_SYMTAB_SHNDX:
70179187Sjb		return "Section indexes (see SHN_XINDEX).";
71179187Sjb	case SHT_GNU_verdef:
72179187Sjb		return "Symbol versions provided";
73179187Sjb	case SHT_GNU_verneed:
74179187Sjb		return "Symbol versions required";
75179187Sjb	case SHT_GNU_versym:
76179187Sjb		return "Symbol version table";
77179187Sjb	case SHT_AMD64_UNWIND:
78179187Sjb		return "AMD64 unwind";
79179187Sjb	default:
80179187Sjb		return "Unknown";
81179187Sjb	}
82179187Sjb}
83179187Sjb
84179187Sjbconst char *
85179187Sjbget_attr_desc(uint32_t attr)
86179187Sjb{
87179187Sjb	switch (attr) {
88179187Sjb	case DW_AT_abstract_origin:
89179187Sjb		return "DW_AT_abstract_origin";
90179187Sjb	case DW_AT_accessibility:
91179187Sjb		return "DW_AT_accessibility";
92179187Sjb	case DW_AT_address_class:
93179187Sjb		return "DW_AT_address_class";
94179187Sjb	case DW_AT_artificial:
95179187Sjb		return "DW_AT_artificial";
96179187Sjb	case DW_AT_base_types:
97179187Sjb		return "DW_AT_base_types";
98179187Sjb	case DW_AT_bit_offset:
99179187Sjb		return "DW_AT_bit_offset";
100179187Sjb	case DW_AT_bit_size:
101179187Sjb		return "DW_AT_bit_size";
102179187Sjb	case DW_AT_byte_size:
103179187Sjb		return "DW_AT_byte_size";
104179187Sjb	case DW_AT_calling_convention:
105179187Sjb		return "DW_AT_calling_convention";
106179187Sjb	case DW_AT_common_reference:
107179187Sjb		return "DW_AT_common_reference";
108179187Sjb	case DW_AT_comp_dir:
109179187Sjb		return "DW_AT_comp_dir";
110179187Sjb	case DW_AT_const_value:
111179187Sjb		return "DW_AT_const_value";
112179187Sjb	case DW_AT_containing_type:
113179187Sjb		return "DW_AT_containing_type";
114179187Sjb	case DW_AT_count:
115179187Sjb		return "DW_AT_count";
116179187Sjb	case DW_AT_data_member_location:
117179187Sjb		return "DW_AT_data_member_location";
118179187Sjb	case DW_AT_decl_column:
119179187Sjb		return "DW_AT_decl_column";
120179187Sjb	case DW_AT_decl_file:
121179187Sjb		return "DW_AT_decl_file";
122179187Sjb	case DW_AT_decl_line:
123179187Sjb		return "DW_AT_decl_line";
124179187Sjb	case DW_AT_declaration:
125179187Sjb		return "DW_AT_declaration";
126179187Sjb	case DW_AT_default_value:
127179187Sjb		return "DW_AT_default_value";
128179187Sjb	case DW_AT_discr:
129179187Sjb		return "DW_AT_discr";
130179187Sjb	case DW_AT_discr_list:
131179187Sjb		return "DW_AT_discr_list";
132179187Sjb	case DW_AT_discr_value:
133179187Sjb		return "DW_AT_discr_value";
134179187Sjb	case DW_AT_element_list:
135179187Sjb		return "DW_AT_element_list";
136179187Sjb	case DW_AT_encoding:
137179187Sjb		return "DW_AT_encoding";
138179187Sjb	case DW_AT_external:
139179187Sjb		return "DW_AT_external";
140179187Sjb	case DW_AT_frame_base:
141179187Sjb		return "DW_AT_frame_base";
142179187Sjb	case DW_AT_friend:
143179187Sjb		return "DW_AT_friend";
144179187Sjb	case DW_AT_high_pc:
145179187Sjb		return "DW_AT_high_pc";
146179187Sjb	case DW_AT_identifier_case:
147179187Sjb		return "DW_AT_identifier_case";
148179187Sjb	case DW_AT_import:
149179187Sjb		return "DW_AT_import";
150179187Sjb	case DW_AT_inline:
151179187Sjb		return "DW_AT_inline";
152179187Sjb	case DW_AT_is_optional:
153179187Sjb		return "DW_AT_is_optional";
154179187Sjb	case DW_AT_language:
155179187Sjb		return "DW_AT_language";
156179187Sjb	case DW_AT_location:
157179187Sjb		return "DW_AT_location";
158179187Sjb	case DW_AT_low_pc:
159179187Sjb		return "DW_AT_low_pc";
160179187Sjb	case DW_AT_lower_bound:
161179187Sjb		return "DW_AT_lower_bound";
162179187Sjb	case DW_AT_macro_info:
163179187Sjb		return "DW_AT_macro_info";
164179187Sjb	case DW_AT_member:
165179187Sjb		return "DW_AT_member";
166179187Sjb	case DW_AT_name:
167179187Sjb		return "DW_AT_name";
168179187Sjb	case DW_AT_namelist_item:
169179187Sjb		return "DW_AT_namelist_item";
170179187Sjb	case DW_AT_ordering:
171179187Sjb		return "DW_AT_ordering";
172179187Sjb	case DW_AT_priority:
173179187Sjb		return "DW_AT_priority";
174179187Sjb	case DW_AT_producer:
175179187Sjb		return "DW_AT_producer";
176179187Sjb	case DW_AT_prototyped:
177179187Sjb		return "DW_AT_prototyped";
178179187Sjb	case DW_AT_return_addr:
179179187Sjb		return "DW_AT_return_addr";
180179187Sjb	case DW_AT_segment:
181179187Sjb		return "DW_AT_segment";
182179187Sjb	case DW_AT_sibling:
183179187Sjb		return "DW_AT_sibling";
184179187Sjb	case DW_AT_specification:
185179187Sjb		return "DW_AT_specification";
186179187Sjb	case DW_AT_start_scope:
187179187Sjb		return "DW_AT_start_scope";
188179187Sjb	case DW_AT_static_link:
189179187Sjb		return "DW_AT_static_link";
190179187Sjb	case DW_AT_stmt_list:
191179187Sjb		return "DW_AT_stmt_list";
192179187Sjb	case DW_AT_stride_size:
193179187Sjb		return "DW_AT_stride_size";
194179187Sjb	case DW_AT_string_length:
195179187Sjb		return "DW_AT_string_length";
196179187Sjb	case DW_AT_subscr_data:
197179187Sjb		return "DW_AT_subscr_data";
198179187Sjb	case DW_AT_type:
199179187Sjb		return "DW_AT_type";
200179187Sjb	case DW_AT_upper_bound:
201179187Sjb		return "DW_AT_upper_bound";
202179187Sjb	case DW_AT_use_location:
203179187Sjb		return "DW_AT_use_location";
204179187Sjb	case DW_AT_variable_parameter:
205179187Sjb		return "DW_AT_variable_parameter";
206179187Sjb	case DW_AT_virtuality:
207179187Sjb		return "DW_AT_virtuality";
208179187Sjb	case DW_AT_visibility:
209179187Sjb		return "DW_AT_visibility";
210179187Sjb	case DW_AT_vtable_elem_location:
211179187Sjb		return "DW_AT_vtable_elem_location";
212179187Sjb	default:
213179187Sjb		break;
214179187Sjb	}
215179187Sjb
216179187Sjb	return "Unknown attribute";
217179187Sjb}
218179187Sjb
219179187Sjbconst char *
220179187Sjbget_form_desc(uint32_t form)
221179187Sjb{
222179187Sjb	switch (form) {
223179187Sjb	case DW_FORM_addr:
224179187Sjb		return "DW_FORM_addr";
225179187Sjb	case DW_FORM_block:
226179187Sjb		return "DW_FORM_block";
227179187Sjb	case DW_FORM_block1:
228179187Sjb		return "DW_FORM_block1";
229179187Sjb	case DW_FORM_block2:
230179187Sjb		return "DW_FORM_block2";
231179187Sjb	case DW_FORM_block4:
232179187Sjb		return "DW_FORM_block4";
233179187Sjb	case DW_FORM_data1:
234179187Sjb		return "DW_FORM_data1";
235179187Sjb	case DW_FORM_data2:
236179187Sjb		return "DW_FORM_data2";
237179187Sjb	case DW_FORM_data4:
238179187Sjb		return "DW_FORM_data4";
239179187Sjb	case DW_FORM_data8:
240179187Sjb		return "DW_FORM_data8";
241179187Sjb	case DW_FORM_flag:
242179187Sjb		return "DW_FORM_flag";
243239872Sdim	case DW_FORM_flag_present:
244239872Sdim		return "DW_FORM_flag_present";
245179187Sjb	case DW_FORM_indirect:
246179187Sjb		return "DW_FORM_indirect";
247179187Sjb	case DW_FORM_ref1:
248179187Sjb		return "DW_FORM_ref1";
249179187Sjb	case DW_FORM_ref2:
250179187Sjb		return "DW_FORM_ref2";
251179187Sjb	case DW_FORM_ref4:
252179187Sjb		return "DW_FORM_ref4";
253179187Sjb	case DW_FORM_ref8:
254179187Sjb		return "DW_FORM_ref8";
255179187Sjb	case DW_FORM_ref_addr:
256179187Sjb		return "DW_FORM_ref_addr";
257179187Sjb	case DW_FORM_ref_udata:
258179187Sjb		return "DW_FORM_ref_udata";
259179187Sjb	case DW_FORM_sdata:
260179187Sjb		return "DW_FORM_sdata";
261179187Sjb	case DW_FORM_string:
262179187Sjb		return "DW_FORM_string";
263179187Sjb	case DW_FORM_strp:
264179187Sjb		return "DW_FORM_strp";
265179187Sjb	case DW_FORM_udata:
266179187Sjb		return "DW_FORM_udata";
267179187Sjb	default:
268179187Sjb		break;
269179187Sjb	}
270179187Sjb
271179187Sjb	return "Unknown attribute";
272179187Sjb}
273179187Sjb
274179187Sjbconst char *
275179187Sjbget_tag_desc(uint32_t tag)
276179187Sjb{
277179187Sjb	switch (tag) {
278179187Sjb	case DW_TAG_access_declaration:
279179187Sjb		return "DW_TAG_access_declaration";
280179187Sjb	case DW_TAG_array_type:
281179187Sjb		return "DW_TAG_array_type";
282179187Sjb	case DW_TAG_base_type:
283179187Sjb		return "DW_TAG_base_type";
284179187Sjb	case DW_TAG_catch_block:
285179187Sjb		return "DW_TAG_catch_block";
286179187Sjb	case DW_TAG_class_type:
287179187Sjb		return "DW_TAG_class_type";
288179187Sjb	case DW_TAG_common_block:
289179187Sjb		return "DW_TAG_common_block";
290179187Sjb	case DW_TAG_common_inclusion:
291179187Sjb		return "DW_TAG_common_inclusion";
292179187Sjb	case DW_TAG_compile_unit:
293179187Sjb		return "DW_TAG_compile_unit";
294179187Sjb	case DW_TAG_condition:
295179187Sjb		return "DW_TAG_condition";
296179187Sjb	case DW_TAG_const_type:
297179187Sjb		return "DW_TAG_const_type";
298179187Sjb	case DW_TAG_constant:
299179187Sjb		return "DW_TAG_constant";
300179187Sjb	case DW_TAG_dwarf_procedure:
301179187Sjb		return "DW_TAG_dwarf_procedure";
302179187Sjb	case DW_TAG_entry_point:
303179187Sjb		return "DW_TAG_entry_point";
304179187Sjb	case DW_TAG_enumeration_type:
305179187Sjb		return "DW_TAG_enumeration_type";
306179187Sjb	case DW_TAG_enumerator:
307179187Sjb		return "DW_TAG_enumerator";
308179187Sjb	case DW_TAG_formal_parameter:
309179187Sjb		return "DW_TAG_formal_parameter";
310179187Sjb	case DW_TAG_friend:
311179187Sjb		return "DW_TAG_friend";
312179187Sjb	case DW_TAG_imported_declaration:
313179187Sjb		return "DW_TAG_imported_declaration";
314179187Sjb	case DW_TAG_imported_module:
315179187Sjb		return "DW_TAG_imported_module";
316179187Sjb	case DW_TAG_imported_unit:
317179187Sjb		return "DW_TAG_imported_unit";
318179187Sjb	case DW_TAG_inheritance:
319179187Sjb		return "DW_TAG_inheritance";
320179187Sjb	case DW_TAG_inlined_subroutine:
321179187Sjb		return "DW_TAG_inlined_subroutine";
322179187Sjb	case DW_TAG_interface_type:
323179187Sjb		return "DW_TAG_interface_type";
324179187Sjb	case DW_TAG_label:
325179187Sjb		return "DW_TAG_label";
326179187Sjb	case DW_TAG_lexical_block:
327179187Sjb		return "DW_TAG_lexical_block";
328179187Sjb	case DW_TAG_member:
329179187Sjb		return "DW_TAG_member";
330179187Sjb	case DW_TAG_module:
331179187Sjb		return "DW_TAG_module";
332179187Sjb	case DW_TAG_namelist:
333179187Sjb		return "DW_TAG_namelist";
334179187Sjb	case DW_TAG_namelist_item:
335179187Sjb		return "DW_TAG_namelist_item";
336179187Sjb	case DW_TAG_namespace:
337179187Sjb		return "DW_TAG_namespace";
338179187Sjb	case DW_TAG_packed_type:
339179187Sjb		return "DW_TAG_packed_type";
340179187Sjb	case DW_TAG_partial_unit:
341179187Sjb		return "DW_TAG_partial_unit";
342179187Sjb	case DW_TAG_pointer_type:
343179187Sjb		return "DW_TAG_pointer_type";
344179187Sjb	case DW_TAG_ptr_to_member_type:
345179187Sjb		return "DW_TAG_ptr_to_member_type";
346179187Sjb	case DW_TAG_reference_type:
347179187Sjb		return "DW_TAG_reference_type";
348179187Sjb	case DW_TAG_restrict_type:
349179187Sjb		return "DW_TAG_restrict_type";
350179187Sjb	case DW_TAG_set_type:
351179187Sjb		return "DW_TAG_set_type";
352179187Sjb	case DW_TAG_shared_type:
353179187Sjb		return "DW_TAG_shared_type";
354179187Sjb	case DW_TAG_string_type:
355179187Sjb		return "DW_TAG_string_type";
356179187Sjb	case DW_TAG_structure_type:
357179187Sjb		return "DW_TAG_structure_type";
358179187Sjb	case DW_TAG_subprogram:
359179187Sjb		return "DW_TAG_subprogram";
360179187Sjb	case DW_TAG_subrange_type:
361179187Sjb		return "DW_TAG_subrange_type";
362179187Sjb	case DW_TAG_subroutine_type:
363179187Sjb		return "DW_TAG_subroutine_type";
364179187Sjb	case DW_TAG_template_type_parameter:
365179187Sjb		return "DW_TAG_template_type_parameter";
366179187Sjb	case DW_TAG_template_value_parameter:
367179187Sjb		return "DW_TAG_template_value_parameter";
368179187Sjb	case DW_TAG_thrown_type:
369179187Sjb		return "DW_TAG_thrown_type";
370179187Sjb	case DW_TAG_try_block:
371179187Sjb		return "DW_TAG_try_block";
372179187Sjb	case DW_TAG_typedef:
373179187Sjb		return "DW_TAG_typedef";
374179187Sjb	case DW_TAG_union_type:
375179187Sjb		return "DW_TAG_union_type";
376179187Sjb	case DW_TAG_unspecified_parameters:
377179187Sjb		return "DW_TAG_unspecified_parameters";
378179187Sjb	case DW_TAG_unspecified_type:
379179187Sjb		return "DW_TAG_unspecified_type";
380179187Sjb	case DW_TAG_variable:
381179187Sjb		return "DW_TAG_variable";
382179187Sjb	case DW_TAG_variant:
383179187Sjb		return "DW_TAG_variant";
384179187Sjb	case DW_TAG_variant_part:
385179187Sjb		return "DW_TAG_variant_part";
386179187Sjb	case DW_TAG_volatile_type:
387179187Sjb		return "DW_TAG_volatile_type";
388179187Sjb	case DW_TAG_with_stmt:
389179187Sjb		return "DW_TAG_with_stmt";
390179187Sjb	default:
391179187Sjb		break;
392179187Sjb	}
393179187Sjb
394179187Sjb	return "Unknown tag";
395179187Sjb}
396179187Sjb
397179187Sjbvoid
398179187Sjbdwarf_dump_abbrev(Dwarf_Debug dbg)
399179187Sjb{
400179187Sjb	Dwarf_Abbrev a;
401179187Sjb	Dwarf_Attribute at;
402179187Sjb	Dwarf_CU cu;
403179187Sjb
404179187Sjb	printf("Contents of the .debug_abbrev section:\n\nEntry Tag\n");
405179187Sjb
406179187Sjb	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
407179187Sjb		STAILQ_FOREACH(a, &cu->cu_abbrev, a_next) {
408179187Sjb			printf("%5lu %-30s [%s children]\n",
409179187Sjb			    (u_long) a->a_entry, get_tag_desc(a->a_tag),
410179187Sjb			    (a->a_children == DW_CHILDREN_yes) ? "has" : "no");
411179187Sjb
412179187Sjb			STAILQ_FOREACH(at, &a->a_attrib, at_next)
413179187Sjb				printf("      %-30s %s\n", get_attr_desc(at->at_attrib),
414179187Sjb				    get_form_desc(at->at_form));
415179187Sjb		}
416179187Sjb	}
417179187Sjb}
418179187Sjb#ifdef DOODAD
419179187Sjb    case DW_AT_inline:
420179187Sjb      switch (uvalue)
421179187Sjb	{
422179187Sjb	case DW_INL_not_inlined:
423179187Sjb	  printf (_("(not inlined)"));
424179187Sjb	  break;
425179187Sjb	case DW_INL_inlined:
426179187Sjb	  printf (_("(inlined)"));
427179187Sjb	  break;
428179187Sjb	case DW_INL_declared_not_inlined:
429179187Sjb	  printf (_("(declared as inline but ignored)"));
430179187Sjb	  break;
431179187Sjb	case DW_INL_declared_inlined:
432179187Sjb	  printf (_("(declared as inline and inlined)"));
433179187Sjb	  break;
434179187Sjb	default:
435179187Sjb	  printf (_("  (Unknown inline attribute value: %lx)"), uvalue);
436179187Sjb	  break;
437179187Sjb	}
438179187Sjb      break;
439179187Sjb
440179187Sjb    case DW_AT_language:
441179187Sjb      switch (uvalue)
442179187Sjb	{
443179187Sjb	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
444179187Sjb	case DW_LANG_C89:		printf ("(ANSI C)"); break;
445179187Sjb	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
446179187Sjb	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
447179187Sjb	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
448179187Sjb	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
449179187Sjb	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
450179187Sjb	case DW_LANG_Ada83:		printf ("(Ada)"); break;
451179187Sjb	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
452179187Sjb	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
453179187Sjb	  /* DWARF 2.1 values.	*/
454179187Sjb	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
455179187Sjb	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
456179187Sjb	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
457179187Sjb	  /* MIPS extension.  */
458179187Sjb	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
459179187Sjb	  /* UPC extension.  */
460179187Sjb	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
461179187Sjb	default:
462179187Sjb	  printf ("(Unknown: %lx)", uvalue);
463179187Sjb	  break;
464179187Sjb	}
465179187Sjb      break;
466179187Sjb
467179187Sjb    case DW_AT_encoding:
468179187Sjb      switch (uvalue)
469179187Sjb	{
470179187Sjb	case DW_ATE_void:		printf ("(void)"); break;
471179187Sjb	case DW_ATE_address:		printf ("(machine address)"); break;
472179187Sjb	case DW_ATE_boolean:		printf ("(boolean)"); break;
473179187Sjb	case DW_ATE_complex_float:	printf ("(complex float)"); break;
474179187Sjb	case DW_ATE_float:		printf ("(float)"); break;
475179187Sjb	case DW_ATE_signed:		printf ("(signed)"); break;
476179187Sjb	case DW_ATE_signed_char:	printf ("(signed char)"); break;
477179187Sjb	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
478179187Sjb	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
479179187Sjb	  /* DWARF 2.1 value.  */
480179187Sjb	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
481179187Sjb	default:
482179187Sjb	  if (uvalue >= DW_ATE_lo_user
483179187Sjb	      && uvalue <= DW_ATE_hi_user)
484179187Sjb	    printf ("(user defined type)");
485179187Sjb	  else
486179187Sjb	    printf ("(unknown type)");
487179187Sjb	  break;
488179187Sjb	}
489179187Sjb      break;
490179187Sjb
491179187Sjb    case DW_AT_accessibility:
492179187Sjb      switch (uvalue)
493179187Sjb	{
494179187Sjb	case DW_ACCESS_public:		printf ("(public)"); break;
495179187Sjb	case DW_ACCESS_protected:	printf ("(protected)"); break;
496179187Sjb	case DW_ACCESS_private:		printf ("(private)"); break;
497179187Sjb	default:
498179187Sjb	  printf ("(unknown accessibility)");
499179187Sjb	  break;
500179187Sjb	}
501179187Sjb      break;
502179187Sjb
503179187Sjb    case DW_AT_visibility:
504179187Sjb      switch (uvalue)
505179187Sjb	{
506179187Sjb	case DW_VIS_local:		printf ("(local)"); break;
507179187Sjb	case DW_VIS_exported:		printf ("(exported)"); break;
508179187Sjb	case DW_VIS_qualified:		printf ("(qualified)"); break;
509179187Sjb	default:			printf ("(unknown visibility)"); break;
510179187Sjb	}
511179187Sjb      break;
512179187Sjb
513179187Sjb    case DW_AT_virtuality:
514179187Sjb      switch (uvalue)
515179187Sjb	{
516179187Sjb	case DW_VIRTUALITY_none:	printf ("(none)"); break;
517179187Sjb	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
518179187Sjb	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
519179187Sjb	default:			printf ("(unknown virtuality)"); break;
520179187Sjb	}
521179187Sjb      break;
522179187Sjb
523179187Sjb    case DW_AT_identifier_case:
524179187Sjb      switch (uvalue)
525179187Sjb	{
526179187Sjb	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
527179187Sjb	case DW_ID_up_case:		printf ("(up_case)"); break;
528179187Sjb	case DW_ID_down_case:		printf ("(down_case)"); break;
529179187Sjb	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
530179187Sjb	default:			printf ("(unknown case)"); break;
531179187Sjb	}
532179187Sjb      break;
533179187Sjb
534179187Sjb    case DW_AT_calling_convention:
535179187Sjb      switch (uvalue)
536179187Sjb	{
537179187Sjb	case DW_CC_normal:	printf ("(normal)"); break;
538179187Sjb	case DW_CC_program:	printf ("(program)"); break;
539179187Sjb	case DW_CC_nocall:	printf ("(nocall)"); break;
540179187Sjb	default:
541179187Sjb	  if (uvalue >= DW_CC_lo_user
542179187Sjb	      && uvalue <= DW_CC_hi_user)
543179187Sjb	    printf ("(user defined)");
544179187Sjb	  else
545179187Sjb	    printf ("(unknown convention)");
546179187Sjb	}
547179187Sjb      break;
548179187Sjb
549179187Sjb    case DW_AT_ordering:
550179187Sjb      switch (uvalue)
551179187Sjb	{
552179187Sjb	case -1: printf ("(undefined)"); break;
553179187Sjb	case 0:  printf ("(row major)"); break;
554179187Sjb	case 1:  printf ("(column major)"); break;
555179187Sjb	}
556179187Sjb      break;
557179187Sjb
558179187Sjb    case DW_AT_frame_base:
559179187Sjb    case DW_AT_location:
560179187Sjb    case DW_AT_data_member_location:
561179187Sjb    case DW_AT_vtable_elem_location:
562179187Sjb    case DW_AT_allocated:
563179187Sjb    case DW_AT_associated:
564179187Sjb    case DW_AT_data_location:
565179187Sjb    case DW_AT_stride:
566179187Sjb    case DW_AT_upper_bound:
567179187Sjb    case DW_AT_lower_bound:
568179187Sjb      if (block_start)
569179187Sjb	{
570179187Sjb	  printf ("(");
571179187Sjb	  decode_location_expression (block_start, pointer_size, uvalue);
572179187Sjb	  printf (")");
573179187Sjb	}
574179187Sjb      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
575179187Sjb	{
576179187Sjb	  printf ("(");
577179187Sjb	  printf ("location list");
578179187Sjb	  printf (")");
579179187Sjb	}
580179187Sjb      break;
581179187Sjb#endif
582179187Sjb
583179187Sjbstatic void
584179187Sjbdwarf_dump_av_attr(Dwarf_Die die __unused, Dwarf_AttrValue av)
585179187Sjb{
586179187Sjb	switch (av->av_attrib) {
587179187Sjb	case DW_AT_accessibility:
588179187Sjb		break;
589179187Sjb
590179187Sjb	case DW_AT_calling_convention:
591179187Sjb		break;
592179187Sjb
593179187Sjb	case DW_AT_encoding:
594179187Sjb		break;
595179187Sjb
596179187Sjb	case DW_AT_identifier_case:
597179187Sjb		break;
598179187Sjb
599179187Sjb	case DW_AT_inline:
600179187Sjb		break;
601179187Sjb
602179187Sjb	case DW_AT_language:
603179187Sjb		break;
604179187Sjb
605179187Sjb	case DW_AT_ordering:
606179187Sjb		break;
607179187Sjb
608179187Sjb	case DW_AT_virtuality:
609179187Sjb		break;
610179187Sjb
611179187Sjb	case DW_AT_visibility:
612179187Sjb		break;
613179187Sjb
614179187Sjb	case DW_AT_frame_base:
615179187Sjb	case DW_AT_location:
616179187Sjb	case DW_AT_data_member_location:
617179187Sjb	case DW_AT_vtable_elem_location:
618179187Sjb	case DW_AT_upper_bound:
619179187Sjb	case DW_AT_lower_bound:
620179187Sjb		break;
621179187Sjb
622179187Sjb	default:
623179187Sjb		break;
624179187Sjb	}
625179187Sjb}
626179187Sjb
627179187Sjbvoid
628179187Sjbdwarf_dump_av(Dwarf_Die die, Dwarf_AttrValue av)
629179187Sjb{
630179187Sjb	uint64_t i;
631179187Sjb
632179187Sjb	printf("      %-30s : %-16s ",
633179187Sjb	    get_attr_desc(av->av_attrib),
634179187Sjb	    get_form_desc(av->av_form));
635179187Sjb
636179187Sjb	switch (av->av_form) {
637179187Sjb	case DW_FORM_addr:
638179187Sjb		printf("0x%llx", (unsigned long long) av->u[0].u64);
639179187Sjb		break;
640179187Sjb	case DW_FORM_block:
641179187Sjb	case DW_FORM_block1:
642179187Sjb	case DW_FORM_block2:
643179187Sjb	case DW_FORM_block4:
644179187Sjb		printf("%lu byte block:", (u_long) av->u[0].u64);
645179187Sjb		for (i = 0; i < av->u[0].u64; i++)
646179187Sjb			printf(" %02x", av->u[1].u8p[i]);
647179187Sjb		break;
648179187Sjb	case DW_FORM_data1:
649179187Sjb	case DW_FORM_data2:
650179187Sjb	case DW_FORM_data4:
651179187Sjb	case DW_FORM_data8:
652179187Sjb	case DW_FORM_flag:
653239872Sdim	case DW_FORM_flag_present:
654179187Sjb		printf("%llu", (unsigned long long) av->u[0].u64);
655179187Sjb		break;
656179187Sjb	case DW_FORM_ref1:
657179187Sjb	case DW_FORM_ref2:
658179187Sjb	case DW_FORM_ref4:
659179187Sjb	case DW_FORM_ref8:
660179187Sjb	case DW_FORM_ref_udata:
661179187Sjb		printf("<%llx>", (unsigned long long) (av->u[0].u64 +
662179187Sjb		    die->die_cu->cu_offset));
663179187Sjb		break;
664179187Sjb	case DW_FORM_string:
665179187Sjb		printf("%s", av->u[0].s);
666179187Sjb		break;
667179187Sjb	case DW_FORM_strp:
668179187Sjb		printf("(indirect string, offset 0x%llx): %s",
669179187Sjb		    (unsigned long long) av->u[0].u64, av->u[1].s);
670179187Sjb		break;
671179187Sjb	default:
672179187Sjb		printf("unknown form");
673179187Sjb		break;
674179187Sjb	}
675179187Sjb
676179187Sjb	/* Dump any extra attribute-specific information. */
677179187Sjb	dwarf_dump_av_attr(die, av);
678179187Sjb
679179187Sjb	printf("\n");
680179187Sjb}
681179187Sjb
682179187Sjbvoid
683179187Sjbdwarf_dump_die_at_offset(Dwarf_Debug dbg, Dwarf_Off off)
684179187Sjb{
685179187Sjb	Dwarf_CU cu;
686179187Sjb	Dwarf_Die die;
687179187Sjb
688179187Sjb	if (dbg == NULL)
689179187Sjb		return;
690179187Sjb
691179187Sjb	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
692179187Sjb		STAILQ_FOREACH(die, &cu->cu_die, die_next) {
693179187Sjb			if ((off_t) die->die_offset == off) {
694179187Sjb				dwarf_dump_die(die);
695179187Sjb				return;
696179187Sjb			}
697179187Sjb		}
698179187Sjb	}
699179187Sjb}
700179187Sjb
701179187Sjbvoid
702179187Sjbdwarf_dump_die(Dwarf_Die die)
703179187Sjb{
704179187Sjb	Dwarf_AttrValue av;
705179187Sjb
706179187Sjb	printf("<%d><%llx>: Abbrev number: %llu (%s)\n",
707179187Sjb	    die->die_level, (unsigned long long) die->die_offset,
708179187Sjb	    (unsigned long long) die->die_abnum,
709179187Sjb	    get_tag_desc(die->die_a->a_tag));
710179187Sjb
711179187Sjb	STAILQ_FOREACH(av, &die->die_attrval, av_next)
712179187Sjb		dwarf_dump_av(die, av);
713179187Sjb}
714179187Sjb
715179187Sjbvoid
716179187Sjbdwarf_dump_raw(Dwarf_Debug dbg)
717179187Sjb{
718179187Sjb	Dwarf_CU cu;
719179187Sjb	char *p = (char *) dbg;
720179187Sjb	int i;
721179187Sjb
722179187Sjb	printf("dbg %p\n",dbg);
723179187Sjb
724179187Sjb	if (dbg == NULL)
725179187Sjb		return;
726179187Sjb
727179187Sjb	for (i = 0; i < (int) sizeof(*dbg); i++) {
728179187Sjb		if (*p >= 0x20 && *p < 0x7f) {
729179187Sjb			printf(" %c",*p++ & 0xff);
730179187Sjb		} else {
731179187Sjb			printf(" %02x",*p++ & 0xff);
732179187Sjb		}
733179187Sjb	}
734179187Sjb	printf("\n");
735179187Sjb
736179187Sjb	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
737179187Sjb		p = (char *) cu;
738179187Sjb		printf("cu %p\n",cu);
739179187Sjb		for (i = 0; i < (int) sizeof(*cu); i++) {
740179187Sjb			if (*p >= 0x20 && *p < 0x7f) {
741179187Sjb				printf(" %c",*p++ & 0xff);
742179187Sjb			} else {
743179187Sjb				printf(" %02x",*p++ & 0xff);
744179187Sjb			}
745179187Sjb		}
746179187Sjb		printf("\n");
747179187Sjb	}
748179187Sjb}
749179187Sjb
750179187Sjbstatic void
751179187Sjbdwarf_dump_tree_dies(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Error *error)
752179187Sjb{
753179187Sjb	Dwarf_Die child;
754179187Sjb	int ret;
755179187Sjb
756179187Sjb	do {
757179187Sjb		dwarf_dump_die(die);
758179187Sjb
759179187Sjb		if ((ret = dwarf_child(die, &child, error) == DWARF_E_NO_ENTRY)) {
760179187Sjb			/* No children. */
761179187Sjb		} else if (ret != DWARF_E_NONE) {
762179187Sjb			printf("Error %s\n", dwarf_errmsg(error));
763179187Sjb			return;
764179187Sjb		} else
765179187Sjb			dwarf_dump_tree_dies(dbg, child, error);
766179187Sjb
767179187Sjb		if (dwarf_siblingof(dbg, die, &die, error) != DWARF_E_NONE)
768179187Sjb			die = NULL;
769179187Sjb
770179187Sjb	} while (die != NULL);
771179187Sjb}
772179187Sjb
773179187Sjbvoid
774179187Sjbdwarf_dump_tree(Dwarf_Debug dbg)
775179187Sjb{
776179187Sjb	Dwarf_CU cu;
777179187Sjb	Dwarf_Die die;
778179187Sjb	Dwarf_Error error;
779179187Sjb	Dwarf_Half cu_pointer_size;
780179187Sjb	Dwarf_Half cu_version;
781179187Sjb	Dwarf_Unsigned cu_abbrev_offset;
782179187Sjb	Dwarf_Unsigned cu_header_length;
783179187Sjb	Dwarf_Unsigned cu_next_offset;
784179187Sjb
785179187Sjb	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
786179187Sjb		printf ("\nCompilation Unit @ offset %llx:\n",
787179187Sjb		    (unsigned long long) cu->cu_offset);
788179187Sjb		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
789179187Sjb		printf ("    Version:         %hu\n", cu->cu_version);
790179187Sjb		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
791179187Sjb		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
792179187Sjb
793179187Sjb		if (dwarf_next_cu_header(dbg, &cu_header_length,
794179187Sjb		    &cu_version, &cu_abbrev_offset, &cu_pointer_size,
795179187Sjb		    &cu_next_offset, &error) != DWARF_E_NONE) {
796179187Sjb			printf("Error %s\n", dwarf_errmsg(&error));
797179187Sjb			return;
798179187Sjb		}
799179187Sjb
800179187Sjb		if (dwarf_siblingof(dbg, NULL, &die, &error) != DWARF_E_NONE) {
801179187Sjb			printf("Error %s\n", dwarf_errmsg(&error));
802179187Sjb			return;
803179187Sjb		}
804179187Sjb
805179187Sjb		dwarf_dump_tree_dies(dbg, die, &error);
806179187Sjb
807179187Sjb	}
808179187Sjb}
809179187Sjb
810179187Sjbvoid
811179187Sjbdwarf_dump_info(Dwarf_Debug dbg)
812179187Sjb{
813179187Sjb	Dwarf_CU cu;
814179187Sjb	Dwarf_Die die;
815179187Sjb
816179187Sjb	printf("Contents of the .debug_info section:\n");
817179187Sjb
818179187Sjb	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
819179187Sjb		printf ("\nCompilation Unit @ offset %llx:\n",
820179187Sjb		    (unsigned long long) cu->cu_offset);
821179187Sjb		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
822179187Sjb		printf ("    Version:         %hu\n", cu->cu_version);
823179187Sjb		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
824179187Sjb		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
825179187Sjb
826179187Sjb		STAILQ_FOREACH(die, &cu->cu_die, die_next)
827179187Sjb			dwarf_dump_die(die);
828179187Sjb	}
829179187Sjb}
830179187Sjb
831179187Sjb
832179187Sjbvoid
833179187Sjbdwarf_dump_shstrtab(Dwarf_Debug dbg)
834179187Sjb{
835179187Sjb	char *name;
836179187Sjb	int indx = 0;
837179187Sjb
838179187Sjb	printf("---------------------\nSection header string table contents:\n");
839179187Sjb	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, indx)) != NULL) {
840179187Sjb		printf("%5d '%s'\n",indx,name);
841179187Sjb		indx += strlen(name) + 1;
842179187Sjb	}
843179187Sjb}
844179187Sjb
845179187Sjbvoid
846179187Sjbdwarf_dump_strtab(Dwarf_Debug dbg)
847179187Sjb{
848179187Sjb	char *name;
849179187Sjb	int indx = 0;
850179187Sjb
851179187Sjb	printf("---------------------\nString table contents:\n");
852179187Sjb	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, indx)) != NULL) {
853179187Sjb		printf("%5d '%s'\n",indx,name);
854179187Sjb		indx += strlen(name) + 1;
855179187Sjb	}
856179187Sjb}
857179187Sjb
858179187Sjbvoid
859179187Sjbdwarf_dump_dbgstr(Dwarf_Debug dbg)
860179187Sjb{
861179187Sjb	char *name;
862179187Sjb	int indx = 0;
863179187Sjb
864179187Sjb	printf("---------------------\nDebug string table contents:\n");
865179187Sjb	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_debug_str].s_shnum, indx)) != NULL) {
866179187Sjb		printf("%5d '%s'\n",indx,name);
867179187Sjb		indx += strlen(name) + 1;
868179187Sjb	}
869179187Sjb}
870179187Sjb
871179187Sjbvoid
872179187Sjbdwarf_dump_symtab(Dwarf_Debug dbg)
873179187Sjb{
874179187Sjb	GElf_Sym sym;
875179187Sjb	char *name;
876179187Sjb	int indx = 0;
877179187Sjb
878179187Sjb	printf("---------------------\nSymbol table contents:\n");
879179187Sjb	while (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data,  indx++, &sym) != NULL) {
880179187Sjb		if ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, sym.st_name)) == NULL)
881179187Sjb			printf("sym.st_name %u indx %d sym.st_size %lu\n",sym.st_name,indx,(u_long) sym.st_size);
882179187Sjb		else
883179187Sjb			printf("'%s' sym.st_name %u indx %d sym.st_size %lu\n",name,sym.st_name,indx,(u_long) sym.st_size);
884179187Sjb	}
885179187Sjb}
886179187Sjb
887179187Sjbvoid
888179187Sjbdwarf_dump(Dwarf_Debug dbg)
889179187Sjb{
890179187Sjb	dwarf_dump_strtab(dbg);
891179187Sjb	dwarf_dump_shstrtab(dbg);
892179187Sjb	dwarf_dump_dbgstr(dbg);
893179187Sjb	dwarf_dump_symtab(dbg);
894179187Sjb	dwarf_dump_info(dbg);
895179187Sjb}
896