Index: contrib/elftoolchain/addr2line/addr2line.c =================================================================== --- contrib/elftoolchain/addr2line/addr2line.c +++ contrib/elftoolchain/addr2line/addr2line.c @@ -84,6 +84,8 @@ static char unknown[] = { '?', '?', '\0' }; static Dwarf_Addr section_base; static struct CU *culist; +static Dwarf_Unsigned locache = ~0ULL, hicache = 0ULL; +static Dwarf_Die last_die = NULL; #define USAGE_MESSAGE "\ Usage: %s [options] hexaddress...\n\ @@ -403,8 +405,18 @@ cu = NULL; die = NULL; - while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, - &de)) == DW_DLV_OK) { + + // using cache + if (addr >= locache && addr < hicache) { + die = last_die; + goto status_ok; + } else if (last_die != NULL) { + // cache miss AND not new cu + goto next_cu; + } + + while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, + &de)) == DW_DLV_OK) { die = NULL; while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) { if (die != NULL) @@ -420,6 +432,7 @@ if (tag == DW_TAG_compile_unit) break; } + if (ret_die == NULL) { warnx("could not find DW_TAG_compile_unit die"); goto next_cu; @@ -465,6 +478,13 @@ } next_cu: + // if we got here, addr is not in this cu, clear cache + if (last_die != NULL) { + dwarf_dealloc(dbg, last_die, DW_DLA_DIE); + last_die = NULL; + } + locache = ~0ULL; + hicache = 0ULL; if (die != NULL) { dwarf_dealloc(dbg, die, DW_DLA_DIE); die = NULL; @@ -474,6 +494,12 @@ if (ret != DW_DLV_OK || die == NULL) goto out; + locache = lopc; + hicache = hipc; + last_die = die; + +status_ok: + switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { case DW_DLV_OK: break; @@ -573,20 +599,8 @@ print_inlines(cu, f->inlined_caller, f->call_file, f->call_line); - if (die != NULL) + if (die != NULL && (die != last_die)) 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