X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dwarf_prototypes.c;h=9c369048ef5aa07ab34a73cbef764d520a1056ea;hb=daac7cac98b5be89209263ba200d7df3c69b70b4;hp=25390e2463c1fb1db4f01edf5a45ac6f074d7956;hpb=3c2f28cc0082c3acc1524d0c76646ecd1da686e7;p=platform%2Fupstream%2Fltrace.git diff --git a/dwarf_prototypes.c b/dwarf_prototypes.c index 25390e2..9c36904 100644 --- a/dwarf_prototypes.c +++ b/dwarf_prototypes.c @@ -94,7 +94,7 @@ static bool _dump_ltrace_tree(const struct arg_type_info *info, int indent) { struct arg_type_info *info; int own_info; - }* elements = (struct struct_field*)info->u.entries.data; + } *elements = (struct struct_field*)info->u.entries.data; unsigned int i; for(i=0; iu.entries.size; i++) _dump_ltrace_tree(elements[i].info, indent+1); @@ -171,34 +171,37 @@ static bool get_die_numeric(uint64_t *result, static bool get_integer_base_type(enum arg_type *type, int byte_size, bool is_signed) { - switch (byte_size) { - case sizeof(char): + // not using a switch() here because sizeof(int) == sizeof(long) on some + // architectures, and removing that case for those arches is a pain + if (byte_size == sizeof(char)) { *type = ARGTYPE_CHAR; return true; + } - case sizeof(short): + if (byte_size == sizeof(short)) { *type = is_signed ? ARGTYPE_SHORT : ARGTYPE_USHORT; return true; + } - case sizeof(int): + if (byte_size == sizeof(int)) { *type = is_signed ? ARGTYPE_INT : ARGTYPE_UINT; return true; + } - case sizeof(long): + if (byte_size == sizeof(long)) { *type = is_signed ? ARGTYPE_LONG : ARGTYPE_ULONG; return true; - - default: - return false; } + + return false; } // returns an ltrace ARGTYPE_XXX base type from the given die. If we dont // support a particular type (or an error occurred), I regturn ARGTYPE_VOID static enum arg_type get_base_type(Dwarf_Die *die) { - int64_t encoding; - if (!get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding)) + uint64_t encoding; + if (!get_die_numeric(&encoding, die, DW_AT_encoding)) return ARGTYPE_VOID; if (encoding == DW_ATE_void) @@ -296,7 +299,7 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent, value_destroy(value); \ free(value); \ } \ - if (lens != NULL ) { \ + if (lens != NULL) { \ lens_destroy(&lens->super); \ free(lens); \ } \ @@ -312,10 +315,10 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent, return ret; \ } while (0) - struct arg_type_info* result = NULL; - struct enum_lens* lens = NULL; - const char* dupkey = NULL; - struct value* value = NULL; + struct arg_type_info *result = NULL; + struct enum_lens *lens = NULL; + const char *dupkey = NULL; + struct value *value = NULL; Dwarf_Off die_offset = dwarf_dieoffset(parent); @@ -325,7 +328,10 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent, CLEANUP_AND_RETURN_ERROR(NULL); } - dict_insert(type_dieoffset_hash, &die_offset, &result); + if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) { + complain(parent, "Couldn't insert into cache dict"); + CLEANUP_AND_RETURN_ERROR(NULL); + } uint64_t byte_size; if (!get_die_numeric(&byte_size, parent, DW_AT_byte_size)) { @@ -416,9 +422,9 @@ static struct arg_type_info *get_enum(Dwarf_Die *parent, } // returns a newly-allocated art_type_info*, or NULL on error -static struct arg_type_info *get_array( Dwarf_Die *parent, - struct protolib *plib, - struct dict *type_dieoffset_hash) +static struct arg_type_info *get_array(Dwarf_Die *parent, + struct protolib *plib, + struct dict *type_dieoffset_hash) { #define CLEANUP_AND_RETURN_ERROR(ret) do { \ @@ -443,9 +449,9 @@ static struct arg_type_info *get_array( Dwarf_Die *parent, } while (0) - struct arg_type_info* result = NULL; - struct expr_node* length = NULL; - struct arg_type_info* array_type = NULL; + struct arg_type_info *result = NULL; + struct expr_node *length = NULL; + struct arg_type_info *array_type = NULL; int newly_allocated_array_type = 0; Dwarf_Off die_offset = dwarf_dieoffset(parent); @@ -462,10 +468,13 @@ static struct arg_type_info *get_array( Dwarf_Die *parent, CLEANUP_AND_RETURN_ERROR(NULL); } - dict_insert(type_dieoffset_hash, &die_offset, &result); + if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) { + complain(parent, "Couldn't insert into cache dict"); + CLEANUP_AND_RETURN_ERROR(NULL); + } array_type = get_type(&newly_allocated_array_type, &type_die, plib, type_dieoffset_hash); - if ( array_type == NULL ) { + if (array_type == NULL) { complain(parent, "Couldn't figure out array's type"); CLEANUP_AND_RETURN_ERROR(NULL); } @@ -559,8 +568,8 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent, } while (0) - struct arg_type_info* result = NULL; - struct arg_type_info* member_type = NULL; + struct arg_type_info *result = NULL; + struct arg_type_info *member_type = NULL; int newly_allocated_member_type = 0; Dwarf_Off die_offset = dwarf_dieoffset(parent); @@ -571,7 +580,10 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent, CLEANUP_AND_RETURN_ERROR(NULL); } type_init_struct(result); - dict_insert(type_dieoffset_hash, &die_offset, &result); + if (dict_insert(type_dieoffset_hash, &die_offset, &result) != 0) { + complain(parent, "Couldn't insert into cache dict"); + CLEANUP_AND_RETURN_ERROR(NULL); + } Dwarf_Die die; if (dwarf_child(parent, &die) != 0) { @@ -602,8 +614,11 @@ static struct arg_type_info *get_structure(Dwarf_Die *parent, complain(&die, "Couldn't parse type from DWARF data"); CLEANUP_AND_RETURN_ERROR(NULL); } - type_struct_add(result, member_type, - newly_allocated_member_type); + if (type_struct_add(result, member_type, + newly_allocated_member_type) != 0) { + complain(&die, "Couldn't add type to struct"); + CLEANUP_AND_RETURN_ERROR(NULL); + } NEXT_SIBLING(&die); } @@ -638,8 +653,18 @@ static struct arg_type_info *get_type(int *newly_allocated_result, return ret; \ } while (0) - struct arg_type_info* result = NULL; - struct arg_type_info* pointee = NULL; +#define DICT_INSERT_AND_CHECK(type_dieoffset_hash, die_offset, result) \ + do { \ + if (dict_insert(type_dieoffset_hash, \ + die_offset, result) != 0) { \ + complain(type_die, \ + "Couldn't insert into cache dict"); \ + CLEANUP_AND_RETURN_ERROR(NULL); \ + } \ + } while(0) + + struct arg_type_info *result = NULL; + struct arg_type_info *pointee = NULL; int newly_allocated_pointee = 0; Dwarf_Off die_offset = dwarf_dieoffset(type_die); @@ -677,7 +702,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result, case DW_TAG_base_type: complain(type_die, "Storing base type"); result = type_get_simple(get_base_type(type_die)); - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; case DW_TAG_subroutine_type: @@ -686,7 +711,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result, // dereference these, it'll get a segfault complain(type_die, "Storing subroutine type"); result = type_get_simple(ARGTYPE_VOID); - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; case DW_TAG_pointer_type: @@ -695,7 +720,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result, // void* complain(type_die, "Storing void-pointer type"); result = type_get_voidptr(); - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; } @@ -707,7 +732,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result, complain(type_die, "alloc error"); CLEANUP_AND_RETURN_ERROR(NULL); } - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); pointee = get_type(&newly_allocated_pointee, &next_die, plib, type_dieoffset_hash); if (pointee == NULL) @@ -743,7 +768,7 @@ static struct arg_type_info *get_type(int *newly_allocated_result, result = type_get_simple(ARGTYPE_VOID); complain(type_die, "Storing void type"); } - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; case DW_TAG_enumeration_type: @@ -769,24 +794,25 @@ static struct arg_type_info *get_type(int *newly_allocated_result, case DW_TAG_union_type: result = type_get_simple(ARGTYPE_VOID); complain(type_die, "Storing union-as-void type"); - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; default: complain(type_die, "Unknown type tag 0x%x. Returning void", dwarf_tag(type_die)); result = type_get_simple(ARGTYPE_VOID); - dict_insert(type_dieoffset_hash, &die_offset, &result); + DICT_INSERT_AND_CHECK(type_dieoffset_hash, &die_offset, &result); return result; } +#undef DICT_INSERT_AND_CHECK #undef CLEANUP_AND_RETURN_ERROR } // fills in *proto with a prototype. Returns true on success -static bool get_prototype( struct prototype *result, - Dwarf_Die *subroutine, struct protolib *plib, - struct dict *type_dieoffset_hash) +static bool get_prototype(struct prototype *result, + Dwarf_Die *subroutine, struct protolib *plib, + struct dict *type_dieoffset_hash) { #define CLEANUP_AND_RETURN_ERROR(ret) do { \ @@ -799,7 +825,7 @@ static bool get_prototype( struct prototype *result, } while (0) - struct arg_type_info* argument_type = NULL; + struct arg_type_info *argument_type = NULL; int newly_allocated_argument_type = 0; prototype_init(result); @@ -878,23 +904,10 @@ static bool get_prototype( struct prototype *result, #undef CLEANUP_AND_RETURN_ERROR } -static bool import_subprogram(struct protolib *plib, struct library *lib, - struct dict *type_dieoffset_hash, - Dwarf_Die *die) +static bool import_subprogram_name(struct protolib *plib, struct library *lib, + struct dict *type_dieoffset_hash, + Dwarf_Die *die, const char* function_name) { - // 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; - } - 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)) { @@ -920,7 +933,7 @@ static bool import_subprogram(struct protolib *plib, struct library *lib, } const char *function_name_dup = strdup(function_name); - if ( function_name_dup == NULL ) { + if (function_name_dup == NULL) { complain(die, "couldn't strdup"); prototype_destroy(&proto); return false; @@ -929,6 +942,36 @@ static bool import_subprogram(struct protolib *plib, struct library *lib, return true; } +static bool import_subprogram_die(struct protolib *plib, struct library *lib, + struct dict *type_dieoffset_hash, + Dwarf_Die *die) +{ + // If there is a linkage name, I use it (this is required for C++ code, + // in particular). + // + // I use the plain name regardless, since sometimes the exported symbol + // corresponds to the plain name, NOT the linkage name. For instance I + // see this on my Debian/sid amd64 box. In its libc, the linkage name of + // __nanosleep is __GI___nanosleep, but the export is __nanosleep + const char *function_name; + Dwarf_Attribute attr; + + if (dwarf_attr(die, DW_AT_linkage_name, &attr) != NULL && + (function_name = dwarf_formstring(&attr)) != NULL && + !import_subprogram_name(plib, lib, type_dieoffset_hash, die, + function_name)) { + return false; + } + + if ((function_name = dwarf_diename(die)) != NULL && + !import_subprogram_name(plib, lib, type_dieoffset_hash, die, + function_name)) { + return false; + } + + return true; +} + static bool process_die_compileunit(struct protolib *plib, struct library *lib, struct dict *type_dieoffset_hash, Dwarf_Die *parent) @@ -942,8 +985,8 @@ static bool process_die_compileunit(struct protolib *plib, struct library *lib, while (1) { if (dwarf_tag(&die) == DW_TAG_subprogram) - if (!import_subprogram(plib, lib, type_dieoffset_hash, - &die)) + if (!import_subprogram_die(plib, lib, type_dieoffset_hash, + &die)) complain(&die, "Error importing subprogram. " "Skipping"); @@ -953,7 +996,8 @@ static bool process_die_compileunit(struct protolib *plib, struct library *lib, return true; } -static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl) +static void import(struct protolib *plib, struct library *lib, + Dwfl_Module *dwfl_module) { // 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 @@ -966,7 +1010,7 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl) Dwarf_Addr bias; Dwarf_Die *die = NULL; - while ((die = dwfl_nextcu(dwfl, die, &bias)) != NULL) { + while ((die = dwfl_module_nextcu(dwfl_module, die, &bias)) != NULL) { if (dwarf_tag(die) == DW_TAG_compile_unit) process_die_compileunit(plib, lib, &type_dieoffset_hash, die); @@ -980,15 +1024,14 @@ static void import(struct protolib *plib, struct library *lib, Dwfl *dwfl) bool import_DWARF_prototypes(struct library *lib) { - struct protolib* plib = lib->protolib; - Dwfl* dwfl = lib->dwfl; + struct protolib *plib = lib->protolib; debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'", lib->soname); if (plib == NULL) { const char *soname_dup = strdup(lib->soname); - if ( soname_dup == NULL ) { + if (soname_dup == NULL) { fprintf(stderr, "couldn't strdup"); return false; } @@ -1000,7 +1043,7 @@ bool import_DWARF_prototypes(struct library *lib) } } - import(plib, lib, dwfl); + import(plib, lib, lib->dwfl_module); lib->protolib = plib; return true;