summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dwarf_prototypes.c112
1 files changed, 71 insertions, 41 deletions
diff --git a/dwarf_prototypes.c b/dwarf_prototypes.c
index 64d7820..936d94f 100644
--- a/dwarf_prototypes.c
+++ b/dwarf_prototypes.c
@@ -1,7 +1,4 @@
-/* Most of this is Copyright Dima Kogan <dima@secretsauce.net>
- *
- * Pieces of this were taken from dwarf_prototypes.c in the dwarves project.
- * Those are Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>.
+/* Copyright Dima Kogan <dima@secretsauce.net>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of version 2 of the GNU General Public License as published by the
@@ -144,53 +141,62 @@ static bool dump_ltrace_tree(const struct arg_type_info* info)
#endif
-
-static uint64_t attr_numeric(Dwarf_Die *die, uint32_t name)
+// pulls a numerical value out of a particular attribute in a die. Returns true
+// if successful. The result is returned in *result. Note that this is cast to
+// (uint64_t), regardless of the actual type of the input
+static bool get_die_numeric(uint64_t* result,
+ Dwarf_Die *die, unsigned int attr_name)
{
- Dwarf_Attribute attr;
- uint32_t form;
+ Dwarf_Attribute attr ;
- if (dwarf_attr(die, name, &attr) == NULL)
- return 0;
+ union {
+ Dwarf_Word udata;
+ Dwarf_Sword sdata;
+ Dwarf_Addr addr;
+ bool flag;
+ } u;
+
+ if (dwarf_attr(die, attr_name, &attr) == NULL)
+ return false;
+
+ unsigned int form = dwarf_whatform(&attr);
+
+#define PROCESS_NUMERIC(type) \
+ if (dwarf_form ## type(&attr, &u.type) != 0) \
+ return false; \
+ *result = (uint64_t)u.type; \
+ return true
- form = dwarf_whatform(&attr);
switch (form) {
- case DW_FORM_addr: {
- Dwarf_Addr addr;
- if (dwarf_formaddr(&attr, &addr) == 0)
- return addr;
- }
- break;
+ case DW_FORM_addr:
+ PROCESS_NUMERIC(addr);
+
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
+ case DW_FORM_udata:
+ PROCESS_NUMERIC(udata);
+
case DW_FORM_sdata:
- case DW_FORM_udata: {
- Dwarf_Word value;
- if (dwarf_formudata(&attr, &value) == 0)
- return value;
- }
- break;
+ PROCESS_NUMERIC(sdata);
+
case DW_FORM_flag:
- case DW_FORM_flag_present: {
- bool value;
- if (dwarf_formflag(&attr, &value) == 0)
- return value;
- }
- break;
+ PROCESS_NUMERIC(flag);
+
default:
- complain(die, "DW_AT_<0x%x>=0x%x", name, form);
- break;
+ complain(die, "Unknown numeric form %d for attr_name: %d", form, attr_name);
+ return false;
}
-
- return 0;
+#undef PROCESS_NUMERIC
}
static enum arg_type get_base_type(Dwarf_Die* die)
{
- int encoding = attr_numeric(die, DW_AT_encoding);
+ int64_t encoding;
+ if( !get_die_numeric((uint64_t*)&encoding, die, DW_AT_encoding) )
+ return ARGTYPE_VOID;
if (encoding == DW_ATE_void )
return ARGTYPE_VOID;
@@ -198,11 +204,17 @@ static enum arg_type get_base_type(Dwarf_Die* die)
if (encoding == DW_ATE_signed_char || encoding == DW_ATE_unsigned_char )
return ARGTYPE_CHAR;
+ uint64_t byte_size;
+ if (!get_die_numeric(&byte_size, die, DW_AT_byte_size))
+ return ARGTYPE_VOID;
+
if (encoding == DW_ATE_signed ||
encoding == DW_ATE_unsigned ||
encoding == DW_ATE_boolean) {
+
bool is_signed = (encoding == DW_ATE_signed);
- switch (attr_numeric(die, DW_AT_byte_size)) {
+
+ switch (byte_size) {
case sizeof(char):
return ARGTYPE_CHAR;
@@ -222,7 +234,7 @@ static enum arg_type get_base_type(Dwarf_Die* die)
}
if (encoding == DW_ATE_float) {
- switch (attr_numeric(die, DW_AT_byte_size)) {
+ switch (byte_size) {
case sizeof(float):
return ARGTYPE_FLOAT;
@@ -238,7 +250,7 @@ static enum arg_type get_base_type(Dwarf_Die* die)
#if 0
if (encoding == DW_ATE_complex_float) {
- switch (attr_numeric(die, DW_AT_byte_size)) {
+ switch (byte_size) {
case 2*sizeof(float):
return ARGTYPE_FLOAT;
@@ -325,7 +337,13 @@ static bool get_enum(struct arg_type_info* enum_info, Dwarf_Die* parent)
}
value_init_detached(value, NULL, type_get_simple( ARGTYPE_INT ), 0);
- value_set_word(value, attr_numeric(&die, DW_AT_const_value));
+ uint64_t enum_value;
+ if (!get_die_numeric(&enum_value, &die, DW_AT_const_value)) {
+ complain(&die, "Couldn't get enum value");
+ return false;
+ }
+
+ value_set_word(value, (long)enum_value);
if (lens_enum_add( lens, dupkey, 0, value, 0 )) {
complain(&die, "Couldn't add enum element");
@@ -370,21 +388,33 @@ static bool get_array(struct arg_type_info* array_info, Dwarf_Die* parent)
}
if (dwarf_hasattr(&subrange, DW_AT_lower_bound)) {
- if (attr_numeric(&subrange, DW_AT_lower_bound) != 0) {
+ uint64_t lower_bound;
+ if (!get_die_numeric(&lower_bound, &subrange, DW_AT_lower_bound)) {
+ complain( parent, "Couldn't read lower bound");
+ return false;
+ }
+
+ if (lower_bound != 0) {
complain( parent,
"Array subrange has a nonzero lower bound. Don't know what to do");
return false;
}
}
- int N;
+ uint64_t N;
if (!dwarf_hasattr(&subrange, DW_AT_upper_bound)) {
// no upper bound is defined. This is probably a variable-width array,
// and I don't know how long it is. Let's say 0 to be safe
N = 0;
}
else
- N = attr_numeric(&subrange, DW_AT_upper_bound)+1;
+ {
+ if (!get_die_numeric(&N, &subrange, DW_AT_upper_bound)) {
+ complain( parent, "Couldn't read upper bound");
+ return false;
+ }
+ N++;
+ }
// I'm not checking the subrange type. It should be some sort of integer,
// and I don't know what it would mean for it to be something else