Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Mar 2020 16:25:28 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r358587 - stable/12/contrib/elftoolchain/addr2line
Message-ID:  <202003031625.023GPSW4082615@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Tue Mar  3 16:25:28 2020
New Revision: 358587
URL: https://svnweb.freebsd.org/changeset/base/358587

Log:
  MFC r357844: addr2line: Handle DW_AT_ranges in compile units
  
  Based on original submission by Marat Radchenko in ELF Tool Chain
  ticket #545, rebased and updated by Tiger Gao.
  
  Also r357862, use stdbool.h header for bool
  
  PR:		217736
  Submitted by:	Marat Radchenko <marat@slonopotamus.org>
  Submitted by:	Tiger Gao <tig@freebsdfoundation.org>
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/12/contrib/elftoolchain/addr2line/addr2line.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/contrib/elftoolchain/addr2line/addr2line.c
==============================================================================
--- stable/12/contrib/elftoolchain/addr2line/addr2line.c	Tue Mar  3 15:49:34 2020	(r358586)
+++ stable/12/contrib/elftoolchain/addr2line/addr2line.c	Tue Mar  3 16:25:28 2020	(r358587)
@@ -65,6 +65,7 @@ struct CU {
 	Dwarf_Signed nsrcfiles;
 	STAILQ_HEAD(, Func) funclist;
 	Dwarf_Die die;
+	Dwarf_Debug dbg;
 };
 
 static struct option longopts[] = {
@@ -345,7 +346,8 @@ cont_search:
 		collect_func(dbg, ret_die, parent, cu);
 
 	/* Cleanup */
-	dwarf_dealloc(dbg, die, DW_DLA_DIE);
+	if (die != cu->die)
+		dwarf_dealloc(dbg, die, DW_DLA_DIE);
 
 	if (abst_die != NULL)
 		dwarf_dealloc(dbg, abst_die, DW_DLA_DIE);
@@ -411,6 +413,102 @@ culookup(Dwarf_Unsigned addr)
 	return (NULL);
 }
 
