From 6d679a7d9d8dbf9bc2c67cc0be747af2a9557314 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 21 Apr 2019 10:02:02 +0000 Subject: [PATCH] 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 --- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/core/runtime.d | 3 +- .../core/sys/dragonflybsd/execinfo.d | 208 ++++++++++-------- .../libdruntime/core/sys/freebsd/execinfo.d | 204 +++++++++-------- .../libdruntime/core/sys/netbsd/execinfo.d | 204 +++++++++-------- 5 files changed, 331 insertions(+), 290 deletions(-) diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index dd5f621082f..405be921eb3 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -70b9fea60246e63d936ad6826b1b48b6e0f1de8f +4b2674b36b1f6aac75db2a5aa38d67d4be55a987 The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d index 0ead04752e4..1fd54407aa5 100644 --- a/libphobos/libdruntime/core/runtime.d +++ b/libphobos/libdruntime/core/runtime.d @@ -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 ); } diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/execinfo.d b/libphobos/libdruntime/core/sys/dragonflybsd/execinfo.d index 9d2d615f786..9f91a0be6ca 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/execinfo.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/execinfo.d @@ -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' -} diff --git a/libphobos/libdruntime/core/sys/freebsd/execinfo.d b/libphobos/libdruntime/core/sys/freebsd/execinfo.d index 7b4ad6c03c4..cbdf70219dc 100644 --- a/libphobos/libdruntime/core/sys/freebsd/execinfo.d +++ b/libphobos/libdruntime/core/sys/freebsd/execinfo.d @@ -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' -} diff --git a/libphobos/libdruntime/core/sys/netbsd/execinfo.d b/libphobos/libdruntime/core/sys/netbsd/execinfo.d index 6287557a7e3..97b2a45d365 100644 --- a/libphobos/libdruntime/core/sys/netbsd/execinfo.d +++ b/libphobos/libdruntime/core/sys/netbsd/execinfo.d @@ -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' -} -- 2.30.2