00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "globals.h"
00035
00036
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #include <fcntl.h>
00040 #ifdef HAVE_GETOPT_H
00041 #include <getopt.h>
00042 #endif
00043
00044 extern char *optarg;
00045
00046 #define OKAY 0
00047 #define FAILED 1
00048 #define BYTES_PER_INSTRUCTION 4
00049
00050 #if ! defined(BUILD_OS_DARWIN)
00051 static string process_args(int argc, char *argv[]);
00052 static void print_infos(Dwarf_Debug dbg);
00053
00054 static string program_name;
00055 int check_error = 0;
00056
00057
00058 extern string attrib_buf;
00059 extern int attrib_bufsiz;
00060
00061
00062
00063 extern Dwarf_Die current_cu_die_for_print_frames;
00064
00065
00066 boolean info_flag = FALSE;
00067 boolean use_old_dwarf_loclist = FALSE;
00068
00069
00070
00071
00072 static boolean line_flag = FALSE;
00073 static boolean abbrev_flag = FALSE;
00074 static boolean frame_flag = FALSE;
00075 static boolean exceptions_flag = FALSE;
00076 static boolean pubnames_flag = FALSE;
00077 static boolean macinfo_flag = FALSE;
00078 static boolean loc_flag = FALSE;
00079 static boolean aranges_flag = FALSE;
00080 static boolean string_flag = FALSE;
00081 static boolean reloc_flag = FALSE;
00082 static boolean static_func_flag = FALSE;
00083 static boolean static_var_flag = FALSE;
00084 static boolean type_flag = FALSE;
00085 static boolean weakname_flag = FALSE;
00086
00087 int verbose = 0;
00088 boolean dense = FALSE;
00089 boolean ellipsis = FALSE;
00090 boolean dst_format = FALSE;
00091
00092 boolean check_abbrev_code = FALSE;
00093 boolean check_pubname_attr = FALSE;
00094 boolean check_reloc_offset = FALSE;
00095 boolean check_attr_tag = FALSE;
00096 boolean check_tag_tree = FALSE;
00097 boolean check_type_offset = FALSE;
00098
00099 static boolean dwarf_check = FALSE;
00100
00101 char cu_name[BUFSIZ];
00102 boolean cu_name_flag = FALSE;
00103 Dwarf_Unsigned cu_offset = 0;
00104
00105 Dwarf_Check_Result abbrev_code_result;
00106 Dwarf_Check_Result pubname_attr_result;
00107 Dwarf_Check_Result reloc_offset_result;
00108 Dwarf_Check_Result attr_tag_result;
00109 Dwarf_Check_Result tag_tree_result;
00110 Dwarf_Check_Result type_offset_result;
00111
00112 Dwarf_Error err;
00113
00114 #define PRINT_CHECK_RESULT(str,result) {\
00115 fprintf(stderr, "%-24s%8d%8d\n", str, result.checks, result.errors); \
00116 }
00117
00118 static int process_one_file(Elf * elf, string file_name, int archive);
00119
00120
00121
00122
00123 int
00124 main(int argc, char *argv[])
00125 {
00126 string file_name;
00127 int f;
00128 Elf_Cmd cmd;
00129 Elf *arf, *elf;
00130 int archive = 0;
00131
00132 (void) elf_version(EV_NONE);
00133 if (elf_version(EV_CURRENT) == EV_NONE) {
00134 (void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n");
00135 exit(1);
00136 }
00137
00138 file_name = process_args(argc, argv);
00139 #ifdef __CYGWIN__
00140 f = open(file_name, O_RDONLY | O_BINARY);
00141 #else
00142 f = open(file_name, O_RDONLY);
00143 #endif
00144 if (f == -1) {
00145 fprintf(stderr, "%s ERROR: can't open %s\n", program_name,
00146 file_name);
00147 return (FAILED);
00148 }
00149
00150 cmd = ELF_C_READ;
00151 arf = elf_begin(f, cmd, (Elf *) 0);
00152 if (elf_kind(arf) == ELF_K_AR) {
00153 archive = 1;
00154 }
00155 while ((elf = elf_begin(f, cmd, arf)) != 0) {
00156 Elf32_Ehdr *eh32;
00157
00158 #ifdef HAVE_ELF64_GETEHDR
00159 Elf64_Ehdr *eh64;
00160 #endif
00161 eh32 = elf32_getehdr(elf);
00162 if (!eh32) {
00163 #ifdef HAVE_ELF64_GETEHDR
00164
00165 eh64 = elf64_getehdr(elf);
00166 if (!eh64) {
00167
00168
00169 } else {
00170 process_one_file(elf, file_name, archive);
00171 }
00172 #endif
00173 } else {
00174 process_one_file(elf, file_name, archive);
00175 }
00176 cmd = elf_next(elf);
00177 elf_end(elf);
00178 }
00179 elf_end(arf);
00180 if (check_error)
00181 return FAILED;
00182 else
00183 return OKAY;
00184 }
00185
00186
00187
00188
00189
00190
00191 static int
00192 process_one_file(Elf * elf, string file_name, int archive)
00193 {
00194 Dwarf_Debug dbg;
00195 int dres;
00196
00197 dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
00198 if (dres == DW_DLV_NO_ENTRY) {
00199 printf("No DWARF information present in %s\n", file_name);
00200 return 0;
00201 }
00202 if (dres != DW_DLV_OK) {
00203 print_error(dbg, "dwarf_elf_init", dres, err);
00204 }
00205
00206 attrib_buf = (string) malloc(ATTRIB_BUFSIZ);
00207 if (attrib_buf == NULL) {
00208 fprintf(stderr, "%s ERROR: mallocing %d bytes for buffer\n",
00209 program_name, ATTRIB_BUFSIZ);
00210 exit(FAILED);
00211 }
00212 attrib_bufsiz = ATTRIB_BUFSIZ;
00213
00214
00215 if (archive) {
00216 Elf_Arhdr *mem_header = elf_getarhdr(elf);
00217
00218 printf("\narchive member \t%s\n",
00219 mem_header ? mem_header->ar_name : "");
00220 }
00221
00222 if (info_flag || line_flag || cu_name_flag)
00223 print_infos(dbg);
00224 if (pubnames_flag)
00225 print_pubnames(dbg);
00226 if (macinfo_flag)
00227 print_macinfo(dbg);
00228 if (loc_flag)
00229 print_locs(dbg);
00230 if (abbrev_flag)
00231 print_abbrevs(dbg);
00232 if (string_flag)
00233 print_strings(dbg);
00234 if (aranges_flag)
00235 print_aranges(dbg);
00236 if (frame_flag) {
00237 current_cu_die_for_print_frames = 0;
00238 print_frames(dbg);
00239 }
00240 if (static_func_flag)
00241 print_static_funcs(dbg);
00242 if (static_var_flag)
00243 print_static_vars(dbg);
00244 if (type_flag)
00245 print_types(dbg);
00246 if (weakname_flag)
00247 print_weaknames(dbg);
00248 if (reloc_flag)
00249 print_relocinfo(dbg);
00250 if (dwarf_check) {
00251 fprintf(stderr, "DWARF CHECK RESULT\n");
00252 fprintf(stderr, "<item> <checks><errors>\n");
00253 }
00254 if (check_pubname_attr)
00255 PRINT_CHECK_RESULT("pubname_attr", pubname_attr_result)
00256 if (check_attr_tag)
00257 PRINT_CHECK_RESULT("attr_tag", attr_tag_result)
00258 if (check_tag_tree)
00259 PRINT_CHECK_RESULT("tag_tree", tag_tree_result)
00260 if (check_type_offset)
00261 PRINT_CHECK_RESULT("type_offset",
00262 type_offset_result)
00263
00264 dres = dwarf_finish(dbg, &err);
00265 if (dres != DW_DLV_OK) {
00266 print_error(dbg, "dwarf_finish", dres, err);
00267 }
00268
00269 if (attrib_buf != NULL)
00270 free(attrib_buf);
00271
00272
00273 return 0;
00274
00275 }
00276
00277
00278 static string
00279 process_args(int argc, char *argv[])
00280 {
00281 extern int optind;
00282 int c;
00283 boolean usage_error = FALSE;
00284 int oarg;
00285
00286 program_name = argv[0];
00287
00288 while ((c =
00289 getopt(argc, argv, "ailfghbprmcsvdeok:gu:t:ywz")) != EOF) {
00290 switch (c) {
00291 case 'g':
00292 use_old_dwarf_loclist = TRUE;
00293 case 'i':
00294 info_flag = TRUE;
00295 break;
00296 case 'l':
00297 line_flag = TRUE;
00298 break;
00299 case 'f':
00300 frame_flag = TRUE;
00301 break;
00302 case 'b':
00303 abbrev_flag = TRUE;
00304 break;
00305 case 'p':
00306 pubnames_flag = TRUE;
00307 break;
00308 case 'r':
00309 aranges_flag = TRUE;
00310 break;
00311 case 'm':
00312 macinfo_flag = TRUE;
00313 break;
00314 case 'c':
00315 loc_flag = TRUE;
00316 break;
00317 case 's':
00318 string_flag = TRUE;
00319 break;
00320 case 'a':
00321 info_flag = line_flag = frame_flag = abbrev_flag = TRUE;
00322 pubnames_flag = aranges_flag = macinfo_flag = TRUE;
00323 loc_flag = string_flag = TRUE;
00324 reloc_flag = TRUE;
00325 static_func_flag = static_var_flag = TRUE;
00326 type_flag = weakname_flag = TRUE;
00327 break;
00328 case 'v':
00329 verbose++;
00330 break;
00331 case 'd':
00332 dense = TRUE;
00333 break;
00334 case 'e':
00335 ellipsis = TRUE;
00336 break;
00337 case 'o':
00338 reloc_flag = TRUE;
00339 break;
00340 case 'k':
00341 dwarf_check = TRUE;
00342 oarg = optarg[0];
00343 switch (oarg) {
00344 case 'a':
00345 check_pubname_attr = TRUE;
00346 check_attr_tag = TRUE;
00347 check_tag_tree = check_type_offset = TRUE;
00348 pubnames_flag = info_flag = TRUE;
00349 break;
00350 case 'e':
00351 check_pubname_attr = TRUE;
00352 pubnames_flag = TRUE;
00353 break;
00354 case 'r':
00355 check_attr_tag = TRUE;
00356 info_flag = TRUE;
00357 break;
00358 case 't':
00359 check_tag_tree = TRUE;
00360 info_flag = TRUE;
00361 break;
00362 case 'y':
00363 check_type_offset = TRUE;
00364 info_flag = TRUE;
00365 break;
00366 default:
00367 usage_error = TRUE;
00368 break;
00369 }
00370 break;
00371 case 'u':
00372 cu_name_flag = TRUE;
00373 strcpy(cu_name, optarg);
00374 break;
00375 case 't':
00376 oarg = optarg[0];
00377 switch (oarg) {
00378 case 'a':
00379
00380 static_func_flag = static_var_flag = TRUE;
00381 break;
00382 case 'f':
00383
00384 static_func_flag = TRUE;
00385 break;
00386 case 'v':
00387
00388 static_var_flag = TRUE;
00389 break;
00390 default:
00391 usage_error = TRUE;
00392 break;
00393 }
00394 break;
00395 case 'y':
00396 type_flag = TRUE;
00397 break;
00398 case 'w':
00399 weakname_flag = TRUE;
00400 break;
00401 case 'z':
00402 fprintf(stderr, "-z is no longer supported:ignored\n");
00403 break;
00404 default:
00405 usage_error = TRUE;
00406 break;
00407 }
00408 }
00409 if (usage_error || (optind != (argc - 1))) {
00410 fprintf(stderr, "Usage: %s <options> <object file>\n",
00411 program_name);
00412 fprintf(stderr, "options:\t-a\tprint all sections\n");
00413 fprintf(stderr, "\t\t-b\tprint abbrev section\n");
00414 fprintf(stderr, "\t\t-c\tprint loc section\n");
00415 fprintf(stderr,
00416 "\t\t-d\tdense: one line per entry (info section only)\n");
00417 fprintf(stderr,
00418 "\t\t-e\tellipsis: short names for tags, attrs etc.\n");
00419 fprintf(stderr, "\t\t-f\tprint frame section\n");
00420 fprintf(stderr, "\t\t-g\t(use incomplete loclist support)\n");
00421 fprintf(stderr, "\t\t-h\tprint exception tables\n");
00422 fprintf(stderr, "\t\t-i\tprint info section\n");
00423 fprintf(stderr, "\t\t-k[aerty] check dwarf information\n");
00424 fprintf(stderr, "\t\t a\tdo all checks\n");
00425 fprintf(stderr, "\t\t e\texamine attributes of pubnames\n");
00426 fprintf(stderr, "\t\t r\texamine attr-tag relation\n");
00427 fprintf(stderr, "\t\t t\texamine tag trees\n");
00428 fprintf(stderr, "\t\t y\texamine type info\n");
00429 fprintf(stderr, "\t\t-l\tprint line section\n");
00430 fprintf(stderr, "\t\t-m\tprint macinfo section\n");
00431 fprintf(stderr, "\t\t-o\tprint relocation info\n");
00432 fprintf(stderr, "\t\t-p\tprint pubnames section\n");
00433 fprintf(stderr, "\t\t-r\tprint aranges section\n");
00434 fprintf(stderr, "\t\t-s\tprint string section\n");
00435 fprintf(stderr, "\t\t-t[afv] static: \n");
00436 fprintf(stderr, "\t\t a\tprint both sections\n");
00437 fprintf(stderr, "\t\t f\tprint static func section\n");
00438 fprintf(stderr, "\t\t v\tprint static var section\n");
00439 fprintf(stderr,
00440 "\t\t-u<file> print sections only for specified file\n");
00441 fprintf(stderr, "\t\t-v\tverbose: show more information\n");
00442 fprintf(stderr, "\t\t-w\tprint weakname section\n");
00443 fprintf(stderr, "\t\t-y\tprint type section\n");
00444 exit(FAILED);
00445 }
00446 return argv[optind];
00447 }
00448
00449
00450 static void
00451 print_infos(Dwarf_Debug dbg)
00452 {
00453 Dwarf_Unsigned cu_header_length;
00454 Dwarf_Unsigned abbrev_offset;
00455 Dwarf_Half version_stamp;
00456 Dwarf_Half address_size;
00457 Dwarf_Die cu_die;
00458 Dwarf_Unsigned next_cu_offset;
00459 int nres;
00460
00461 if (info_flag)
00462 printf("\n.debug_info\n");
00463
00464
00465 while ((nres =
00466 dwarf_next_cu_header(dbg, &cu_header_length, &version_stamp,
00467 &abbrev_offset, &address_size,
00468 &next_cu_offset, &err))
00469 == DW_DLV_OK) {
00470 int sres;
00471
00472 if (cu_name_flag) {
00473 int tres;
00474 Dwarf_Half tag;
00475 Dwarf_Attribute attrib;
00476 Dwarf_Half theform;
00477 int fres;
00478 int ares;
00479
00480 sres = dwarf_siblingof(dbg, NULL, &cu_die, &err);
00481 if (sres != DW_DLV_OK) {
00482 print_error(dbg, "siblingof cu header", sres, err);
00483 }
00484 tres = dwarf_tag(cu_die, &tag, &err);
00485 if (tres != DW_DLV_OK) {
00486 print_error(dbg, "tag of cu die", tres, err);
00487 }
00488 ares = dwarf_attr(cu_die, DW_AT_name, &attrib, &err);
00489 if (ares != DW_DLV_OK) {
00490 print_error(dbg, "dwarf DW_AT_name ", ares, err);
00491 }
00492 fres = dwarf_whatform(attrib, &theform, &err);
00493 if (fres != DW_DLV_OK) {
00494 print_error(dbg, "dwarf_whatform problem ", fres, err);
00495 } else if (theform == DW_FORM_string
00496 || theform == DW_FORM_strp) {
00497 string temps;
00498 int strres;
00499 string p;
00500
00501 strres = dwarf_formstring(attrib, &temps, &err);
00502 p = temps;
00503 if (strres != DW_DLV_OK) {
00504 print_error(dbg,
00505 "formstring failed unexpectedly",
00506 strres, err);
00507 }
00508 if (cu_name[0] != '/') {
00509 p = strrchr(temps, '/');
00510 if (p == NULL) {
00511 p = temps;
00512 } else {
00513 p++;
00514 }
00515 }
00516 if (strcmp(cu_name, p)) {
00517 dwarf_dealloc(dbg, temps, DW_DLA_STRING);
00518 continue;
00519 }
00520 dwarf_dealloc(dbg, temps, DW_DLA_STRING);
00521 } else {
00522 print_error(dbg,
00523 "dwarf_whatform unexpected value",
00524 fres, err);
00525 }
00526 dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
00527 dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
00528 }
00529 if (verbose && info_flag) {
00530 if (dense) {
00531 printf("<%s>", "cu_header");
00532 printf(" %s<%llu>", "cu_header_length",
00533 cu_header_length);
00534 printf(" %s<%d>", "version_stamp", version_stamp);
00535 printf(" %s<%llu>", "abbrev_offset", abbrev_offset);
00536 printf(" %s<%d>\n", "address_size", address_size);
00537
00538 } else {
00539 printf("\nCU_HEADER:\n");
00540 printf("\t\t%-28s%llu\n", "cu_header_length",
00541 cu_header_length);
00542 printf("\t\t%-28s%d\n", "version_stamp", version_stamp);
00543 printf("\t\t%-28s%llu\n", "abbrev_offset",
00544 abbrev_offset);
00545 printf("\t\t%-28s%d", "address_size", address_size);
00546 }
00547 }
00548
00549
00550 sres = dwarf_siblingof(dbg, NULL, &cu_die, &err);
00551 if (sres == DW_DLV_OK) {
00552 if (info_flag || cu_name_flag) {
00553 Dwarf_Signed cnt = 0;
00554 char **srcfiles = 0;
00555 int srcf = dwarf_srcfiles(cu_die,
00556 &srcfiles, &cnt, &err);
00557
00558 if (srcf != DW_DLV_OK) {
00559 srcfiles = 0;
00560 cnt = 0;
00561 }
00562
00563 print_die_and_children(dbg, cu_die, srcfiles, cnt);
00564 if (srcf == DW_DLV_OK) {
00565 int si;
00566
00567 for (si = 0; si < cnt; ++si) {
00568 dwarf_dealloc(dbg, srcfiles[si], DW_DLA_STRING);
00569 }
00570 dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
00571 }
00572 }
00573 if (line_flag)
00574 print_line_numbers_this_cu(dbg, cu_die);
00575 dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
00576 } else if (sres == DW_DLV_NO_ENTRY) {
00577
00578 } else {
00579 print_error(dbg, "Regetting cu_die", sres, err);
00580 }
00581 cu_offset = next_cu_offset;
00582 }
00583 if (nres == DW_DLV_ERROR) {
00584 string errmsg = dwarf_errmsg(err);
00585 long long myerr = dwarf_errno(err);
00586
00587 fprintf(stderr, "%s ERROR: %s: %s (%lld)\n",
00588 program_name, "attempting to print .debug_info",
00589 errmsg, myerr);
00590 fprintf(stderr, "attempting to continue.\n");
00591 }
00592 }
00593
00594 #else
00595 static string program_name = "";
00596 boolean ellipsis = FALSE;
00597 int main() { fprintf(stderr, "Not yet supported on Mac OS\n"); return 1; }
00598 #endif
00599
00600
00601 void
00602 print_error(Dwarf_Debug dbg, string msg, int dwarf_code,
00603 Dwarf_Error err)
00604 {
00605 if (dwarf_code == DW_DLV_ERROR) {
00606 string errmsg = dwarf_errmsg(err);
00607 long long myerr = dwarf_errno(err);
00608
00609 fprintf(stderr, "%s ERROR: %s: %s (%lld)\n",
00610 program_name, msg, errmsg, myerr);
00611 } else if (dwarf_code == DW_DLV_NO_ENTRY) {
00612 fprintf(stderr, "%s NO ENTRY: %s: \n", program_name, msg);
00613 } else if (dwarf_code == DW_DLV_OK) {
00614 fprintf(stderr, "%s: %s \n", program_name, msg);
00615 } else {
00616 fprintf(stderr, "%s InternalError: %s: code %d\n",
00617 program_name, msg, dwarf_code);
00618 }
00619 exit(FAILED);
00620
00621 }