1/*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <stdlib.h>
30#include <string.h>
31#include "_libdwarf.h"
32
33const char *
34get_sht_desc(uint32_t sh_type)
35{
36	switch (sh_type) {
37	case SHT_NULL:
38		return "inactive";
39	case SHT_PROGBITS:
40		return "program defined information";
41	case SHT_SYMTAB:
42		return "symbol table section";
43	case SHT_STRTAB:
44		return "string table section";
45	case SHT_RELA:
46		return "relocation section with addends";
47	case SHT_HASH:
48		return "symbol hash table section";
49	case SHT_DYNAMIC:
50		return "dynamic section";
51	case SHT_NOTE:
52		return "note section";
53	case SHT_NOBITS:
54		return "no space section";
55	case SHT_REL:
56		return "relocation section - no addends";
57	case SHT_SHLIB:
58		return "reserved - purpose unknown";
59	case SHT_DYNSYM:
60		return "dynamic symbol table section";
61	case SHT_INIT_ARRAY:
62		return "Initialization function pointers.";
63	case SHT_FINI_ARRAY:
64		return "Termination function pointers.";
65	case SHT_PREINIT_ARRAY:
66		return "Pre-initialization function ptrs.";
67	case SHT_GROUP:
68		return "Section group.";
69	case SHT_SYMTAB_SHNDX:
70		return "Section indexes (see SHN_XINDEX).";
71	case SHT_GNU_verdef:
72		return "Symbol versions provided";
73	case SHT_GNU_verneed:
74		return "Symbol versions required";
75	case SHT_GNU_versym:
76		return "Symbol version table";
77	case SHT_AMD64_UNWIND:
78		return "AMD64 unwind";
79	default:
80		return "Unknown";
81	}
82}
83
84const char *
85get_attr_desc(uint32_t attr)
86{
87	switch (attr) {
88	case DW_AT_abstract_origin:
89		return "DW_AT_abstract_origin";
90	case DW_AT_accessibility:
91		return "DW_AT_accessibility";
92	case DW_AT_address_class:
93		return "DW_AT_address_class";
94	case DW_AT_artificial:
95		return "DW_AT_artificial";
96	case DW_AT_base_types:
97		return "DW_AT_base_types";
98	case DW_AT_bit_offset:
99		return "DW_AT_bit_offset";
100	case DW_AT_bit_size:
101		return "DW_AT_bit_size";
102	case DW_AT_byte_size:
103		return "DW_AT_byte_size";
104	case DW_AT_calling_convention:
105		return "DW_AT_calling_convention";
106	case DW_AT_common_reference:
107		return "DW_AT_common_reference";
108	case DW_AT_comp_dir:
109		return "DW_AT_comp_dir";
110	case DW_AT_const_value:
111		return "DW_AT_const_value";
112	case DW_AT_containing_type:
113		return "DW_AT_containing_type";
114	case DW_AT_count:
115		return "DW_AT_count";
116	case DW_AT_data_member_location:
117		return "DW_AT_data_member_location";
118	case DW_AT_decl_column:
119		return "DW_AT_decl_column";
120	case DW_AT_decl_file:
121		return "DW_AT_decl_file";
122	case DW_AT_decl_line:
123		return "DW_AT_decl_line";
124	case DW_AT_declaration:
125		return "DW_AT_declaration";
126	case DW_AT_default_value:
127		return "DW_AT_default_value";
128	case DW_AT_discr:
129		return "DW_AT_discr";
130	case DW_AT_discr_list:
131		return "DW_AT_discr_list";
132	case DW_AT_discr_value:
133		return "DW_AT_discr_value";
134	case DW_AT_element_list:
135		return "DW_AT_element_list";
136	case DW_AT_encoding:
137		return "DW_AT_encoding";
138	case DW_AT_external:
139		return "DW_AT_external";
140	case DW_AT_frame_base:
141		return "DW_AT_frame_base";
142	case DW_AT_friend:
143		return "DW_AT_friend";
144	case DW_AT_high_pc:
145		return "DW_AT_high_pc";
146	case DW_AT_identifier_case:
147		return "DW_AT_identifier_case";
148	case DW_AT_import:
149		return "DW_AT_import";
150	case DW_AT_inline:
151		return "DW_AT_inline";
152	case DW_AT_is_optional:
153		return "DW_AT_is_optional";
154	case DW_AT_language:
155		return "DW_AT_language";
156	case DW_AT_location:
157		return "DW_AT_location";
158	case DW_AT_low_pc:
159		return "DW_AT_low_pc";
160	case DW_AT_lower_bound:
161		return "DW_AT_lower_bound";
162	case DW_AT_macro_info:
163		return "DW_AT_macro_info";
164	case DW_AT_member:
165		return "DW_AT_member";
166	case DW_AT_name:
167		return "DW_AT_name";
168	case DW_AT_namelist_item:
169		return "DW_AT_namelist_item";
170	case DW_AT_ordering:
171		return "DW_AT_ordering";
172	case DW_AT_priority:
173		return "DW_AT_priority";
174	case DW_AT_producer:
175		return "DW_AT_producer";
176	case DW_AT_prototyped:
177		return "DW_AT_prototyped";
178	case DW_AT_return_addr:
179		return "DW_AT_return_addr";
180	case DW_AT_segment:
181		return "DW_AT_segment";
182	case DW_AT_sibling:
183		return "DW_AT_sibling";
184	case DW_AT_specification:
185		return "DW_AT_specification";
186	case DW_AT_start_scope:
187		return "DW_AT_start_scope";
188	case DW_AT_static_link:
189		return "DW_AT_static_link";
190	case DW_AT_stmt_list:
191		return "DW_AT_stmt_list";
192	case DW_AT_stride_size:
193		return "DW_AT_stride_size";
194	case DW_AT_string_length:
195		return "DW_AT_string_length";
196	case DW_AT_subscr_data:
197		return "DW_AT_subscr_data";
198	case DW_AT_type:
199		return "DW_AT_type";
200	case DW_AT_upper_bound:
201		return "DW_AT_upper_bound";
202	case DW_AT_use_location:
203		return "DW_AT_use_location";
204	case DW_AT_variable_parameter:
205		return "DW_AT_variable_parameter";
206	case DW_AT_virtuality:
207		return "DW_AT_virtuality";
208	case DW_AT_visibility:
209		return "DW_AT_visibility";
210	case DW_AT_vtable_elem_location:
211		return "DW_AT_vtable_elem_location";
212	default:
213		break;
214	}
215
216	return "Unknown attribute";
217}
218
219const char *
220get_form_desc(uint32_t form)
221{
222	switch (form) {
223	case DW_FORM_addr:
224		return "DW_FORM_addr";
225	case DW_FORM_block:
226		return "DW_FORM_block";
227	case DW_FORM_block1:
228		return "DW_FORM_block1";
229	case DW_FORM_block2:
230		return "DW_FORM_block2";
231	case DW_FORM_block4:
232		return "DW_FORM_block4";
233	case DW_FORM_data1:
234		return "DW_FORM_data1";
235	case DW_FORM_data2:
236		return "DW_FORM_data2";
237	case DW_FORM_data4:
238		return "DW_FORM_data4";
239	case DW_FORM_data8:
240		return "DW_FORM_data8";
241	case DW_FORM_flag:
242		return "DW_FORM_flag";
243	case DW_FORM_flag_present:
244		return "DW_FORM_flag_present";
245	case DW_FORM_indirect:
246		return "DW_FORM_indirect";
247	case DW_FORM_ref1:
248		return "DW_FORM_ref1";
249	case DW_FORM_ref2:
250		return "DW_FORM_ref2";
251	case DW_FORM_ref4:
252		return "DW_FORM_ref4";
253	case DW_FORM_ref8:
254		return "DW_FORM_ref8";
255	case DW_FORM_ref_addr:
256		return "DW_FORM_ref_addr";
257	case DW_FORM_ref_udata:
258		return "DW_FORM_ref_udata";
259	case DW_FORM_sdata:
260		return "DW_FORM_sdata";
261	case DW_FORM_string:
262		return "DW_FORM_string";
263	case DW_FORM_strp:
264		return "DW_FORM_strp";
265	case DW_FORM_udata:
266		return "DW_FORM_udata";
267	default:
268		break;
269	}
270
271	return "Unknown attribute";
272}
273
274const char *
275get_tag_desc(uint32_t tag)
276{
277	switch (tag) {
278	case DW_TAG_access_declaration:
279		return "DW_TAG_access_declaration";
280	case DW_TAG_array_type:
281		return "DW_TAG_array_type";
282	case DW_TAG_base_type:
283		return "DW_TAG_base_type";
284	case DW_TAG_catch_block:
285		return "DW_TAG_catch_block";
286	case DW_TAG_class_type:
287		return "DW_TAG_class_type";
288	case DW_TAG_common_block:
289		return "DW_TAG_common_block";
290	case DW_TAG_common_inclusion:
291		return "DW_TAG_common_inclusion";
292	case DW_TAG_compile_unit:
293		return "DW_TAG_compile_unit";
294	case DW_TAG_condition:
295		return "DW_TAG_condition";
296	case DW_TAG_const_type:
297		return "DW_TAG_const_type";
298	case DW_TAG_constant:
299		return "DW_TAG_constant";
300	case DW_TAG_dwarf_procedure:
301		return "DW_TAG_dwarf_procedure";
302	case DW_TAG_entry_point:
303		return "DW_TAG_entry_point";
304	case DW_TAG_enumeration_type:
305		return "DW_TAG_enumeration_type";
306	case DW_TAG_enumerator:
307		return "DW_TAG_enumerator";
308	case DW_TAG_formal_parameter:
309		return "DW_TAG_formal_parameter";
310	case DW_TAG_friend:
311		return "DW_TAG_friend";
312	case DW_TAG_imported_declaration:
313		return "DW_TAG_imported_declaration";
314	case DW_TAG_imported_module:
315		return "DW_TAG_imported_module";
316	case DW_TAG_imported_unit:
317		return "DW_TAG_imported_unit";
318	case DW_TAG_inheritance:
319		return "DW_TAG_inheritance";
320	case DW_TAG_inlined_subroutine:
321		return "DW_TAG_inlined_subroutine";
322	case DW_TAG_interface_type:
323		return "DW_TAG_interface_type";
324	case DW_TAG_label:
325		return "DW_TAG_label";
326	case DW_TAG_lexical_block:
327		return "DW_TAG_lexical_block";
328	case DW_TAG_member:
329		return "DW_TAG_member";
330	case DW_TAG_module:
331		return "DW_TAG_module";
332	case DW_TAG_namelist:
333		return "DW_TAG_namelist";
334	case DW_TAG_namelist_item:
335		return "DW_TAG_namelist_item";
336	case DW_TAG_namespace:
337		return "DW_TAG_namespace";
338	case DW_TAG_packed_type:
339		return "DW_TAG_packed_type";
340	case DW_TAG_partial_unit:
341		return "DW_TAG_partial_unit";
342	case DW_TAG_pointer_type:
343		return "DW_TAG_pointer_type";
344	case DW_TAG_ptr_to_member_type:
345		return "DW_TAG_ptr_to_member_type";
346	case DW_TAG_reference_type:
347		return "DW_TAG_reference_type";
348	case DW_TAG_restrict_type:
349		return "DW_TAG_restrict_type";
350	case DW_TAG_set_type:
351		return "DW_TAG_set_type";
352	case DW_TAG_shared_type:
353		return "DW_TAG_shared_type";
354	case DW_TAG_string_type:
355		return "DW_TAG_string_type";
356	case DW_TAG_structure_type:
357		return "DW_TAG_structure_type";
358	case DW_TAG_subprogram:
359		return "DW_TAG_subprogram";
360	case DW_TAG_subrange_type:
361		return "DW_TAG_subrange_type";
362	case DW_TAG_subroutine_type:
363		return "DW_TAG_subroutine_type";
364	case DW_TAG_template_type_parameter:
365		return "DW_TAG_template_type_parameter";
366	case DW_TAG_template_value_parameter:
367		return "DW_TAG_template_value_parameter";
368	case DW_TAG_thrown_type:
369		return "DW_TAG_thrown_type";
370	case DW_TAG_try_block:
371		return "DW_TAG_try_block";
372	case DW_TAG_typedef:
373		return "DW_TAG_typedef";
374	case DW_TAG_union_type:
375		return "DW_TAG_union_type";
376	case DW_TAG_unspecified_parameters:
377		return "DW_TAG_unspecified_parameters";
378	case DW_TAG_unspecified_type:
379		return "DW_TAG_unspecified_type";
380	case DW_TAG_variable:
381		return "DW_TAG_variable";
382	case DW_TAG_variant:
383		return "DW_TAG_variant";
384	case DW_TAG_variant_part:
385		return "DW_TAG_variant_part";
386	case DW_TAG_volatile_type:
387		return "DW_TAG_volatile_type";
388	case DW_TAG_with_stmt:
389		return "DW_TAG_with_stmt";
390	default:
391		break;
392	}
393
394	return "Unknown tag";
395}
396
397void
398dwarf_dump_abbrev(Dwarf_Debug dbg)
399{
400	Dwarf_Abbrev a;
401	Dwarf_Attribute at;
402	Dwarf_CU cu;
403
404	printf("Contents of the .debug_abbrev section:\n\nEntry Tag\n");
405
406	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
407		STAILQ_FOREACH(a, &cu->cu_abbrev, a_next) {
408			printf("%5lu %-30s [%s children]\n",
409			    (u_long) a->a_entry, get_tag_desc(a->a_tag),
410			    (a->a_children == DW_CHILDREN_yes) ? "has" : "no");
411
412			STAILQ_FOREACH(at, &a->a_attrib, at_next)
413				printf("      %-30s %s\n", get_attr_desc(at->at_attrib),
414				    get_form_desc(at->at_form));
415		}
416	}
417}
418#ifdef DOODAD
419    case DW_AT_inline:
420      switch (uvalue)
421	{
422	case DW_INL_not_inlined:
423	  printf (_("(not inlined)"));
424	  break;
425	case DW_INL_inlined:
426	  printf (_("(inlined)"));
427	  break;
428	case DW_INL_declared_not_inlined:
429	  printf (_("(declared as inline but ignored)"));
430	  break;
431	case DW_INL_declared_inlined:
432	  printf (_("(declared as inline and inlined)"));
433	  break;
434	default:
435	  printf (_("  (Unknown inline attribute value: %lx)"), uvalue);
436	  break;
437	}
438      break;
439
440    case DW_AT_language:
441      switch (uvalue)
442	{
443	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
444	case DW_LANG_C89:		printf ("(ANSI C)"); break;
445	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
446	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
447	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
448	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
449	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
450	case DW_LANG_Ada83:		printf ("(Ada)"); break;
451	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
452	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
453	  /* DWARF 2.1 values.	*/
454	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
455	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
456	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
457	  /* MIPS extension.  */
458	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
459	  /* UPC extension.  */
460	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
461	default:
462	  printf ("(Unknown: %lx)", uvalue);
463	  break;
464	}
465      break;
466
467    case DW_AT_encoding:
468      switch (uvalue)
469	{
470	case DW_ATE_void:		printf ("(void)"); break;
471	case DW_ATE_address:		printf ("(machine address)"); break;
472	case DW_ATE_boolean:		printf ("(boolean)"); break;
473	case DW_ATE_complex_float:	printf ("(complex float)"); break;
474	case DW_ATE_float:		printf ("(float)"); break;
475	case DW_ATE_signed:		printf ("(signed)"); break;
476	case DW_ATE_signed_char:	printf ("(signed char)"); break;
477	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
478	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
479	  /* DWARF 2.1 value.  */
480	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
481	default:
482	  if (uvalue >= DW_ATE_lo_user
483	      && uvalue <= DW_ATE_hi_user)
484	    printf ("(user defined type)");
485	  else
486	    printf ("(unknown type)");
487	  break;
488	}
489      break;
490
491    case DW_AT_accessibility:
492      switch (uvalue)
493	{
494	case DW_ACCESS_public:		printf ("(public)"); break;
495	case DW_ACCESS_protected:	printf ("(protected)"); break;
496	case DW_ACCESS_private:		printf ("(private)"); break;
497	default:
498	  printf ("(unknown accessibility)");
499	  break;
500	}
501      break;
502
503    case DW_AT_visibility:
504      switch (uvalue)
505	{
506	case DW_VIS_local:		printf ("(local)"); break;
507	case DW_VIS_exported:		printf ("(exported)"); break;
508	case DW_VIS_qualified:		printf ("(qualified)"); break;
509	default:			printf ("(unknown visibility)"); break;
510	}
511      break;
512
513    case DW_AT_virtuality:
514      switch (uvalue)
515	{
516	case DW_VIRTUALITY_none:	printf ("(none)"); break;
517	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
518	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
519	default:			printf ("(unknown virtuality)"); break;
520	}
521      break;
522
523    case DW_AT_identifier_case:
524      switch (uvalue)
525	{
526	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
527	case DW_ID_up_case:		printf ("(up_case)"); break;
528	case DW_ID_down_case:		printf ("(down_case)"); break;
529	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
530	default:			printf ("(unknown case)"); break;
531	}
532      break;
533
534    case DW_AT_calling_convention:
535      switch (uvalue)
536	{
537	case DW_CC_normal:	printf ("(normal)"); break;
538	case DW_CC_program:	printf ("(program)"); break;
539	case DW_CC_nocall:	printf ("(nocall)"); break;
540	default:
541	  if (uvalue >= DW_CC_lo_user
542	      && uvalue <= DW_CC_hi_user)
543	    printf ("(user defined)");
544	  else
545	    printf ("(unknown convention)");
546	}
547      break;
548
549    case DW_AT_ordering:
550      switch (uvalue)
551	{
552	case -1: printf ("(undefined)"); break;
553	case 0:  printf ("(row major)"); break;
554	case 1:  printf ("(column major)"); break;
555	}
556      break;
557
558    case DW_AT_frame_base:
559    case DW_AT_location:
560    case DW_AT_data_member_location:
561    case DW_AT_vtable_elem_location:
562    case DW_AT_allocated:
563    case DW_AT_associated:
564    case DW_AT_data_location:
565    case DW_AT_stride:
566    case DW_AT_upper_bound:
567    case DW_AT_lower_bound:
568      if (block_start)
569	{
570	  printf ("(");
571	  decode_location_expression (block_start, pointer_size, uvalue);
572	  printf (")");
573	}
574      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
575	{
576	  printf ("(");
577	  printf ("location list");
578	  printf (")");
579	}
580      break;
581#endif
582
583static void
584dwarf_dump_av_attr(Dwarf_Die die __unused, Dwarf_AttrValue av)
585{
586	switch (av->av_attrib) {
587	case DW_AT_accessibility:
588		break;
589
590	case DW_AT_calling_convention:
591		break;
592
593	case DW_AT_encoding:
594		break;
595
596	case DW_AT_identifier_case:
597		break;
598
599	case DW_AT_inline:
600		break;
601
602	case DW_AT_language:
603		break;
604
605	case DW_AT_ordering:
606		break;
607
608	case DW_AT_virtuality:
609		break;
610
611	case DW_AT_visibility:
612		break;
613
614	case DW_AT_frame_base:
615	case DW_AT_location:
616	case DW_AT_data_member_location:
617	case DW_AT_vtable_elem_location:
618	case DW_AT_upper_bound:
619	case DW_AT_lower_bound:
620		break;
621
622	default:
623		break;
624	}
625}
626
627void
628dwarf_dump_av(Dwarf_Die die, Dwarf_AttrValue av)
629{
630	uint64_t i;
631
632	printf("      %-30s : %-16s ",
633	    get_attr_desc(av->av_attrib),
634	    get_form_desc(av->av_form));
635
636	switch (av->av_form) {
637	case DW_FORM_addr:
638		printf("0x%llx", (unsigned long long) av->u[0].u64);
639		break;
640	case DW_FORM_block:
641	case DW_FORM_block1:
642	case DW_FORM_block2:
643	case DW_FORM_block4:
644		printf("%lu byte block:", (u_long) av->u[0].u64);
645		for (i = 0; i < av->u[0].u64; i++)
646			printf(" %02x", av->u[1].u8p[i]);
647		break;
648	case DW_FORM_data1:
649	case DW_FORM_data2:
650	case DW_FORM_data4:
651	case DW_FORM_data8:
652	case DW_FORM_flag:
653	case DW_FORM_flag_present:
654		printf("%llu", (unsigned long long) av->u[0].u64);
655		break;
656	case DW_FORM_ref1:
657	case DW_FORM_ref2:
658	case DW_FORM_ref4:
659	case DW_FORM_ref8:
660	case DW_FORM_ref_udata:
661		printf("<%llx>", (unsigned long long) (av->u[0].u64 +
662		    die->die_cu->cu_offset));
663		break;
664	case DW_FORM_string:
665		printf("%s", av->u[0].s);
666		break;
667	case DW_FORM_strp:
668		printf("(indirect string, offset 0x%llx): %s",
669		    (unsigned long long) av->u[0].u64, av->u[1].s);
670		break;
671	default:
672		printf("unknown form");
673		break;
674	}
675
676	/* Dump any extra attribute-specific information. */
677	dwarf_dump_av_attr(die, av);
678
679	printf("\n");
680}
681
682void
683dwarf_dump_die_at_offset(Dwarf_Debug dbg, Dwarf_Off off)
684{
685	Dwarf_CU cu;
686	Dwarf_Die die;
687
688	if (dbg == NULL)
689		return;
690
691	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
692		STAILQ_FOREACH(die, &cu->cu_die, die_next) {
693			if ((off_t) die->die_offset == off) {
694				dwarf_dump_die(die);
695				return;
696			}
697		}
698	}
699}
700
701void
702dwarf_dump_die(Dwarf_Die die)
703{
704	Dwarf_AttrValue av;
705
706	printf("<%d><%llx>: Abbrev number: %llu (%s)\n",
707	    die->die_level, (unsigned long long) die->die_offset,
708	    (unsigned long long) die->die_abnum,
709	    get_tag_desc(die->die_a->a_tag));
710
711	STAILQ_FOREACH(av, &die->die_attrval, av_next)
712		dwarf_dump_av(die, av);
713}
714
715void
716dwarf_dump_raw(Dwarf_Debug dbg)
717{
718	Dwarf_CU cu;
719	char *p = (char *) dbg;
720	int i;
721
722	printf("dbg %p\n",dbg);
723
724	if (dbg == NULL)
725		return;
726
727	for (i = 0; i < (int) sizeof(*dbg); i++) {
728		if (*p >= 0x20 && *p < 0x7f) {
729			printf(" %c",*p++ & 0xff);
730		} else {
731			printf(" %02x",*p++ & 0xff);
732		}
733	}
734	printf("\n");
735
736	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
737		p = (char *) cu;
738		printf("cu %p\n",cu);
739		for (i = 0; i < (int) sizeof(*cu); i++) {
740			if (*p >= 0x20 && *p < 0x7f) {
741				printf(" %c",*p++ & 0xff);
742			} else {
743				printf(" %02x",*p++ & 0xff);
744			}
745		}
746		printf("\n");
747	}
748}
749
750static void
751dwarf_dump_tree_dies(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Error *error)
752{
753	Dwarf_Die child;
754	int ret;
755
756	do {
757		dwarf_dump_die(die);
758
759		if ((ret = dwarf_child(die, &child, error) == DWARF_E_NO_ENTRY)) {
760			/* No children. */
761		} else if (ret != DWARF_E_NONE) {
762			printf("Error %s\n", dwarf_errmsg(error));
763			return;
764		} else
765			dwarf_dump_tree_dies(dbg, child, error);
766
767		if (dwarf_siblingof(dbg, die, &die, error) != DWARF_E_NONE)
768			die = NULL;
769
770	} while (die != NULL);
771}
772
773void
774dwarf_dump_tree(Dwarf_Debug dbg)
775{
776	Dwarf_CU cu;
777	Dwarf_Die die;
778	Dwarf_Error error;
779	Dwarf_Half cu_pointer_size;
780	Dwarf_Half cu_version;
781	Dwarf_Unsigned cu_abbrev_offset;
782	Dwarf_Unsigned cu_header_length;
783	Dwarf_Unsigned cu_next_offset;
784
785	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
786		printf ("\nCompilation Unit @ offset %llx:\n",
787		    (unsigned long long) cu->cu_offset);
788		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
789		printf ("    Version:         %hu\n", cu->cu_version);
790		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
791		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
792
793		if (dwarf_next_cu_header(dbg, &cu_header_length,
794		    &cu_version, &cu_abbrev_offset, &cu_pointer_size,
795		    &cu_next_offset, &error) != DWARF_E_NONE) {
796			printf("Error %s\n", dwarf_errmsg(&error));
797			return;
798		}
799
800		if (dwarf_siblingof(dbg, NULL, &die, &error) != DWARF_E_NONE) {
801			printf("Error %s\n", dwarf_errmsg(&error));
802			return;
803		}
804
805		dwarf_dump_tree_dies(dbg, die, &error);
806
807	}
808}
809
810void
811dwarf_dump_info(Dwarf_Debug dbg)
812{
813	Dwarf_CU cu;
814	Dwarf_Die die;
815
816	printf("Contents of the .debug_info section:\n");
817
818	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
819		printf ("\nCompilation Unit @ offset %llx:\n",
820		    (unsigned long long) cu->cu_offset);
821		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
822		printf ("    Version:         %hu\n", cu->cu_version);
823		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
824		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
825
826		STAILQ_FOREACH(die, &cu->cu_die, die_next)
827			dwarf_dump_die(die);
828	}
829}
830
831
832void
833dwarf_dump_shstrtab(Dwarf_Debug dbg)
834{
835	char *name;
836	int indx = 0;
837
838	printf("---------------------\nSection header string table contents:\n");
839	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, indx)) != NULL) {
840		printf("%5d '%s'\n",indx,name);
841		indx += strlen(name) + 1;
842	}
843}
844
845void
846dwarf_dump_strtab(Dwarf_Debug dbg)
847{
848	char *name;
849	int indx = 0;
850
851	printf("---------------------\nString table contents:\n");
852	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, indx)) != NULL) {
853		printf("%5d '%s'\n",indx,name);
854		indx += strlen(name) + 1;
855	}
856}
857
858void
859dwarf_dump_dbgstr(Dwarf_Debug dbg)
860{
861	char *name;
862	int indx = 0;
863
864	printf("---------------------\nDebug string table contents:\n");
865	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_debug_str].s_shnum, indx)) != NULL) {
866		printf("%5d '%s'\n",indx,name);
867		indx += strlen(name) + 1;
868	}
869}
870
871void
872dwarf_dump_symtab(Dwarf_Debug dbg)
873{
874	GElf_Sym sym;
875	char *name;
876	int indx = 0;
877
878	printf("---------------------\nSymbol table contents:\n");
879	while (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data,  indx++, &sym) != NULL) {
880		if ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, sym.st_name)) == NULL)
881			printf("sym.st_name %u indx %d sym.st_size %lu\n",sym.st_name,indx,(u_long) sym.st_size);
882		else
883			printf("'%s' sym.st_name %u indx %d sym.st_size %lu\n",name,sym.st_name,indx,(u_long) sym.st_size);
884	}
885}
886
887void
888dwarf_dump(Dwarf_Debug dbg)
889{
890	dwarf_dump_strtab(dbg);
891	dwarf_dump_shstrtab(dbg);
892	dwarf_dump_dbgstr(dbg);
893	dwarf_dump_symtab(dbg);
894	dwarf_dump_info(dbg);
895}
896