tools/elf4rom/libs/dwarf-20071209/dwarfdump/dwarfdump.c
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/libs/dwarf-20071209/dwarfdump/dwarfdump.c	Fri Jan 15 09:07:44 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#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, "<item>                  <checks><errors>\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=<path> meaning name dwarfdump.conf file -x
+		   abi=<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=<path-to-conf> \n");
+		    fprintf(stderr, " and  \n");
+		    fprintf(stderr, "-x abi=<abi-in-conf> \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 <options> <object file>\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<file> 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=<path>\tname dwarfdump.conf\n");
+    fprintf(stderr, "\t\t-x abi=<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);
+
+}