[RFC dwarves 2/3] dwarf_loader: make more effort to retrieve a function address

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Many DW_AT_subroutine DIEs do not have address info associated
directly; some use DW_AT_ranges, and some have address info
stored with the associated abstract origin.  Use these information
sources to improve address retrieval for "struct function"
representations.

Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>
---
 dwarf_loader.c | 29 +++++++++++++++++++++++++----
 dwarves.h      |  3 ++-
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/dwarf_loader.c b/dwarf_loader.c
index e1ba7bc..d46e82a 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -1519,6 +1519,17 @@ static struct function *function__new(Dwarf_Die *die, struct cu *cu, struct conf
 		func->vtable_entry    = -1;
 		if (dwarf_hasattr(die, DW_AT_vtable_elem_location))
 			func->vtable_entry = attr_offset(die, DW_AT_vtable_elem_location);
+		/* some functions will have entry address in the start address
+		 * in DW_AT_ranges.
+		 */
+		if (dwarf_hasattr(die, DW_AT_ranges)) {
+			Dwarf_Addr base, start, high_pc;
+			ptrdiff_t offset = 0;
+
+			dwarf_ranges(die, offset, &base, &start, &high_pc);
+			if (start)
+				func->addr = (uint64_t)start;
+		}
 		func->cu_total_size_inline_expansions = 0;
 		func->cu_total_nr_inline_expansions = 0;
 		func->priv = NULL;
@@ -2805,7 +2816,7 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
 	case DW_TAG_subprogram: {
 		struct function *fn = tag__function(tag);
 
-		if (fn->name == 0)  {
+		if (fn->name == 0 || function__addr(fn) == 0) {
 			if (dtag->abstract_origin == 0 &&
 			    dtag->specification == 0) {
 				/*
@@ -2818,9 +2829,19 @@ static int tag__recode_dwarf_type(struct tag *tag, struct cu *cu)
 			dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, abstract_origin);
 			if (dtype == NULL)
 				dtype = dwarf_cu__find_tag_by_ref(cu->priv, dtag, specification);
-			if (dtype != NULL)
-				fn->name = tag__function(dtag__tag(dtype))->name;
-			else {
+			if (dtype != NULL) {
+				struct function *dfn = tag__function(dtag__tag(dtype));
+				if (fn->name == 0)
+					fn->name = dfn->name;
+				/* share function address info between tag and
+				 * abstract origin.
+				 */
+				if (!function__addr(fn))
+					fn->addr = function__addr(dfn);
+				else if (!function__addr(dfn))
+					dfn->addr = function__addr(fn);
+			}
+			if (fn->name == 0) {
 				fprintf(stderr,
 					"%s: couldn't find name for "
 					"function %#llx, abstract_origin=%#llx,"
diff --git a/dwarves.h b/dwarves.h
index 36c6898..847e13d 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -1081,6 +1081,7 @@ struct function {
 	const char	 *name;
 	const char	 *linkage_name;
 	const char	 *alias;	/* name.isra.0 */
+	uint64_t	 addr;
 	uint32_t	 cu_total_size_inline_expansions;
 	uint16_t	 cu_total_nr_inline_expansions;
 	uint8_t		 inlined:2;
@@ -1146,7 +1147,7 @@ const char *function__prototype_conf(const struct function *func,
 
 static __pure inline uint64_t function__addr(const struct function *func)
 {
-	return func->lexblock.ip.addr;
+	return func->lexblock.ip.addr ?: func->addr;
 }
 
 static __pure inline uint32_t function__size(const struct function *func)
-- 
2.39.3





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux