[ltrace-commits] 10/40: reworked attr_numeric() to report failures

Petr Machata pmachata-guest at moszumanska.debian.org
Sun May 11 22:38:53 UTC 2014


This is an automated email from the git hooks/post-receive script.

pmachata-guest pushed a commit to branch master
in repository ltrace.

commit 21f53552fb5353a5b0efdc7bb08685e1596d665a
Author: Dima Kogan <dima at secretsauce.net>
Date:   Tue Apr 22 16:22:08 2014 -0700

    reworked attr_numeric() to report failures
    
    This whole file is thus copyright me
---
 dwarf_prototypes.c | 112 +++++++++++++++++++++++++++++++++--------------------
 1 file 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 at 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 at redhat.com>.
+/* Copyright Dima Kogan <dima at 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

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/ltrace.git



More information about the ltrace-commits mailing list