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

Commit

Permalink
Support file/line dwarf in FreeBSD
Browse files Browse the repository at this point in the history
  • Loading branch information
yazd committed Sep 28, 2015
1 parent f0f8eda commit fb7bd91
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 13 deletions.
6 changes: 5 additions & 1 deletion src/core/runtime.d
Expand Up @@ -568,7 +568,11 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
enum FIRSTFRAME = 0;
}

version(linux)
version(linux) enum enableDwarf = true;
else version(FreeBSD) enum enableDwarf = true;
else enum enableDwarf = false;

static if (enableDwarf)
{
import core.internal.traits : externDFunc;

Expand Down
28 changes: 21 additions & 7 deletions src/rt/backtrace/dwarf.d
Expand Up @@ -12,7 +12,10 @@

module rt.backtrace.dwarf;

version(linux):
version(linux) version = linux_or_freebsd;
else version(FreeBSD) version = linux_or_freebsd;

version(linux_or_freebsd):

import rt.util.container.array;
import rt.backtrace.elf;
Expand All @@ -31,7 +34,8 @@ struct Location
int traceHandlerOpApplyImpl(const void*[] callstack, scope int delegate(ref size_t, ref const(char[])) dg)
{
import core.stdc.stdio : snprintf;
import core.sys.linux.execinfo : backtrace_symbols;
version(linux) import core.sys.linux.execinfo : backtrace_symbols;
else version(FreeBSD) import core.sys.freebsd.execinfo : backtrace_symbols;
import core.sys.posix.stdlib : free;

const char** frameList = backtrace_symbols(callstack.ptr, cast(int) callstack.length);
Expand Down Expand Up @@ -373,11 +377,21 @@ bool runStateMachine(const(LPHeader)* lpHeader, const(ubyte)[] program, const(ub

const(char)[] getDemangledSymbol(const(char)[] btSymbol, ref char[1024] buffer)
{
// format is: module(_D6module4funcAFZv) [0x00000000]
// or: module(_D6module4funcAFZv+0x78) [0x00000000]
auto bptr = cast(char*) memchr(btSymbol.ptr, '(', btSymbol.length);
auto eptr = cast(char*) memchr(btSymbol.ptr, ')', btSymbol.length);
auto pptr = cast(char*) memchr(btSymbol.ptr, '+', btSymbol.length);
version(linux)
{
// format is: module(_D6module4funcAFZv) [0x00000000]
// or: module(_D6module4funcAFZv+0x78) [0x00000000]
auto bptr = cast(char*) memchr(btSymbol.ptr, '(', btSymbol.length);
auto eptr = cast(char*) memchr(btSymbol.ptr, ')', btSymbol.length);
auto pptr = cast(char*) memchr(btSymbol.ptr, '+', btSymbol.length);
}
else version(FreeBSD)
{
// format is: 0x00000000 <_D6module4funcAFZv+0x78> at module
auto bptr = cast(char*) memchr(btSymbol.ptr, '<', btSymbol.length);
auto eptr = cast(char*) memchr(btSymbol.ptr, '>', btSymbol.length);
auto pptr = cast(char*) memchr(btSymbol.ptr, '+', btSymbol.length);
}

if (pptr && pptr < eptr)
eptr = pptr;
Expand Down
44 changes: 41 additions & 3 deletions src/rt/backtrace/elf.d
Expand Up @@ -11,18 +11,33 @@

module rt.backtrace.elf;

version(linux):
version(linux) version = linux_or_freebsd;
else version(FreeBSD) version = linux_or_freebsd;

version(linux_or_freebsd):

import core.sys.posix.fcntl;
import core.sys.posix.unistd;

public import core.sys.linux.elf;
version(linux) public import core.sys.linux.elf;
version(FreeBSD) public import core.sys.freebsd.sys.elf;

struct ElfFile
{
static bool openSelf(ElfFile* file) @nogc nothrow
{
file.fd = open("/proc/self/exe", O_RDONLY);
version (linux)
{
auto selfPath = "/proc/self/exe".ptr;
}
else version (FreeBSD)
{
char[1024] selfPathBuffer = void;
auto selfPath = getFreeBSDExePath(selfPathBuffer[]);
if (selfPath is null) return false;
}

file.fd = open(selfPath, O_RDONLY);
if (file.fd >= 0)
{
// memory map header
Expand Down Expand Up @@ -120,6 +135,29 @@ size_t findSectionByName(const(ElfFile)* file, ElfSection* stringSection, const(

private:

version (FreeBSD)
{
extern (C) int sysctl(const int* name, uint namelen, void* oldp, size_t* oldlenp, const void* newp, size_t newlen) @nogc nothrow;
const(char)* getFreeBSDExePath(char[] buffer) @nogc nothrow
{
enum
{
CTL_KERN = 1,
KERN_PROC = 14,
KERN_PROC_PATHNAME = 12
}

int[4] mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1];
size_t len = buffer.length;

auto result = sysctl(mib.ptr, mib.length, buffer.ptr, &len, null, 0); // get the length of the path
if (result != 0) return null;
if (len + 1 > buffer.length) return null;
buffer[len] = 0;
return buffer.ptr;
}
}

bool isValidElfHeader(const(Elf_Ehdr)* ehdr) @nogc nothrow
{
if (ehdr.e_ident[EI_MAG0] != ELFMAG0) return false;
Expand Down
8 changes: 6 additions & 2 deletions test/exceptions/Makefile
Expand Up @@ -3,9 +3,13 @@ include ../common.mak
TESTS:=stderr_msg unittest_assert
ifeq ($(OS)-$(BUILD),linux-debug)
TESTS:=$(TESTS) line_trace
DIFF:=diff
SED:=sed
endif
ifeq ($(OS)-$(BUILD),freebsd-debug)
TESTS:=$(TESTS) line_trace
endif

DIFF:=diff
SED:=sed

.PHONY: all clean
all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS)))
Expand Down

0 comments on commit fb7bd91

Please sign in to comment.