From 8be4a1ca56ca3f72898f517c62608ec9708c36be Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Thu, 3 May 2018 04:44:36 +0200 Subject: [PATCH] Fix Issue 18068 - No file names and line numbers in stack trace --- src/rt/backtrace/dwarf.d | 9 ++++++- src/rt/backtrace/elf.d | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/rt/backtrace/dwarf.d b/src/rt/backtrace/dwarf.d index f1853b2c95e..52e792411ea 100644 --- a/src/rt/backtrace/dwarf.d +++ b/src/rt/backtrace/dwarf.d @@ -69,8 +69,15 @@ int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size { // resolve addresses locations.length = callstack.length; + auto elfObj = image.baseAddress(); foreach(size_t i; 0 .. callstack.length) - locations[i].address = cast(size_t) callstack[i]; + { + typeof(elfObj.begin) offset; + if (elfObj.begin <= cast(size_t) callstack[i] && cast(size_t) callstack[i] <= elfObj.end) + offset = elfObj.begin; + + locations[i].address = cast(size_t) callstack[i] - offset; + } resolveAddresses(debugLineSectionData, locations[]); } diff --git a/src/rt/backtrace/elf.d b/src/rt/backtrace/elf.d index 7a9b44f9918..904844b0eca 100644 --- a/src/rt/backtrace/elf.d +++ b/src/rt/backtrace/elf.d @@ -58,6 +58,62 @@ struct Image return null; } + + @property auto baseAddress() + { + version(linux) + { + import core.sys.linux.link; + import core.sys.linux.elf; + } + else version(FreeBSD) + { + import core.sys.freebsd.link_elf; + import core.sys.freebsd.elf; + } + else version(DragonFlyBSD) + { + import core.sys.dragonflybsd.link_elf; + import core.sys.freebsd.elf; + } + struct ElfBaseAddress + { + ElfW!"Addr" begin; + ElfW!"Addr" end; + bool set; + } + ElfBaseAddress elfAddress; + + // the DWARF addresses for DSOs are relative + const isDynamicSharedObject = (file.ehdr.e_type == ET_DYN); + if (!isDynamicSharedObject) + return elfAddress; + + extern(C) int dl_iterate_phdr_cb_ngc_tracehandler(dl_phdr_info* info, size_t, void* elfObj) @nogc + { + auto obj = cast(ElfBaseAddress*) elfObj; + // only take the first address as this will be the main binary + if (obj.set) + return 0; + + obj.set = true; + // search for the executable code segment + foreach (const ref phdr; info.dlpi_phdr[0 .. info.dlpi_phnum]) + { + if (phdr.p_type == PT_LOAD && phdr.p_flags & PF_X) + { + obj.begin = info.dlpi_addr + phdr.p_vaddr; + obj.end = obj.begin + phdr.p_memsz; + } + } + // temporarily fall back to this + obj.begin = info.dlpi_addr; + obj.end = obj.begin + info.dlpi_phdr.p_memsz; + return 0; + } + dl_iterate_phdr(&dl_iterate_phdr_cb_ngc_tracehandler, &elfAddress); + return elfAddress; + } } private: