0
0
Fork 0
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:
Jason Volk 2019-09-19 22:02:57 -07:00
parent 15c4c3cc63
commit 99d080767f
5 changed files with 170 additions and 0 deletions

45
include/ircd/backtrace.h Normal file
View 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;
}

View file

@ -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"

View file

@ -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
View 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
}

View file

@ -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
//