]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libdwarf/dwarf_dump.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libdwarf / dwarf_dump.c
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
33 const char *
34 get_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
84 const char *
85 get_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
219 const char *
220 get_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
272 const char *
273 get_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
395 void
396 dwarf_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
581 static void
582 dwarf_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
625 void
626 dwarf_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
679 void
680 dwarf_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
698 void
699 dwarf_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
712 void
713 dwarf_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
747 static void
748 dwarf_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
770 void
771 dwarf_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
807 void
808 dwarf_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
829 void
830 dwarf_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
842 void
843 dwarf_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
855 void
856 dwarf_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
868 void
869 dwarf_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
884 void
885 dwarf_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 }