diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-10-20 14:42:03 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-10-20 14:42:03 +0400 |
commit | bb1c3da3c12651f1c408d96dd6d33ae157bdadd6 (patch) | |
tree | 4a535b35500684ac6a928bf0fd661325b5a04697 /dwarfexample | |
download | dwarfutils-upstream.tar.gz |
Imported Upstream version 20120410upstream/20120410upstream
Diffstat (limited to 'dwarfexample')
-rw-r--r-- | dwarfexample/ChangeLog | 5 | ||||
-rw-r--r-- | dwarfexample/ChangeLog2009 | 8 | ||||
-rw-r--r-- | dwarfexample/ChangeLog2010 | 11 | ||||
-rw-r--r-- | dwarfexample/Makefile | 18 | ||||
-rw-r--r-- | dwarfexample/NEWS | 6 | ||||
-rw-r--r-- | dwarfexample/frame1.c | 408 | ||||
-rw-r--r-- | dwarfexample/simplereader.c | 384 |
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); + } +} + + + |