+/*
+ * Check whether addr falls into range(s) of current CU, and save current CU
+ * to lookup tree if so.
+ */
+static int
+check_range(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Unsigned addr,
+    struct CU **cu)
+{
+	Dwarf_Error de;
+	Dwarf_Unsigned addr_base, lopc, hipc;
+	Dwarf_Off ranges_off;
+	Dwarf_Signed ranges_cnt;
+	Dwarf_Ranges *ranges;
+	int i, ret;
+	bool in_range;
+
+	addr_base = 0;
+	ranges = NULL;
+	ranges_cnt = 0;
+	in_range = false;
+
+	ret = dwarf_attrval_unsigned(die, DW_AT_ranges, &ranges_off, &de);
+	if (ret == DW_DLV_NO_ENTRY) {
+		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ==
+		    DW_DLV_OK) {
+			if (lopc == curlopc)
+				return (DW_DLV_ERROR);
+			if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc,
+				&de) == DW_DLV_OK) {
+				/*
+				 * Check if the address falls into the PC
+				 * range of this CU.
+				 */
+				if (handle_high_pc(die, lopc, &hipc) !=
+					DW_DLV_OK)
+					return (DW_DLV_ERROR);
+			} else {
+				/* Assume ~0ULL if DW_AT_high_pc not present */
+				hipc = ~0ULL;
+			}
+
+			if (addr >= lopc && addr < hipc) {
+				in_range = true;
+			}
+		}
+	} else if (ret == DW_DLV_OK) {
+		ret = dwarf_get_ranges(dbg, ranges_off, &ranges,
+			&ranges_cnt, NULL, &de);
+		if (ret != DW_DLV_OK)
+			return (ret);
+
+		if (!ranges || ranges_cnt <= 0)
+			return (DW_DLV_ERROR);
+
+		for (i = 0; i < ranges_cnt; i++) {
+			if (ranges[i].dwr_type == DW_RANGES_END)
+				return (DW_DLV_NO_ENTRY);
+
+			if (ranges[i].dwr_type ==
+				DW_RANGES_ADDRESS_SELECTION) {
+				addr_base = ranges[i].dwr_addr2;
+				continue;
+			}
+
+			/* DW_RANGES_ENTRY */
+			lopc = ranges[i].dwr_addr1 + addr_base;
+			hipc = ranges[i].dwr_addr2 + addr_base;
+
+			if (lopc == curlopc)
+				return (DW_DLV_ERROR);
+
+			if (addr >= lopc && addr < hipc){
+				in_range = true;
+				break;
+			}
+		}
+	} else {
+		return (DW_DLV_ERROR);
+	}
+	
+	if (in_range) {
+		if ((*cu = calloc(1, sizeof(struct CU))) == NULL)
+			err(EXIT_FAILURE, "calloc");
+		(*cu)->lopc = lopc;
+		(*cu)->hipc = hipc;
+		(*cu)->die = die;
+		(*cu)->dbg = dbg;
+		STAILQ_INIT(&(*cu)->funclist);
+		RB_INSERT(cutree, &cuhead, *cu);
+		curlopc = lopc;
+		return (DW_DLV_OK);
+	} else {
+		return (DW_DLV_NO_ENTRY);
+	}
+}
+
 static void
 translate(Dwarf_Debug dbg, Elf *e, const char* addrstr)
 {
@@ -418,10 +516,9 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr
 	Dwarf_Line *lbuf;
 	Dwarf_Error de;
 	Dwarf_Half tag;
-	Dwarf_Unsigned lopc, hipc, addr, lineno, plineno;
+	Dwarf_Unsigned addr, lineno, plineno;
 	Dwarf_Signed lcount;
 	Dwarf_Addr lineaddr, plineaddr;
-	Dwarf_Off off;
 	struct CU *cu;
 	struct Func *f;
 	const char *funcname;
@@ -439,6 +536,7 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr
 	cu = culookup(addr);
 	if (cu != NULL) {
 		die = cu->die;
+		dbg = cu->dbg;
 		goto status_ok;
 	}
 
@@ -477,44 +575,11 @@ translate(Dwarf_Debug dbg, Elf *e, const char* addrstr
 			warnx("could not find DW_TAG_compile_unit die");
 			goto next_cu;
 		}
-		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ==
-		    DW_DLV_OK) {
-			if (lopc == curlopc)
-				goto out;
-			if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc,
-			   &de) == DW_DLV_OK) {
-				/*
-				 * Check if the address falls into the PC
-				 * range of this CU.
-				 */
-				if (handle_high_pc(die, lopc, &hipc) !=
-				    DW_DLV_OK)
-					goto out;
-			} else {
-				/* Assume ~0ULL if DW_AT_high_pc not present */
-				hipc = ~0ULL;
-			}
-
-			if (dwarf_dieoffset(die, &off, &de) != DW_DLV_OK) {
-				warnx("dwarf_dieoffset failed: %s",
-				    dwarf_errmsg(de));
-				goto out;
-			}
-
-			if (addr >= lopc && addr < hipc) {
-				if ((cu = calloc(1, sizeof(*cu))) == NULL)
-					err(EXIT_FAILURE, "calloc");
-				cu->off = off;
-				cu->lopc = lopc;
-				cu->hipc = hipc;
-				cu->die = die;
-				STAILQ_INIT(&cu->funclist);
-				RB_INSERT(cutree, &cuhead, cu);
-
-				curlopc = lopc;
-				break;
-			}
-		}
+		ret = check_range(dbg, die, addr, &cu);
+		if (ret == DW_DLV_OK)
+			break;
+		if (ret == DW_DLV_ERROR)
+			goto out;
 next_cu:
 		if (die != NULL) {
 			dwarf_dealloc(dbg, die, DW_DLA_DIE);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202003031625.023GPSW4082615>