84 lines
2.0 KiB
C++
84 lines
2.0 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2019, Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include "backtrace.hpp"
|
|
|
|
#include "cast.hpp"
|
|
#include "iterator/zip.hpp"
|
|
|
|
#include <fmt/ostream.h>
|
|
|
|
#include <ostream>
|
|
#include <memory>
|
|
|
|
#include <execinfo.h>
|
|
|
|
using cruft::backtrace;
|
|
|
|
static constexpr std::size_t DEFAULT_DEPTH = 16;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
backtrace::backtrace (void)
|
|
: m_frames (DEFAULT_DEPTH)
|
|
{
|
|
do {
|
|
int const target = static_cast<int> (m_frames.size ());
|
|
int const last = ::backtrace (
|
|
m_frames.data (), target
|
|
);
|
|
|
|
if (last < target) {
|
|
m_frames.resize (last);
|
|
break;
|
|
}
|
|
|
|
m_frames.resize (m_frames.size () * 2);
|
|
} while (1);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
std::ostream&
|
|
cruft::operator <<(std::ostream &os, backtrace const &rhs) {
|
|
fmt::print (os, "{}", rhs);
|
|
return os;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
fmt::format_context::iterator
|
|
fmt::formatter<cruft::backtrace>::format (
|
|
cruft::backtrace const &obj,
|
|
fmt::format_context &ctx
|
|
) const {
|
|
fmt::format_to (ctx.out (), "[ ");
|
|
|
|
auto const &frames = obj.frames ();
|
|
|
|
using strings_t = std::unique_ptr<char *, decltype(&std::free)>;
|
|
strings_t const names (
|
|
backtrace_symbols (
|
|
frames.data (),
|
|
cruft::cast::lossless <int> (frames.size ())
|
|
),
|
|
::free
|
|
);
|
|
|
|
for (auto const [idx,addr]: cruft::iterator::izip (frames)) {
|
|
fmt::format_to (
|
|
ctx.out (),
|
|
"{{ addr: {}, name: '{}', }}, ",
|
|
frames[idx],
|
|
names.get()[idx]
|
|
);
|
|
}
|
|
|
|
|
|
return fmt::format_to (ctx.out (), " ]");
|
|
} |