diff options
-rw-r--r-- | dwarf_prototypes.c | 191 |
1 files changed, 93 insertions, 98 deletions
diff --git a/dwarf_prototypes.c b/dwarf_prototypes.c index 9f03384..f76dbed 100644 --- a/dwarf_prototypes.c +++ b/dwarf_prototypes.c @@ -37,6 +37,12 @@ #define complain( die, format, ... ) #endif +#define NEXT_SIBLING(die) \ + int res = dwarf_siblingof(die, die); \ + if (res == 0) continue; /* sibling exists */ \ + if (res < 0) return false; /* error */ \ + break /* no sibling exists */ + // A map from DIE addresses (Dwarf_Off) to type structures (struct // arg_type_info*). This is created and filled in at the start of each import, // and deleted when the import is complete @@ -59,10 +65,7 @@ static bool _dump_dwarf_tree(Dwarf_Die* die, int indent) return false; } - int res = dwarf_siblingof(die, die); - if (res == 0 ) continue; // sibling exists - if (res < 0 ) return false; // error - break; // no sibling exists + SIBLING(die); } return true; @@ -192,7 +195,7 @@ static bool get_die_numeric(uint64_t* result, #undef PROCESS_NUMERIC } -static bool get_integer_base_type( enum arg_type* type, int byte_size, bool is_signed ) +static bool get_integer_base_type(enum arg_type* type, int byte_size, bool is_signed) { switch (byte_size) { case sizeof(char): @@ -219,13 +222,13 @@ static bool get_integer_base_type( enum arg_type* type, int byte_size, bool is_s static enum arg_type get_base_type(Dwarf_Die* die) { int64_t encoding; - if( !get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding) ) + if( !get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding)) return ARGTYPE_VOID; - if (encoding == DW_ATE_void ) + if (encoding == DW_ATE_void) return ARGTYPE_VOID; - if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char ) + if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char) return ARGTYPE_CHAR; uint64_t byte_size; @@ -372,10 +375,7 @@ static bool get_enum(struct arg_type_info* enum_info, Dwarf_Die* parent) return false; } - int res = dwarf_siblingof(&die, &die); - if (res == 0) continue; /* sibling exists */ - if (res < 0) return false; /* error */ - break; /* no sibling exists */ + NEXT_SIBLING(&die); } return true; @@ -492,10 +492,7 @@ static bool get_structure(struct arg_type_info* struct_info, Dwarf_Die* parent) } type_struct_add( struct_info, member_info, 0 ); - int res = dwarf_siblingof(&die, &die); - if (res == 0) continue; /* sibling exists */ - if (res < 0) return false; /* error */ - break; /* no sibling exists */ + NEXT_SIBLING(&die); } return true; @@ -564,9 +561,9 @@ static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die) return get_structure( *info, type_die ); - case DW_TAG_typedef: ; - case DW_TAG_const_type: ; - case DW_TAG_volatile_type: ; + case DW_TAG_typedef: + case DW_TAG_const_type: + case DW_TAG_volatile_type: { // Various tags are simply pass-through, so I just keep going bool res = true; if (get_type_die(&next_die, type_die )) { @@ -578,9 +575,10 @@ static bool get_type(struct arg_type_info** info, Dwarf_Die* type_die) *info = type_get_simple( ARGTYPE_VOID ); complain(type_die, "Storing void type: %p", *info); } - if (res ) + if (res) dict_insert( &type_hash, &die_offset, info ); return res; + } case DW_TAG_enumeration_type: // We have an enumeration. This has type "int", but has a particular @@ -650,109 +648,107 @@ static bool get_prototype(struct prototype* proto, Dwarf_Die* subroutine) } while(1) { - if (dwarf_tag(&arg_die) != DW_TAG_formal_parameter ) - goto next_prototype_argument; + if (dwarf_tag(&arg_die) == DW_TAG_formal_parameter) { - complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die)); + complain(&arg_die, "arg: 0x%02x", dwarf_tag(&arg_die)); - Dwarf_Die type_die; - if (!get_type_die(&type_die, &arg_die )) { - complain(&arg_die, "Couldn't get the argument type die"); - return false; - } + Dwarf_Die type_die; + if (!get_type_die(&type_die, &arg_die )) { + complain(&arg_die, "Couldn't get the argument type die"); + return false; + } - struct arg_type_info* arg_type_info = NULL; - if (!get_type( &arg_type_info, &type_die )) { - complain(&arg_die, "Couldn't parse arg type from DWARF data"); - return false; - } + struct arg_type_info* arg_type_info = NULL; + if (!get_type( &arg_type_info, &type_die )) { + complain(&arg_die, "Couldn't parse arg type from DWARF data"); + return false; + } - struct param param; - param_init_type(¶m, arg_type_info, 0); - if (prototype_push_param(proto, ¶m) <0) { - complain(&arg_die, "couldn't add argument to the prototype"); - return false; - } + struct param param; + param_init_type(¶m, arg_type_info, 0); + if (prototype_push_param(proto, ¶m) <0) { + complain(&arg_die, "couldn't add argument to the prototype"); + return false; + } #ifdef DUMP_PROTOTYPES - fprintf(stderr, "Adding argument:\n"); - dump_ltrace_tree(arg_type_info); + fprintf(stderr, "Adding argument:\n"); + dump_ltrace_tree(arg_type_info); #endif + } - next_prototype_argument: ; - int res = dwarf_siblingof(&arg_die, &arg_die); - if (res == 0) continue; /* sibling exists */ - if (res < 0) return false; /* error */ - break; /* no sibling exists */ + NEXT_SIBLING(&arg_die); } return true; } -static bool process_die_compileunit(struct protolib* plib, struct library* lib, - Dwarf_Die* parent) +static bool import_subprogram(struct protolib* plib, struct library* lib, + Dwarf_Die* die) { - Dwarf_Die die; - if (dwarf_child(parent, &die) != 0) { - // no child nodes, so nothing to do + // I use the linkage function name if there is one, otherwise the + // plain name + const char* function_name = NULL; + Dwarf_Attribute attr; + if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL) + function_name = dwarf_formstring(&attr); + if (function_name == NULL) + function_name = dwarf_diename(die); + if (function_name == NULL) { + complain(die, "Function has no name. Not importing" ); return true; } - while (1) { - if (dwarf_tag(&die) == DW_TAG_subprogram) { - - // I use the linkage function name if there is one, otherwise the - // plain name - const char* function_name = NULL; - Dwarf_Attribute attr; - if (dwarf_attr(&die, DW_AT_linkage_name, &attr) != NULL) - function_name = dwarf_formstring(&attr); - if (function_name == NULL) - function_name = dwarf_diename(&die); - if (function_name == NULL) { - complain(&die, "Function has no name. Not importing" ); - goto next_prototype; - } + complain(die, "subroutine_type: 0x%02x; function '%s'", + dwarf_tag(die), function_name); + + struct prototype* proto = + protolib_lookup_prototype(plib, function_name, false ); + + if (proto != NULL) { + complain(die, "Prototype already exists. Skipping"); + return true; + } - complain(&die, "subroutine_type: 0x%02x; function '%s'", - dwarf_tag(&die), function_name); + if (!filter_matches_symbol(options.plt_filter, function_name, lib) && + !filter_matches_symbol(options.static_filter, function_name, lib) && + !filter_matches_symbol(options.export_filter, function_name, lib)) { + complain(die, "Prototype not requested by any filter"); + return true; + } - struct prototype* proto = - protolib_lookup_prototype(plib, function_name, true ); + proto = malloc(sizeof(struct prototype)); + if (proto == NULL) { + complain(die, "couldn't alloc prototype"); + return false; + } + prototype_init( proto ); - if (proto != NULL) { - complain(&die, "Prototype already exists. Skipping"); - goto next_prototype; - } + if (!get_prototype(proto, die )) { + complain(die, "couldn't get prototype"); + return false; + } - if (!filter_matches_symbol(options.plt_filter, function_name, lib) && - !filter_matches_symbol(options.static_filter, function_name, lib) && - !filter_matches_symbol(options.export_filter, function_name, lib)) { - complain(&die, "Prototype not requested by any filter"); - goto next_prototype; - } + protolib_add_prototype(plib, function_name, 0, proto); + return true; +} - proto = malloc(sizeof(struct prototype)); - if (proto == NULL) { - complain(&die, "couldn't alloc prototype"); - return false; - } - prototype_init( proto ); +static bool process_die_compileunit(struct protolib* plib, struct library* lib, + Dwarf_Die* parent) +{ + Dwarf_Die die; + if (dwarf_child(parent, &die) != 0) { + // no child nodes, so nothing to do + return true; + } - if (!get_prototype(proto, &die )) { - complain(&die, "couldn't get prototype"); + while (1) { + if (dwarf_tag(&die) == DW_TAG_subprogram) + if(!import_subprogram(plib, lib, &die)) return false; - } - - protolib_add_prototype(plib, function_name, 0, proto); - } - next_prototype:; - int res = dwarf_siblingof(&die, &die); - if (res == 0) continue; /* sibling exists */ - if (res < 0) return false; /* error */ - break; /* no sibling exists */ + NEXT_SIBLING(&die); } return true; @@ -808,6 +804,5 @@ bool import_DWARF_prototypes(struct protolib* plib, struct library* lib, - all my *allocs leak -- protolib_lookup_prototype should look for imports? */ |