summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominique Martinet <asmadeus@codewreck.org>2017-10-03 14:18:19 +0900
committerDominique Martinet <asmadeus@codewreck.org>2017-10-03 14:18:19 +0900
commit7f287e650e470c131c4b6c726e0d09d4ac5433e8 (patch)
tree6db6eebe4df2974a3df7248ad3d82f45eb240fa3
parent21e4dcb88141aefc7a05d35f687793415a81cd15 (diff)
full rewrite
-rw-r--r--dwarf.c310
1 files changed, 127 insertions, 183 deletions
diff --git a/dwarf.c b/dwarf.c
index 7d305fe..637d710 100644
--- a/dwarf.c
+++ b/dwarf.c
@@ -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);
+}