Page MenuHomeFreeBSD

D23418.id67571.diff
No OneTemporary

D23418.id67571.diff

Index: contrib/elftoolchain/addr2line/addr2line.c
===================================================================
--- contrib/elftoolchain/addr2line/addr2line.c
+++ contrib/elftoolchain/addr2line/addr2line.c
@@ -25,6 +25,7 @@
*/
#include <sys/param.h>
+#include <sys/tree.h>
#include <capsicum_helpers.h>
#include <dwarf.h>
@@ -39,7 +40,6 @@
#include <stdlib.h>
#include <string.h>
-#include "uthash.h"
#include "_elftc.h"
ELFTC_VCSID("$Id: addr2line.c 3499 2016-11-25 16:06:29Z emaste $");
@@ -57,13 +57,14 @@
};
struct CU {
+ RB_ENTRY(CU) entry;
Dwarf_Off off;
Dwarf_Unsigned lopc;
Dwarf_Unsigned hipc;
char **srcfiles;
Dwarf_Signed nsrcfiles;
STAILQ_HEAD(, Func) funclist;
- UT_hash_handle hh;
+ Dwarf_Die die;
};
static struct option longopts[] = {
@@ -80,10 +81,26 @@
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
+
static int demangle, func, base, inlines, print_addr, pretty_print;
static char unknown[] = { '?', '?', '\0' };
static Dwarf_Addr section_base;
-static struct CU *culist;
+static struct CU *last_cu;
+/* Need a new curlopc that stores last lopc value.
+ * We used to use locache to do this, but locache is not stable anymore
+ * as tree lookup updates cache.
+ */
+static Dwarf_Unsigned curlopc = ~0ULL;
+static RB_HEAD(cutree, CU) head = RB_INITIALIZER(&head);
+
+static int
+lopccmp(struct CU *e1, struct CU *e2)
+{
+ return (e1->lopc < e2->lopc ? -1 : e1->lopc > e2->lopc);
+}
+
+RB_PROTOTYPE(cutree, CU, entry, lopccmp);
+RB_GENERATE(cutree, CU, entry, lopccmp)
#define USAGE_MESSAGE "\
Usage: %s [options] hexaddress...\n\
@@ -378,6 +395,46 @@
f->call_line);
}
+static int
+culookup(struct CU **cu, Dwarf_Die *die, Dwarf_Unsigned addr)
+{
+ struct CU find, *res;
+
+ if (last_cu != NULL && addr >= last_cu->lopc && addr < last_cu->hipc) {
+ *cu = last_cu;
+ *die = last_cu->die;
+ return 0;
+ }
+
+ /* Address isn't in cache. Check if it's in cutree. */
+ find.lopc = addr;
+ res = RB_NFIND(cutree, &head, &find);
+ if (res != NULL) {
+ /* go back one res if addr != res->lopc */
+ if (res->lopc != addr) {
+ res = RB_PREV(cutree, &head, res);
+ /* res can be NULL when tree only has useless_node */
+ }
+ /* Found the potential CU, but have to check if addr falls in range */
+ if (res != NULL && addr >= res->lopc && addr < res->hipc) {
+ *die = res->die;
+ *cu = res;
+ last_cu = *cu;
+ return 0;
+ }
+ } else {
+ /* We check the max node */
+ res = RB_MAX(cutree, &head);
+ if (res != NULL && addr >= res->lopc && addr < res->hipc) {
+ *die = res->die;
+ *cu = res;
+ last_cu = *cu;
+ return 0;
+ }
+ }
+ return 1;
+}
+
static void
translate(Dwarf_Debug dbg, Elf *e, const char* addrstr)
{
@@ -402,9 +459,26 @@
file = unknown;
cu = NULL;
die = NULL;
+ ret = DW_DLV_OK;
- while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
- &de)) == DW_DLV_OK) {
+ if (culookup(&cu, &die, addr) == 0) {
+ goto status_ok;
+ }
+ while (true) {
+ /*
+ * We resume the CU scan from the last place we found a match. Because
+ * when we have 2 sequential addresses, and the second one is of the next CU,
+ * it is faster to just go to the next CU instead of starting from the beginning.
+ */
+ ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
+ &de);
+ if (ret == DW_DLV_NO_ENTRY) {
+ if (curlopc == ~0ULL) {
+ goto out;
+ }
+ ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
+ &de);
+ }
die = NULL;
while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) {
if (die != NULL)
@@ -420,12 +494,16 @@
if (tag == DW_TAG_compile_unit)
break;
}
+
if (ret_die == NULL) {
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) {
/*
@@ -440,30 +518,33 @@
hipc = ~0ULL;
}
- /*
- * Record the CU in the hash table for faster lookup
- * later.
- */
if (dwarf_dieoffset(die, &off, &de) != DW_DLV_OK) {
warnx("dwarf_dieoffset failed: %s",
dwarf_errmsg(de));
goto out;
}
- HASH_FIND(hh, culist, &off, sizeof(off), cu);
- if (cu == NULL) {
- if ((cu = calloc(1, sizeof(*cu))) == NULL)
+
+ 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);
- HASH_ADD(hh, culist, off, sizeof(off), cu);
- }
- if (addr >= lopc && addr < hipc)
+ /* Add this addr's CU info from brute force to tree */
+ RB_INSERT(cutree, &head, cu);
+
+ /* update curlopc. Not affected by tree or cache lookup. */
+ curlopc = lopc;
+
+ /* update single cache */
+ last_cu = cu;
break;
+ }
}
-
next_cu:
if (die != NULL) {
dwarf_dealloc(dbg, die, DW_DLA_DIE);
@@ -474,6 +555,8 @@
if (ret != DW_DLV_OK || die == NULL)
goto out;
+status_ok:
+
switch (dwarf_srclines(die, &lbuf, &lcount, &de)) {
case DW_DLV_OK:
break;
@@ -572,21 +655,6 @@
cu->srcfiles != NULL && f != NULL && f->inlined_caller != NULL)
print_inlines(cu, f->inlined_caller, f->call_file,
f->call_line);
-
- if (die != NULL)
- dwarf_dealloc(dbg, die, DW_DLA_DIE);
-
- /*
- * Reset internal CU pointer, so we will start from the first CU
- * next round.
- */
- while (ret != DW_DLV_NO_ENTRY) {
- if (ret == DW_DLV_ERROR)
- errx(EXIT_FAILURE, "dwarf_next_cu_header: %s",
- dwarf_errmsg(de));
- ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL,
- &de);
- }
}
static void

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 9:07 AM (13 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28327446
Default Alt Text
D23418.id67571.diff (5 KB)

Event Timeline