mirror of
https://github.com/matrix-construct/construct
synced 2024-11-30 10:42:47 +01:00
108 lines
2.5 KiB
C++
108 lines
2.5 KiB
C++
// Matrix Construct
|
|
//
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
#include <RB_INC_EXECINFO_H
|
|
#include <RB_INC_SYS_MMAN_H
|
|
|
|
#if defined(__GNUC__) && defined(HAVE_EXECINFO_H)
|
|
#define IRCD_BACKTRACE_SUPPORT
|
|
#endif
|
|
|
|
#if defined(IRCD_BACKTRACE_SUPPORT) && defined(HAVE_SYS_MMAN_H) && !defined(__clang__)
|
|
#define IRCD_BACKTRACE_GLIBC_WORKAROUND
|
|
#endif
|
|
|
|
#if defined(IRCD_BACKTRACE_GLIBC_WORKAROUND)
|
|
// The problem here is that backtrace(3) performs checks against this value
|
|
// which is not correct for our own allocated `ircd::ctx` stacks. To workaround
|
|
// this we neutralize the value before calling backtrace(3) and restore it
|
|
// afterward. While this symbol is extern accessible, the page its on is
|
|
// write-protected at some point, so we have to re-allow writing to it here.
|
|
//
|
|
// sysdeps/i386/backtrace.c | elf/dl-support.c
|
|
// > This is a global variable set at program start time. It marks the
|
|
// > highest used stack address.
|
|
//
|
|
extern void *
|
|
__libc_stack_end;
|
|
|
|
void
|
|
__attribute__((constructor))
|
|
ircd_backtrace_allow_libc_fix()
|
|
{
|
|
static const auto &prot
|
|
{
|
|
PROT_READ | PROT_WRITE
|
|
};
|
|
|
|
const auto &addr
|
|
{
|
|
uintptr_t(&__libc_stack_end) & ~(getpagesize() - 1UL)
|
|
};
|
|
|
|
ircd::syscall(::mprotect, (void *)addr, sizeof(__libc_stack_end), prot);
|
|
}
|
|
#endif defined(IRCD_BACKTRACE_GLIBC_WORKAROUND)
|
|
|
|
//
|
|
// backtrace::backtrace
|
|
//
|
|
|
|
namespace ircd
|
|
{
|
|
thread_local std::array<const void *, 512> backtrace_buffer;
|
|
}
|
|
|
|
ircd::backtrace::backtrace()
|
|
:backtrace
|
|
{
|
|
backtrace_buffer.data(),
|
|
backtrace_buffer.size()
|
|
}
|
|
{
|
|
}
|
|
|
|
ircd::backtrace::backtrace(const mutable_buffer &buf)
|
|
:backtrace
|
|
{
|
|
reinterpret_cast<const void **>
|
|
(
|
|
const_cast<const char **>
|
|
(
|
|
std::addressof(data(buf))
|
|
)
|
|
),
|
|
buffer::size(buf) / sizeof(void *)
|
|
}
|
|
{
|
|
}
|
|
|
|
ircd::backtrace::backtrace(const void **const &array,
|
|
const size_t &count)
|
|
:array
|
|
{
|
|
array
|
|
}
|
|
,count
|
|
{
|
|
0UL
|
|
}
|
|
{
|
|
#if defined(IRCD_BACKTRACE_GLIBC_WORKAROUND)
|
|
const scope_restore stack_check_workaround
|
|
{
|
|
__libc_stack_end, reinterpret_cast<void *>(uintptr_t(-1UL))
|
|
};
|
|
#endif
|
|
|
|
#if defined(IRCD_BACKTRACE_SUPPORT)
|
|
this->count = ::backtrace(const_cast<void **>(this->array), count);
|
|
#endif
|
|
}
|