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
merge done from the dlang/druntime repository.
......@@ -519,9 +519,8 @@ extern (C) bool runModuleUnitTests()
{
static enum MAXFRAMES = 128;
void*[MAXFRAMES] callstack;
int numframes;
numframes = backtrace( callstack.ptr, MAXFRAMES );
auto numframes = backtrace( callstack.ptr, MAXFRAMES );
backtrace_symbols_fd( callstack.ptr, numframes, 2 );
}
......
......@@ -9,125 +9,139 @@
module core.sys.dragonflybsd.execinfo;
version (DragonFlyBSD):
extern (C):
nothrow:
extern (C) nothrow @system:
version (GNU)
version = BacktraceExternal;
import core.sys.dragonflybsd.dlfcn;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) int backtrace(void** buffer, int size)
version (BacktraceExternal)
{
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void backtrace_symbols_fd(const(void*)*, size_t, int);
char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
}
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)
{
static void* realloc(void* p, size_t len) nothrow
extern (D) int backtrace(void** buffer, int size)
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
foreach (i, addr; buffer[0 .. size])
extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
{
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);
static void* realloc(void* p, size_t len) nothrow
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
}
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
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];
p[i] = cast(char*)p + pos;
import core.sys.posix.unistd : write;
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)
{
import core.sys.posix.unistd : write;
import core.stdc.stdlib : alloca;
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;
}
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
import core.stdc.stdio : snprintf;
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
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);
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 cast(size_t)len + 1; // + '\0'
}
}
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):
extern (C):
nothrow:
import core.sys.freebsd.dlfcn;
version (GNU)
version = BacktraceExternal;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) int backtrace(void** buffer, int size)
version (BacktraceExternal)
{
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void backtrace_symbols_fd(const(void*)*, size_t, int);
char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
}
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)
{
static void* realloc(void* p, size_t len) nothrow
extern (D) int backtrace(void** buffer, int size)
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
foreach (i, addr; buffer[0 .. size])
extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
{
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);
static void* realloc(void* p, size_t len) nothrow
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
}
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
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];
p[i] = cast(char*)p + pos;
import core.sys.posix.unistd : write;
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)
{
import core.sys.posix.unistd : write;
import core.stdc.stdlib : alloca;
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;
}
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
import core.stdc.stdio : snprintf;
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
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);
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 cast(size_t)len + 1; // + '\0'
}
}
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):
extern (C):
nothrow:
import core.sys.netbsd.dlfcn;
version (GNU)
version = BacktraceExternal;
// Use extern (D) so that these functions don't collide with libexecinfo.
extern (D) int backtrace(void** buffer, int size)
version (BacktraceExternal)
{
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
size_t backtrace(void**, size_t);
char** backtrace_symbols(const(void*)*, size_t);
void backtrace_symbols_fd(const(void*)*, size_t, int);
char** backtrace_symbols_fmt(const(void*)*, size_t, const char*);
int backtrace_symbols_fd_fmt(const(void*)*, size_t, int, const char*);
}
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)
{
static void* realloc(void* p, size_t len) nothrow
extern (D) int backtrace(void** buffer, int size)
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
import core.thread : thread_stackBottom;
void** p, pend=cast(void**)thread_stackBottom();
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;
foreach (i, addr; buffer[0 .. size])
extern (D) char** backtrace_symbols(const(void*)* buffer, int size)
{
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);
static void* realloc(void* p, size_t len) nothrow
{
static import cstdlib=core.stdc.stdlib;
auto res = cstdlib.realloc(p, len);
if (res is null) cstdlib.free(p);
return res;
}
if (size <= 0) return null;
size_t pos = size * (char*).sizeof;
char** p = cast(char**)realloc(null, pos);
if (p is null) return null;
formatStackFrame(cast(char*)p + pos, len, addr, info) == len || assert(0);
p[i] = cast(char*)pos;
pos += len;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
{
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];
p[i] = cast(char*)p + pos;
import core.sys.posix.unistd : write;
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)
{
import core.sys.posix.unistd : write;
import core.stdc.stdlib : alloca;
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;
}
if (size <= 0) return;
Dl_info info;
foreach (i, addr; buffer[0 .. size])
private size_t formatStackFrame(char* p, size_t plen, const(void)* addr, const ref Dl_info info)
{
if (dladdr(addr, &info) == 0)
(cast(ubyte*)&info)[0 .. info.sizeof] = 0;
fixupDLInfo(addr, info);
import core.stdc.stdio : snprintf;
enum maxAlloca = 1024;
enum min = (size_t a, size_t b) => a <= b ? a : b;
immutable len = min(formatStackFrame(null, 0, addr, info), maxAlloca);
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);
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 cast(size_t)len + 1; // + '\0'
}
}
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