dwarf_dump.c revision 179187
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: head/lib/libdwarf/dwarf_dump.c 179187 2008-05-22 02:14:23Z jb $
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_indirect:
244		return "DW_FORM_indirect";
245	case DW_FORM_ref1:
246		return "DW_FORM_ref1";
247	case DW_FORM_ref2:
248		return "DW_FORM_ref2";
249	case DW_FORM_ref4:
250		return "DW_FORM_ref4";
251	case DW_FORM_ref8:
252		return "DW_FORM_ref8";
253	case DW_FORM_ref_addr:
254		return "DW_FORM_ref_addr";
255	case DW_FORM_ref_udata:
256		return "DW_FORM_ref_udata";
257	case DW_FORM_sdata:
258		return "DW_FORM_sdata";
259	case DW_FORM_string:
260		return "DW_FORM_string";
261	case DW_FORM_strp:
262		return "DW_FORM_strp";
263	case DW_FORM_udata:
264		return "DW_FORM_udata";
265	default:
266		break;
267	}
268
269	return "Unknown attribute";
270}
271
272const char *
273get_tag_desc(uint32_t tag)
274{
275	switch (tag) {
276	case DW_TAG_access_declaration:
277		return "DW_TAG_access_declaration";
278	case DW_TAG_array_type:
279		return "DW_TAG_array_type";
280	case DW_TAG_base_type:
281		return "DW_TAG_base_type";
282	case DW_TAG_catch_block:
283		return "DW_TAG_catch_block";
284	case DW_TAG_class_type:
285		return "DW_TAG_class_type";
286	case DW_TAG_common_block:
287		return "DW_TAG_common_block";
288	case DW_TAG_common_inclusion:
289		return "DW_TAG_common_inclusion";
290	case DW_TAG_compile_unit:
291		return "DW_TAG_compile_unit";
292	case DW_TAG_condition:
293		return "DW_TAG_condition";
294	case DW_TAG_const_type:
295		return "DW_TAG_const_type";
296	case DW_TAG_constant:
297		return "DW_TAG_constant";
298	case DW_TAG_dwarf_procedure:
299		return "DW_TAG_dwarf_procedure";
300	case DW_TAG_entry_point:
301		return "DW_TAG_entry_point";
302	case DW_TAG_enumeration_type:
303		return "DW_TAG_enumeration_type";
304	case DW_TAG_enumerator:
305		return "DW_TAG_enumerator";
306	case DW_TAG_formal_parameter:
307		return "DW_TAG_formal_parameter";
308	case DW_TAG_friend:
309		return "DW_TAG_friend";
310	case DW_TAG_imported_declaration:
311		return "DW_TAG_imported_declaration";
312	case DW_TAG_imported_module:
313		return "DW_TAG_imported_module";
314	case DW_TAG_imported_unit:
315		return "DW_TAG_imported_unit";
316	case DW_TAG_inheritance:
317		return "DW_TAG_inheritance";
318	case DW_TAG_inlined_subroutine:
319		return "DW_TAG_inlined_subroutine";
320	case DW_TAG_interface_type:
321		return "DW_TAG_interface_type";
322	case DW_TAG_label:
323		return "DW_TAG_label";
324	case DW_TAG_lexical_block:
325		return "DW_TAG_lexical_block";
326	case DW_TAG_member:
327		return "DW_TAG_member";
328	case DW_TAG_module:
329		return "DW_TAG_module";
330	case DW_TAG_namelist:
331		return "DW_TAG_namelist";
332	case DW_TAG_namelist_item:
333		return "DW_TAG_namelist_item";
334	case DW_TAG_namespace:
335		return "DW_TAG_namespace";
336	case DW_TAG_packed_type:
337		return "DW_TAG_packed_type";
338	case DW_TAG_partial_unit:
339		return "DW_TAG_partial_unit";
340	case DW_TAG_pointer_type:
341		return "DW_TAG_pointer_type";
342	case DW_TAG_ptr_to_member_type:
343		return "DW_TAG_ptr_to_member_type";
344	case DW_TAG_reference_type:
345		return "DW_TAG_reference_type";
346	case DW_TAG_restrict_type:
347		return "DW_TAG_restrict_type";
348	case DW_TAG_set_type:
349		return "DW_TAG_set_type";
350	case DW_TAG_shared_type:
351		return "DW_TAG_shared_type";
352	case DW_TAG_string_type:
353		return "DW_TAG_string_type";
354	case DW_TAG_structure_type:
355		return "DW_TAG_structure_type";
356	case DW_TAG_subprogram:
357		return "DW_TAG_subprogram";
358	case DW_TAG_subrange_type:
359		return "DW_TAG_subrange_type";
360	case DW_TAG_subroutine_type:
361		return "DW_TAG_subroutine_type";
362	case DW_TAG_template_type_parameter:
363		return "DW_TAG_template_type_parameter";
364	case DW_TAG_template_value_parameter:
365		return "DW_TAG_template_value_parameter";
366	case DW_TAG_thrown_type:
367		return "DW_TAG_thrown_type";
368	case DW_TAG_try_block:
369		return "DW_TAG_try_block";
370	case DW_TAG_typedef:
371		return "DW_TAG_typedef";
372	case DW_TAG_union_type:
373		return "DW_TAG_union_type";
374	case DW_TAG_unspecified_parameters:
375		return "DW_TAG_unspecified_parameters";
376	case DW_TAG_unspecified_type:
377		return "DW_TAG_unspecified_type";
378	case DW_TAG_variable:
379		return "DW_TAG_variable";
380	case DW_TAG_variant:
381		return "DW_TAG_variant";
382	case DW_TAG_variant_part:
383		return "DW_TAG_variant_part";
384	case DW_TAG_volatile_type:
385		return "DW_TAG_volatile_type";
386	case DW_TAG_with_stmt:
387		return "DW_TAG_with_stmt";
388	default:
389		break;
390	}
391
392	return "Unknown tag";
393}
394
395void
396dwarf_dump_abbrev(Dwarf_Debug dbg)
397{
398	Dwarf_Abbrev a;
399	Dwarf_Attribute at;
400	Dwarf_CU cu;
401
402	printf("Contents of the .debug_abbrev section:\n\nEntry Tag\n");
403
404	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
405		STAILQ_FOREACH(a, &cu->cu_abbrev, a_next) {
406			printf("%5lu %-30s [%s children]\n",
407			    (u_long) a->a_entry, get_tag_desc(a->a_tag),
408			    (a->a_children == DW_CHILDREN_yes) ? "has" : "no");
409
410			STAILQ_FOREACH(at, &a->a_attrib, at_next)
411				printf("      %-30s %s\n", get_attr_desc(at->at_attrib),
412				    get_form_desc(at->at_form));
413		}
414	}
415}
416#ifdef DOODAD
417    case DW_AT_inline:
418      switch (uvalue)
419	{
420	case DW_INL_not_inlined:
421	  printf (_("(not inlined)"));
422	  break;
423	case DW_INL_inlined:
424	  printf (_("(inlined)"));
425	  break;
426	case DW_INL_declared_not_inlined:
427	  printf (_("(declared as inline but ignored)"));
428	  break;
429	case DW_INL_declared_inlined:
430	  printf (_("(declared as inline and inlined)"));
431	  break;
432	default:
433	  printf (_("  (Unknown inline attribute value: %lx)"), uvalue);
434	  break;
435	}
436      break;
437
438    case DW_AT_language:
439      switch (uvalue)
440	{
441	case DW_LANG_C:			printf ("(non-ANSI C)"); break;
442	case DW_LANG_C89:		printf ("(ANSI C)"); break;
443	case DW_LANG_C_plus_plus:	printf ("(C++)"); break;
444	case DW_LANG_Fortran77:		printf ("(FORTRAN 77)"); break;
445	case DW_LANG_Fortran90:		printf ("(Fortran 90)"); break;
446	case DW_LANG_Modula2:		printf ("(Modula 2)"); break;
447	case DW_LANG_Pascal83:		printf ("(ANSI Pascal)"); break;
448	case DW_LANG_Ada83:		printf ("(Ada)"); break;
449	case DW_LANG_Cobol74:		printf ("(Cobol 74)"); break;
450	case DW_LANG_Cobol85:		printf ("(Cobol 85)"); break;
451	  /* DWARF 2.1 values.	*/
452	case DW_LANG_C99:		printf ("(ANSI C99)"); break;
453	case DW_LANG_Ada95:		printf ("(ADA 95)"); break;
454	case DW_LANG_Fortran95:		printf ("(Fortran 95)"); break;
455	  /* MIPS extension.  */
456	case DW_LANG_Mips_Assembler:	printf ("(MIPS assembler)"); break;
457	  /* UPC extension.  */
458	case DW_LANG_Upc:		printf ("(Unified Parallel C)"); break;
459	default:
460	  printf ("(Unknown: %lx)", uvalue);
461	  break;
462	}
463      break;
464
465    case DW_AT_encoding:
466      switch (uvalue)
467	{
468	case DW_ATE_void:		printf ("(void)"); break;
469	case DW_ATE_address:		printf ("(machine address)"); break;
470	case DW_ATE_boolean:		printf ("(boolean)"); break;
471	case DW_ATE_complex_float:	printf ("(complex float)"); break;
472	case DW_ATE_float:		printf ("(float)"); break;
473	case DW_ATE_signed:		printf ("(signed)"); break;
474	case DW_ATE_signed_char:	printf ("(signed char)"); break;
475	case DW_ATE_unsigned:		printf ("(unsigned)"); break;
476	case DW_ATE_unsigned_char:	printf ("(unsigned char)"); break;
477	  /* DWARF 2.1 value.  */
478	case DW_ATE_imaginary_float:	printf ("(imaginary float)"); break;
479	default:
480	  if (uvalue >= DW_ATE_lo_user
481	      && uvalue <= DW_ATE_hi_user)
482	    printf ("(user defined type)");
483	  else
484	    printf ("(unknown type)");
485	  break;
486	}
487      break;
488
489    case DW_AT_accessibility:
490      switch (uvalue)
491	{
492	case DW_ACCESS_public:		printf ("(public)"); break;
493	case DW_ACCESS_protected:	printf ("(protected)"); break;
494	case DW_ACCESS_private:		printf ("(private)"); break;
495	default:
496	  printf ("(unknown accessibility)");
497	  break;
498	}
499      break;
500
501    case DW_AT_visibility:
502      switch (uvalue)
503	{
504	case DW_VIS_local:		printf ("(local)"); break;
505	case DW_VIS_exported:		printf ("(exported)"); break;
506	case DW_VIS_qualified:		printf ("(qualified)"); break;
507	default:			printf ("(unknown visibility)"); break;
508	}
509      break;
510
511    case DW_AT_virtuality:
512      switch (uvalue)
513	{
514	case DW_VIRTUALITY_none:	printf ("(none)"); break;
515	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
516	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
517	default:			printf ("(unknown virtuality)"); break;
518	}
519      break;
520
521    case DW_AT_identifier_case:
522      switch (uvalue)
523	{
524	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
525	case DW_ID_up_case:		printf ("(up_case)"); break;
526	case DW_ID_down_case:		printf ("(down_case)"); break;
527	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
528	default:			printf ("(unknown case)"); break;
529	}
530      break;
531
532    case DW_AT_calling_convention:
533      switch (uvalue)
534	{
535	case DW_CC_normal:	printf ("(normal)"); break;
536	case DW_CC_program:	printf ("(program)"); break;
537	case DW_CC_nocall:	printf ("(nocall)"); break;
538	default:
539	  if (uvalue >= DW_CC_lo_user
540	      && uvalue <= DW_CC_hi_user)
541	    printf ("(user defined)");
542	  else
543	    printf ("(unknown convention)");
544	}
545      break;
546
547    case DW_AT_ordering:
548      switch (uvalue)
549	{
550	case -1: printf ("(undefined)"); break;
551	case 0:  printf ("(row major)"); break;
552	case 1:  printf ("(column major)"); break;
553	}
554      break;
555
556    case DW_AT_frame_base:
557    case DW_AT_location:
558    case DW_AT_data_member_location:
559    case DW_AT_vtable_elem_location:
560    case DW_AT_allocated:
561    case DW_AT_associated:
562    case DW_AT_data_location:
563    case DW_AT_stride:
564    case DW_AT_upper_bound:
565    case DW_AT_lower_bound:
566      if (block_start)
567	{
568	  printf ("(");
569	  decode_location_expression (block_start, pointer_size, uvalue);
570	  printf (")");
571	}
572      else if (form == DW_FORM_data4 || form == DW_FORM_data8)
573	{
574	  printf ("(");
575	  printf ("location list");
576	  printf (")");
577	}
578      break;
579#endif
580
581static void
582dwarf_dump_av_attr(Dwarf_Die die __unused, Dwarf_AttrValue av)
583{
584	switch (av->av_attrib) {
585	case DW_AT_accessibility:
586		break;
587
588	case DW_AT_calling_convention:
589		break;
590
591	case DW_AT_encoding:
592		break;
593
594	case DW_AT_identifier_case:
595		break;
596
597	case DW_AT_inline:
598		break;
599
600	case DW_AT_language:
601		break;
602
603	case DW_AT_ordering:
604		break;
605
606	case DW_AT_virtuality:
607		break;
608
609	case DW_AT_visibility:
610		break;
611
612	case DW_AT_frame_base:
613	case DW_AT_location:
614	case DW_AT_data_member_location:
615	case DW_AT_vtable_elem_location:
616	case DW_AT_upper_bound:
617	case DW_AT_lower_bound:
618		break;
619
620	default:
621		break;
622	}
623}
624
625void
626dwarf_dump_av(Dwarf_Die die, Dwarf_AttrValue av)
627{
628	uint64_t i;
629
630	printf("      %-30s : %-16s ",
631	    get_attr_desc(av->av_attrib),
632	    get_form_desc(av->av_form));
633
634	switch (av->av_form) {
635	case DW_FORM_addr:
636		printf("0x%llx", (unsigned long long) av->u[0].u64);
637		break;
638	case DW_FORM_block:
639	case DW_FORM_block1:
640	case DW_FORM_block2:
641	case DW_FORM_block4:
642		printf("%lu byte block:", (u_long) av->u[0].u64);
643		for (i = 0; i < av->u[0].u64; i++)
644			printf(" %02x", av->u[1].u8p[i]);
645		break;
646	case DW_FORM_data1:
647	case DW_FORM_data2:
648	case DW_FORM_data4:
649	case DW_FORM_data8:
650	case DW_FORM_flag:
651		printf("%llu", (unsigned long long) av->u[0].u64);
652		break;
653	case DW_FORM_ref1:
654	case DW_FORM_ref2:
655	case DW_FORM_ref4:
656	case DW_FORM_ref8:
657	case DW_FORM_ref_udata:
658		printf("<%llx>", (unsigned long long) (av->u[0].u64 +
659		    die->die_cu->cu_offset));
660		break;
661	case DW_FORM_string:
662		printf("%s", av->u[0].s);
663		break;
664	case DW_FORM_strp:
665		printf("(indirect string, offset 0x%llx): %s",
666		    (unsigned long long) av->u[0].u64, av->u[1].s);
667		break;
668	default:
669		printf("unknown form");
670		break;
671	}
672
673	/* Dump any extra attribute-specific information. */
674	dwarf_dump_av_attr(die, av);
675
676	printf("\n");
677}
678
679void
680dwarf_dump_die_at_offset(Dwarf_Debug dbg, Dwarf_Off off)
681{
682	Dwarf_CU cu;
683	Dwarf_Die die;
684
685	if (dbg == NULL)
686		return;
687
688	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
689		STAILQ_FOREACH(die, &cu->cu_die, die_next) {
690			if ((off_t) die->die_offset == off) {
691				dwarf_dump_die(die);
692				return;
693			}
694		}
695	}
696}
697
698void
699dwarf_dump_die(Dwarf_Die die)
700{
701	Dwarf_AttrValue av;
702
703	printf("<%d><%llx>: Abbrev number: %llu (%s)\n",
704	    die->die_level, (unsigned long long) die->die_offset,
705	    (unsigned long long) die->die_abnum,
706	    get_tag_desc(die->die_a->a_tag));
707
708	STAILQ_FOREACH(av, &die->die_attrval, av_next)
709		dwarf_dump_av(die, av);
710}
711
712void
713dwarf_dump_raw(Dwarf_Debug dbg)
714{
715	Dwarf_CU cu;
716	char *p = (char *) dbg;
717	int i;
718
719	printf("dbg %p\n",dbg);
720
721	if (dbg == NULL)
722		return;
723
724	for (i = 0; i < (int) sizeof(*dbg); i++) {
725		if (*p >= 0x20 && *p < 0x7f) {
726			printf(" %c",*p++ & 0xff);
727		} else {
728			printf(" %02x",*p++ & 0xff);
729		}
730	}
731	printf("\n");
732
733	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
734		p = (char *) cu;
735		printf("cu %p\n",cu);
736		for (i = 0; i < (int) sizeof(*cu); i++) {
737			if (*p >= 0x20 && *p < 0x7f) {
738				printf(" %c",*p++ & 0xff);
739			} else {
740				printf(" %02x",*p++ & 0xff);
741			}
742		}
743		printf("\n");
744	}
745}
746
747static void
748dwarf_dump_tree_dies(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Error *error)
749{
750	Dwarf_Die child;
751	int ret;
752
753	do {
754		dwarf_dump_die(die);
755
756		if ((ret = dwarf_child(die, &child, error) == DWARF_E_NO_ENTRY)) {
757			/* No children. */
758		} else if (ret != DWARF_E_NONE) {
759			printf("Error %s\n", dwarf_errmsg(error));
760			return;
761		} else
762			dwarf_dump_tree_dies(dbg, child, error);
763
764		if (dwarf_siblingof(dbg, die, &die, error) != DWARF_E_NONE)
765			die = NULL;
766
767	} while (die != NULL);
768}
769
770void
771dwarf_dump_tree(Dwarf_Debug dbg)
772{
773	Dwarf_CU cu;
774	Dwarf_Die die;
775	Dwarf_Error error;
776	Dwarf_Half cu_pointer_size;
777	Dwarf_Half cu_version;
778	Dwarf_Unsigned cu_abbrev_offset;
779	Dwarf_Unsigned cu_header_length;
780	Dwarf_Unsigned cu_next_offset;
781
782	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
783		printf ("\nCompilation Unit @ offset %llx:\n",
784		    (unsigned long long) cu->cu_offset);
785		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
786		printf ("    Version:         %hu\n", cu->cu_version);
787		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
788		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
789
790		if (dwarf_next_cu_header(dbg, &cu_header_length,
791		    &cu_version, &cu_abbrev_offset, &cu_pointer_size,
792		    &cu_next_offset, &error) != DWARF_E_NONE) {
793			printf("Error %s\n", dwarf_errmsg(&error));
794			return;
795		}
796
797		if (dwarf_siblingof(dbg, NULL, &die, &error) != DWARF_E_NONE) {
798			printf("Error %s\n", dwarf_errmsg(&error));
799			return;
800		}
801
802		dwarf_dump_tree_dies(dbg, die, &error);
803
804	}
805}
806
807void
808dwarf_dump_info(Dwarf_Debug dbg)
809{
810	Dwarf_CU cu;
811	Dwarf_Die die;
812
813	printf("Contents of the .debug_info section:\n");
814
815	STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
816		printf ("\nCompilation Unit @ offset %llx:\n",
817		    (unsigned long long) cu->cu_offset);
818		printf ("    Length:          %lu\n", (u_long) cu->cu_length);
819		printf ("    Version:         %hu\n", cu->cu_version);
820		printf ("    Abbrev Offset:   %lu\n", (u_long) cu->cu_abbrev_offset);
821		printf ("    Pointer Size:    %u\n", (u_int) cu->cu_pointer_size);
822
823		STAILQ_FOREACH(die, &cu->cu_die, die_next)
824			dwarf_dump_die(die);
825	}
826}
827
828
829void
830dwarf_dump_shstrtab(Dwarf_Debug dbg)
831{
832	char *name;
833	int indx = 0;
834
835	printf("---------------------\nSection header string table contents:\n");
836	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, indx)) != NULL) {
837		printf("%5d '%s'\n",indx,name);
838		indx += strlen(name) + 1;
839	}
840}
841
842void
843dwarf_dump_strtab(Dwarf_Debug dbg)
844{
845	char *name;
846	int indx = 0;
847
848	printf("---------------------\nString table contents:\n");
849	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, indx)) != NULL) {
850		printf("%5d '%s'\n",indx,name);
851		indx += strlen(name) + 1;
852	}
853}
854
855void
856dwarf_dump_dbgstr(Dwarf_Debug dbg)
857{
858	char *name;
859	int indx = 0;
860
861	printf("---------------------\nDebug string table contents:\n");
862	while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_debug_str].s_shnum, indx)) != NULL) {
863		printf("%5d '%s'\n",indx,name);
864		indx += strlen(name) + 1;
865	}
866}
867
868void
869dwarf_dump_symtab(Dwarf_Debug dbg)
870{
871	GElf_Sym sym;
872	char *name;
873	int indx = 0;
874
875	printf("---------------------\nSymbol table contents:\n");
876	while (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data,  indx++, &sym) != NULL) {
877		if ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, sym.st_name)) == NULL)
878			printf("sym.st_name %u indx %d sym.st_size %lu\n",sym.st_name,indx,(u_long) sym.st_size);
879		else
880			printf("'%s' sym.st_name %u indx %d sym.st_size %lu\n",name,sym.st_name,indx,(u_long) sym.st_size);
881	}
882}
883
884void
885dwarf_dump(Dwarf_Debug dbg)
886{
887	dwarf_dump_strtab(dbg);
888	dwarf_dump_shstrtab(dbg);
889	dwarf_dump_dbgstr(dbg);
890	dwarf_dump_symtab(dbg);
891	dwarf_dump_info(dbg);
892}
893