]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libdwarf/dwarf_dump.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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_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
274 const char *
275 get_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
397 void
398 dwarf_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
583 static void
584 dwarf_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
627 void
628 dwarf_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
682 void
683 dwarf_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
701 void
702 dwarf_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
715 void
716 dwarf_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
750 static void
751 dwarf_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
773 void
774 dwarf_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
810 void
811 dwarf_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
832 void
833 dwarf_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
845 void
846 dwarf_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
858 void
859 dwarf_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
871 void
872 dwarf_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
887 void
888 dwarf_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 }