summaryrefslogtreecommitdiff
path: root/dwarfexample
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
committerIgor Pashev <pashev.igor@gmail.com>2012-10-20 14:42:03 +0400
commitbb1c3da3c12651f1c408d96dd6d33ae157bdadd6 (patch)
tree4a535b35500684ac6a928bf0fd661325b5a04697 /dwarfexample
downloaddwarfutils-upstream.tar.gz
Imported Upstream version 20120410upstream/20120410upstream
Diffstat (limited to 'dwarfexample')
-rw-r--r--dwarfexample/ChangeLog5
-rw-r--r--dwarfexample/ChangeLog20098
-rw-r--r--dwarfexample/ChangeLog201011
-rw-r--r--dwarfexample/Makefile18
-rw-r--r--dwarfexample/NEWS6
-rw-r--r--dwarfexample/frame1.c408
-rw-r--r--dwarfexample/simplereader.c384
7 files changed, 840 insertions, 0 deletions
diff --git a/dwarfexample/ChangeLog b/dwarfexample/ChangeLog
new file mode 100644
index 0000000..e635b2f
--- /dev/null
+++ b/dwarfexample/ChangeLog
@@ -0,0 +1,5 @@
+2011-06-04 DavidAnderson <davea42@earthlink.net>
+ * frame1.c, simplereader.c: Altered indentation to
+ multiples of 4 spaces, no tabs. No substantive change.
+2011-01-13 DavidAnderson <davea42@earthlink.net>
+ * New year starts.
diff --git a/dwarfexample/ChangeLog2009 b/dwarfexample/ChangeLog2009
new file mode 100644
index 0000000..e65d29b
--- /dev/null
+++ b/dwarfexample/ChangeLog2009
@@ -0,0 +1,8 @@
+August 7, 2009 David Anderson <davea42@earthlink.net>
+ * frame1.c: This is a new example that uses frame functions.
+July 21, 2009 David Anderson <davea42@earthlink.net>
+ * simplereader.c: After cur_die = sib_die; nothing was printing
+ cur_die, so added a print call after the assignment.
+July 8, 2009 David Anderson <davea42@earthlink.net>
+ * Makefile: New trivial Makefile to build the example.
+ * simplereader.c: New trivial example using libdwarf.
diff --git a/dwarfexample/ChangeLog2010 b/dwarfexample/ChangeLog2010
new file mode 100644
index 0000000..76ebe69
--- /dev/null
+++ b/dwarfexample/ChangeLog2010
@@ -0,0 +1,11 @@
+April 26, 2010 David Anderson <davea42@earthlink.net>
+ * simplereader.c: Now prints all TAGs regardless of
+ whether a DIE has a DW_AT_name attribute. All names
+ print an "" pair so it's easy to recognize empty names
+ and names with embedded spaces.
+March 31, 2010 David Anderson <davea42@earthlink.net>
+ * simplereader.c: Added a new option --names which
+ shows additional detail on getting attributes and source
+ file information.
+January 3, 2010 David Anderson <davea42@earthlink.net>
+ * frame1.c, simplereader.c: Update copyright year.
diff --git a/dwarfexample/Makefile b/dwarfexample/Makefile
new file mode 100644
index 0000000..0fb18d2
--- /dev/null
+++ b/dwarfexample/Makefile
@@ -0,0 +1,18 @@
+
+
+LIBDIR= -L../libdwarf
+LIBS= -ldwarf -lelf
+CFLAGS= -Wall -I../libdwarf
+
+all: simplereader frame1
+
+simplereader: simplereader.c
+ $(CC) $(CFLAGS) simplereader.c -o simplereader $(LIBDIR) $(LIBS)
+frame1: frame1.c
+ $(CC) $(CFLAGS) frame1.c -o frame1 $(LIBDIR) $(LIBS)
+
+clean:
+ rm -f simplereader.o
+ rm -f simplereader
+ rm -f frame1
+ rm -f frame1.o
diff --git a/dwarfexample/NEWS b/dwarfexample/NEWS
new file mode 100644
index 0000000..c9ad467
--- /dev/null
+++ b/dwarfexample/NEWS
@@ -0,0 +1,6 @@
+July 21, 2009
+ Roni Simonian noticed a call to print_die_data(dbg,cur_die,in_level);
+ was missing so not all DIEs would print. Good Catch!
+July 8, 2009
+ Created a sample libdwarf consumer. Using BSD license so
+ anyone can use it. And a trivial Makefile.
diff --git a/dwarfexample/frame1.c b/dwarfexample/frame1.c
new file mode 100644
index 0000000..80d3430
--- /dev/null
+++ b/dwarfexample/frame1.c
@@ -0,0 +1,408 @@
+/*
+ Copyright (c) 2009-2010 David Anderson.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the example nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+/* simplereader.c
+ This is an example of code reading dwarf .debug_frame.
+ It is kept as simple as possible to expose essential features.
+ It does not do all possible error reporting or error handling.
+
+ It specifically calls dwarf_expand_frame_instructions()
+ to verify that works without crashing!
+
+ To use, try
+ make
+ ./frame1 frame1
+*/
+#include <sys/types.h> /* For open() */
+#include <sys/stat.h> /* For open() */
+#include <fcntl.h> /* For open() */
+#include <stdlib.h> /* For exit() */
+#include <unistd.h> /* For close() */
+#include <string.h> /* For strcmp* */
+#include <stdio.h>
+#include <errno.h>
+#include "dwarf.h"
+#include "libdwarf.h"
+
+
+static void read_frame_data(Dwarf_Debug dbg);
+static void print_fde_instrs(Dwarf_Debug dbg, Dwarf_Fde fde,
+ int fdenum, Dwarf_Error *error);
+static void print_regtable(Dwarf_Fde fde,Dwarf_Regtable3 *tab3,int oldrulecount,
+ Dwarf_Debug dbg,Dwarf_Error *error);
+static void
+print_cie_instrs(Dwarf_Debug dbg,Dwarf_Cie cie,Dwarf_Error *error);
+
+
+#define UNDEF_VAL 2000
+#define SAME_VAL 2001
+#define CFA_VAL 2002
+
+
+int
+main(int argc, char **argv)
+{
+
+ Dwarf_Debug dbg = 0;
+ int fd = -1;
+ const char *filepath = "<stdin>";
+ int res = DW_DLV_ERROR;
+ Dwarf_Error error;
+ Dwarf_Handler errhand = 0;
+ Dwarf_Ptr errarg = 0;
+ int regtabrulecount = 0;
+
+ if(argc < 2) {
+ fd = 0; /* stdin */
+ } else {
+ filepath = argv[1];
+ fd = open(filepath,O_RDONLY);
+ }
+ if(fd < 0) {
+ printf("Failure attempting to open %s\n",filepath);
+ }
+ res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("Giving up, dwarf_init failed, cannot do DWARF processing\n");
+ exit(1);
+ }
+ /* Do this setting after init before any real operations.
+ These return the old values, but here we do not
+ need to know the old values. The sizes and
+ values here are higher than most ABIs and entirely
+ arbitrary.
+
+ The setting of initial_value to
+ the same as undefined-value (the other possible choice being
+ same-value) is arbitrary, different ABIs do differ, and
+ you have to know which is right. */
+ regtabrulecount=1999;
+ dwarf_set_frame_undefined_value(dbg, UNDEF_VAL);
+ dwarf_set_frame_rule_initial_value(dbg, UNDEF_VAL);
+ dwarf_set_frame_same_value(dbg,SAME_VAL);
+ dwarf_set_frame_cfa_value(dbg,CFA_VAL);
+ dwarf_set_frame_rule_table_size(dbg,regtabrulecount);
+
+ read_frame_data(dbg);
+ res = dwarf_finish(dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_finish failed!\n");
+ }
+ close(fd);
+ return 0;
+}
+
+static void
+read_frame_data(Dwarf_Debug dbg)
+{
+ Dwarf_Error error;
+ Dwarf_Signed cie_element_count = 0;
+ Dwarf_Signed fde_element_count = 0;
+ Dwarf_Cie *cie_data = 0;
+ Dwarf_Fde *fde_data = 0;
+ int res = DW_DLV_ERROR;
+ Dwarf_Signed fdenum = 0;
+
+
+ res = dwarf_get_fde_list(dbg,&cie_data,&cie_element_count,
+ &fde_data,&fde_element_count,&error);
+ if(res == DW_DLV_NO_ENTRY) {
+ printf("No frame data present ");
+ exit(0);
+ }
+ if( res == DW_DLV_ERROR) {
+ printf("Error reading frame data ");
+ exit(1);
+ }
+ printf( "%" DW_PR_DSd " cies present. "
+ "%" DW_PR_DSd " fdes present. \n",
+ cie_element_count,fde_element_count);
+ /*if(fdenum >= fde_element_count) {
+ printf("Want fde %d but only %" DW_PR_DSd " present\n",fdenum,
+ fde_element_count);
+ exit(1);
+ }*/
+
+ for(fdenum = 0; fdenum < fde_element_count; ++fdenum) {
+ Dwarf_Cie cie = 0;
+ printf("Print cie of fde %" DW_PR_DSd "\n",fdenum);
+ res = dwarf_get_cie_of_fde(fde_data[fdenum],&cie,&error);
+ if(res != DW_DLV_OK) {
+ printf("Error accessing fdenum %" DW_PR_DSd
+ " to get its cie\n",fdenum);
+ exit(1);
+ }
+ print_cie_instrs(dbg,cie,&error);
+ printf("Print fde %" DW_PR_DSd "\n",fdenum);
+ print_fde_instrs(dbg,fde_data[fdenum],fdenum,&error);
+ }
+
+ /* Done with the data. */
+ dwarf_fde_cie_list_dealloc(dbg,cie_data,cie_element_count,
+ fde_data, fde_element_count);
+ return;
+}
+static void
+print_cie_instrs(Dwarf_Debug dbg,Dwarf_Cie cie,Dwarf_Error *error)
+{
+ int res = DW_DLV_ERROR;
+ Dwarf_Unsigned bytes_in_cie = 0;
+ Dwarf_Small version = 0;
+ char *augmentation = 0;
+ Dwarf_Unsigned code_alignment_factor = 0;
+ Dwarf_Signed data_alignment_factor = 0;
+ Dwarf_Half return_address_register_rule = 0;
+ Dwarf_Ptr instrp = 0;
+ Dwarf_Unsigned instr_len = 0;
+
+ res = dwarf_get_cie_info(cie,&bytes_in_cie,
+ &version, &augmentation, &code_alignment_factor,
+ &data_alignment_factor, &return_address_register_rule,
+ &instrp,&instr_len,error);
+ if(res != DW_DLV_OK) {
+ printf("Unable to get cie info!\n");
+ exit(1);
+ }
+}
+
+static void
+print_frame_instrs(Dwarf_Debug dbg,Dwarf_Frame_Op *frame_op_list,
+ Dwarf_Signed frame_op_count)
+{
+ Dwarf_Signed i = 0;
+ printf("Base op. Ext op. Reg. Offset. Instr-offset.\n");
+ for(i = 0; i < frame_op_count; ++i) {
+ printf("[%" DW_PR_DSd "]", i);
+ printf(" %d. ", frame_op_list[i].fp_base_op);
+ printf(" %d. ", frame_op_list[i].fp_extended_op);
+ printf(" %" DW_PR_DSd ". ", frame_op_list[i].fp_offset);
+ printf(" 0x%" DW_PR_DUx ". ", frame_op_list[i].fp_instr_offset);
+ printf("\n");
+ }
+}
+
+static void
+print_fde_instrs(Dwarf_Debug dbg,
+ Dwarf_Fde fde,int fdenum, Dwarf_Error *error)
+{
+ int res;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Unsigned func_length = 0;
+ Dwarf_Ptr fde_bytes;
+ Dwarf_Unsigned fde_byte_length = 0;
+ Dwarf_Off cie_offset = 0;
+ Dwarf_Signed cie_index = 0;
+ Dwarf_Off fde_offset = 0;
+ Dwarf_Addr arbitrary_addr = 0;
+ Dwarf_Addr actual_pc = 0;
+ Dwarf_Regtable3 tab3;
+ int oldrulecount = 0;
+ Dwarf_Ptr outinstrs = 0;
+ Dwarf_Unsigned instrslen = 0;
+ Dwarf_Frame_Op * frame_op_list = 0;
+ Dwarf_Signed frame_op_count = 0;
+ Dwarf_Cie cie = 0;
+
+
+ res = dwarf_get_fde_range(fde,&lowpc,&func_length,&fde_bytes,
+ &fde_byte_length,&cie_offset,&cie_index,&fde_offset,error);
+ if(res != DW_DLV_OK) {
+ printf("Problem getting fde range \n");
+ exit(1);
+ }
+
+ arbitrary_addr = lowpc + (func_length/2);
+ printf("function low pc 0x%" DW_PR_DUx
+ " and length 0x%" DW_PR_DUx
+ " and addr we choose 0x%" DW_PR_DUx
+ "\n",
+ lowpc,func_length,arbitrary_addr);
+
+ /* 1 is arbitrary. We are winding up getting the
+ rule count here while leaving things unchanged. */
+ oldrulecount = dwarf_set_frame_rule_table_size(dbg,1);
+ dwarf_set_frame_rule_table_size(dbg,oldrulecount);
+
+ tab3.rt3_reg_table_size = oldrulecount;
+ tab3.rt3_rules = (struct Dwarf_Regtable_Entry3_s *) malloc(
+ sizeof(struct Dwarf_Regtable_Entry3_s)* oldrulecount);
+ if (!tab3.rt3_rules) {
+ printf("Unable to malloc for %d rules\n",oldrulecount);
+ exit(1);
+ }
+
+ res = dwarf_get_fde_info_for_all_regs3(fde,arbitrary_addr ,
+ &tab3,&actual_pc,error);
+
+ if(res != DW_DLV_OK) {
+ printf("dwarf_get_fde_info_for_all_regs3 failed!\n");
+ exit(1);
+ }
+ print_regtable(fde,&tab3,oldrulecount,dbg,error);
+
+ res = dwarf_get_fde_instr_bytes(fde,&outinstrs,&instrslen,error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_get_fde_instr_bytes failed!\n");
+ exit(1);
+ }
+ res = dwarf_get_cie_of_fde(fde,&cie,error);
+ if(res != DW_DLV_OK) {
+ printf("Error getting cie from fde\n");
+ exit(1);
+ }
+
+ res = dwarf_expand_frame_instructions(cie,
+ outinstrs,instrslen,&frame_op_list,
+ &frame_op_count,error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_expand_frame_instructions failed!\n");
+ exit(1);
+ }
+ printf("Frame op count: %" DW_PR_DUu "\n",frame_op_count);
+ print_frame_instrs(dbg,frame_op_list,frame_op_count);
+
+ dwarf_dealloc(dbg,frame_op_list, DW_DLA_FRAME_BLOCK);
+ free(tab3.rt3_rules);
+}
+
+static void
+print_reg(int r)
+{
+ switch(r) {
+ case SAME_VAL:
+ printf(" %d SAME_VAL ",r);
+ break;
+ case UNDEF_VAL:
+ printf(" %d UNDEF_VAL ",r);
+ break;
+ case CFA_VAL:
+ printf(" %d (CFA) ",r);
+ break;
+ default:
+ printf(" r%d ",r);
+ break;
+ }
+}
+
+static void
+print_one_regentry(const char *prefix,Dwarf_Fde fde,Dwarf_Debug dbg,
+ int oldrulecount,struct Dwarf_Regtable_Entry3_s *entry,
+ Dwarf_Error * error)
+{
+ int is_cfa = !strcmp("cfa",prefix);
+ printf("%s ",prefix);
+ printf("type: %d %s ",
+ entry->dw_value_type,
+ (entry->dw_value_type == DW_EXPR_OFFSET)? "DW_EXPR_OFFSET":
+ (entry->dw_value_type == DW_EXPR_VAL_OFFSET)? "DW_EXPR_VAL_OFFSET":
+ (entry->dw_value_type == DW_EXPR_EXPRESSION)? "DW_EXPR_EXPRESSION":
+ (entry->dw_value_type == DW_EXPR_VAL_EXPRESSION)?
+ "DW_EXPR_VAL_EXPRESSION":
+ "Unknown");
+ switch(entry->dw_value_type) {
+ case DW_EXPR_OFFSET:
+ print_reg(entry->dw_regnum);
+ printf(" offset_rel? %d ",entry->dw_offset_relevant);
+ if(entry->dw_offset_relevant) {
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ if(is_cfa) {
+ printf("defines cfa value");
+ } else {
+ printf("address of value is CFA plus signed offset");
+ }
+ if(!is_cfa && entry->dw_regnum != CFA_VAL) {
+ printf(" compiler botch, regnum != CFA_VAL");
+ }
+ } else {
+ printf("value in register");
+ }
+ break;
+ case DW_EXPR_VAL_OFFSET:
+ print_reg(entry->dw_regnum);
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ if(is_cfa) {
+ printf("does this make sense? No?");
+ } else {
+ printf("value at CFA plus signed offset");
+ }
+ if(!is_cfa && entry->dw_regnum != CFA_VAL) {
+ printf(" compiler botch, regnum != CFA_VAL");
+ }
+ break;
+ case DW_EXPR_EXPRESSION:
+ print_reg(entry->dw_regnum);
+ printf(" offset_rel? %d ",entry->dw_offset_relevant);
+ printf(" offset %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
+ printf(" Value is at address given by expr val ");
+ /* printf(" block-ptr 0x%" DW_PR_DUx " ",
+ (Dwarf_Unsigned)entry->dw_block_ptr); */
+ break;
+ case DW_EXPR_VAL_EXPRESSION:
+ printf(" expression byte len %" DW_PR_DSd " " ,
+ entry->dw_offset_or_block_len);
+ printf("Block ptr set? %s ",entry->dw_block_ptr?"yes":"no");
+ printf(" Value is expr val ");
+ if(!entry->dw_block_ptr) {
+ printf("Compiler botch. ");
+ }
+ /* printf(" block-ptr 0x%" DW_PR_DUx " ",
+ (Dwarf_Unsigned)entry->dw_block_ptr); */
+ break;
+ }
+ printf("\n");
+}
+
+static void
+print_regtable(Dwarf_Fde fde,Dwarf_Regtable3 *tab3,int oldrulecount,
+ Dwarf_Debug dbg,Dwarf_Error *error)
+{
+ int r;
+ /* We won't print too much. A bit arbitrary. */
+ int max = 10;
+ if(max > tab3->rt3_reg_table_size) {
+ max = tab3->rt3_reg_table_size;
+ }
+ print_one_regentry("cfa",fde,dbg,oldrulecount,&tab3->rt3_cfa_rule,
+ error);
+
+ for(r = 0; r < max; r++) {
+ char rn[30];
+ snprintf(rn,sizeof(rn),"reg %d",r);
+ print_one_regentry(rn, fde,dbg,oldrulecount,tab3->rt3_rules+r,
+ error);
+ }
+
+
+}
+
+
+
+
diff --git a/dwarfexample/simplereader.c b/dwarfexample/simplereader.c
new file mode 100644
index 0000000..da21b65
--- /dev/null
+++ b/dwarfexample/simplereader.c
@@ -0,0 +1,384 @@
+/*
+ Copyright (c) 2009-2010 David Anderson. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the example nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+/* simplereader.c
+ This is an example of code reading dwarf .debug_info.
+ It is kept as simple as possible to expose essential features.
+ It does not do all possible error reporting or error handling.
+
+ The --names
+ option adds some extra printing.
+
+ To use, try
+ make
+ ./simplereader simplereader
+*/
+#include <sys/types.h> /* For open() */
+#include <sys/stat.h> /* For open() */
+#include <fcntl.h> /* For open() */
+#include <stdlib.h> /* For exit() */
+#include <unistd.h> /* For close() */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "dwarf.h"
+#include "libdwarf.h"
+
+struct srcfilesdata {
+ char ** srcfiles;
+ Dwarf_Signed srcfilescount;
+ int srcfilesres;
+};
+
+static void read_cu_list(Dwarf_Debug dbg);
+static void print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level,
+ struct srcfilesdata *sf);
+static void get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level,
+ struct srcfilesdata *sf);
+static void resetsrcfiles(Dwarf_Debug dbg,struct srcfilesdata *sf);
+
+static int namesoptionon = 0;
+
+int
+main(int argc, char **argv)
+{
+
+ Dwarf_Debug dbg = 0;
+ int fd = -1;
+ const char *filepath = "<stdin>";
+ int res = DW_DLV_ERROR;
+ Dwarf_Error error;
+ Dwarf_Handler errhand = 0;
+ Dwarf_Ptr errarg = 0;
+
+ if(argc < 2) {
+ fd = 0; /* stdin */
+ } else {
+ int i = 0;
+ for(i = 1; i < (argc-1) ; ++i) {
+ if(strcmp(argv[i],"--names") == 0) {
+ namesoptionon=1;
+ } else {
+ printf("Unknown argument \"%s\" ignored\n",argv[i]);
+ }
+ }
+ filepath = argv[i];
+ fd = open(filepath,O_RDONLY);
+ }
+ if(argc > 2) {
+ }
+ if(fd < 0) {
+ printf("Failure attempting to open \"%s\"\n",filepath);
+ }
+ res = dwarf_init(fd,DW_DLC_READ,errhand,errarg, &dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("Giving up, cannot do DWARF processing\n");
+ exit(1);
+ }
+
+ read_cu_list(dbg);
+ res = dwarf_finish(dbg,&error);
+ if(res != DW_DLV_OK) {
+ printf("dwarf_finish failed!\n");
+ }
+ close(fd);
+ return 0;
+}
+
+static void
+read_cu_list(Dwarf_Debug dbg)
+{
+ Dwarf_Unsigned cu_header_length = 0;
+ Dwarf_Half version_stamp = 0;
+ Dwarf_Unsigned abbrev_offset = 0;
+ Dwarf_Half address_size = 0;
+ Dwarf_Unsigned next_cu_header = 0;
+ Dwarf_Error error;
+ int cu_number = 0;
+
+ for(;;++cu_number) {
+ struct srcfilesdata sf;
+ sf.srcfilesres = DW_DLV_ERROR;
+ sf.srcfiles = 0;
+ sf.srcfilescount = 0;
+ Dwarf_Die no_die = 0;
+ Dwarf_Die cu_die = 0;
+ int res = DW_DLV_ERROR;
+ res = dwarf_next_cu_header(dbg,&cu_header_length,
+ &version_stamp, &abbrev_offset, &address_size,
+ &next_cu_header, &error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_next_cu_header\n");
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Done. */
+ return;
+ }
+ /* The CU will have a single sibling, a cu_die. */
+ res = dwarf_siblingof(dbg,no_die,&cu_die,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_siblingof on CU die \n");
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Impossible case. */
+ printf("no entry! in dwarf_siblingof on CU die \n");
+ exit(1);
+ }
+ get_die_and_siblings(dbg,cu_die,0,&sf);
+ dwarf_dealloc(dbg,cu_die,DW_DLA_DIE);
+ resetsrcfiles(dbg,&sf);
+ }
+}
+
+static void
+get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level,
+ struct srcfilesdata *sf)
+{
+ int res = DW_DLV_ERROR;
+ Dwarf_Die cur_die=in_die;
+ Dwarf_Die child = 0;
+ Dwarf_Error error;
+
+ print_die_data(dbg,in_die,in_level,sf);
+
+ for(;;) {
+ Dwarf_Die sib_die = 0;
+ res = dwarf_child(cur_die,&child,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_child , level %d \n",in_level);
+ exit(1);
+ }
+ if(res == DW_DLV_OK) {
+ get_die_and_siblings(dbg,child,in_level+1,sf);
+ }
+ /* res == DW_DLV_NO_ENTRY */
+ res = dwarf_siblingof(dbg,cur_die,&sib_die,&error);
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_siblingof , level %d \n",in_level);
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ /* Done at this level. */
+ break;
+ }
+ /* res == DW_DLV_OK */
+ if(cur_die != in_die) {
+ dwarf_dealloc(dbg,cur_die,DW_DLA_DIE);
+ }
+ cur_die = sib_die;
+ print_die_data(dbg,cur_die,in_level,sf);
+ }
+ return;
+}
+static void
+get_addr(Dwarf_Attribute attr,Dwarf_Addr *val)
+{
+ Dwarf_Error error = 0;
+ int res;
+ Dwarf_Addr uval = 0;
+ res = dwarf_formaddr(attr,&uval,&error);
+ if(res == DW_DLV_OK) {
+ *val = uval;
+ return;
+ }
+ return;
+}
+static void
+get_number(Dwarf_Attribute attr,Dwarf_Unsigned *val)
+{
+ Dwarf_Error error = 0;
+ int res;
+ Dwarf_Signed sval = 0;
+ Dwarf_Unsigned uval = 0;
+ res = dwarf_formudata(attr,&uval,&error);
+ if(res == DW_DLV_OK) {
+ *val = uval;
+ return;
+ }
+ res = dwarf_formsdata(attr,&sval,&error);
+ if(res == DW_DLV_OK) {
+ *val = sval;
+ return;
+ }
+ return;
+}
+static void
+print_subprog(Dwarf_Debug dbg,Dwarf_Die die, int level,
+ struct srcfilesdata *sf)
+{
+ int res;
+ Dwarf_Error error = 0;
+ Dwarf_Attribute *attrbuf = 0;
+ Dwarf_Addr lowpc = 0;
+ Dwarf_Addr highpc = 0;
+ Dwarf_Signed attrcount = 0;
+ Dwarf_Unsigned i;
+ Dwarf_Unsigned filenum = 0;
+ Dwarf_Unsigned linenum = 0;
+ char *filename = 0;
+ res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
+ if(res != DW_DLV_OK) {
+ return;
+ }
+ for(i = 0; i < attrcount ; ++i) {
+ Dwarf_Half aform;
+ res = dwarf_whatattr(attrbuf[i],&aform,&error);
+ if(res == DW_DLV_OK) {
+ if(aform == DW_AT_decl_file) {
+ get_number(attrbuf[i],&filenum);
+ if((filenum > 0) && (sf->srcfilescount > (filenum-1))) {
+ filename = sf->srcfiles[filenum-1];
+ }
+ }
+ if(aform == DW_AT_decl_line) {
+ get_number(attrbuf[i],&linenum);
+ }
+ if(aform == DW_AT_low_pc) {
+ get_addr(attrbuf[i],&lowpc);
+ }
+ if(aform == DW_AT_high_pc) {
+ get_addr(attrbuf[i],&highpc);
+ }
+ }
+ dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR);
+ }
+ if(filenum || linenum) {
+ printf("<%3d> file: %" DW_PR_DUu " %s line %"
+ DW_PR_DUu "\n",level,filenum,filename?filename:"",linenum);
+ }
+ if(lowpc) {
+ printf("<%3d> low_pc : 0x%" DW_PR_DUx "\n",
+ level, (Dwarf_Unsigned)lowpc);
+ }
+ if(highpc) {
+ printf("<%3d> high_pc: 0x%" DW_PR_DUx "\n",
+ level, (Dwarf_Unsigned)highpc);
+ }
+ dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST);
+}
+
+static void
+print_comp_dir(Dwarf_Debug dbg,Dwarf_Die die,int level, struct srcfilesdata *sf)
+{
+ int res;
+ Dwarf_Error error = 0;
+ Dwarf_Attribute *attrbuf = 0;
+ Dwarf_Signed attrcount = 0;
+ Dwarf_Unsigned i;
+ res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
+ if(res != DW_DLV_OK) {
+ return;
+ }
+ sf->srcfilesres = dwarf_srcfiles(die,&sf->srcfiles,&sf->srcfilescount,
+ &error);
+ for(i = 0; i < attrcount ; ++i) {
+ Dwarf_Half aform;
+ res = dwarf_whatattr(attrbuf[i],&aform,&error);
+ if(res == DW_DLV_OK) {
+ if(aform == DW_AT_comp_dir) {
+ char *name = 0;
+ res = dwarf_formstring(attrbuf[i],&name,&error);
+ if(res == DW_DLV_OK) {
+ printf( "<%3d> compilation directory : \"%s\"\n",
+ level,name);
+ }
+ }
+ if(aform == DW_AT_stmt_list) {
+ /* Offset of stmt list for this CU in .debug_line */
+ }
+ }
+ dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR);
+ }
+ dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST);
+}
+
+static void
+resetsrcfiles(Dwarf_Debug dbg,struct srcfilesdata *sf)
+{
+ Dwarf_Signed sri = 0;
+ for (sri = 0; sri < sf->srcfilescount; ++sri) {
+ dwarf_dealloc(dbg, sf->srcfiles[sri], DW_DLA_STRING);
+ }
+ dwarf_dealloc(dbg, sf->srcfiles, DW_DLA_LIST);
+ sf->srcfilesres = DW_DLV_ERROR;
+ sf->srcfiles = 0;
+ sf->srcfilescount = 0;
+}
+
+static void
+print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level,
+ struct srcfilesdata *sf)
+{
+ char *name = 0;
+ Dwarf_Error error = 0;
+ Dwarf_Half tag = 0;
+ const char *tagname = 0;
+ int localname = 0;
+
+ int res = dwarf_diename(print_me,&name,&error);
+
+ if(res == DW_DLV_ERROR) {
+ printf("Error in dwarf_diename , level %d \n",level);
+ exit(1);
+ }
+ if(res == DW_DLV_NO_ENTRY) {
+ name = "<no DW_AT_name attr>";
+ localname = 1;
+ }
+ res = dwarf_tag(print_me,&tag,&error);
+ if(res != DW_DLV_OK) {
+ printf("Error in dwarf_tag , level %d \n",level);
+ exit(1);
+ }
+ res = dwarf_get_TAG_name(tag,&tagname);
+ if(res != DW_DLV_OK) {
+ printf("Error in dwarf_get_TAG_name , level %d \n",level);
+ exit(1);
+ }
+ if(namesoptionon) {
+ if( tag == DW_TAG_subprogram) {
+ printf( "<%3d> subprogram : \"%s\"\n",level,name);
+ print_subprog(dbg,print_me,level,sf);
+ } else if (tag == DW_TAG_compile_unit ||
+ tag == DW_TAG_partial_unit ||
+ tag == DW_TAG_type_unit) {
+
+ resetsrcfiles(dbg,sf);
+ printf( "<%3d> source file : \"%s\"\n",level,name);
+ print_comp_dir(dbg,print_me,level,sf);
+ }
+ } else {
+ printf("<%d> tag: %d %s name: \"%s\"\n",level,tag,tagname,name);
+ }
+ if(!localname) {
+ dwarf_dealloc(dbg,name,DW_DLA_STRING);
+ }
+}
+
+
+