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)
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)) {
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) {
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) {
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);
}
return ret; \
} while (0)
+#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;
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:
// 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:
// 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;
}
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)
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:
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
}
#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)) {
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)
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");
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
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);
bool import_DWARF_prototypes(struct library *lib)
{
struct protolib *plib = lib->protolib;
- Dwfl *dwfl = lib->dwfl;
debug(DEBUG_FUNCTION, "Importing DWARF prototypes from '%s'",
lib->soname);
}
}
- import(plib, lib, dwfl);
+ import(plib, lib, lib->dwfl_module);
lib->protolib = plib;
return true;