2014-09-17 18:20:28 +10:00
|
|
|
/*
|
2018-08-04 15:14:06 +10:00
|
|
|
* 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/.
|
2014-09-17 18:20:28 +10:00
|
|
|
*
|
2019-07-02 16:37:43 +10:00
|
|
|
* Copyright 2019, Danny Robson <danny@nerdcruft.net>
|
2014-09-17 18:20:28 +10:00
|
|
|
*/
|
|
|
|
|
2011-05-23 17:18:52 +10:00
|
|
|
#include "backtrace.hpp"
|
|
|
|
|
2017-11-22 16:49:37 +11:00
|
|
|
#include "cast.hpp"
|
2019-07-02 16:37:43 +10:00
|
|
|
#include "iterator/zip.hpp"
|
2011-05-23 17:18:52 +10:00
|
|
|
|
2023-07-21 14:20:49 +10:00
|
|
|
#include <fmt/ostream.h>
|
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
#include <ostream>
|
2011-05-23 17:18:52 +10:00
|
|
|
#include <memory>
|
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
#include <execinfo.h>
|
|
|
|
|
|
|
|
using cruft::backtrace;
|
|
|
|
|
|
|
|
static constexpr std::size_t DEFAULT_DEPTH = 16;
|
|
|
|
|
2014-09-17 18:20:28 +10:00
|
|
|
|
2016-03-11 13:28:56 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2019-07-02 16:37:43 +10:00
|
|
|
backtrace::backtrace (void)
|
|
|
|
: m_frames (DEFAULT_DEPTH)
|
2016-04-19 16:08:56 +10:00
|
|
|
{
|
2019-07-02 16:37:43 +10:00
|
|
|
do {
|
|
|
|
int const target = static_cast<int> (m_frames.size ());
|
|
|
|
int const last = ::backtrace (
|
|
|
|
m_frames.data (), target
|
|
|
|
);
|
2011-05-23 17:18:52 +10:00
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
if (last < target) {
|
|
|
|
m_frames.resize (last);
|
|
|
|
break;
|
|
|
|
}
|
2014-07-02 15:38:05 +10:00
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
m_frames.resize (m_frames.size () * 2);
|
|
|
|
} while (1);
|
2011-05-23 17:18:52 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-11 13:28:56 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2016-04-05 11:09:28 +10:00
|
|
|
std::ostream&
|
2019-07-02 16:37:43 +10:00
|
|
|
cruft::operator <<(std::ostream &os, backtrace const &rhs) {
|
2023-07-21 14:20:49 +10:00
|
|
|
fmt::print (os, "{}", rhs);
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
fmt::format_context::iterator
|
|
|
|
fmt::formatter<cruft::backtrace>::format (
|
|
|
|
cruft::backtrace const &obj,
|
|
|
|
fmt::format_context &ctx
|
|
|
|
) {
|
|
|
|
fmt::format_to (ctx.out (), "[ ");
|
2019-07-02 16:37:43 +10:00
|
|
|
|
2023-07-21 14:20:49 +10:00
|
|
|
auto const &frames = obj.frames ();
|
2011-05-23 17:18:52 +10:00
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
using strings_t = std::unique_ptr<char *, decltype(&std::free)>;
|
|
|
|
strings_t const names (
|
2018-09-12 14:01:21 +10:00
|
|
|
backtrace_symbols (
|
|
|
|
frames.data (),
|
|
|
|
cruft::cast::lossless <int> (frames.size ())
|
|
|
|
),
|
|
|
|
::free
|
|
|
|
);
|
2011-05-23 17:18:52 +10:00
|
|
|
|
2019-07-02 16:37:43 +10:00
|
|
|
for (auto const [idx,addr]: cruft::iterator::izip (frames)) {
|
2023-07-21 14:20:49 +10:00
|
|
|
fmt::format_to (
|
|
|
|
ctx.out (),
|
|
|
|
"{{ addr: {}, name: '{}', }}, ",
|
|
|
|
frames[idx],
|
|
|
|
names.get()[idx]
|
|
|
|
);
|
2019-07-02 16:37:43 +10:00
|
|
|
}
|
2011-05-23 17:18:52 +10:00
|
|
|
|
2023-07-21 14:20:49 +10:00
|
|
|
|
|
|
|
return fmt::format_to (ctx.out (), " ]");
|
|
|
|
}
|