diff options
-rw-r--r-- | dwarf.c | 310 |
1 files changed, 127 insertions, 183 deletions
@@ -1,198 +1,142 @@ -/* - Copyright (c) 2009, 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. - - 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 <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> #include <stdio.h> #include <errno.h> #include "dwarf.h" #include "libdwarf.h" -static void read_cu_list(Dwarf_Debug dbg); -static void print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level); -static void get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level); - -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 { - 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, 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 parse_dwarf(Dwarf_Debug dbg, const char *struct_name, const char *field_name); +static void parse_level(Dwarf_Debug dbg, Dwarf_Die die, const char *struct_name, const char *field_name, int level); -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) { - 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); - dwarf_dealloc(dbg,cu_die,DW_DLA_DIE); - } +void usage(char *argv[]) { + printf("%s file struct field\n", argv[0]); } -static void -get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level) -{ - 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); - - 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); - } - /* 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; - } - return; +int main(int argc, char *argv[]) { + Dwarf_Debug dbg = 0; + int fd = -1; + const char *filepath; + const char *struct_name, *field_name; + int res = DW_DLV_ERROR; + Dwarf_Error error; + Dwarf_Handler errhand = 0; + Dwarf_Ptr errarg = 0; + + if(argc < 4) { + usage(argv); + exit(1); + } + + filepath = argv[1]; + struct_name = argv[2]; + field_name = argv[3]; + + 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, cannot do DWARF processing\n"); + exit(1); + } + + parse_dwarf(dbg, struct_name, field_name); + + res = dwarf_finish(dbg,&error); + if(res != DW_DLV_OK) { + printf("dwarf_finish failed!\n"); + } + close(fd); + return 0; } -static void -print_die_data(Dwarf_Debug dbg, Dwarf_Die print_me,int level) -{ - char *name = 0; - Dwarf_Error error = 0; - Dwarf_Half tag = 0; - const char *tagname = 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) { - return; - } - 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); - } - printf("<%d> tag: %d %s name: %s\n",level,tag,tagname,name); - dwarf_dealloc(dbg,name,DW_DLA_STRING); +static void parse_dwarf(Dwarf_Debug dbg, const char *struct_name, + const char *field_name) { + Dwarf_Bool is_info = 1; + Dwarf_Unsigned cu_length; + Dwarf_Half cu_version; + Dwarf_Off cu_abbrev_offset; + Dwarf_Half cu_pointer_size; + Dwarf_Half cu_offset_size; + Dwarf_Half cu_extension_size; + Dwarf_Sig8 type_signature; + Dwarf_Unsigned type_offset; + Dwarf_Unsigned cu_next_offset; + Dwarf_Error err; + int rc; + + + while (1) { + Dwarf_Die die, next; + + rc = dwarf_next_cu_header_c(dbg, is_info, &cu_length, + &cu_version, &cu_abbrev_offset, &cu_pointer_size, + &cu_offset_size, &cu_extension_size, &type_signature, + &type_offset, &cu_next_offset, &err); + + if (rc == DW_DLV_NO_ENTRY) + break; + if (rc != DW_DLV_OK) { + printf("error dwarf_next_cu_header_c: %d %s\n", rc, dwarf_errmsg(err)); + exit(1); + } + + + rc = dwarf_siblingof(dbg, NULL, &die, &err); + if (rc != DW_DLV_OK) { + printf("first dwarf_siblingof failed: %d %s\n", rc, dwarf_errmsg(err)); + exit(1); + } + + parse_level(dbg, die, struct_name, field_name, 0); + } + + printf("struct %s / member %s not found\n", struct_name, field_name); + exit(2); } +static void parse_level(Dwarf_Debug dbg, Dwarf_Die die, const char *struct_name, const char *field_name, int level) { + Dwarf_Die next; + Dwarf_Error err; + int rc; + + do { + char *name; + const char *tag_name; + Dwarf_Half tag; + rc = dwarf_diename(die, &name, &err); + if (rc == DW_DLV_NO_ENTRY) { + printf("no diename for %p?\n", die); + break; + } + if (rc != DW_DLV_OK) { + printf("dwarf_diename error: %d %s\n", rc, dwarf_errmsg(err)); + exit(1); + } + rc = dwarf_tag(die, &tag, &err); + if (rc != DW_DLV_OK) { + printf("dwarf_tag error: %d %s\n", rc, dwarf_errmsg(err)); + exit(1); + } + + rc = dwarf_get_TAG_name(tag, &tag_name); + if (rc != DW_DLV_OK) { + printf("dwarf_get_TAG_name error: %d\n", rc); + exit(1); + } + + printf("<%d> %p <%d> %s: %s\n", level, die, tag, tag_name, name); + + rc = dwarf_siblingof(dbg, die, &next, &err); + dwarf_dealloc(dbg, die, DW_DLA_DIE); + + die = next; + } while (die); +} |