Skip to content

Commit

Permalink
#1495: use libunwind to get backtrace
Browse files Browse the repository at this point in the history
  • Loading branch information
cz4rs committed Jan 14, 2022
1 parent 1d66dd5 commit 281ff0b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/vt/configs/error/pretty_print_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ inline std::string prettyPrintStack(StackVectorType const& stack) {
int i = 0;
for (auto&& t : stack) {
auto ret_str = fmt::format(
"{}{}{:<3}{} {}{:<3} {:<13}{} {}{}{} + {}{}\n",
"{}{}{:<3}{} {}{:<3} {:#x}{} {}{}{} + {}{}\n",
prefix,
bred, i, reset,
magenta, std::get<0>(t), std::get<1>(t), reset,
Expand Down
91 changes: 36 additions & 55 deletions src/vt/configs/error/stack_out.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,80 +41,61 @@
//@HEADER
*/

#include <fmt/core.h>

#include "vt/configs/error/stack_out.h"

#include <cstdlib>
#include <vector>
#include <tuple>
#include <sstream>

#include <execinfo.h>
#include <dlfcn.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <cxxabi.h>

namespace vt { namespace debug { namespace stack {

DumpStackType dumpStack(int skip) {
void* callstack[128];
int const max_frames = sizeof(callstack) / sizeof(callstack[0]);
int num_frames = backtrace(callstack, max_frames);
char** symbols = backtrace_symbols(callstack, num_frames);
std::ostringstream trace_buf;
StackVectorType tuple;
StackVectorType stack;

for (auto i = skip; i < num_frames; i++) {
//printf("%s\n", symbols[i]);
unw_cursor_t cursor;
unw_context_t context;

std::string str = "";
Dl_info info;
if (dladdr(callstack[i], &info) && info.dli_sname) {
char *demangled = nullptr;
int status = -1;
if (info.dli_sname[0] == '_') {
demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
}
auto const call = status == 0 ?
demangled : info.dli_sname == 0 ? symbols[i] : info.dli_sname;
// Initialize cursor to current frame for local unwinding.
unw_getcontext(&context);
unw_init_local(&cursor, &context);

tuple.emplace_back(
std::forward_as_tuple(
static_cast<int>(2 + sizeof(void*) * 2), callstack[i], call,
static_cast<char*>(callstack[i]) - static_cast<char*>(info.dli_saddr)
)
);
// Unwind frames one by one, going up the frame stack.
int i = 0;
do {
if (i++ < skip) {
continue;
}

auto const& t = tuple.back();
str = fmt::format(
"{:<4} {:<4} {:<15} {} + {}\n",
i, std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t)
);
unw_word_t offset, pc;
unw_get_reg(&cursor, UNW_REG_IP, &pc);
if (pc == 0) {
break;
}

std::free(demangled);
} else {
char sym[256];
if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
char* nameptr = sym;
int status;
char* demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
if (status == 0) {
nameptr = demangled;
}

tuple.emplace_back(
stack.emplace_back(
std::forward_as_tuple(
static_cast<int>(2 + sizeof(void*) * 2), callstack[i], symbols[i], 0
)
static_cast<int>(2 + sizeof(void*) * 2), pc, nameptr, offset)
);

auto const& t = tuple.back();
str = fmt::format(
"{:10} {} {} {}\n", i, std::get<0>(t), std::get<1>(t), std::get<2>(t)
);
std::free(demangled);
} else {
// FIXME!
std::printf(" -- error: unable to obtain symbol name for this frame\n");
}

trace_buf << str;
}
std::free(symbols);

if (num_frames == max_frames) {
trace_buf << "[truncated]\n";
}
while (unw_step(&cursor) > 0);

return std::make_tuple(trace_buf.str(),tuple);
// FIXME! - is "truncated" backup still necessary?
return std::make_tuple("",stack);
}

}}} /* end namespace vt::debug::stack */
Expand Down
3 changes: 2 additions & 1 deletion src/vt/configs/error/stack_out.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@
#define INCLUDED_VT_CONFIGS_ERROR_STACK_OUT_H

#include <cstdlib>
#include <string>
#include <vector>
#include <tuple>

namespace vt { namespace debug { namespace stack {

using StackTupleType = std::tuple<int32_t,void*,std::string,std::size_t>;
using StackTupleType = std::tuple<int32_t,uint64_t,std::string,std::size_t>;
using StackVectorType = std::vector<StackTupleType>;
using DumpStackType = std::tuple<std::string,StackVectorType>;

Expand Down

0 comments on commit 281ff0b

Please sign in to comment.