From 399c5a5cde5f6f8c00fbe275e8003479c8f3539c Mon Sep 17 00:00:00 2001 From: Alfred Persson Forsberg Date: Thu, 28 Jul 2022 19:51:58 +0200 Subject: [PATCH] initial commit Signed-off-by: Alfred Persson Forsberg --- execinfo.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++ execinfo.h | 45 +++++++++++++++++ meson.build | 16 ++++++ 3 files changed, 201 insertions(+) create mode 100644 execinfo.c create mode 100644 execinfo.h create mode 100644 meson.build diff --git a/execinfo.c b/execinfo.c new file mode 100644 index 0000000..7981628 --- /dev/null +++ b/execinfo.c @@ -0,0 +1,140 @@ +#define UNW_LOCAL_ONLY +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define D10(x) ceil(log10(((x) == 0) ? 2 : ((x) + 1))) + +inline static void * +realloc_safe(void *ptr, size_t size) { + void *nptr; + + nptr = realloc(ptr, size); + if (nptr == NULL) + free(ptr); + return nptr; +} + +int backtrace(void** buffer, int size) { + unw_cursor_t cur; + unw_context_t ctx; + + unw_getcontext(&ctx); + unw_init_local(&cur, &ctx); + unw_step(&cur); // step over the 'backtrace' call. (this function) + int i = 0; + + do { + if (++i == size) { + return i - 1; + } + unw_word_t ip; + unw_get_reg(&cur, UNW_REG_IP, &ip); + buffer[i - 1] = (void*)ip; + } while (unw_step(&cur)); + return i - 1; +} + +// pasted from resslinux/libexecinfo + +char **backtrace_symbols(void *const *buffer, int size) { + size_t clen, alen; + int i, offset; + char **rval; + Dl_info info; + + clen = size * sizeof(char *); + rval = malloc(clen); + if (rval == NULL) + return NULL; + for (i = 0; i < size; i++) { + if (dladdr(buffer[i], &info) != 0) { + if (info.dli_sname == NULL) { + info.dli_sname = "???"; // "cannot find symbol name :d "; + } + if (info.dli_saddr == NULL) { + info.dli_saddr = buffer[i]; + } + offset = buffer[i] - info.dli_saddr; + /* "0x01234567 at filename" */ + alen = 2 + /* "0x" */ + (sizeof(void *) * 2) + /* "01234567" */ + 2 + /* " <" */ + strlen(info.dli_sname) + /* "function" */ + 1 + /* "+" */ + 10 + /* "offset */ + 5 + /* "> at " */ + strlen(info.dli_fname) + /* "filename" */ + 1; /* "\0" */ + rval = realloc_safe(rval, clen + alen); + if (rval == NULL) + return NULL; + snprintf((char *) rval + clen, alen, "%p <%s+%d> at %s", + buffer[i], info.dli_sname, offset, info.dli_fname); + } else { + alen = 2 + /* "0x" */ + (sizeof(void *) * 2) + /* "01234567" */ + 1; /* "\0" */ + rval = realloc_safe(rval, clen + alen); + if (rval == NULL) + return NULL; + snprintf((char *) rval + clen, alen, "%p", buffer[i]); + } + rval[i] = (char *) clen; + clen += alen; + } + + for (i = 0; i < size; i++) + rval[i] += (long) rval; + + return rval; +} + +void backtrace_symbols_fd(void *const *buffer, int size, int fd) { + int i, len, offset; + char *buf; + Dl_info info; + + for (i = 0; i < size; i++) { + if (dladdr(buffer[i], &info) != 0) { + if (info.dli_sname == NULL) + info.dli_sname = "???"; + if (info.dli_saddr == NULL) + info.dli_saddr = buffer[i]; + offset = buffer[i] - info.dli_saddr; + /* "0x01234567 at filename" */ + len = 2 + /* "0x" */ + (sizeof(void *) * 2) + /* "01234567" */ + 2 + /* " <" */ + strlen(info.dli_sname) + /* "function" */ + 1 + /* "+" */ + D10(offset) + /* "offset */ + 5 + /* "> at " */ + strlen(info.dli_fname) + /* "filename" */ + 2; /* "\n\0" */ + buf = alloca(len); + if (buf == NULL) + return; + snprintf(buf, len, "%p <%s+%d> at %s\n", + buffer[i], info.dli_sname, offset, info.dli_fname); + } else { + len = 2 + /* "0x" */ + (sizeof(void *) * 2) + /* "01234567" */ + 2; /* "\n\0" */ + buf = alloca(len); + if (buf == NULL) + return; + snprintf(buf, len, "%p\n", buffer[i]); + } + write(fd, buf, strlen(buf)); + } +} diff --git a/execinfo.h b/execinfo.h new file mode 100644 index 0000000..1ee8651 --- /dev/null +++ b/execinfo.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003 Maxim Sobolev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: execinfo.h,v 1.2 2004/07/19 05:20:29 sobomax Exp $ + */ + +#ifndef _EXECINFO_H_ +#define _EXECINFO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int backtrace(void **, int); +char ** backtrace_symbols(void *const *, int); +void backtrace_symbols_fd(void *const *, int, int); +char ** bt_name(void *const *, int, int); + +#ifdef __cplusplus +} +#endif + +#endif /* _EXECINFO_H_ */ diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..e885458 --- /dev/null +++ b/meson.build @@ -0,0 +1,16 @@ +project('execinfo', 'c', version : '1.0.0') + +# pkg = import('pkgconfig') +prog_python = import('python').find_installation('python3') + +dep_unwind = dependency('libunwind-generic', required: true)#, required : true) +# deps = [ dep_unwind ] + +execinfo = library('execinfo', 'execinfo.c', + dependencies : [dep_unwind], + install : true) + +install_headers('execinfo.h') + +#pkg.generate(execinfo, +# description : 'Clone of the backtrace facility found in glibc implemented with libunwind')