mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 02:02:38 +01:00
ircd: Add interface to backtrace(3).
This commit is contained in:
parent
15c4c3cc63
commit
99d080767f
5 changed files with 170 additions and 0 deletions
45
include/ircd/backtrace.h
Normal file
45
include/ircd/backtrace.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// 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.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_BACKTRACE_H
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
struct backtrace;
|
||||
}
|
||||
|
||||
struct ircd::backtrace
|
||||
{
|
||||
void **array;
|
||||
size_t count;
|
||||
|
||||
public:
|
||||
void *operator[](const size_t &) const;
|
||||
const size_t &size() const;
|
||||
|
||||
backtrace(void **const &, const size_t &);
|
||||
backtrace(const mutable_buffer &);
|
||||
backtrace();
|
||||
};
|
||||
|
||||
inline void *
|
||||
ircd::backtrace::operator[](const size_t &i)
|
||||
const
|
||||
{
|
||||
return i < count? array[i] : nullptr;
|
||||
}
|
||||
|
||||
inline const size_t &
|
||||
ircd::backtrace::size()
|
||||
const
|
||||
{
|
||||
return count;
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
#include "exception.h"
|
||||
#include "run.h"
|
||||
#include "demangle.h"
|
||||
#include "backtrace.h"
|
||||
#include "localee.h"
|
||||
#include "timedate.h"
|
||||
#include "logger.h"
|
||||
|
|
|
@ -122,6 +122,7 @@ libircd_la_SOURCES += vg.cc
|
|||
libircd_la_SOURCES += exception.cc
|
||||
libircd_la_SOURCES += util.cc
|
||||
libircd_la_SOURCES += demangle.cc
|
||||
libircd_la_SOURCES += backtrace.cc
|
||||
libircd_la_SOURCES += locale.cc
|
||||
libircd_la_SOURCES += timedate.cc
|
||||
libircd_la_SOURCES += lex_cast.cc
|
||||
|
|
108
ircd/backtrace.cc
Normal file
108
ircd/backtrace.cc
Normal file
|
@ -0,0 +1,108 @@
|
|||
// 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)
|
||||
#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<void *, 512> backtrace_buffer;
|
||||
}
|
||||
|
||||
ircd::backtrace::backtrace()
|
||||
:backtrace
|
||||
{
|
||||
backtrace_buffer.data(),
|
||||
backtrace_buffer.size()
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::backtrace::backtrace(const mutable_buffer &buf)
|
||||
:backtrace
|
||||
{
|
||||
reinterpret_cast<void **>
|
||||
(
|
||||
const_cast<char **>
|
||||
(
|
||||
std::addressof(data(buf))
|
||||
)
|
||||
),
|
||||
buffer::size(buf) / sizeof(void *)
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::backtrace::backtrace(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(this->array, count);
|
||||
#endif
|
||||
}
|
|
@ -511,6 +511,21 @@ console_cmd__demangle(opt &out, const string_view &line)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__bt(opt &out, const string_view &line)
|
||||
{
|
||||
const ircd::backtrace bt;
|
||||
for(size_t i(0); i < bt.size(); ++i)
|
||||
{
|
||||
out
|
||||
<< std::dec << std::setw(3) << i << ':'
|
||||
<< ' ' << std::hex << '[' << uintptr_t(bt[i]) << ']'
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// main
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue