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

Refactor some backtrace code to make it possible to use libunwind #3322

Merged
merged 2 commits into from
Jan 2, 2021
Merged
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
113 changes: 69 additions & 44 deletions src/core/internal/backtrace/dwarf.d
Original file line number Diff line number Diff line change
Expand Up @@ -169,65 +169,90 @@ int traceHandlerOpApplyImpl(const(void*)[] callstack, scope int delegate(ref siz

auto image = Image.openSelf();

int processCallstack(const(ubyte)[] debugLineSectionData)
// find address -> file, line mapping using dwarf debug_line
Array!Location locations;
locations.length = callstack.length;
foreach (size_t i; 0 .. callstack.length)
{
// find address -> file, line mapping using dwarf debug_line
Array!Location locations;
locations.length = callstack.length;
foreach (size_t i; 0 .. callstack.length)
{
locations[i].address = callstack[i];
locations[i].procedure = getMangledSymbolName(frameList[i][0 .. strlen(frameList[i])]);
}

if (debugLineSectionData)
resolveAddresses(debugLineSectionData, locations[], image.baseAddress);
locations[i].address = callstack[i];
locations[i].procedure = getMangledSymbolName(frameList[i][0 .. strlen(frameList[i])]);
}

char[1536] buffer = void;
size_t bufferLength;
scope sink = (scope const char[] data) {
// We cannot write anymore
if (bufferLength > buffer.length)
return;
return image.isValid
? image.processDebugLineSectionData(
(line) => locations[].processCallstack(line, image.baseAddress, dg))
: locations[].processCallstack(null, image.baseAddress, dg);
}

if (bufferLength + data.length > buffer.length)
{
buffer[bufferLength .. $] = data[0 .. buffer.length - bufferLength];
buffer[$ - 3 .. $] = "...";
// +1 is a marker for the '...', otherwise if the symbol
// name was to exactly fill the buffer,
// we'd discard anything else without printing the '...'.
bufferLength = buffer.length + 1;
return;
}
struct TraceInfoBuffer
{
private char[1536] buf = void;
private size_t position;

buffer[bufferLength .. bufferLength + data.length] = data;
bufferLength += data.length;
};
// BUG: https://issues.dlang.org/show_bug.cgi?id=21285
@safe pure nothrow @nogc
{
///
inout(char)[] opSlice() inout return
{
return this.buf[0 .. this.position > $ ? $ : this.position];
}

foreach (idx, const ref loc; locations)
///
void reset()
{
bufferLength = 0;
loc.toString(sink);
this.position = 0;
}
}

auto lvalue = buffer[0 .. bufferLength > $ ? $ : bufferLength];
if (auto ret = dg(idx, lvalue))
return ret;
/// Used as `sink` argument to `Location.toString`
void put(scope const char[] data)
{
// We cannot write anymore
if (this.position > this.buf.length)
return;

if (loc.procedure == "_Dmain")
break;
if (this.position + data.length > this.buf.length)
{
this.buf[this.position .. $] = data[0 .. this.buf.length - this.position];
this.buf[$ - 3 .. $] = "...";
// +1 is a marker for the '...', otherwise if the symbol
// name was to exactly fill the buffer,
// we'd discard anything else without printing the '...'.
this.position = this.buf.length + 1;
return;
}

return 0;
this.buf[this.position .. this.position + data.length] = data;
this.position += data.length;
}

return image.isValid
? image.processDebugLineSectionData(&processCallstack)
: processCallstack(null);
}

private:

int processCallstack(Location[] locations, const(ubyte)[] debugLineSectionData,
size_t baseAddress, scope int delegate(ref size_t, ref const(char[])) dg)
{
if (debugLineSectionData)
resolveAddresses(debugLineSectionData, locations, baseAddress);

TraceInfoBuffer buffer;
foreach (idx, const ref loc; locations)
{
buffer.reset();
loc.toString(&buffer.put);

auto lvalue = buffer[];
if (auto ret = dg(idx, lvalue))
return ret;

if (loc.procedure == "_Dmain")
break;
}

return 0;
}

// the lifetime of the Location data is bound to the lifetime of debugLineSectionData
void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations, size_t baseAddress) @nogc nothrow
{
Expand Down