1 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc. 2 Written by Ulrich Drepper <drepper (at) redhat.com>, 1998. 3 4 This program is Open Source software; you can redistribute it and/or 5 modify it under the terms of the Open Software License version 1.0 as 6 published by the Open Source Initiative. 7 8 You should have received a copy of the Open Software License along 9 with this program; if not, you may obtain a copy of the Open Software 10 License version 1.0 from http://www.opensource.org/licenses/osl.php or 11 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 12 3001 King Ranch Road, Ukiah, CA 95482. */ 13 14 #include <config.h> 15 16 #include <dwarf.h> 17 #include <inttypes.h> 18 #include <libelf.h> 19 #include <libdw.h> 20 #include <fcntl.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 26 static const char *tagnames[] = 27 { 28 [DW_TAG_array_type] = "DW_TAG_array_type", 29 [DW_TAG_class_type] = "DW_TAG_class_type", 30 [DW_TAG_entry_point] = "DW_TAG_entry_point", 31 [DW_TAG_enumeration_type] = "DW_TAG_enumeration_type", 32 [DW_TAG_formal_parameter] = "DW_TAG_formal_parameter", 33 [DW_TAG_imported_declaration] = "DW_TAG_imported_declaration", 34 [DW_TAG_label] = "DW_TAG_label", 35 [DW_TAG_lexical_block] = "DW_TAG_lexical_block", 36 [DW_TAG_member] = "DW_TAG_member", 37 [DW_TAG_pointer_type] = "DW_TAG_pointer_type", 38 [DW_TAG_reference_type] = "DW_TAG_reference_type", 39 [DW_TAG_compile_unit] = "DW_TAG_compile_unit", 40 [DW_TAG_string_type] = "DW_TAG_string_type", 41 [DW_TAG_structure_type] = "DW_TAG_structure_type", 42 [DW_TAG_subroutine_type] = "DW_TAG_subroutine_type", 43 [DW_TAG_typedef] = "DW_TAG_typedef", 44 [DW_TAG_union_type] = "DW_TAG_union_type", 45 [DW_TAG_unspecified_parameters] = "DW_TAG_unspecified_parameters", 46 [DW_TAG_variant] = "DW_TAG_variant", 47 [DW_TAG_common_block] = "DW_TAG_common_block", 48 [DW_TAG_common_inclusion] = "DW_TAG_common_inclusion", 49 [DW_TAG_inheritance] = "DW_TAG_inheritance", 50 [DW_TAG_inlined_subroutine] = "DW_TAG_inlined_subroutine", 51 [DW_TAG_module] = "DW_TAG_module", 52 [DW_TAG_ptr_to_member_type] = "DW_TAG_ptr_to_member_type", 53 [DW_TAG_set_type] = "DW_TAG_set_type", 54 [DW_TAG_subrange_type] = "DW_TAG_subrange_type", 55 [DW_TAG_with_stmt] = "DW_TAG_with_stmt", 56 [DW_TAG_access_declaration] = "DW_TAG_access_declaration", 57 [DW_TAG_base_type] = "DW_TAG_base_type", 58 [DW_TAG_catch_block] = "DW_TAG_catch_block", 59 [DW_TAG_const_type] = "DW_TAG_const_type", 60 [DW_TAG_constant] = "DW_TAG_constant", 61 [DW_TAG_enumerator] = "DW_TAG_enumerator", 62 [DW_TAG_file_type] = "DW_TAG_file_type", 63 [DW_TAG_friend] = "DW_TAG_friend", 64 [DW_TAG_namelist] = "DW_TAG_namelist", 65 [DW_TAG_namelist_item] = "DW_TAG_namelist_item", 66 [DW_TAG_packed_type] = "DW_TAG_packed_type", 67 [DW_TAG_subprogram] = "DW_TAG_subprogram", 68 [DW_TAG_template_type_param] = "DW_TAG_template_type_param", 69 [DW_TAG_template_value_param] = "DW_TAG_template_value_param", 70 [DW_TAG_thrown_type] = "DW_TAG_thrown_type", 71 [DW_TAG_try_block] = "DW_TAG_try_block", 72 [DW_TAG_variant_part] = "DW_TAG_variant_part", 73 [DW_TAG_variable] = "DW_TAG_variable", 74 [DW_TAG_volatile_type] = "DW_TAG_volatile_type" 75 }; 76 #define ntagnames (sizeof (tagnames) / sizeof (tagnames[0])) 77 78 79 const struct 80 { 81 int code; 82 const char *name; 83 } attrs[] = 84 { 85 { DW_AT_sibling, "sibling" }, 86 { DW_AT_location, "location" }, 87 { DW_AT_name, "name" }, 88 { DW_AT_ordering, "ordering" }, 89 { DW_AT_subscr_data, "subscr_data" }, 90 { DW_AT_byte_size, "byte_size" }, 91 { DW_AT_bit_offset, "bit_offset" }, 92 { DW_AT_bit_size, "bit_size" }, 93 { DW_AT_element_list, "element_list" }, 94 { DW_AT_stmt_list, "stmt_list" }, 95 { DW_AT_low_pc, "low_pc" }, 96 { DW_AT_high_pc, "high_pc" }, 97 { DW_AT_language, "language" }, 98 { DW_AT_member, "member" }, 99 { DW_AT_discr, "discr" }, 100 { DW_AT_discr_value, "discr_value" }, 101 { DW_AT_visibility, "visibility" }, 102 { DW_AT_import, "import" }, 103 { DW_AT_string_length, "string_length" }, 104 { DW_AT_common_reference, "common_reference" }, 105 { DW_AT_comp_dir, "comp_dir" }, 106 { DW_AT_const_value, "const_value" }, 107 { DW_AT_containing_type, "containing_type" }, 108 { DW_AT_default_value, "default_value" }, 109 { DW_AT_inline, "inline" }, 110 { DW_AT_is_optional, "is_optional" }, 111 { DW_AT_lower_bound, "lower_bound" }, 112 { DW_AT_producer, "producer" }, 113 { DW_AT_prototyped, "prototyped" }, 114 { DW_AT_return_addr, "return_addr" }, 115 { DW_AT_start_scope, "start_scope" }, 116 { DW_AT_stride_size, "stride_size" }, 117 { DW_AT_upper_bound, "upper_bound" }, 118 { DW_AT_abstract_origin, "abstract_origin" }, 119 { DW_AT_accessibility, "accessibility" }, 120 { DW_AT_address_class, "address_class" }, 121 { DW_AT_artificial, "artificial" }, 122 { DW_AT_base_types, "base_types" }, 123 { DW_AT_calling_convention, "calling_convention" }, 124 { DW_AT_count, "count" }, 125 { DW_AT_data_member_location, "data_member_location" }, 126 { DW_AT_decl_column, "decl_column" }, 127 { DW_AT_decl_file, "decl_file" }, 128 { DW_AT_decl_line, "decl_line" }, 129 { DW_AT_declaration, "declaration" }, 130 { DW_AT_discr_list, "discr_list" }, 131 { DW_AT_encoding, "encoding" }, 132 { DW_AT_external, "external" }, 133 { DW_AT_frame_base, "frame_base" }, 134 { DW_AT_friend, "friend" }, 135 { DW_AT_identifier_case, "identifier_case" }, 136 { DW_AT_macro_info, "macro_info" }, 137 { DW_AT_namelist_items, "namelist_items" }, 138 { DW_AT_priority, "priority" }, 139 { DW_AT_segment, "segment" }, 140 { DW_AT_specification, "specification" }, 141 { DW_AT_static_link, "static_link" }, 142 { DW_AT_type, "type" }, 143 { DW_AT_use_location, "use_location" }, 144 { DW_AT_variable_parameter, "variable_parameter" }, 145 { DW_AT_virtuality, "virtuality" }, 146 { DW_AT_vtable_elem_location, "vtable_elem_location" }, 147 { DW_AT_MIPS_fde, "MIPS_fde" }, 148 { DW_AT_MIPS_loop_begin, "MIPS_loop_begin" }, 149 { DW_AT_MIPS_tail_loop_begin, "MIPS_tail_loop_begin" }, 150 { DW_AT_MIPS_epilog_begin, "MIPS_epilog_begin" }, 151 { DW_AT_MIPS_loop_unroll_factor, "MIPS_loop_unroll_factor" }, 152 { DW_AT_MIPS_software_pipeline_depth, "MIPS_software_pipeline_depth" }, 153 { DW_AT_MIPS_linkage_name, "MIPS_linkage_name" }, 154 { DW_AT_MIPS_stride, "MIPS_stride" }, 155 { DW_AT_MIPS_abstract_name, "MIPS_abstract_name" }, 156 { DW_AT_MIPS_clone_origin, "MIPS_clone_origin" }, 157 { DW_AT_MIPS_has_inlines, "MIPS_has_inlines" }, 158 { DW_AT_MIPS_stride_byte, "MIPS_stride_byte" }, 159 { DW_AT_MIPS_stride_elem, "MIPS_stride_elem" }, 160 { DW_AT_MIPS_ptr_dopetype, "MIPS_ptr_dopetype" }, 161 { DW_AT_MIPS_allocatable_dopetype, "MIPS_allocatable_dopetype" }, 162 { DW_AT_MIPS_assumed_shape_dopetype, "MIPS_assumed_shape_dopetype" }, 163 { DW_AT_MIPS_assumed_size, "MIPS_assumed_size" }, 164 { DW_AT_sf_names, "sf_names" }, 165 { DW_AT_src_info, "src_info" }, 166 { DW_AT_mac_info, "mac_info" }, 167 { DW_AT_src_coords, "src_coords" }, 168 { DW_AT_body_begin, "body_begin" }, 169 { DW_AT_body_end, "body_end" } 170 }; 171 #define nattrs (sizeof (attrs) / sizeof (attrs[0])) 172 173 174 void 175 handle (Dwarf *dbg, Dwarf_Die *die, int n) 176 { 177 Dwarf_Die child; 178 unsigned int tag; 179 const char *str; 180 char buf[30]; 181 const char *name; 182 Dwarf_Off off; 183 Dwarf_Off cuoff; 184 size_t cnt; 185 Dwarf_Addr addr; 186 int i; 187 188 tag = dwarf_tag (die); 189 if (tag != DW_TAG_invalid) 190 { 191 if (tag < ntagnames) 192 str = tagnames[tag]; 193 else 194 { 195 snprintf (buf, sizeof buf, "%#x", tag); 196 str = buf; 197 } 198 } 199 else 200 str = "* NO TAG *"; 201 202 name = dwarf_diename (die); 203 if (name == 0) 204 name = "* NO NAME *"; 205 206 off = dwarf_dieoffset (die); 207 cuoff = dwarf_cuoffset (die); 208 209 printf ("%*s%s\n", n * 5, "", str); 210 printf ("%*s Name : %s\n", n * 5, "", name); 211 printf ("%*s Offset : %lld\n", n * 5, "", (long long int) off); 212 printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff); 213 214 printf ("%*s Attrs :", n * 5, ""); 215 for (cnt = 0; cnt < nattrs; ++cnt) 216 if (dwarf_hasattr (die, attrs[cnt].code)) 217 printf (" %s", attrs[cnt].name); 218 puts (""); 219 220 if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0) 221 { 222 Dwarf_Attribute attr; 223 Dwarf_Addr addr2; 224 printf ("%*s low PC : %#llx\n", 225 n * 5, "", (unsigned long long int) addr); 226 227 if (dwarf_attr (die, DW_AT_low_pc, &attr) == NULL 228 || dwarf_formaddr (&attr, &addr2) != 0 229 || addr != addr2) 230 puts ("************* DW_AT_low_pc verify failed ************"); 231 else if (! dwarf_hasform (&attr, DW_FORM_addr)) 232 puts ("************* DW_AT_low_pc form failed ************"); 233 else if (dwarf_whatform (&attr) != DW_FORM_addr) 234 puts ("************* DW_AT_low_pc form (2) failed ************"); 235 else if (dwarf_whatattr (&attr) != DW_AT_low_pc) 236 puts ("************* DW_AT_low_pc attr failed ************"); 237 } 238 if (dwarf_hasattr (die, DW_AT_high_pc) && dwarf_highpc (die, &addr) == 0) 239 { 240 Dwarf_Attribute attr; 241 Dwarf_Addr addr2; 242 printf ("%*s high PC : %#llx\n", 243 n * 5, "", (unsigned long long int) addr); 244 if (dwarf_attr (die, DW_AT_high_pc, &attr) == NULL 245 || dwarf_formaddr (&attr, &addr2) != 0 246 || addr != addr2) 247 puts ("************* DW_AT_high_pc verify failed ************"); 248 else if (! dwarf_hasform (&attr, DW_FORM_addr)) 249 puts ("************* DW_AT_high_pc form failed ************"); 250 else if (dwarf_whatform (&attr) != DW_FORM_addr) 251 puts ("************* DW_AT_high_pc form (2) failed ************"); 252 else if (dwarf_whatattr (&attr) != DW_AT_high_pc) 253 puts ("************* DW_AT_high_pc attr failed ************"); 254 } 255 256 if (dwarf_hasattr (die, DW_AT_byte_size) && (i = dwarf_bytesize (die)) != -1) 257 { 258 Dwarf_Attribute attr; 259 Dwarf_Word u2; 260 unsigned int u; 261 printf ("%*s byte size : %d\n", n * 5, "", i); 262 if (dwarf_attr (die, DW_AT_byte_size, &attr) == NULL 263 || dwarf_formudata (&attr, &u2) != 0 264 || i != (int) u2) 265 puts ("************* DW_AT_byte_size verify failed ************"); 266 else if (! dwarf_hasform (&attr, DW_FORM_data1) 267 && ! dwarf_hasform (&attr, DW_FORM_data2) 268 && ! dwarf_hasform (&attr, DW_FORM_data4) 269 && ! dwarf_hasform (&attr, DW_FORM_data8) 270 && ! dwarf_hasform (&attr, DW_FORM_sdata) 271 && ! dwarf_hasform (&attr, DW_FORM_udata)) 272 puts ("************* DW_AT_byte_size form failed ************"); 273 else if ((u = dwarf_whatform (&attr)) == 0 274 || (u != DW_FORM_data1 275 && u != DW_FORM_data2 276 && u != DW_FORM_data4 277 && u != DW_FORM_data8 278 && u != DW_FORM_sdata 279 && u != DW_FORM_udata)) 280 puts ("************* DW_AT_byte_size form (2) failed ************"); 281 else if (dwarf_whatattr (&attr) != DW_AT_byte_size) 282 puts ("************* DW_AT_byte_size attr failed ************"); 283 } 284 if (dwarf_hasattr (die, DW_AT_bit_size) && (i = dwarf_bitsize (die)) != -1) 285 { 286 Dwarf_Attribute attr; 287 Dwarf_Word u2; 288 unsigned int u; 289 printf ("%*s bit size : %d\n", n * 5, "", i); 290 if (dwarf_attr (die, DW_AT_bit_size, &attr) == NULL 291 || dwarf_formudata (&attr, &u2) != 0 292 || i != (int) u2) 293 puts ("************* DW_AT_bit_size test failed ************"); 294 else if (! dwarf_hasform (&attr, DW_FORM_data1) 295 && ! dwarf_hasform (&attr, DW_FORM_data2) 296 && ! dwarf_hasform (&attr, DW_FORM_data4) 297 && ! dwarf_hasform (&attr, DW_FORM_data8) 298 && ! dwarf_hasform (&attr, DW_FORM_sdata) 299 && ! dwarf_hasform (&attr, DW_FORM_udata)) 300 puts ("************* DW_AT_bit_size form failed ************"); 301 else if ((u = dwarf_whatform (&attr)) == 0 302 || (u != DW_FORM_data1 303 && u != DW_FORM_data2 304 && u != DW_FORM_data4 305 && u != DW_FORM_data8 306 && u != DW_FORM_sdata 307 && u != DW_FORM_udata)) 308 puts ("************* DW_AT_bit_size form (2) failed ************"); 309 else if (dwarf_whatattr (&attr) != DW_AT_bit_size) 310 puts ("************* DW_AT_bit_size attr failed ************"); 311 } 312 if (dwarf_hasattr (die, DW_AT_bit_offset) 313 && (i = dwarf_bitoffset (die)) != -1) 314 { 315 Dwarf_Attribute attr; 316 Dwarf_Word u2; 317 unsigned int u; 318 printf ("%*s bit offset: %d\n", n * 5, "", i); 319 if (dwarf_attr (die, DW_AT_bit_offset, &attr) == NULL 320 || dwarf_formudata (&attr, &u2) != 0 321 || i != (int) u2) 322 puts ("************* DW_AT_bit_offset test failed ************"); 323 else if (! dwarf_hasform (&attr, DW_FORM_data1) 324 && ! dwarf_hasform (&attr, DW_FORM_data2) 325 && ! dwarf_hasform (&attr, DW_FORM_data4) 326 && ! dwarf_hasform (&attr, DW_FORM_data8) 327 && ! dwarf_hasform (&attr, DW_FORM_sdata) 328 && ! dwarf_hasform (&attr, DW_FORM_udata)) 329 puts ("************* DW_AT_bit_offset form failed ************"); 330 else if ((u = dwarf_whatform (&attr)) == 0 331 || (u != DW_FORM_data1 332 && u != DW_FORM_data2 333 && u != DW_FORM_data4 334 && u != DW_FORM_data8 335 && u != DW_FORM_sdata 336 && u != DW_FORM_udata)) 337 puts ("************* DW_AT_bit_offset form (2) failed ************"); 338 else if (dwarf_whatattr (&attr) != DW_AT_bit_offset) 339 puts ("************* DW_AT_bit_offset attr failed ************"); 340 } 341 342 if (dwarf_hasattr (die, DW_AT_language) && (i = dwarf_srclang (die)) != -1) 343 { 344 Dwarf_Attribute attr; 345 Dwarf_Word u2; 346 unsigned int u; 347 printf ("%*s language : %d\n", n * 5, "", i); 348 if (dwarf_attr (die, DW_AT_language, &attr) == NULL 349 || dwarf_formudata (&attr, &u2) != 0 350 || i != (int) u2) 351 puts ("************* DW_AT_language test failed ************"); 352 else if (! dwarf_hasform (&attr, DW_FORM_data1) 353 && ! dwarf_hasform (&attr, DW_FORM_data2) 354 && ! dwarf_hasform (&attr, DW_FORM_data4) 355 && ! dwarf_hasform (&attr, DW_FORM_data8) 356 && ! dwarf_hasform (&attr, DW_FORM_sdata) 357 && ! dwarf_hasform (&attr, DW_FORM_udata)) 358 puts ("************* DW_AT_language form failed ************"); 359 else if ((u = dwarf_whatform (&attr)) == 0 360 || (u != DW_FORM_data1 361 && u != DW_FORM_data2 362 && u != DW_FORM_data4 363 && u != DW_FORM_data8 364 && u != DW_FORM_sdata 365 && u != DW_FORM_udata)) 366 puts ("************* DW_AT_language form (2) failed ************"); 367 else if (dwarf_whatattr (&attr) != DW_AT_language) 368 puts ("************* DW_AT_language attr failed ************"); 369 } 370 371 if (dwarf_hasattr (die, DW_AT_ordering) 372 && (i = dwarf_arrayorder (die)) != -1) 373 { 374 Dwarf_Attribute attr; 375 Dwarf_Word u2; 376 unsigned int u; 377 printf ("%*s ordering : %d\n", n * 5, "", i); 378 if (dwarf_attr (die, DW_AT_ordering, &attr) == NULL 379 || dwarf_formudata (&attr, &u2) != 0 380 || i != (int) u2) 381 puts ("************* DW_AT_ordering test failed ************"); 382 else if (! dwarf_hasform (&attr, DW_FORM_data1) 383 && ! dwarf_hasform (&attr, DW_FORM_data2) 384 && ! dwarf_hasform (&attr, DW_FORM_data4) 385 && ! dwarf_hasform (&attr, DW_FORM_data8) 386 && ! dwarf_hasform (&attr, DW_FORM_sdata) 387 && ! dwarf_hasform (&attr, DW_FORM_udata)) 388 puts ("************* DW_AT_ordering failed ************"); 389 else if ((u = dwarf_whatform (&attr)) == 0 390 || (u != DW_FORM_data1 391 && u != DW_FORM_data2 392 && u != DW_FORM_data4 393 && u != DW_FORM_data8 394 && u != DW_FORM_sdata 395 && u != DW_FORM_udata)) 396 puts ("************* DW_AT_ordering form (2) failed ************"); 397 else if (dwarf_whatattr (&attr) != DW_AT_ordering) 398 puts ("************* DW_AT_ordering attr failed ************"); 399 } 400 401 if (dwarf_hasattr (die, DW_AT_comp_dir)) 402 { 403 Dwarf_Attribute attr; 404 if (dwarf_attr (die, DW_AT_comp_dir, &attr) == NULL 405 || (name = dwarf_formstring (&attr)) == NULL) 406 puts ("************* DW_AT_comp_dir attr failed ************"); 407 else 408 printf ("%*s directory : %s\n", n * 5, "", name); 409 } 410 411 if (dwarf_hasattr (die, DW_AT_producer)) 412 { 413 Dwarf_Attribute attr; 414 if (dwarf_attr (die, DW_AT_producer, &attr) == NULL 415 || (name = dwarf_formstring (&attr)) == NULL) 416 puts ("************* DW_AT_comp_dir attr failed ************"); 417 else 418 printf ("%*s producer : %s\n", n * 5, "", name); 419 } 420 421 if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0) 422 handle (dbg, &child, n + 1); 423 if (dwarf_siblingof (die, die) == 0) 424 handle (dbg, die, n); 425 } 426 427 428 int 429 main (int argc, char *argv[]) 430 { 431 int cnt; 432 433 for (cnt = 1; cnt < argc; ++cnt) 434 { 435 int fd = open (argv[cnt], O_RDONLY); 436 Dwarf *dbg; 437 438 printf ("file: %s\n", basename (argv[cnt])); 439 440 dbg = dwarf_begin (fd, DWARF_C_READ); 441 if (dbg == NULL) 442 { 443 printf ("%s not usable\n", argv[cnt]); 444 close (fd); 445 continue; 446 } 447 448 Dwarf_Off off = 0; 449 Dwarf_Off old_off = 0; 450 size_t hsize; 451 Dwarf_Off abbrev; 452 uint8_t addresssize; 453 uint8_t offsetsize; 454 while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize, 455 &offsetsize) == 0) 456 { 457 printf ("New CU: off = %llu, hsize = %zu, ab = %llu, as = %" PRIu8 458 ", os = %" PRIu8 "\n", 459 (unsigned long long int) old_off, hsize, 460 (unsigned long long int) abbrev, addresssize, 461 offsetsize); 462 463 Dwarf_Die die; 464 if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL) 465 handle (dbg, &die, 1); 466 467 old_off = off; 468 } 469 470 dwarf_end (dbg); 471 close (fd); 472 } 473 474 return 0; 475 } 476