diff -r a587897e3bb2 -r 2925e6e5efd7 tools/elf4rom/libs/dwarf-20071209/dwarfdump/dwarfdump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/elf4rom/libs/dwarf-20071209/dwarfdump/dwarfdump.c Tue Jan 26 13:28:08 2010 +0000 @@ -0,0 +1,763 @@ +/* + Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright (C) 2007 David Anderson. All Rights Reserved. + Portions Copyright 2007 Sun Microsystems, Inc. All rights reserved. + + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it would be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Further, this software is distributed without any warranty that it is + free of the rightful claim of any third person regarding infringement + or the like. Any license provided herein, whether implied or + otherwise, applies only to this software file. Patent licenses, if + any, provided herein do not apply to combinations of this program with + other software, or any other product whatsoever. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street - Fifth Floor, Boston MA 02110-1301, USA. + + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, + Mountain View, CA 94043, or: + + http://www.sgi.com + + For further information regarding this notice, see: + + http://oss.sgi.com/projects/GenInfo/NoticeExplan + + +$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/dwarfdump.c,v 1.48 2006/04/18 18:05:57 davea Exp $ */ + +/* The address of the Free Software Foundation is + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + SGI has moved from the Crittenden Lane address. +*/ + + + +#include "globals.h" + +/* for 'open' */ +#include +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +#include "makename.h" +#include "dwconf.h" +extern char *optarg; + +#define OKAY 0 +#define FAILED 1 +#define BYTES_PER_INSTRUCTION 4 + +static string process_args(int argc, char *argv[]); +static void print_infos(Dwarf_Debug dbg); +static void print_usage_message(void); + +static string program_name; +int check_error = 0; + +/* defined in print_sections.c, die for the current compile unit, + used in get_fde_proc_name() */ +extern Dwarf_Die current_cu_die_for_print_frames; + + +boolean info_flag = FALSE; +boolean use_old_dwarf_loclist = FALSE; /* This so both dwarf_loclist() + and dwarf_loclist_n() can be + tested. Defaults to new + dwarf_loclist_n() */ + +static boolean line_flag = FALSE; +static boolean abbrev_flag = FALSE; +static boolean frame_flag = FALSE; /* .debug_frame section. */ +static boolean eh_frame_flag = FALSE; /* GNU .eh_frame section. */ +static boolean pubnames_flag = FALSE; +static boolean macinfo_flag = FALSE; +static boolean loc_flag = FALSE; +static boolean aranges_flag = FALSE; +static boolean string_flag = FALSE; +static boolean reloc_flag = FALSE; +static boolean static_func_flag = FALSE; +static boolean static_var_flag = FALSE; +static boolean type_flag = FALSE; +static boolean weakname_flag = FALSE; + +int verbose = 0; +boolean dense = FALSE; +boolean ellipsis = FALSE; +boolean dst_format = FALSE; +boolean show_global_offsets = FALSE; + +boolean check_abbrev_code = FALSE; +boolean check_pubname_attr = FALSE; +boolean check_reloc_offset = FALSE; +boolean check_attr_tag = FALSE; +boolean check_tag_tree = FALSE; +boolean check_type_offset = FALSE; +boolean generic_1000_regs = FALSE; + +static boolean dwarf_check = FALSE; + +/* These configure items are for the + frame data. +*/ +static char *config_file_path = 0; +static char *config_file_abi = 0; +static char *config_file_defaults[] = { + "./dwarfdump.conf", + /* Note: HOME location uses .dwarfdump. */ + "HOME/.dwarfdump.conf", +#ifdef CONFPREFIX +/* See Makefile.in "libdir" and CFLAGS */ +/* We need 2 levels of macro to get the name turned into + the string we want. */ +#define STR2(s) # s +#define STR(s) STR2(s) + STR(CONFPREFIX) + "/dwarfdump.conf", +#else + "/usr/lib/dwarfdump.conf", +#endif + 0 +}; +static struct dwconf_s config_file_data; + +char cu_name[BUFSIZ]; +boolean cu_name_flag = FALSE; +Dwarf_Unsigned cu_offset = 0; + +Dwarf_Check_Result abbrev_code_result; +Dwarf_Check_Result pubname_attr_result; +Dwarf_Check_Result reloc_offset_result; +Dwarf_Check_Result attr_tag_result; +Dwarf_Check_Result tag_tree_result; +Dwarf_Check_Result type_offset_result; + +Dwarf_Error err; + +#define PRINT_CHECK_RESULT(str,result) {\ + fprintf(stderr, "%-24s%8d%8d\n", str, result.checks, result.errors); \ +} + +static int process_one_file(Elf * elf, string file_name, int archive, + struct dwconf_s *conf); +static int +open_a_file(string name) +{ + int f = 0; + +#ifdef __CYGWIN__ + f = open(name, O_RDONLY | O_BINARY); +#else + f = open(name, O_RDONLY); +#endif + return f; + +} + +/* + * Iterate through dwarf and print all info. + */ +int +main(int argc, char *argv[]) +{ + string file_name; + int f; + Elf_Cmd cmd; + Elf *arf, *elf; + int archive = 0; + + (void) elf_version(EV_NONE); + if (elf_version(EV_CURRENT) == EV_NONE) { + (void) fprintf(stderr, "dwarfdump: libelf.a out of date.\n"); + exit(1); + } + + file_name = process_args(argc, argv); + f = open_a_file(file_name); + if (f == -1) { + fprintf(stderr, "%s ERROR: can't open %s\n", program_name, + file_name); + return (FAILED); + } + + cmd = ELF_C_READ; + arf = elf_begin(f, cmd, (Elf *) 0); + if (elf_kind(arf) == ELF_K_AR) { + archive = 1; + } + while ((elf = elf_begin(f, cmd, arf)) != 0) { + Elf32_Ehdr *eh32; + +#ifdef HAVE_ELF64_GETEHDR + Elf64_Ehdr *eh64; +#endif /* HAVE_ELF64_GETEHDR */ + eh32 = elf32_getehdr(elf); + if (!eh32) { +#ifdef HAVE_ELF64_GETEHDR + /* not a 32-bit obj */ + eh64 = elf64_getehdr(elf); + if (!eh64) { + /* not a 64-bit obj either! */ + /* dwarfdump is quiet when not an object */ + } else { + process_one_file(elf, file_name, archive, + &config_file_data); + } +#endif /* HAVE_ELF64_GETEHDR */ + } else { + process_one_file(elf, file_name, archive, + &config_file_data); + } + cmd = elf_next(elf); + elf_end(elf); + } + elf_end(arf); + /* Trivial malloc space cleanup. */ + clean_up_die_esb(); + clean_up_syms_malloc_data(); + + if (check_error) + return FAILED; + else + return OKAY; +} + +/* + Given a file which we know is an elf file, process + the dwarf data. + +*/ +static int +process_one_file(Elf * elf, string file_name, int archive, + struct dwconf_s *config_file_data) +{ + Dwarf_Debug dbg; + int dres; + + dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err); + if (dres == DW_DLV_NO_ENTRY) { + printf("No DWARF information present in %s\n", file_name); + return 0; + } + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_elf_init", dres, err); + } + + if (archive) { + Elf_Arhdr *mem_header = elf_getarhdr(elf); + + printf("\narchive member \t%s\n", + mem_header ? mem_header->ar_name : ""); + } + dwarf_set_frame_rule_inital_value(dbg, + config_file_data-> + cf_initial_rule_value); + dwarf_set_frame_rule_table_size(dbg, + config_file_data-> + cf_table_entry_count); + + if (info_flag || line_flag || cu_name_flag) + print_infos(dbg); + if (pubnames_flag) + print_pubnames(dbg); + if (macinfo_flag) + print_macinfo(dbg); + if (loc_flag) + print_locs(dbg); + if (abbrev_flag) + print_abbrevs(dbg); + if (string_flag) + print_strings(dbg); + if (aranges_flag) + print_aranges(dbg); + if (frame_flag || eh_frame_flag) { + current_cu_die_for_print_frames = 0; + print_frames(dbg, frame_flag, eh_frame_flag, config_file_data); + } + if (static_func_flag) + print_static_funcs(dbg); + if (static_var_flag) + print_static_vars(dbg); + /* DWARF_PUBTYPES is the standard typenames dwarf section. + SGI_TYPENAME is the same concept but is SGI specific ( it was + defined 10 years before dwarf pubtypes). */ + + if (type_flag) { + print_types(dbg, DWARF_PUBTYPES); + print_types(dbg, SGI_TYPENAME); + } + if (weakname_flag) + print_weaknames(dbg); + if (reloc_flag) + print_relocinfo(dbg); + if (dwarf_check) { + fprintf(stderr, "DWARF CHECK RESULT\n"); + fprintf(stderr, " \n"); + } + if (check_pubname_attr) + PRINT_CHECK_RESULT("pubname_attr", pubname_attr_result) + if (check_attr_tag) + PRINT_CHECK_RESULT("attr_tag", attr_tag_result) + if (check_tag_tree) + PRINT_CHECK_RESULT("tag_tree", tag_tree_result) + if (check_type_offset) + PRINT_CHECK_RESULT("type_offset", + type_offset_result) + + dres = dwarf_finish(dbg, &err); + if (dres != DW_DLV_OK) { + print_error(dbg, "dwarf_finish", dres, err); + } + return 0; + +} + +static void do_all() +{ + info_flag = line_flag = frame_flag = abbrev_flag = TRUE; + pubnames_flag = aranges_flag = macinfo_flag = TRUE; + loc_flag = string_flag = TRUE; + reloc_flag = TRUE; + static_func_flag = static_var_flag = TRUE; + type_flag = weakname_flag = TRUE; +} + +/* process arguments and return object filename */ +static string +process_args(int argc, char *argv[]) +{ + extern int optind; + int c = 0; + boolean usage_error = FALSE; + int oarg = 0; + + program_name = argv[0]; + + /* j q unused */ + if (argv[1] != NULL && argv[1][0] != '-') { + do_all(); + } + + while ((c = + getopt(argc, argv, + "abcdefFgGhik:lmoprRst:u:vVwx:yz")) != EOF) { + switch (c) { + case 'x': /* Select abi/path to use */ + { + char *path = 0; + char *abi = 0; + + /* -x name= meaning name dwarfdump.conf file -x + abi= meaning select abi from dwarfdump.conf + file. Must always select abi to use dwarfdump.conf */ + if (strncmp(optarg, "name=", 5) == 0) { + path = makename(&optarg[5]); + if (strlen(path) < 1) + goto badopt; + config_file_path = path; + } else if (strncmp(optarg, "abi=", 4) == 0) { + abi = makename(&optarg[4]); + if (strlen(abi) < 1) + goto badopt; + config_file_abi = abi; + break; + } else { + badopt: + fprintf(stderr, "-x name= \n"); + fprintf(stderr, " and \n"); + fprintf(stderr, "-x abi= \n"); + fprintf(stderr, "are legal, not -x %s\n", optarg); + usage_error = TRUE; + break; + } + } + break; + case 'g': + use_old_dwarf_loclist = TRUE; + /* FALL THROUGH. */ + case 'i': + info_flag = TRUE; + break; + case 'l': + line_flag = TRUE; + break; + case 'f': + frame_flag = TRUE; + break; + case 'F': + eh_frame_flag = TRUE; + break; + case 'b': + abbrev_flag = TRUE; + break; + case 'p': + pubnames_flag = TRUE; + break; + case 'r': + aranges_flag = TRUE; + break; + case 'R': + generic_1000_regs = TRUE; + info_flag = TRUE; + break; + case 'm': + macinfo_flag = TRUE; + break; + case 'c': + loc_flag = TRUE; + break; + case 's': + string_flag = TRUE; + break; + case 'a': + do_all(); + break; + case 'v': + verbose++; + break; + case 'V': + { + printf("%s\n","Version 4May2007"); + } + break; + case 'd': + dense = TRUE; + break; + case 'e': + ellipsis = TRUE; + break; + case 'o': + reloc_flag = TRUE; + break; + case 'k': + dwarf_check = TRUE; + oarg = optarg[0]; + switch (oarg) { + case 'a': + check_pubname_attr = TRUE; + check_attr_tag = TRUE; + check_tag_tree = check_type_offset = TRUE; + pubnames_flag = info_flag = TRUE; + break; + case 'e': + check_pubname_attr = TRUE; + pubnames_flag = TRUE; + break; + case 'r': + check_attr_tag = TRUE; + info_flag = TRUE; + break; + case 't': + check_tag_tree = TRUE; + info_flag = TRUE; + break; + case 'y': + check_type_offset = TRUE; + info_flag = TRUE; + break; + default: + usage_error = TRUE; + break; + } + break; + case 'u': /* compile unit */ + cu_name_flag = TRUE; + strcpy(cu_name, optarg); + break; + case 't': + oarg = optarg[0]; + switch (oarg) { + case 'a': + /* all */ + static_func_flag = static_var_flag = TRUE; + break; + case 'f': + /* .debug_static_func */ + static_func_flag = TRUE; + break; + case 'v': + /* .debug_static_var */ + static_var_flag = TRUE; + break; + default: + usage_error = TRUE; + break; + } + break; + case 'y': /* .debug_types */ + type_flag = TRUE; + break; + case 'w': /* .debug_weaknames */ + weakname_flag = TRUE; + break; + case 'z': + fprintf(stderr, "-z is no longer supported:ignored\n"); + break; + case 'G': + show_global_offsets = TRUE; + break; + default: + usage_error = TRUE; + break; + } + } + + init_conf_file_data(&config_file_data); + if (config_file_abi && generic_1000_regs) { + printf("Specifying both -R and -x abi= is not allowed. Use one " + "or the other. -x abi= ignored.\n"); + config_file_abi = FALSE; + } + if(generic_1000_regs) { + init_generic_config_1000_regs(&config_file_data); + } + if (config_file_abi && (frame_flag || eh_frame_flag)) { + int res = find_conf_file_and_read_config(config_file_path, + config_file_abi, + config_file_defaults, + &config_file_data); + + if (res > 0) { + printf + ("Frame not configured due to error(s). Giving up.\n"); + eh_frame_flag = FALSE; + frame_flag = FALSE; + } + } + if (usage_error || (optind != (argc - 1))) { + print_usage_message(); + exit(FAILED); + } + return argv[optind]; +} + +static void +print_usage_message(void) +{ + fprintf(stderr, "Usage: %s \n", + program_name); + fprintf(stderr, "options:\t-a\tprint all .debug_* sections\n"); + fprintf(stderr, "\t\t-b\tprint abbrev section\n"); + fprintf(stderr, "\t\t-c\tprint loc section\n"); + fprintf(stderr, + "\t\t-d\tdense: one line per entry (info section only)\n"); + fprintf(stderr, + "\t\t-e\tellipsis: short names for tags, attrs etc.\n"); + fprintf(stderr, "\t\t-f\tprint dwarf frame section\n"); + fprintf(stderr, "\t\t-F\tprint gnu .eh_frame section\n"); + fprintf(stderr, "\t\t-g\t(use incomplete loclist support)\n"); + fprintf(stderr, "\t\t-G\tshow global die offsets\n"); + fprintf(stderr, "\t\t-h\tprint exception tables\n"); + fprintf(stderr, "\t\t-i\tprint info section\n"); + fprintf(stderr, "\t\t-k[aerty] check dwarf information\n"); + fprintf(stderr, "\t\t a\tdo all checks\n"); + fprintf(stderr, "\t\t e\texamine attributes of pubnames\n"); + fprintf(stderr, "\t\t r\texamine attr-tag relation\n"); + fprintf(stderr, "\t\t t\texamine tag trees\n"); + fprintf(stderr, "\t\t y\texamine type info\n"); + fprintf(stderr, "\t\t-l\tprint line section\n"); + fprintf(stderr, "\t\t-m\tprint macinfo section\n"); + fprintf(stderr, "\t\t-o\tprint relocation info\n"); + fprintf(stderr, "\t\t-p\tprint pubnames section\n"); + fprintf(stderr, "\t\t-r\tprint aranges section\n"); + fprintf(stderr, "\t\t-R\tPrint frame register names as r33 etc\n"); + fprintf(stderr, "\t\t \t and allow up to 1000 registers.\n"); + fprintf(stderr, "\t\t \t Print using a 'generic' register set.\n"); + fprintf(stderr, "\t\t-s\tprint string section\n"); + fprintf(stderr, "\t\t-t[afv] static: \n"); + fprintf(stderr, "\t\t a\tprint both sections\n"); + fprintf(stderr, "\t\t f\tprint static func section\n"); + fprintf(stderr, "\t\t v\tprint static var section\n"); + fprintf(stderr, + "\t\t-u print sections only for specified file\n"); + fprintf(stderr, "\t\t-v\tverbose: show more information\n"); + fprintf(stderr, "\t\t-vv verbose: show even more information\n"); + fprintf(stderr, "\t\t-V print version information\n"); + fprintf(stderr, "\t\t-x name=\tname dwarfdump.conf\n"); + fprintf(stderr, "\t\t-x abi=\tname abi in dwarfdump.conf\n"); + fprintf(stderr, "\t\t-w\tprint weakname section\n"); + fprintf(stderr, "\t\t-y\tprint type section\n"); + +} + +/* process each compilation unit in .debug_info */ +static void +print_infos(Dwarf_Debug dbg) +{ + Dwarf_Unsigned cu_header_length = 0; + Dwarf_Unsigned abbrev_offset = 0; + Dwarf_Half version_stamp = 0; + Dwarf_Half address_size = 0; + Dwarf_Die cu_die = 0; + Dwarf_Unsigned next_cu_offset = 0; + int nres = DW_DLV_OK; + + if (info_flag) + printf("\n.debug_info\n"); + + /* Loop until it fails. */ + while ((nres = + dwarf_next_cu_header(dbg, &cu_header_length, &version_stamp, + &abbrev_offset, &address_size, + &next_cu_offset, &err)) + == DW_DLV_OK) { + int sres; + + if (cu_name_flag) { + int tres; + Dwarf_Half tag; + Dwarf_Attribute attrib; + Dwarf_Half theform; + int fres; + int ares; + + sres = dwarf_siblingof(dbg, NULL, &cu_die, &err); + if (sres != DW_DLV_OK) { + print_error(dbg, "siblingof cu header", sres, err); + } + tres = dwarf_tag(cu_die, &tag, &err); + if (tres != DW_DLV_OK) { + print_error(dbg, "tag of cu die", tres, err); + } + ares = dwarf_attr(cu_die, DW_AT_name, &attrib, &err); + if (ares != DW_DLV_OK) { + print_error(dbg, "dwarf DW_AT_name ", ares, err); + } + fres = dwarf_whatform(attrib, &theform, &err); + if (fres != DW_DLV_OK) { + print_error(dbg, "dwarf_whatform problem ", fres, err); + } else if (theform == DW_FORM_string + || theform == DW_FORM_strp) { + string temps; + int strres; + string p; + + strres = dwarf_formstring(attrib, &temps, &err); + p = temps; + if (strres != DW_DLV_OK) { + print_error(dbg, + "formstring failed unexpectedly", + strres, err); + } + if (cu_name[0] != '/') { + p = strrchr(temps, '/'); + if (p == NULL) { + p = temps; + } else { + p++; + } + } + if (strcmp(cu_name, p)) { + continue; + } + } else { + print_error(dbg, + "dwarf_whatform unexpected value", + fres, err); + } + dwarf_dealloc(dbg, attrib, DW_DLA_ATTR); + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + } + if (verbose) { + if (dense) { + printf("<%s>", "cu_header"); + printf(" %s<%llu>", "cu_header_length", + cu_header_length); + printf(" %s<%d>", "version_stamp", version_stamp); + printf(" %s<%llu>", "abbrev_offset", abbrev_offset); + printf(" %s<%d>\n", "address_size", address_size); + + } else { + printf("\nCU_HEADER:\n"); + printf("\t\t%-28s%llu\n", "cu_header_length", + cu_header_length); + printf("\t\t%-28s%d\n", "version_stamp", version_stamp); + printf("\t\t%-28s%llu\n", "abbrev_offset", + abbrev_offset); + printf("\t\t%-28s%d", "address_size", address_size); + } + } + + /* process a single compilation unit in .debug_info. */ + sres = dwarf_siblingof(dbg, NULL, &cu_die, &err); + if (sres == DW_DLV_OK) { + if (info_flag || cu_name_flag) { + Dwarf_Signed cnt = 0; + char **srcfiles = 0; + int srcf = dwarf_srcfiles(cu_die, + &srcfiles, &cnt, &err); + + if (srcf != DW_DLV_OK) { + srcfiles = 0; + cnt = 0; + } + + print_die_and_children(dbg, cu_die, srcfiles, cnt); + if (srcf == DW_DLV_OK) { + int si; + + for (si = 0; si < cnt; ++si) { + dwarf_dealloc(dbg, srcfiles[si], DW_DLA_STRING); + } + dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST); + } + } + if (line_flag) + print_line_numbers_this_cu(dbg, cu_die); + dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); + } else if (sres == DW_DLV_NO_ENTRY) { + /* do nothing I guess. */ + } else { + print_error(dbg, "Regetting cu_die", sres, err); + } + cu_offset = next_cu_offset; + } + if (nres == DW_DLV_ERROR) { + string errmsg = dwarf_errmsg(err); + Dwarf_Unsigned myerr = dwarf_errno(err); + + fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", + program_name, "attempting to print .debug_info", + errmsg, (unsigned long) myerr); + fprintf(stderr, "attempting to continue.\n"); + } +} + +/* ARGSUSED */ +void +print_error(Dwarf_Debug dbg, string msg, int dwarf_code, + Dwarf_Error err) +{ + fflush(stdout); + fflush(stderr); + if (dwarf_code == DW_DLV_ERROR) { + string errmsg = dwarf_errmsg(err); + Dwarf_Unsigned myerr = dwarf_errno(err); + + fprintf(stderr, "%s ERROR: %s: %s (%lu)\n", + program_name, msg, errmsg, (unsigned long) myerr); + } else if (dwarf_code == DW_DLV_NO_ENTRY) { + fprintf(stderr, "%s NO ENTRY: %s: \n", program_name, msg); + } else if (dwarf_code == DW_DLV_OK) { + fprintf(stderr, "%s: %s \n", program_name, msg); + } else { + fprintf(stderr, "%s InternalError: %s: code %d\n", + program_name, msg, dwarf_code); + } + fflush(stderr); + exit(FAILED); + +}