Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/rt/backtrace/dwarf.d
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size
foreach(size_t i; 0 .. callstack.length)
locations[i].address = cast(size_t) callstack[i];

resolveAddresses(debugLineSectionData, locations[]);
resolveAddresses(debugLineSectionData, locations[], image.baseAddress);
}
}

Expand Down Expand Up @@ -108,7 +108,7 @@ int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size
private:

// the lifetime of the Location data is the lifetime of the mmapped ElfSection
void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations) @nogc nothrow
void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations, size_t baseAddress) @nogc nothrow
{
debug(DwarfDebugMachine) import core.stdc.stdio;

Expand Down Expand Up @@ -202,6 +202,9 @@ void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations)
runStateMachine(lph, program, standardOpcodeLengths,
(size_t address, LocationInfo locInfo, bool isEndSequence)
{
// adjust to ASLR offset
address += baseAddress;
debug(DwarfDebugMachine) printf("-- offsetting 0x%x to 0x%x\n", address - baseAddress, address);
// If loc.line != -1, then it has been set previously.
// Some implementations (eg. dmd) write an address to
// the debug data multiple times, but so far I have found
Expand Down
56 changes: 56 additions & 0 deletions src/rt/backtrace/elf.d
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,62 @@ struct Image

return null;
}

@property size_t baseAddress()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an awful lot of logic for a property, and would be run needlessly if called multiple times by a caller that isn't aware of the implementation. The baseAddress shouldn't change during the lifetime of an Image, so wouldn't it be better to put this in the constructor, and store the result as a field?

{
version(linux)
{
import core.sys.linux.link;
import core.sys.linux.elf;
}
else version(FreeBSD)
{
import core.sys.freebsd.sys.link_elf;
import core.sys.freebsd.sys.elf;
}
else version(DragonFlyBSD)
{
import core.sys.dragonflybsd.sys.link_elf;
import core.sys.dragonflybsd.sys.elf;
}

static struct ElfAddress
{
size_t begin;
bool set;
}
ElfAddress elfAddress;

// the DWARF addresses for DSOs are relative
const isDynamicSharedObject = (file.ehdr.e_type == ET_DYN);
if (!isDynamicSharedObject)
return 0;

extern(C) int dl_iterate_phdr_cb_ngc_tracehandler(dl_phdr_info* info, size_t, void* elfObj) @nogc
{
auto obj = cast(ElfAddress*) 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.length = phdr.p_memsz;
}
}
// temporarily fall back to this
obj.begin = info.dlpi_addr;
//obj.length = info.dlpi_phdr.p_memsz;
return 0;
}
dl_iterate_phdr(&dl_iterate_phdr_cb_ngc_tracehandler, &elfAddress);
return elfAddress.begin;
}
}

private:
Expand Down
5 changes: 5 additions & 0 deletions src/rt/backtrace/macho.d
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,9 @@ struct Image
auto data = getsectiondata(self, "__DWARF", "__debug_line", &size);
return data[0 .. size];
}

@property size_t baseAddress()
{
return 0;
}
}
18 changes: 18 additions & 0 deletions test/exceptions/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ TESTS:=stderr_msg unittest_assert invalid_memory_operation unknown_gc static_dto

ifeq ($(OS)-$(BUILD),linux-debug)
TESTS:=$(TESTS) line_trace rt_trap_exceptions
ifeq ($(MODEL), 64)
TESTS+=line_trace_shared
endif
LINE_TRACE_DFLAGS:=-L--export-dynamic
endif
ifeq ($(OS)-$(BUILD),freebsd-debug)
Expand Down Expand Up @@ -33,6 +36,14 @@ $(ROOT)/line_trace.done: $(ROOT)/line_trace
@rm -f $(ROOT)/line_trace.output
@touch $@

$(ROOT)/line_trace_shared.done: $(ROOT)/line_trace_shared
@echo Testing line_trace
! LD_LIBRARY_PATH="$(ROOT)" $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace_shared $(RUN_ARGS) 2> $(ROOT)/line_trace_shared.output
# Use sed to canonicalize line_trace_shared.output and compare against expected output in line_trace_shared.exp
$(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_shared.output | $(DIFF) -p line_trace_shared.exp -
@rm -f $(ROOT)/line_trace_shared.output
@touch $@

$(ROOT)/chain.done: $(ROOT)/chain
@echo Testing chain
$(QUIET)$(TIMELIMIT)$(ROOT)/chain $(RUN_ARGS) > $(ROOT)/chain.output
Expand All @@ -55,6 +66,13 @@ $(ROOT)/%.done: $(ROOT)/%

$(ROOT)/unittest_assert: DFLAGS+=-unittest
$(ROOT)/line_trace: DFLAGS+=$(LINE_TRACE_DFLAGS)

$(ROOT)/line_trace_shared_lib.so: $(SRC)/line_trace_shared_lib.d
$(QUIET)$(DMD) $(DFLAGS) $(LINE_TRACE_DFLAGS) -shared -of$@ $<

$(ROOT)/line_trace_shared: $(SRC)/line_trace_shared.d $(ROOT)/line_trace_shared_lib.so
$(QUIET)$(DMD) $(LINE_TRACE_DFLAGS) -Isrc -L-L$(ROOT) -L-l:line_trace_shared_lib.so -of$@ $<

$(ROOT)/%: $(SRC)/%.d
$(QUIET)$(DMD) $(DFLAGS) -of$@ $<

Expand Down
2 changes: 2 additions & 0 deletions test/exceptions/line_trace_shared.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
object.Exception@src/line_trace_shared_lib.d(3): exception
----------------
5 changes: 5 additions & 0 deletions test/exceptions/src/line_trace_shared.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
void main()
{
import line_trace_shared_lib;
exception();
}
4 changes: 4 additions & 0 deletions test/exceptions/src/line_trace_shared_lib.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
void exception()
{
throw new Exception("exception");
}