Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit d109d53

Browse files
committed
fix Issue 18068 - Account for DSO-relative DWARF addresses
1 parent 7c2ea83 commit d109d53

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

src/rt/backtrace/dwarf.d

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size
7373
foreach(size_t i; 0 .. callstack.length)
7474
locations[i].address = cast(size_t) callstack[i];
7575

76-
resolveAddresses(debugLineSectionData, locations[]);
76+
resolveAddresses(debugLineSectionData, image.baseAddress, locations[]);
7777
}
7878
}
7979

@@ -123,7 +123,7 @@ int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size
123123
private:
124124

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

@@ -142,6 +142,8 @@ void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations)
142142
runStateMachine(lp,
143143
(size_t address, LocationInfo locInfo, bool isEndSequence)
144144
{
145+
address += baseAddress;
146+
145147
// If loc.line != -1, then it has been set previously.
146148
// Some implementations (eg. dmd) write an address to
147149
// the debug data multiple times, but so far I have found

src/rt/backtrace/elf.d

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ struct Image
5858

5959
return null;
6060
}
61+
62+
@property size_t baseAddress()
63+
{
64+
// the DWARF addresses for DSOs are relative
65+
const isDynamicSharedObject = (file.ehdr.e_type == ET_DYN);
66+
if (!isDynamicSharedObject)
67+
return 0;
68+
69+
return cast(size_t) getMemoryRegionOfExecutable().ptr;
70+
}
6171
}
6272

6373
private:
@@ -322,3 +332,57 @@ else
322332
{
323333
static assert(0, "unsupported byte order");
324334
}
335+
336+
337+
const(void)[] getMemoryRegionOfExecutable() @nogc nothrow
338+
{
339+
import core.sys.posix.unistd : readlink, getpid;
340+
import core.stdc.stdio, core.stdc.stdlib, core.stdc.string;
341+
342+
// get absolute path to executable
343+
char[1024] selfPath = void;
344+
version (FreeBSD)
345+
{
346+
getFreeBSDExePath(selfPath[]);
347+
}
348+
else
349+
{
350+
version (linux)
351+
{
352+
auto selfLink = "/proc/self/exe".ptr;
353+
}
354+
else version (DragonFlyBSD)
355+
{
356+
auto selfLink = "/proc/curproc/file".ptr;
357+
}
358+
359+
const length = readlink(selfLink, selfPath.ptr, selfPath.length);
360+
assert(length > 0 && length < selfPath.length);
361+
selfPath[length] = 0;
362+
}
363+
364+
// open the current process' maps file
365+
char[1024] selfMapsPath = void;
366+
snprintf(selfMapsPath.ptr, selfMapsPath.length, "/proc/%d/maps", getpid());
367+
FILE* fp = fopen(selfMapsPath.ptr, "r");
368+
assert(fp);
369+
scope(exit) fclose(fp);
370+
371+
// use the region in the first line for the executable file
372+
char[128] line = void;
373+
while (fgets(line.ptr, line.length, fp) !is null)
374+
{
375+
line[strlen(line.ptr) - 1] = '\0'; // remove trailing '\n'
376+
char* path = strchr(line.ptr, '/');
377+
if (path && strcmp(selfPath.ptr, path) == 0)
378+
{
379+
char* tail;
380+
const start = cast(void*) strtoul(line.ptr, &tail, 16);
381+
++tail; // skip over '-'
382+
const end = cast(void*) strtoul(tail, &tail, 16);
383+
return start[0 .. end - start];
384+
}
385+
}
386+
387+
assert(0);
388+
}

src/rt/backtrace/macho.d

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,9 @@ struct Image
6767
auto data = getsectiondata(self, "__DWARF", "__debug_line", &size);
6868
return data[0 .. size];
6969
}
70+
71+
@property size_t baseAddress()
72+
{
73+
return 0;
74+
}
7075
}

0 commit comments

Comments
 (0)