Baseline for middle-end system
This commit is contained in:
parent
09ccc95814
commit
5dc819186e
@ -224,6 +224,7 @@ set(
|
||||
src/symbols/symbols_with_libbacktrace.cpp
|
||||
src/symbols/symbols_with_libdwarf.cpp
|
||||
src/symbols/symbols_with_nothing.cpp
|
||||
src/symbols/symbols_core.cpp
|
||||
src/unwind/unwind_with_execinfo.cpp
|
||||
src/unwind/unwind_with_nothing.cpp
|
||||
src/unwind/unwind_with_unwind.cpp
|
||||
|
||||
@ -8,6 +8,36 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||
namespace libbacktrace {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||
namespace libdwarf {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||
namespace libdl {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||
namespace addr2line {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||
namespace dbghelp {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||
namespace nothing {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
}
|
||||
|
||||
84
src/symbols/symbols_core.cpp
Normal file
84
src/symbols/symbols_core.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "symbols.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||
namespace libbacktrace {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||
namespace libdwarf {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||
namespace libdl {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||
namespace addr2line {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||
namespace dbghelp {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||
namespace nothing {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames);
|
||||
}
|
||||
#endif
|
||||
|
||||
void apply_trace(
|
||||
std::vector<stacktrace_frame>& result,
|
||||
const std::vector<stacktrace_frame>& trace
|
||||
) {
|
||||
for(std::size_t i = 0; i < result.size(); i++) {
|
||||
if(result[i].address == 0) {
|
||||
result[i].address = trace[i].address;
|
||||
}
|
||||
if(result[i].line == 0) {
|
||||
result[i].line = trace[i].line;
|
||||
}
|
||||
if(result[i].col == 0) {
|
||||
result[i].col = trace[i].col;
|
||||
}
|
||||
if(result[i].filename.empty()) {
|
||||
result[i].filename = std::move(trace[i].filename);
|
||||
}
|
||||
if(result[i].symbol.empty()) {
|
||||
result[i].symbol = std::move(trace[i].symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
||||
std::vector<stacktrace_frame> trace(frames.size());
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE
|
||||
apply_trace(trace, libbacktrace::resolve_frames(frames));
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF
|
||||
apply_trace(trace, libdwarf::resolve_frames(frames));
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDL
|
||||
apply_trace(trace, libdl::resolve_frames(frames));
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE
|
||||
apply_trace(trace, addr2line::resolve_frames(frames));
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_DBGHELP
|
||||
apply_trace(trace, dbghelp::resolve_frames(frames));
|
||||
#endif
|
||||
#ifdef CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||
apply_trace(trace, nothing::resolve_frames(frames));
|
||||
#endif
|
||||
return trace;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace addr2line {
|
||||
#if IS_LINUX || IS_APPLE
|
||||
bool has_addr2line() {
|
||||
static std::mutex mutex;
|
||||
@ -195,7 +196,12 @@ namespace cpptrace {
|
||||
// If libdl fails to find the shared object for a frame, the path will be empty. I've observed this
|
||||
// on macos when looking up the shared object containing `start`.
|
||||
if(!entry.obj_path.empty()) {
|
||||
///fprintf(stderr, "%s %s\n", to_hex(entry.raw_address).c_str(), to_hex(entry.raw_address - entry.obj_base + base).c_str());
|
||||
///fprintf(
|
||||
/// stderr,
|
||||
/// "%s %s\n",
|
||||
/// to_hex(entry.raw_address).c_str(),
|
||||
/// to_hex(entry.raw_address - entry.obj_base + base).c_str()
|
||||
///);
|
||||
try {
|
||||
entries[entry.obj_path].emplace_back(
|
||||
to_hex(entry.obj_address),
|
||||
@ -280,7 +286,10 @@ namespace cpptrace {
|
||||
filename_end != std::string::npos,
|
||||
"Unexpected edge case while processing addr2line/atos output"
|
||||
);
|
||||
entries_vec[entry_index].second.get().filename = line.substr(filename_start + 3, filename_end - filename_start - 3);
|
||||
entries_vec[entry_index].second.get().filename = line.substr(
|
||||
filename_start + 3,
|
||||
filename_end - filename_start - 3
|
||||
);
|
||||
const std::size_t line_start = filename_end + 1;
|
||||
const std::size_t line_end = line.find(")", filename_end);
|
||||
internal_verify(
|
||||
@ -331,5 +340,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace dbghelp {
|
||||
|
||||
// SymFromAddr only returns the function's name. In order to get information about parameters,
|
||||
// important for C++ stack traces where functions may be overloaded, we have to manually use
|
||||
// Windows DIA to walk debug info structures. Resources:
|
||||
@ -57,7 +59,15 @@ namespace cpptrace {
|
||||
template<typename T, IMAGEHLP_SYMBOL_TYPE_INFO SymType, bool FAILABLE = false>
|
||||
T get_info(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
||||
T info;
|
||||
if(!SymGetTypeInfo(proc, modbase, type_index, static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(SymType), &info)) {
|
||||
if(
|
||||
!SymGetTypeInfo(
|
||||
proc,
|
||||
modbase,
|
||||
type_index,
|
||||
static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(SymType),
|
||||
&info
|
||||
)
|
||||
) {
|
||||
if(FAILABLE) {
|
||||
return (T)-1;
|
||||
} else {
|
||||
@ -73,14 +83,20 @@ namespace cpptrace {
|
||||
template<IMAGEHLP_SYMBOL_TYPE_INFO SymType, bool FAILABLE = false>
|
||||
std::string get_info_wchar(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
||||
WCHAR* info;
|
||||
if(!SymGetTypeInfo(proc, modbase, type_index, static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(SymType), &info)) {
|
||||
if(
|
||||
!SymGetTypeInfo(proc, modbase, type_index, static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(SymType), &info)
|
||||
) {
|
||||
throw std::logic_error(
|
||||
std::string("SymGetTypeInfo failed: ")
|
||||
+ std::system_error(GetLastError(), std::system_category()).what()
|
||||
);
|
||||
}
|
||||
// special case to properly free a buffer and convert string to narrow chars, only used for TI_GET_SYMNAME
|
||||
static_assert(SymType == IMAGEHLP_SYMBOL_TYPE_INFO::TI_GET_SYMNAME, "get_info_wchar called with unexpected IMAGEHLP_SYMBOL_TYPE_INFO");
|
||||
// special case to properly free a buffer and convert string to narrow chars, only used for
|
||||
// TI_GET_SYMNAME
|
||||
static_assert(
|
||||
SymType == IMAGEHLP_SYMBOL_TYPE_INFO::TI_GET_SYMNAME,
|
||||
"get_info_wchar called with unexpected IMAGEHLP_SYMBOL_TYPE_INFO"
|
||||
);
|
||||
std::wstring wstr(info);
|
||||
std::string str;
|
||||
str.reserve(wstr.size());
|
||||
@ -210,7 +226,8 @@ namespace cpptrace {
|
||||
modbase
|
||||
);
|
||||
int n_ignore = class_parent_id != (DWORD)-1; // ignore this param
|
||||
n_children -= n_ignore; // this must be ignored before TI_FINDCHILDREN_PARAMS::Count is set, else error
|
||||
// this must be ignored before TI_FINDCHILDREN_PARAMS::Count is set, else error
|
||||
n_children -= n_ignore;
|
||||
// return type
|
||||
const auto return_type = lookup_type(return_type_id, proc, modbase);
|
||||
if(n_children == 0) {
|
||||
@ -225,7 +242,9 @@ namespace cpptrace {
|
||||
if(
|
||||
!SymGetTypeInfo(
|
||||
proc, modbase, type_index,
|
||||
static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(IMAGEHLP_SYMBOL_TYPE_INFO::TI_FINDCHILDREN),
|
||||
static_cast<::IMAGEHLP_SYMBOL_TYPE_INFO>(
|
||||
IMAGEHLP_SYMBOL_TYPE_INFO::TI_FINDCHILDREN
|
||||
),
|
||||
children
|
||||
)
|
||||
) {
|
||||
@ -256,10 +275,14 @@ namespace cpptrace {
|
||||
case SymTagEnum::SymTagEnum:
|
||||
case SymTagEnum::SymTagUDT:
|
||||
case SymTagEnum::SymTagBaseClass:
|
||||
return {get_info_wchar<IMAGEHLP_SYMBOL_TYPE_INFO::TI_GET_SYMNAME>(type_index, proc, modbase), ""};
|
||||
return {
|
||||
get_info_wchar<IMAGEHLP_SYMBOL_TYPE_INFO::TI_GET_SYMNAME>(type_index, proc, modbase), ""
|
||||
};
|
||||
default:
|
||||
return {
|
||||
"<unknown type " + std::to_string(static_cast<std::underlying_type<SymTagEnum>::type>(tag)) + ">",
|
||||
"<unknown type " +
|
||||
std::to_string(static_cast<std::underlying_type<SymTagEnum>::type>(tag)) +
|
||||
">",
|
||||
""
|
||||
};
|
||||
};
|
||||
@ -339,7 +362,14 @@ namespace cpptrace {
|
||||
proc,
|
||||
symbol->ModBase
|
||||
);
|
||||
function_info fi { proc, symbol->ModBase, 0, int(n_children), class_parent_id != (DWORD)-1, "" };
|
||||
function_info fi {
|
||||
proc,
|
||||
symbol->ModBase,
|
||||
0,
|
||||
int(n_children),
|
||||
class_parent_id != (DWORD)-1,
|
||||
""
|
||||
};
|
||||
SymEnumSymbols(proc, 0, nullptr, enumerator_callback, &fi);
|
||||
std::string signature = symbol->Name + std::string("(") + fi.str + ")";
|
||||
// There's a phenomina with DIA not inserting commas after template parameters. Fix them here.
|
||||
@ -394,5 +424,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace libdl {
|
||||
stacktrace_frame resolve_frame(const void* addr) {
|
||||
Dl_info info;
|
||||
if(dladdr(addr, &info)) { // thread-safe
|
||||
@ -42,5 +43,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace libbacktrace {
|
||||
int full_callback(void* data, uintptr_t address, const char* file, int line, const char* symbol) {
|
||||
stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
|
||||
if(line == 0) {
|
||||
@ -90,5 +91,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -182,6 +182,7 @@ static int dwarf4_ranges(
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace libdwarf {
|
||||
// printbugging as we go
|
||||
constexpr bool dump_dwarf = false;
|
||||
|
||||
@ -614,7 +615,13 @@ namespace cpptrace {
|
||||
return name.find("_Z") || name.find("?h@@");
|
||||
}
|
||||
|
||||
void retrieve_symbol_for_subprogram(Dwarf_Debug dbg, const die_object& die, Dwarf_Addr pc, Dwarf_Half dwversion, stacktrace_frame& frame) {
|
||||
void retrieve_symbol_for_subprogram(
|
||||
Dwarf_Debug dbg,
|
||||
const die_object& die,
|
||||
Dwarf_Addr pc,
|
||||
Dwarf_Half dwversion,
|
||||
stacktrace_frame& frame
|
||||
) {
|
||||
assert(die.get_tag() == DW_TAG_subprogram);
|
||||
Dwarf_Attribute attr;
|
||||
int ret = dwarf_attr(die.get(), DW_AT_linkage_name, &attr, nullptr);
|
||||
@ -676,7 +683,13 @@ namespace cpptrace {
|
||||
frame.symbol = name + "(" + join(params, ", ") + ")";*/
|
||||
}
|
||||
|
||||
void retrieve_symbol(Dwarf_Debug dbg, const die_object& die, Dwarf_Addr pc, Dwarf_Half dwversion, stacktrace_frame& frame) {
|
||||
void retrieve_symbol(
|
||||
Dwarf_Debug dbg,
|
||||
const die_object& die,
|
||||
Dwarf_Addr pc,
|
||||
Dwarf_Half dwversion,
|
||||
stacktrace_frame& frame
|
||||
) {
|
||||
walk_die_list(
|
||||
dbg,
|
||||
die,
|
||||
@ -718,7 +731,13 @@ namespace cpptrace {
|
||||
);
|
||||
}
|
||||
|
||||
void retrieve_line_info(Dwarf_Debug dbg, const die_object& die, Dwarf_Addr pc, Dwarf_Half dwversion, stacktrace_frame& frame) {
|
||||
void retrieve_line_info(
|
||||
Dwarf_Debug dbg,
|
||||
const die_object& die,
|
||||
Dwarf_Addr pc,
|
||||
Dwarf_Half dwversion,
|
||||
stacktrace_frame& frame
|
||||
) {
|
||||
Dwarf_Unsigned version;
|
||||
Dwarf_Small table_count;
|
||||
Dwarf_Line_Context ctxt;
|
||||
@ -899,5 +918,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
namespace cpptrace {
|
||||
namespace detail {
|
||||
namespace nothing {
|
||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
||||
return std::vector<stacktrace_frame>(frames.size(), {
|
||||
0,
|
||||
@ -18,5 +19,6 @@ namespace cpptrace {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user