--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_sections.c Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,1758 @@
+/*
+ Copyright (C) 2000,2003,2004,2005,2006 Silicon Graphics, Inc. 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/print_sections.c,v 1.69 2006/04/17 00:09:56 davea Exp $ */
+#include "globals.h"
+#include "dwarf_names.h"
+#include "dwconf.h"
+
+#include "print_frames.h"
+/*
+ * Print line number information:
+ * filename
+ * new basic-block
+ * [line] [address] <new statement>
+ */
+
+
+static void
+ print_pubname_style_entry(Dwarf_Debug dbg,
+ char *line_title,
+ char *name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_off,
+ Dwarf_Unsigned maxoff);
+
+
+/* referred in dwarfdump.c */
+Dwarf_Die current_cu_die_for_print_frames;
+
+/* If an offset is bad, libdwarf will notice it and
+ return an error.
+ If it does the error checking in
+ print_pubname_style_entry()
+ will be useless as we give up here on an error.
+
+ This intended for checking pubnames-style call return
+ values (for all the pubnames-style interfaces).
+
+ In at least one gigantic executable die_off turned out wrong.
+*/
+
+static void
+deal_with_name_offset_err(Dwarf_Debug dbg,
+ char *err_loc,
+ char *name, Dwarf_Unsigned die_off,
+ int nres, Dwarf_Error err)
+{
+ if (nres == DW_DLV_ERROR) {
+ Dwarf_Unsigned myerr = dwarf_errno(err);
+
+ if (myerr == DW_DLE_OFFSET_BAD) {
+ printf("Error: bad offset %s, %s %lld (0x%llx)\n",
+ err_loc,
+ name,
+ (long long) die_off, (unsigned long long) die_off);
+ }
+ print_error(dbg, err_loc, nres, err);
+ }
+}
+
+static void
+print_source_intro(Dwarf_Die cu_die)
+{
+ Dwarf_Off off = 0;
+ int ores = dwarf_dieoffset(cu_die, &off, &err);
+
+ if (ores == DW_DLV_OK) {
+ printf
+ ("Source lines (from CU-DIE at .debug_info offset %llu):\n",
+ (unsigned long long) off);
+ } else {
+ printf("Source lines (for the CU-DIE at unknown location):\n");
+ }
+}
+
+
+extern void
+print_line_numbers_this_cu(Dwarf_Debug dbg, Dwarf_Die cu_die)
+{
+ Dwarf_Signed linecount = 0;
+ Dwarf_Line *linebuf = NULL;
+ Dwarf_Signed i = 0;
+ Dwarf_Addr pc = 0;
+ Dwarf_Unsigned lineno = 0;
+ Dwarf_Signed column = 0;
+ string filename;
+ Dwarf_Bool newstatement = 0;
+ Dwarf_Bool lineendsequence = 0;
+ Dwarf_Bool new_basic_block = 0;
+ int lres = 0;
+ int sres = 0;
+ int ares = 0;
+ int lires = 0;
+ int cores = 0;
+
+ printf("\n.debug_line: line number info for a single cu\n");
+ if (verbose > 1) {
+ print_source_intro(cu_die);
+ print_one_die(dbg, cu_die, /* print_information= */ 1,
+ /* srcfiles= */ 0, /* cnt= */ 0);
+
+ lres = dwarf_print_lines(cu_die, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_srclines details", lres, err);
+ }
+ return;
+ }
+ lres = dwarf_srclines(cu_die, &linebuf, &linecount, &err);
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_srclines", lres, err);
+ } else if (lres == DW_DLV_NO_ENTRY) {
+ /* no line information is included */
+ } else {
+ print_source_intro(cu_die);
+ if (verbose) {
+ print_one_die(dbg, cu_die, /* print_information= */ 1,
+ /* srcfiles= */ 0, /* cnt= */ 0);
+ }
+ printf
+ ("<source>\t[row,column]\t<pc>\t//<new statement or basic block\n");
+
+ for (i = 0; i < linecount; i++) {
+ Dwarf_Line line = linebuf[i];
+ int nsres;
+
+ sres = dwarf_linesrc(line, &filename, &err);
+ ares = dwarf_lineaddr(line, &pc, &err);
+ if (sres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_linesrc", sres, err);
+ }
+ if (sres == DW_DLV_NO_ENTRY) {
+ filename = "<unknown>";
+ }
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_lineaddr", ares, err);
+ }
+ if (ares == DW_DLV_NO_ENTRY) {
+ pc = 0;
+ }
+ lires = dwarf_lineno(line, &lineno, &err);
+ if (lires == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_lineno", lires, err);
+ }
+ if (lires == DW_DLV_NO_ENTRY) {
+ lineno = -1LL;
+ }
+ cores = dwarf_lineoff(line, &column, &err);
+ if (cores == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_lineoff", cores, err);
+ }
+ if (cores == DW_DLV_NO_ENTRY) {
+ column = -1LL;
+ }
+ printf("%s:\t[%3llu,%2lld]\t%#llx", filename, lineno,
+ column, pc);
+ if (sres == DW_DLV_OK)
+ dwarf_dealloc(dbg, filename, DW_DLA_STRING);
+
+ nsres = dwarf_linebeginstatement(line, &newstatement, &err);
+ if (nsres == DW_DLV_OK) {
+ if (newstatement) {
+ printf("\t// new statement");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "linebeginstatment failed", nsres,
+ err);
+ }
+ nsres = dwarf_lineblock(line, &new_basic_block, &err);
+ if (nsres == DW_DLV_OK) {
+ if (new_basic_block) {
+ printf("\t// new basic block");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ nsres = dwarf_lineendsequence(line, &lineendsequence, &err);
+ if (nsres == DW_DLV_OK) {
+ if (lineendsequence) {
+ printf("\t// end of text sequence");
+ }
+ } else if (nsres == DW_DLV_ERROR) {
+ print_error(dbg, "lineblock failed", nsres, err);
+ }
+ printf("\n");
+
+ }
+ dwarf_srclines_dealloc(dbg, linebuf, linecount);
+ }
+}
+
+/*
+
+A strcpy which ensures NUL terminated string
+and never overruns the output.
+
+*/
+static void
+safe_strcpy(char *out, long outlen, char *in, long inlen)
+{
+ if (inlen >= (outlen - 1)) {
+ strncpy(out, in, outlen - 1);
+ out[outlen - 1] = 0;
+ } else {
+ strcpy(out, in);
+ }
+}
+
+/*
+ Returns 1 if a proc with this low_pc found.
+ Else returns 0.
+
+
+*/
+static int
+get_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc,
+ char *proc_name_buf, int proc_name_buf_len)
+{
+ Dwarf_Signed atcnt = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Attribute *atlist = NULL;
+ Dwarf_Addr low_pc_die = 0;
+ int atres = 0;
+ int funcres = 1;
+ int funcpcfound = 0;
+ int funcnamefound = 1;
+
+ proc_name_buf[0] = 0; /* always set to something */
+ atres = dwarf_attrlist(die, &atlist, &atcnt, &err);
+ if (atres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_attrlist", atres, err);
+ return 0;
+ }
+ if (atres == DW_DLV_NO_ENTRY) {
+ return 0;
+ }
+ for (i = 0; i < atcnt; i++) {
+ Dwarf_Half attr;
+ int ares;
+ string temps;
+ int sres;
+ int dres;
+
+ if (funcnamefound == 1 && funcpcfound == 1) {
+ /* stop as soon as both found */
+ break;
+ }
+ ares = dwarf_whatattr(atlist[i], &attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "get_proc_name whatattr error", ares, err);
+ } else if (ares == DW_DLV_OK) {
+ switch (attr) {
+ case DW_AT_name:
+ sres = dwarf_formstring(atlist[i], &temps, &err);
+ if (sres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "formstring in get_proc_name failed",
+ sres, err);
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ safe_strcpy(proc_name_buf, proc_name_buf_len,
+ "ERROR in dwarf_formstring!", 50);
+ } else if (sres == DW_DLV_NO_ENTRY) {
+ /* 50 is safe wrong length since is bigger than the
+ actual string */
+ safe_strcpy(proc_name_buf, proc_name_buf_len,
+ "NO ENTRY on dwarf_formstring?!", 50);
+ } else {
+ long len = (long) strlen(temps);
+
+ safe_strcpy(proc_name_buf, proc_name_buf_len, temps,
+ len);
+ }
+ funcnamefound = 1; /* FOUND THE NAME */
+ break;
+ case DW_AT_low_pc:
+ dres = dwarf_formaddr(atlist[i], &low_pc_die, &err);
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg, "formaddr in get_proc_name failed",
+ dres, err);
+ low_pc_die = ~low_pc;
+ /* ensure no match */
+ }
+ funcpcfound = 1;
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ for (i = 0; i < atcnt; i++) {
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
+ if (funcnamefound == 0 || funcpcfound == 0 || low_pc != low_pc_die) {
+ funcres = 0;
+ }
+ return (funcres);
+}
+
+/*
+ Modified Depth First Search looking for the procedure:
+ a) only looks for children of subprogram.
+ b) With subprogram looks at current die *before* looking
+ for a child.
+
+ Needed since some languages, including MP Fortran,
+ have nested functions.
+ Return 0 on failure, 1 on success.
+*/
+static int
+get_nested_proc_name(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr low_pc,
+ char *ret_name_buf, int ret_name_buf_len)
+{
+ char name_buf[BUFSIZ];
+ Dwarf_Die curdie = die;
+ int die_locally_gotten = 0;
+ Dwarf_Die prev_child = 0;
+ Dwarf_Die newchild = 0;
+ Dwarf_Die newsibling = 0;
+ Dwarf_Half tag;
+ Dwarf_Error err = 0;
+ int chres = DW_DLV_OK;
+
+ ret_name_buf[0] = 0;
+ while (chres == DW_DLV_OK) {
+ int tres;
+
+ tres = dwarf_tag(curdie, &tag, &err);
+ newchild = 0;
+ err = 0;
+ if (tres == DW_DLV_OK) {
+ int lchres;
+
+ if (tag == DW_TAG_subprogram) {
+ int proc_name_v;
+
+ proc_name_v = get_proc_name(dbg, curdie, low_pc,
+ name_buf, BUFSIZ);
+ if (proc_name_v) {
+ /* this is it */
+ safe_strcpy(ret_name_buf, ret_name_buf_len,
+ name_buf, (long) strlen(name_buf));
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do
+ not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 1;
+ }
+ /* check children of subprograms recursively should
+ this really be check children of anything? */
+
+ lchres = dwarf_child(curdie, &newchild, &err);
+ if (lchres == DW_DLV_OK) {
+ /* look for inner subprogram */
+ int newprog =
+ get_nested_proc_name(dbg, newchild, low_pc,
+ name_buf, BUFSIZ);
+
+ dwarf_dealloc(dbg, newchild, DW_DLA_DIE);
+ if (newprog) {
+ /* Found it. We could just take this name or
+ we could concatenate names together For now,
+ just take name */
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we
+ do not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ safe_strcpy(ret_name_buf, ret_name_buf_len,
+ name_buf, (long) strlen(name_buf));
+ return 1;
+ }
+ } else if (lchres == DW_DLV_NO_ENTRY) {
+ /* nothing to do */
+ } else {
+ print_error(dbg,
+ "get_nested_proc_name dwarf_child() failed ",
+ chres, err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do
+ not want to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ }
+ } /* end if TAG_subprogram */
+ } else {
+ print_error(dbg, "no tag on child read ", tres, err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ }
+ /* try next sibling */
+ prev_child = curdie;
+ chres = dwarf_siblingof(dbg, curdie, &newsibling, &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_cu_header On Child read ", chres,
+ err);
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+ } else if (chres == DW_DLV_NO_ENTRY) {
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, prev_child, DW_DLA_DIE);
+ }
+ return 0; /* proc name not at this level */
+ } else { /* DW_DLV_OK */
+ curdie = newsibling;
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want
+ to dealloc here! */
+ dwarf_dealloc(dbg, prev_child, DW_DLA_DIE);
+ }
+ prev_child = 0;
+ die_locally_gotten = 1;
+ }
+
+ }
+ if (die_locally_gotten) {
+ /* If we got this die from the parent, we do not want to
+ dealloc here! */
+ dwarf_dealloc(dbg, curdie, DW_DLA_DIE);
+ }
+ return 0;
+}
+
+/*
+ For MP Fortran and possibly other languages, functions
+ nest! As a result, we must dig thru all functions,
+ not just the top level.
+
+
+ This remembers the CU die and restarts each search at the start
+ of the current cu.
+
+
+*/
+string
+get_fde_proc_name(Dwarf_Debug dbg, Dwarf_Addr low_pc)
+{
+ static char proc_name[BUFSIZ];
+ Dwarf_Unsigned cu_header_length;
+ Dwarf_Unsigned abbrev_offset;
+ Dwarf_Half version_stamp;
+ Dwarf_Half address_size;
+ Dwarf_Unsigned next_cu_offset = 0;
+ int cures = DW_DLV_OK;
+ int dres = DW_DLV_OK;
+ int chres = DW_DLV_OK;
+ int looping = 0;
+
+ if (current_cu_die_for_print_frames == NULL) {
+ cures
+ = dwarf_next_cu_header(dbg, &cu_header_length,
+ &version_stamp, &abbrev_offset,
+ &address_size, &next_cu_offset,
+ &err);
+ if (cures == DW_DLV_ERROR) {
+ return NULL;
+ } else if (cures == DW_DLV_NO_ENTRY) {
+ /* loop thru the list again */
+ current_cu_die_for_print_frames = 0;
+ ++looping;
+ } else { /* DW_DLV_OK */
+ dres = dwarf_siblingof(dbg, NULL,
+ ¤t_cu_die_for_print_frames,
+ &err);
+ if (dres == DW_DLV_ERROR) {
+ return NULL;
+ }
+ }
+ }
+ if (dres == DW_DLV_OK) {
+ Dwarf_Die child = 0;
+
+ if (current_cu_die_for_print_frames == 0) {
+ /* no information. Possibly a stripped file */
+ return NULL;
+ }
+ chres =
+ dwarf_child(current_cu_die_for_print_frames, &child, &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_cu_header on child read ", chres,
+ err);
+ } else if (chres == DW_DLV_NO_ENTRY) {
+ } else { /* DW_DLV_OK */
+ int gotname =
+ get_nested_proc_name(dbg, child, low_pc, proc_name,
+ BUFSIZ);
+
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ if (gotname) {
+ return (proc_name);
+ }
+ child = 0;
+ }
+ }
+ for (;;) {
+ Dwarf_Die ldie;
+
+ cures = dwarf_next_cu_header(dbg, &cu_header_length,
+ &version_stamp, &abbrev_offset,
+ &address_size, &next_cu_offset,
+ &err);
+
+ if (cures != DW_DLV_OK) {
+ break;
+ }
+
+
+ dres = dwarf_siblingof(dbg, NULL, &ldie, &err);
+
+ if (current_cu_die_for_print_frames) {
+ dwarf_dealloc(dbg, current_cu_die_for_print_frames,
+ DW_DLA_DIE);
+ }
+ current_cu_die_for_print_frames = 0;
+ if (dres == DW_DLV_ERROR) {
+ print_error(dbg,
+ "dwarf_cu_header Child Read finding proc name for .debug_frame",
+ chres, err);
+ continue;
+ } else if (dres == DW_DLV_NO_ENTRY) {
+ ++looping;
+ if (looping > 1) {
+ print_error(dbg, "looping on cu headers!", dres, err);
+ return NULL;
+ }
+ continue;
+ }
+ /* DW_DLV_OK */
+ current_cu_die_for_print_frames = ldie;
+ {
+ int chres;
+ Dwarf_Die child;
+
+ chres =
+ dwarf_child(current_cu_die_for_print_frames, &child,
+ &err);
+ if (chres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf Child Read ", chres, err);
+ } else if (chres == DW_DLV_NO_ENTRY) {
+
+ ; /* do nothing, loop on cu */
+ } else { /* DW_DLV_OK) */
+
+ int gotname =
+ get_nested_proc_name(dbg, child, low_pc, proc_name,
+ BUFSIZ);
+
+ dwarf_dealloc(dbg, child, DW_DLA_DIE);
+ if (gotname) {
+ return (proc_name);
+ }
+ }
+ }
+ }
+ return (NULL);
+}
+
+/* get all the data in .debug_frame (or .eh_frame).
+ The '3' versions mean print using the dwarf3 new interfaces.
+ The non-3 mean use the old interfaces.
+ All combinations of requests are possible.
+*/
+extern void
+print_frames(Dwarf_Debug dbg, int print_debug_frame, int print_eh_frame,
+ struct dwconf_s *config_data)
+{
+ Dwarf_Cie *cie_data = NULL;
+ Dwarf_Signed cie_element_count = 0;
+ Dwarf_Fde *fde_data = NULL;
+ Dwarf_Signed fde_element_count = 0;
+ Dwarf_Signed i;
+ int fres = 0;
+ Dwarf_Half address_size = 0;
+ int framed = 0;
+
+ fres = dwarf_get_address_size(dbg, &address_size, &err);
+ if (fres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_address_size", fres, err);
+ }
+ for (framed = 0; framed < 2; ++framed) {
+ char *framename = 0;
+ int silent_if_missing = 0;
+ int is_eh = 0;
+
+ if (framed == 0) {
+ if (!print_debug_frame) {
+ continue;
+ }
+ framename = ".debug_frame";
+ /*
+ * Big question here is how to print all the info?
+ * Can print the logical matrix, but that is huge,
+ * though could skip lines that don't change.
+ * Either that, or print the instruction statement program
+ * that describes the changes.
+ */
+ fres =
+ dwarf_get_fde_list(dbg, &cie_data, &cie_element_count,
+ &fde_data, &fde_element_count, &err);
+ } else {
+ if (!print_eh_frame) {
+ continue;
+ }
+ is_eh = 1;
+ /* This is gnu g++ exceptions in a .eh_frame section. Which
+ is just like .debug_frame except that the empty, or
+ 'special' CIE_id is 0, not -1 (to distinguish fde from
+ cie). And the augmentation is "eh". As of egcs-1.1.2
+ anyway. A non-zero cie_id is in a fde and is the
+ difference between the fde address and the beginning of
+ the cie it belongs to. This makes sense as this is
+ intended to be referenced at run time, and is part of
+ the running image. For more on augmentation strings, see
+ libdwarf/dwarf_frame.c. */
+
+ /*
+ * Big question here is how to print all the info?
+ * Can print the logical matrix, but that is huge,
+ * though could skip lines that don't change.
+ * Either that, or print the instruction statement program
+ * that describes the changes.
+ */
+ silent_if_missing = 1;
+ framename = ".eh_frame";
+ fres =
+ dwarf_get_fde_list_eh(dbg, &cie_data,
+ &cie_element_count, &fde_data,
+ &fde_element_count, &err);
+ }
+ if (fres == DW_DLV_ERROR) {
+ printf("\n%s\n", framename);
+ print_error(dbg, "dwarf_get_fde_list", fres, err);
+ } else if (fres == DW_DLV_NO_ENTRY) {
+ if (!silent_if_missing)
+ printf("\n%s\n", framename);
+ /* no frame information */
+ } else { /* DW_DLV_OK */
+
+ printf("\n%s\n", framename);
+ printf("\nfde:\n");
+
+ for (i = 0; i < fde_element_count; i++) {
+ print_one_fde(dbg, fde_data[i],
+ i, cie_data, cie_element_count,
+ address_size, is_eh, config_data);
+ }
+ /*
+ Print the cie set. */
+ if (verbose) {
+ printf("\ncie:\n");
+ for (i = 0; i < cie_element_count; i++) {
+ print_one_cie(dbg, cie_data[i], i, address_size,
+ config_data);
+ }
+ }
+ dwarf_fde_cie_list_dealloc(dbg, cie_data, cie_element_count,
+ fde_data, fde_element_count);
+ }
+ }
+ if (current_cu_die_for_print_frames) {
+ dwarf_dealloc(dbg, current_cu_die_for_print_frames, DW_DLA_DIE);
+ current_cu_die_for_print_frames = 0;
+ }
+}
+
+
+
+
+int
+ dwarf_get_section_max_offsets(Dwarf_Debug /* dbg */ ,
+ Dwarf_Unsigned * /* debug_info_size
+ */ ,
+ Dwarf_Unsigned * /* debug_abbrev_size
+ */
+ , Dwarf_Unsigned * /* debug_line_size
+ */ ,
+ Dwarf_Unsigned * /* debug_loc_size
+ */ ,
+ Dwarf_Unsigned *
+ /* debug_aranges_size */ ,
+ Dwarf_Unsigned *
+ /* debug_macinfo_size */ ,
+ Dwarf_Unsigned *
+ /* debug_pubnames_size */ ,
+ Dwarf_Unsigned * /* debug_str_size
+ */ ,
+ Dwarf_Unsigned * /* debug_frame_size
+ */
+ , Dwarf_Unsigned * /* debug_ranges_size
+ */
+ , Dwarf_Unsigned *
+ /* debug_pubtypes_size */ );
+
+/* The new (April 2005) dwarf_get_section_max_offsets()
+ in libdwarf returns all max-offsets, but we only
+ want one of those offsets. This function returns
+ the one we want from that set,
+ making functions needing this offset as readable as possible.
+ (avoiding code duplication).
+*/
+static Dwarf_Unsigned
+get_info_max_offset(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned debug_info_size = 0;
+ Dwarf_Unsigned debug_abbrev_size = 0;
+ Dwarf_Unsigned debug_line_size = 0;
+ Dwarf_Unsigned debug_loc_size = 0;
+ Dwarf_Unsigned debug_aranges_size = 0;
+ Dwarf_Unsigned debug_macinfo_size = 0;
+ Dwarf_Unsigned debug_pubnames_size = 0;
+ Dwarf_Unsigned debug_str_size = 0;
+ Dwarf_Unsigned debug_frame_size = 0;
+ Dwarf_Unsigned debug_ranges_size = 0;
+ Dwarf_Unsigned debug_pubtypes_size = 0;
+
+ dwarf_get_section_max_offsets(dbg,
+ &debug_info_size,
+ &debug_abbrev_size,
+ &debug_line_size,
+ &debug_loc_size,
+ &debug_aranges_size,
+ &debug_macinfo_size,
+ &debug_pubnames_size,
+ &debug_str_size,
+ &debug_frame_size,
+ &debug_ranges_size,
+ &debug_pubtypes_size);
+
+ return debug_info_size;
+}
+
+/* This unifies the code for some error checks to
+ avoid code duplication.
+*/
+static void
+check_info_offset_sanity(char *sec,
+ char *field,
+ char *global,
+ Dwarf_Unsigned offset, Dwarf_Unsigned maxoff)
+{
+ if (maxoff == 0) {
+ /* Lets make a heuristic check. */
+ if (offset > 0xffffffff) {
+ printf("Warning: section %s %s %s offset 0x%llx "
+ "exceptionally large \n",
+ sec, field, global, (unsigned long long) offset);
+ }
+ }
+ if (offset >= maxoff) {
+ printf("Warning: section %s %s %s offset 0x%llx "
+ "larger than max of 0x%llx\n",
+ sec, field, global, (unsigned long long) offset,
+ (unsigned long long) maxoff);
+ }
+}
+
+/* Unified pubnames style output.
+ The error checking here against maxoff may be useless
+ (in that libdwarf may return an error if the offset is bad
+ and we will not get called here).
+ But we leave it in nonetheless as it looks sensible.
+ In at least one gigantic executable such offsets turned out wrong.
+*/
+static void
+print_pubname_style_entry(Dwarf_Debug dbg,
+ char *line_title,
+ char *name,
+ Dwarf_Unsigned die_off,
+ Dwarf_Unsigned cu_off,
+ Dwarf_Unsigned global_cu_offset,
+ Dwarf_Unsigned maxoff)
+{
+ Dwarf_Die die = NULL;
+ Dwarf_Die cu_die = NULL;
+ Dwarf_Off die_CU_off = 0;
+ int dres = 0;
+ int ddres = 0;
+ int cudres = 0;
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK)
+ print_error(dbg, "dwarf_offdie", dres, err);
+
+ /* get offset of die from its cu-header */
+ ddres = dwarf_die_CU_offset(die, &die_CU_off, &err);
+ if (ddres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_die_CU_offset", ddres, err);
+ }
+
+ /* get die at offset cu_off */
+ cudres = dwarf_offdie(dbg, cu_off, &cu_die, &err);
+ if (cudres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ print_error(dbg, "dwarf_offdie", cudres, err);
+ }
+ printf("%s %-15s die-in-sect %lld, cu-in-sect %lld,"
+ " die-in-cu %lld, cu-header-in-sect %lld",
+ line_title, name, (long long) die_off, (long long) cu_off,
+ /* the cu die offset */
+ (long long) die_CU_off,
+ /* following is absolute offset of the ** beginning of the
+ cu */
+ (long long) (die_off - die_CU_off));
+
+ if ((die_off - die_CU_off) != global_cu_offset) {
+ printf(" error: real cuhdr %llu", global_cu_offset);
+ exit(1);
+ }
+ if (verbose) {
+ printf(" cuhdr %llu", global_cu_offset);
+ }
+
+
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+
+
+ printf("\n");
+
+ check_info_offset_sanity(line_title,
+ "die offset", name, die_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "die cu offset", name, die_CU_off, maxoff);
+ check_info_offset_sanity(line_title,
+ "cu offset", name,
+ (die_off - die_CU_off), maxoff);
+
+}
+
+
+/* get all the data in .debug_pubnames */
+extern void
+print_pubnames(Dwarf_Debug dbg)
+{
+ Dwarf_Global *globbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = 0;
+ int res = 0;
+
+ printf("\n.debug_pubnames\n");
+ res = dwarf_get_globals(dbg, &globbuf, &count, &err);
+ if (res == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_globals", res, err);
+ } else if (res == DW_DLV_NO_ENTRY) {
+ /* (err == 0 && count == DW_DLV_NOCOUNT) means there are no
+ pubnames. */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int nres;
+ int cures3;
+ Dwarf_Off global_cu_off = 0;
+
+ nres = dwarf_global_name_offsets(globbuf[i],
+ &name, &die_off, &cu_off,
+ &err);
+ deal_with_name_offset_err(dbg, "dwarf_global_name_offsets",
+ name, die_off, nres, err);
+
+ cures3 = dwarf_global_cu_offset(globbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "global",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+
+
+ ares =
+ dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+ pubname_attr_result.checks++;
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ pubname_attr_result.errors++;
+ DWARF_CHECK_ERROR2(name,
+ "pubname does not have DW_AT_external")
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+ }
+ dwarf_globals_dealloc(dbg, globbuf, count);
+ }
+} /* print_pubnames() */
+
+
+struct macro_counts_s {
+ long mc_start_file;
+ long mc_end_file;
+ long mc_define;
+ long mc_undef;
+ long mc_extension;
+ long mc_code_zero;
+ long mc_unknown;
+};
+
+static void
+print_one_macro_entry_detail(long i,
+ char *type,
+ struct Dwarf_Macro_Details_s *mdp)
+{
+ /* "DW_MACINFO_*: section-offset file-index [line] string\n" */
+ if (mdp->dmd_macro) {
+ printf("%3ld %s: %6llu %2lld [%4lld] \"%s\" \n",
+ i,
+ type,
+ mdp->dmd_offset,
+ mdp->dmd_fileindex, mdp->dmd_lineno, mdp->dmd_macro);
+ } else {
+ printf("%3ld %s: %6llu %2lld [%4lld] 0\n",
+ i,
+ type,
+ mdp->dmd_offset, mdp->dmd_fileindex, mdp->dmd_lineno);
+ }
+
+}
+
+static void
+print_one_macro_entry(long i,
+ struct Dwarf_Macro_Details_s *mdp,
+ struct macro_counts_s *counts)
+{
+
+ switch (mdp->dmd_type) {
+ case 0:
+ counts->mc_code_zero++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_type-code-0", mdp);
+ break;
+
+ case DW_MACINFO_start_file:
+ counts->mc_start_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_start_file", mdp);
+ break;
+
+ case DW_MACINFO_end_file:
+ counts->mc_end_file++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_end_file ", mdp);
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ counts->mc_extension++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_vendor_ext", mdp);
+ break;
+
+ case DW_MACINFO_define:
+ counts->mc_define++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_define ", mdp);
+ break;
+
+ case DW_MACINFO_undef:
+ counts->mc_undef++;
+ print_one_macro_entry_detail(i, "DW_MACINFO_undef ", mdp);
+ break;
+
+ default:
+ {
+ char create_type[50]; /* More than large enough. */
+
+ counts->mc_unknown++;
+ snprintf(create_type, sizeof(create_type),
+ "DW_MACINFO_0x%x", mdp->dmd_type);
+ print_one_macro_entry_detail(i, create_type, mdp);
+ }
+ break;
+ }
+}
+
+/* print data in .debug_macinfo */
+/* FIXME: should print name of file whose index is in macro data
+ here -- somewhere.
+*/
+ /*ARGSUSED*/ extern void
+print_macinfo(Dwarf_Debug dbg)
+{
+ Dwarf_Off offset = 0;
+ Dwarf_Unsigned max = 0;
+ Dwarf_Signed count = 0;
+ long group = 0;
+ Dwarf_Macro_Details *maclist = NULL;
+ int lres = 0;
+
+ printf("\n.debug_macinfo\n");
+
+ while ((lres = dwarf_get_macro_details(dbg, offset,
+ max, &count, &maclist,
+ &err)) == DW_DLV_OK) {
+ long i;
+ struct macro_counts_s counts;
+
+
+ memset(&counts, 0, sizeof(counts));
+
+ printf("\n");
+ printf("compilation-unit .debug_macinfo # %ld\n", group);
+ printf
+ ("num name section-offset file-index [line] \"string\"\n");
+ for (i = 0; i < count; i++) {
+ struct Dwarf_Macro_Details_s *mdp = &maclist[i];
+
+ print_one_macro_entry(i, mdp, &counts);
+ }
+
+ if (counts.mc_start_file == 0) {
+ printf
+ ("DW_MACINFO file count of zero is invalid DWARF2/3\n");
+ }
+ if (counts.mc_start_file != counts.mc_end_file) {
+ printf("Counts of DW_MACINFO file (%ld) end_file (%ld) "
+ "do not match!.\n",
+ counts.mc_start_file, counts.mc_end_file);
+ }
+ if (counts.mc_code_zero < 1) {
+ printf("Count of zeros in macro group should be non-zero "
+ "(1 preferred), count is %ld\n",
+ counts.mc_code_zero);
+ }
+ printf("Macro counts: start file %ld, "
+ "end file %ld, "
+ "define %ld, "
+ "undef %ld "
+ "ext %ld, "
+ "code-zero %ld, "
+ "unknown %ld\n",
+ counts.mc_start_file,
+ counts.mc_end_file,
+ counts.mc_define,
+ counts.mc_undef,
+ counts.mc_extension,
+ counts.mc_code_zero, counts.mc_unknown);
+
+
+ /* int type= maclist[count - 1].dmd_type; */
+ /* ASSERT: type is zero */
+
+ offset = maclist[count - 1].dmd_offset + 1;
+ dwarf_dealloc(dbg, maclist, DW_DLA_STRING);
+ ++group;
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_macro_details", lres, err);
+ }
+}
+
+/* print data in .debug_loc */
+extern void
+print_locs(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Addr hipc_offset = 0;
+ Dwarf_Addr lopc_offset = 0;
+ Dwarf_Ptr data = 0;
+ Dwarf_Unsigned entry_len = 0;
+ Dwarf_Unsigned next_entry = 0;
+ int lres = 0;
+
+ printf("\n.debug_loc format <o b e l> means "
+ "section-offset begin-addr end-addr length-of-block-entry\n");
+ while ((lres = dwarf_get_loclist_entry(dbg, offset,
+ &hipc_offset, &lopc_offset,
+ &data, &entry_len,
+ &next_entry,
+ &err)) == DW_DLV_OK) {
+ printf("\t <obel> 0x%08llx 0x%09llx " "0x%08llx " "%8lld\n",
+ (long long) offset, (long long) lopc_offset,
+ (long long) hipc_offset, (long long) entry_len);
+ offset = next_entry;
+ }
+ if (lres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_loclist_entry", lres, err);
+ }
+}
+
+/* print data in .debug_abbrev */
+extern void
+print_abbrevs(Dwarf_Debug dbg)
+{
+ Dwarf_Abbrev ab;
+ Dwarf_Unsigned offset = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Unsigned attr_count = 0;
+ Dwarf_Half tag = 0;
+ Dwarf_Half attr = 0;
+ Dwarf_Signed form = 0;
+ Dwarf_Off off = 0;
+ Dwarf_Unsigned i = 0;
+ string child_name;
+ Dwarf_Unsigned abbrev_num = 1;
+ Dwarf_Signed child_flag = 0;
+ int abres = 0;
+ int tres = 0;
+ int acres = 0;
+ Dwarf_Unsigned abbrev_code = 0;
+
+ printf("\n.debug_abbrev\n");
+ while ((abres = dwarf_get_abbrev(dbg, offset, &ab,
+ &length, &attr_count,
+ &err)) == DW_DLV_OK) {
+
+ if (attr_count == 0) {
+ /* Simple innocuous zero : null abbrev entry */
+ if (dense) {
+ printf("<%lld><%lld><%lld><%s>\n", abbrev_num, offset, (signed long long) /* abbrev_code
+ */ 0,
+ "null .debug_abbrev entry");
+ } else {
+ printf("<%4lld><%5lld><code: %2lld> %-20s\n", abbrev_num, offset, (signed long long) /* abbrev_code
+ */ 0,
+ "null .debug_abbrev entry");
+ }
+
+ offset += length;
+ ++abbrev_num;
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ continue;
+ }
+ tres = dwarf_get_abbrev_tag(ab, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_tag", tres, err);
+ }
+ tres = dwarf_get_abbrev_code(ab, &abbrev_code, &err);
+ if (tres != DW_DLV_OK) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_code", tres, err);
+ }
+ if (dense)
+ printf("<%lld><%lld><%lld><%s>", abbrev_num,
+ offset, abbrev_code, get_TAG_name(dbg, tag));
+ else
+ printf("<%4lld><%5lld><code: %2lld> %-20s", abbrev_num,
+ offset, abbrev_code, get_TAG_name(dbg, tag));
+ ++abbrev_num;
+ acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &err);
+ if (acres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_children_flag", acres,
+ err);
+ }
+ if (acres == DW_DLV_NO_ENTRY) {
+ child_flag = 0;
+ }
+ child_name = get_children_name(dbg, child_flag);
+ if (dense)
+ printf(" %s", child_name);
+ else
+ printf("%s\n", child_name);
+ /* Abbrev just contains the format of a die, which debug_info
+ then points to with the real data. So here we just print the
+ given format. */
+ for (i = 0; i < attr_count; i++) {
+ int aeres;
+
+ aeres =
+ dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &err);
+ if (aeres == DW_DLV_ERROR) {
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ print_error(dbg, "dwarf_get_abbrev_entry", aeres, err);
+ }
+ if (aeres == DW_DLV_NO_ENTRY) {
+ attr = -1LL;
+ form = -1LL;
+ }
+ if (dense)
+ printf(" <%ld>%s<%s>", (unsigned long) off,
+ get_AT_name(dbg, attr),
+ get_FORM_name(dbg, (Dwarf_Half) form));
+ else
+ printf(" <%5ld>\t%-28s%s\n",
+ (unsigned long) off, get_AT_name(dbg, attr),
+ get_FORM_name(dbg, (Dwarf_Half) form));
+ }
+ dwarf_dealloc(dbg, ab, DW_DLA_ABBREV);
+ offset += length;
+ if (dense)
+ printf("\n");
+ }
+ if (abres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_abbrev", abres, err);
+ }
+}
+
+/* print data in .debug_string */
+extern void
+print_strings(Dwarf_Debug dbg)
+{
+ Dwarf_Signed length = 0;
+ string name;
+ Dwarf_Off offset = 0;
+ int sres = 0;
+
+ printf("\n.debug_string\n");
+ while ((sres = dwarf_get_str(dbg, offset, &name, &length, &err))
+ == DW_DLV_OK) {
+ printf("name at offset %lld, length %lld is %s\n",
+ offset, length, name);
+ offset += length + 1;
+ }
+ /* An inability to find the section is not necessarily
+ a real error, so do not report error unless we've
+ seen a real record. */
+ if(sres == DW_DLV_ERROR && offset != 0) {
+ print_error(dbg, "dwarf_get_str failure", sres, err);
+ }
+}
+
+/* get all the data in .debug_aranges */
+extern void
+print_aranges(Dwarf_Debug dbg)
+{
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Arange *arange_buf = NULL;
+ Dwarf_Addr start = 0;
+ Dwarf_Unsigned length = 0;
+ Dwarf_Off cu_die_offset = 0;
+ Dwarf_Die cu_die = NULL;
+ int ares = 0;
+ int aires = 0;
+
+ printf("\n.debug_aranges\n");
+ ares = dwarf_get_aranges(dbg, &arange_buf, &count, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_aranges", ares, err);
+ } else if (ares == DW_DLV_NO_ENTRY) {
+ /* no arange is included */
+ } else {
+ for (i = 0; i < count; i++) {
+ aires = dwarf_get_arange_info(arange_buf[i],
+ &start, &length,
+ &cu_die_offset, &err);
+ if (aires != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_arange_info", aires, err);
+ } else {
+ int dres;
+
+ dres = dwarf_offdie(dbg, cu_die_offset, &cu_die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ } else {
+ if (cu_name_flag) {
+ Dwarf_Half tag;
+ Dwarf_Attribute attrib;
+ Dwarf_Half theform;
+ int tres;
+ int dares;
+ int fres;
+
+ tres = dwarf_tag(cu_die, &tag, &err);
+ if (tres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_tag in aranges",
+ tres, err);
+ }
+ dares =
+ dwarf_attr(cu_die, DW_AT_name, &attrib,
+ &err);
+ if (dares != DW_DLV_OK) {
+ print_error(dbg, "dwarf_attr arange"
+ " derived die has no name",
+ dres, err);
+ }
+ fres = dwarf_whatform(attrib, &theform, &err);
+ if (fres == DW_DLV_OK) {
+ if (theform == DW_FORM_string
+ || theform == DW_FORM_strp) {
+ string temps;
+ int sres;
+
+ sres =
+ dwarf_formstring(attrib, &temps,
+ &err);
+ if (sres == DW_DLV_OK) {
+ string p = temps;
+
+ if (cu_name[0] != '/') {
+ p = strrchr(temps, '/');
+ if (p == NULL) {
+ p = temps;
+ } else {
+ p++;
+ }
+ }
+ if (!strcmp(cu_name, p)) {
+ } else {
+ continue;
+ }
+ } else {
+ print_error(dbg,
+ "arange: string missing",
+ sres, err);
+ }
+ }
+ } else {
+ print_error(dbg,
+ "dwarf_whatform unexpected value",
+ fres, err);
+ }
+ dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
+ }
+ printf("\narange starts at %llx, "
+ "length of %lld, cu_die_offset = %lld",
+ start, length, cu_die_offset);
+ /* get the offset of the cu header itself in the
+ section */
+ {
+ Dwarf_Off off = 0;
+ int cures3 =
+ dwarf_get_arange_cu_header_offset(arange_buf
+ [i],
+ &off,
+ &err);
+
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_cu_hdr_offset",
+ cures3, err);
+ }
+ if (verbose)
+ printf(" cuhdr %llu", off);
+ }
+ printf("\n");
+ print_one_die(dbg, cu_die, (boolean) TRUE,
+ /* srcfiles= */ 0,
+ /* cnt= */ 0);
+
+ dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
+ }
+ }
+ /* print associated die too? */
+ dwarf_dealloc(dbg, arange_buf[i], DW_DLA_ARANGE);
+ }
+ dwarf_dealloc(dbg, arange_buf, DW_DLA_LIST);
+ }
+}
+
+/* Get all the data in .debug_static_funcs
+ On error, this allows some dwarf memory leaks.
+*/
+extern void
+print_static_funcs(Dwarf_Debug dbg)
+{
+ Dwarf_Func *funcbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ int gfres = 0;
+
+ printf("\n.debug_static_func\n");
+ gfres = dwarf_get_funcs(dbg, &funcbuf, &count, &err);
+ if (gfres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_funcs", gfres, err);
+ } else if (gfres == DW_DLV_NO_ENTRY) {
+ /* no static funcs */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int fnres;
+ int cures3;
+ Dwarf_Unsigned global_cu_off = 0;
+ char *name = 0;
+
+ fnres =
+ dwarf_func_name_offsets(funcbuf[i], &name, &die_off,
+ &cu_off, &err);
+ deal_with_name_offset_err(dbg, "dwarf_func_name_offsets",
+ name, die_off, fnres, err);
+
+ cures3 = dwarf_func_cu_offset(funcbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "static-func", name, die_off,
+ cu_off, global_cu_off, maxoff);
+
+
+ /* print associated die too? */
+ if (check_pubname_attr) {
+ Dwarf_Bool has_attr;
+ int ares;
+ int dres;
+ Dwarf_Die die;
+
+ /* get die at die_off */
+ dres = dwarf_offdie(dbg, die_off, &die, &err);
+ if (dres != DW_DLV_OK) {
+ print_error(dbg, "dwarf_offdie", dres, err);
+ }
+
+
+ ares =
+ dwarf_hasattr(die, DW_AT_external, &has_attr, &err);
+ if (ares == DW_DLV_ERROR) {
+ print_error(dbg, "hassattr on DW_AT_external", ares,
+ err);
+ }
+ pubname_attr_result.checks++;
+ if (ares == DW_DLV_OK && has_attr) {
+ /* Should the value of flag be examined? */
+ } else {
+ pubname_attr_result.errors++;
+ DWARF_CHECK_ERROR2(name,
+ "pubname does not have DW_AT_external")
+ }
+ dwarf_dealloc(dbg, die, DW_DLA_DIE);
+ }
+ }
+ dwarf_funcs_dealloc(dbg, funcbuf, count);
+ }
+} /* print_static_funcs() */
+
+/* get all the data in .debug_static_vars */
+extern void
+print_static_vars(Dwarf_Debug dbg)
+{
+ Dwarf_Var *varbuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = 0;
+ int gvres = 0;
+
+ printf("\n.debug_static_vars\n");
+ gvres = dwarf_get_vars(dbg, &varbuf, &count, &err);
+ if (gvres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_vars", gvres, err);
+ } else if (gvres == DW_DLV_NO_ENTRY) {
+ /* no static vars */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int vnres;
+ int cures3;
+ Dwarf_Off global_cu_off = 0;
+
+ vnres =
+ dwarf_var_name_offsets(varbuf[i], &name, &die_off,
+ &cu_off, &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_var_name_offsets",
+ name, die_off, vnres, err);
+
+ cures3 = dwarf_var_cu_offset(varbuf[i],
+ &global_cu_off, &err);
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_global_cu_offset", cures3, err);
+ }
+
+ print_pubname_style_entry(dbg,
+ "static-var",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dwarf_vars_dealloc(dbg, varbuf, count);
+ }
+} /* print_static_vars */
+
+/* get all the data in .debug_types */
+extern void
+print_types(Dwarf_Debug dbg, enum type_type_e type_type)
+{
+ Dwarf_Type *typebuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = NULL;
+ int gtres = 0;
+
+ char *section_name = NULL;
+ char *offset_err_name = NULL;
+ char *section_open_name = NULL;
+ char *print_name_prefix = NULL;
+ int (*get_types) (Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *,
+ Dwarf_Error *)
+ = 0;
+ int (*get_offset) (Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *,
+ Dwarf_Error *) = NULL;
+ int (*get_cu_offset) (Dwarf_Type, Dwarf_Off *, Dwarf_Error *) =
+ NULL;
+ void (*dealloctype) (Dwarf_Debug, Dwarf_Type *, Dwarf_Signed) =
+ NULL;
+
+
+ if (type_type == DWARF_PUBTYPES) {
+ section_name = ".debug_pubtypes";
+ offset_err_name = "dwarf_pubtype_name_offsets";
+ section_open_name = "dwarf_get_pubtypes";
+ print_name_prefix = "pubtype";
+ get_types = dwarf_get_pubtypes;
+ get_offset = dwarf_pubtype_name_offsets;
+ get_cu_offset = dwarf_pubtype_cu_offset;
+ dealloctype = dwarf_pubtypes_dealloc;
+ } else {
+ /* SGI_TYPENAME */
+ section_name = ".debug_typenames";
+ offset_err_name = "dwarf_type_name_offsets";
+ section_open_name = "dwarf_get_types";
+ print_name_prefix = "type";
+ get_types = dwarf_get_types;
+ get_offset = dwarf_type_name_offsets;
+ get_cu_offset = dwarf_type_cu_offset;
+ dealloctype = dwarf_types_dealloc;
+ }
+
+
+
+ gtres = get_types(dbg, &typebuf, &count, &err);
+ if (gtres == DW_DLV_ERROR) {
+ print_error(dbg, section_open_name, gtres, err);
+ } else if (gtres == DW_DLV_NO_ENTRY) {
+ /* no types */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ /* Before July 2005, the section name was printed
+ unconditionally, now only prints if non-empty section really
+ exists. */
+ printf("\n%s\n", section_name);
+
+ for (i = 0; i < count; i++) {
+ int tnres;
+ int cures3;
+ Dwarf_Off global_cu_off = 0;
+
+ tnres =
+ get_offset(typebuf[i], &name, &die_off, &cu_off, &err);
+ deal_with_name_offset_err(dbg, offset_err_name, name,
+ die_off, tnres, err);
+
+ cures3 = get_cu_offset(typebuf[i], &global_cu_off, &err);
+
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_var_cu_offset", cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ print_name_prefix,
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dealloctype(dbg, typebuf, count);
+ }
+} /* print_types() */
+
+/* get all the data in .debug_weaknames */
+extern void
+print_weaknames(Dwarf_Debug dbg)
+{
+ Dwarf_Weak *weaknamebuf = NULL;
+ Dwarf_Signed count = 0;
+ Dwarf_Signed i = 0;
+ Dwarf_Off die_off = 0;
+ Dwarf_Off cu_off = 0;
+ char *name = NULL;
+ int wkres = 0;
+
+ printf("\n.debug_weaknames\n");
+ wkres = dwarf_get_weaks(dbg, &weaknamebuf, &count, &err);
+ if (wkres == DW_DLV_ERROR) {
+ print_error(dbg, "dwarf_get_weaks", wkres, err);
+ } else if (wkres == DW_DLV_NO_ENTRY) {
+ /* no weaknames */
+ } else {
+ Dwarf_Unsigned maxoff = get_info_max_offset(dbg);
+
+ for (i = 0; i < count; i++) {
+ int tnres;
+ int cures3;
+
+ Dwarf_Unsigned global_cu_off = 0;
+
+ tnres = dwarf_weak_name_offsets(weaknamebuf[i],
+ &name, &die_off, &cu_off,
+ &err);
+ deal_with_name_offset_err(dbg,
+ "dwarf_weak_name_offsets",
+ name, die_off, tnres, err);
+
+ cures3 = dwarf_weak_cu_offset(weaknamebuf[i],
+ &global_cu_off, &err);
+
+ if (cures3 != DW_DLV_OK) {
+ print_error(dbg, "dwarf_weakname_cu_offset",
+ cures3, err);
+ }
+ print_pubname_style_entry(dbg,
+ "weakname",
+ name, die_off, cu_off,
+ global_cu_off, maxoff);
+
+ /* print associated die too? */
+ }
+ dwarf_weaks_dealloc(dbg, weaknamebuf, count);
+ }
+} /* print_weaknames() */
+
+
+
+/*
+ decode ULEB
+*/
+Dwarf_Unsigned
+local_dwarf_decode_u_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ unsigned char byte = 0;
+ Dwarf_Unsigned number = 0;
+ unsigned int shift = 0;
+ unsigned int byte_length = 1;
+
+ byte = *leb128;
+ for (;;) {
+ number |= (byte & 0x7f) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+ }
+
+ byte_length++;
+ byte = *(++leb128);
+ }
+}
+
+#define BITSINBYTE 8
+Dwarf_Signed
+local_dwarf_decode_s_leb128(unsigned char *leb128,
+ unsigned int *leb128_length)
+{
+ Dwarf_Signed number = 0;
+ Dwarf_Bool sign = 0;
+ Dwarf_Signed shift = 0;
+ unsigned char byte = *leb128;
+ Dwarf_Signed byte_length = 1;
+
+ /* byte_length being the number of bytes of data absorbed so far in
+ turning the leb into a Dwarf_Signed. */
+
+ for (;;) {
+ sign = byte & 0x40;
+ number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
+ shift += 7;
+
+ if ((byte & 0x80) == 0) {
+ break;
+ }
+ ++leb128;
+ byte = *leb128;
+ byte_length++;
+ }
+
+ if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
+ number |= -((Dwarf_Signed) 1 << shift);
+ }
+
+ if (leb128_length != NULL)
+ *leb128_length = byte_length;
+ return (number);
+}
+
+
+/* Dumping a dwarf-expression as a byte stream. */
+void
+dump_block(char *prefix, char *data, Dwarf_Signed len)
+{
+ char *end_data = data + len;
+ char *cur = data;
+ int i = 0;
+
+ printf("%s", prefix);
+ for (; cur < end_data; ++cur, ++i) {
+ if (i > 0 && i % 4 == 0)
+ printf(" ");
+ printf("%02x", 0xff & *cur);
+
+ }
+}