From patchwork Sun Apr 21 10:07:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1088452 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-499520-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=gdcproject.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="C3XqdhSM"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44n54B68qYz9s4Y for ; Sun, 21 Apr 2019 20:07:33 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=GWkwK6ndGgS0Nm75GM3CVh9CueARyUDe6S19XLxa2KSxMM DWd0VL3JrUnKaayMpZxQMFd5r/Vr+yw9mmvkPz6JLfk7qsAidpWB9MnX4hZL9IkH T95mDaxYFaFCOEmJM/1JAmQFQY2rx8u2Muc5arlxsdroVmqf9DLNkz3jxoX8Q= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=f0cp3WhVJJOez47HuDxl3/Qfk0w=; b=C3XqdhSMV2UsZ3uag2aW RPtrztQmFe4Uf462MecFHhKjsc5nsKBnFqkZOn7GgnRikxslflrdsmiPtx7Yay/v 75DIJTa6UcNLH22N2HtiXirOTMil3J9zjbMvPfgomimV6mUXzrWH+g/UAgs3vZf8 Ts7sKONvHwKDSvQOFCpvcP4= Received: (qmail 92289 invoked by alias); 21 Apr 2019 10:07:24 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 92277 invoked by uid 89); 21 Apr 2019 10:07:23 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.0 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=MERGE, backtrace, netbsd, ebp X-HELO: mail-qk1-f180.google.com Received: from mail-qk1-f180.google.com (HELO mail-qk1-f180.google.com) (209.85.222.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 21 Apr 2019 10:07:20 +0000 Received: by mail-qk1-f180.google.com with SMTP id p19so2689609qkm.10 for ; Sun, 21 Apr 2019 03:07:20 -0700 (PDT) MIME-Version: 1.0 From: Iain Buclaw Date: Sun, 21 Apr 2019 12:07:07 +0200 Message-ID: Subject: [PATCH, libphobos] Committed merge with upstream druntime 4b2674b3 To: gcc-patches X-IsSubscribed: yes Hi, This patch merges the libdruntime sub-library with upstream druntime 4b2674b3. Adds version (BacktraceExternal) for using libexecinfo instead of internal implementation on FreeBSD, NetBSD, and DragonFly. Bootstrapped and regression tested on x86_64-linux-gnu, with preliminary build testing done on x86_64-freebsd11.2, x86_64-dragonfly5.4, and x86_64-netbsd8.0. Committed to trunk as r270482. 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' -}