Commit 6d679a7d by Iain Buclaw

libphobos: Merge upstream druntime 4b2674b3

Adds version (BacktraceExternal) for using libexecinfo instead of
internal implementation on FreeBSD, NetBSD, and DragonFly.

Reviewed-on: https://github.com/dlang/druntime/pull/2560

From-SVN: r270482
parent 42d3fe9a
70b9fea60246e63d936ad6826b1b48b6e0f1de8f 4b2674b36b1f6aac75db2a5aa38d67d4be55a987
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository. merge done from the dlang/druntime repository.
...@@ -519,9 +519,8 @@ extern (C) bool runModuleUnitTests() ...@@ -519,9 +519,8 @@ extern (C) bool runModuleUnitTests()
{ {
static enum MAXFRAMES = 128; static enum MAXFRAMES = 128;
void*[MAXFRAMES] callstack; void*[MAXFRAMES] callstack;
int numframes;
numframes = backtrace( callstack.ptr, MAXFRAMES ); auto numframes = backtrace( callstack.ptr, MAXFRAMES );
backtrace_symbols_fd( callstack.ptr, numframes, 2 ); backtrace_symbols_fd( callstack.ptr, numframes, 2 );
} }
......
...@@ -9,125 +9,139 @@ ...@@ -9,125 +9,139 @@
module core.sys.dragonflybsd.execinfo; module core.sys.dragonflybsd.execinfo;
version (DragonFlyBSD): version (DragonFlyBSD):
extern (C):
nothrow:
extern (C) nothrow @system: version (GNU)
version = BacktraceExternal;
import core.sys.dragonflybsd.dlfcn; version (BacktraceExternal)
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) int backtrace(void** buffer, int size)
{ {
import core.thread : thread_stackBottom; size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void** p, pend=cast(void**)thread_stackBottom(); void backtrace_symbols_fd(const(void*)*, size_t, int);
version (D_InlineAsm_X86) char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
asm nothrow @trusted { mov p[EBP], EBP; } int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
else
{
import core.sys.dragonflybsd.dlfcn;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) char** backtrace_symbols(const(void*)* buffer, int size) extern (D) int backtrace(void** buffer, int size)
{
static void* realloc(void* p, size_t len) nothrow
{ {
static import cstdlib=core.stdc.stdlib; import core.thread : thread_stackBottom;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p); void** p, pend=cast(void**)thread_stackBottom();
return res; version (D_InlineAsm_X86)
asm nothrow @trusted { mov p[EBP], EBP; }
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
Dl_info info; extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) static void* realloc(void* p, size_t len) nothrow
(cast(ubyte*)&info)[0 .. info.sizeof] = 0; {
fixupDLInfo(addr, info); static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
immutable len = formatStackFrame(null, 0, addr, info); if (res is null) cstdlib.free(p);
assert(len > 0); return res;
}
p = cast(char**)realloc(p, pos + len);
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null; if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0); Dl_info info;
foreach (i, addr; buffer[0 .. size])
p[i] = cast(char*)pos; {
pos += len; if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
immutable len = formatStackFrame(null, 0, addr, info);
assert(len > 0);
p = cast(char**)realloc(p, pos + len);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
}
foreach (i; 0 .. size)
{
pos = cast(size_t)p[i];
p[i] = cast(char*)p + pos;
}
return p;
} }
foreach (i; 0 .. size)
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd)
{ {
pos = cast(size_t)p[i]; import core.sys.posix.unistd : write;
p[i] = cast(char*)p + pos; import core.stdc.stdlib : alloca;
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
assert(len > 0);
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
}
} }
return p;
}
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd) private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{ {
import core.sys.posix.unistd : write; if (info.dli_fname is null) info.dli_fname = "???";
import core.stdc.stdlib : alloca; if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
if (size <= 0) return;
Dl_info info; private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) import core.stdc.stdio : snprintf;
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024; immutable off = addr - info.dli_saddr;
enum min = (size_t a, size_t b) => a <= b ? a : b; immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca); addr, info.dli_sname, off, info.dli_fname);
assert(len > 0); assert(len > 0);
return cast(size_t)len + 1; // + '\0'
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
} }
} }
private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{
if (info.dli_fname is null) info.dli_fname = "???";
if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
import core.stdc.stdio : snprintf;
immutable off = addr - info.dli_saddr;
immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
addr, info.dli_sname, off, info.dli_fname);
assert(len > 0);
return cast(size_t)len + 1; // + '\0'
}
...@@ -12,122 +12,136 @@ version (FreeBSD): ...@@ -12,122 +12,136 @@ version (FreeBSD):
extern (C): extern (C):
nothrow: nothrow:
import core.sys.freebsd.dlfcn; version (GNU)
version = BacktraceExternal;
// Use extern (D) so that these functions don't collide with libexecinfo. version (BacktraceExternal)
extern (D) int backtrace(void** buffer, int size)
{ {
import core.thread : thread_stackBottom; size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void** p, pend=cast(void**)thread_stackBottom(); void backtrace_symbols_fd(const(void*)*, size_t, int);
version (D_InlineAsm_X86) char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
asm nothrow @trusted { mov p[EBP], EBP; } int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
else
{
import core.sys.freebsd.dlfcn;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) char** backtrace_symbols(const(void*)* buffer, int size) extern (D) int backtrace(void** buffer, int size)
{
static void* realloc(void* p, size_t len) nothrow
{ {
static import cstdlib=core.stdc.stdlib; import core.thread : thread_stackBottom;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p); void** p, pend=cast(void**)thread_stackBottom();
return res; version (D_InlineAsm_X86)
asm nothrow @trusted { mov p[EBP], EBP; }
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
Dl_info info; extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) static void* realloc(void* p, size_t len) nothrow
(cast(ubyte*)&info)[0 .. info.sizeof] = 0; {
fixupDLInfo(addr, info); static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
immutable len = formatStackFrame(null, 0, addr, info); if (res is null) cstdlib.free(p);
assert(len > 0); return res;
}
p = cast(char**)realloc(p, pos + len);
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null; if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0); Dl_info info;
foreach (i, addr; buffer[0 .. size])
p[i] = cast(char*)pos; {
pos += len; if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
immutable len = formatStackFrame(null, 0, addr, info);
assert(len > 0);
p = cast(char**)realloc(p, pos + len);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
}
foreach (i; 0 .. size)
{
pos = cast(size_t)p[i];
p[i] = cast(char*)p + pos;
}
return p;
} }
foreach (i; 0 .. size)
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd)
{ {
pos = cast(size_t)p[i]; import core.sys.posix.unistd : write;
p[i] = cast(char*)p + pos; import core.stdc.stdlib : alloca;
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
assert(len > 0);
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
}
} }
return p;
}
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd) private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{ {
import core.sys.posix.unistd : write; if (info.dli_fname is null) info.dli_fname = "???";
import core.stdc.stdlib : alloca; if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
if (size <= 0) return;
Dl_info info; private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) import core.stdc.stdio : snprintf;
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024; immutable off = addr - info.dli_saddr;
enum min = (size_t a, size_t b) => a <= b ? a : b; immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca); addr, info.dli_sname, off, info.dli_fname);
assert(len > 0); assert(len > 0);
return cast(size_t)len + 1; // + '\0'
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
} }
} }
private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{
if (info.dli_fname is null) info.dli_fname = "???";
if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
import core.stdc.stdio : snprintf;
immutable off = addr - info.dli_saddr;
immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
addr, info.dli_sname, off, info.dli_fname);
assert(len > 0);
return cast(size_t)len + 1; // + '\0'
}
...@@ -12,122 +12,136 @@ version (NetBSD): ...@@ -12,122 +12,136 @@ version (NetBSD):
extern (C): extern (C):
nothrow: nothrow:
import core.sys.netbsd.dlfcn; version (GNU)
version = BacktraceExternal;
// Use extern (D) so that these functions don't collide with libexecinfo. version (BacktraceExternal)
extern (D) int backtrace(void** buffer, int size)
{ {
import core.thread : thread_stackBottom; size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void** p, pend=cast(void**)thread_stackBottom(); void backtrace_symbols_fd(const(void*)*, size_t, int);
version (D_InlineAsm_X86) char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
asm nothrow @trusted { mov p[EBP], EBP; } int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
else
{
import core.sys.netbsd.dlfcn;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) char** backtrace_symbols(const(void*)* buffer, int size) extern (D) int backtrace(void** buffer, int size)
{
static void* realloc(void* p, size_t len) nothrow
{ {
static import cstdlib=core.stdc.stdlib; import core.thread : thread_stackBottom;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p); void** p, pend=cast(void**)thread_stackBottom();
return res; version (D_InlineAsm_X86)
asm nothrow @trusted { mov p[EBP], EBP; }
else version (D_InlineAsm_X86_64)
asm nothrow @trusted { mov p[RBP], RBP; }
else
static assert(false, "Architecture not supported.");
int i;
for (; i < size && p < pend; ++i)
{
buffer[i] = *(p + 1);
auto pnext = cast(void**)*p;
if (pnext <= p) break;
p = pnext;
}
return i;
} }
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
Dl_info info; extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) static void* realloc(void* p, size_t len) nothrow
(cast(ubyte*)&info)[0 .. info.sizeof] = 0; {
fixupDLInfo(addr, info); static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
immutable len = formatStackFrame(null, 0, addr, info); if (res is null) cstdlib.free(p);
assert(len > 0); return res;
}
p = cast(char**)realloc(p, pos + len);
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null; if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0); Dl_info info;
foreach (i, addr; buffer[0 .. size])
p[i] = cast(char*)pos; {
pos += len; if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
immutable len = formatStackFrame(null, 0, addr, info);
assert(len > 0);
p = cast(char**)realloc(p, pos + len);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
}
foreach (i; 0 .. size)
{
pos = cast(size_t)p[i];
p[i] = cast(char*)p + pos;
}
return p;
} }
foreach (i; 0 .. size)
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd)
{ {
pos = cast(size_t)p[i]; import core.sys.posix.unistd : write;
p[i] = cast(char*)p + pos; import core.stdc.stdlib : alloca;
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
assert(len > 0);
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
}
} }
return p;
}
extern (D) void backtrace_symbols_fd(const(void*)* buffer, int size, int fd) private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{ {
import core.sys.posix.unistd : write; if (info.dli_fname is null) info.dli_fname = "???";
import core.stdc.stdlib : alloca; if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
if (size <= 0) return;
Dl_info info; private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
foreach (i, addr; buffer[0 .. size])
{ {
if (dladdr(addr, &info) == 0) import core.stdc.stdio : snprintf;
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
enum maxAlloca = 1024; immutable off = addr - info.dli_saddr;
enum min = (size_t a, size_t b) => a <= b ? a : b; immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca); addr, info.dli_sname, off, info.dli_fname);
assert(len > 0); assert(len > 0);
return cast(size_t)len + 1; // + '\0'
auto p = cast(char*)alloca(len);
if (p is null) return;
formatStackFrame(p, len, addr, info) >= len || assert(0);
p[len - 1] = '\n';
write(fd, p, len);
} }
} }
private void fixupDLInfo(const(void)* addr, ref Dl_info info)
{
if (info.dli_fname is null) info.dli_fname = "???";
if (info.dli_fbase is null) info.dli_fbase = null;
if (info.dli_sname is null) info.dli_sname = "???";
if (info.dli_saddr is null) info.dli_saddr = cast(void*)addr;
}
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
import core.stdc.stdio : snprintf;
immutable off = addr - info.dli_saddr;
immutable len = snprintf(p, plen, "%p <%s+%zd> at %s",
addr, info.dli_sname, off, info.dli_fname);
assert(len > 0);
return cast(size_t)len + 1; // + '\0'
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment