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_libbacktrace.cpp
|
||||||
src/symbols/symbols_with_libdwarf.cpp
|
src/symbols/symbols_with_libdwarf.cpp
|
||||||
src/symbols/symbols_with_nothing.cpp
|
src/symbols/symbols_with_nothing.cpp
|
||||||
|
src/symbols/symbols_core.cpp
|
||||||
src/unwind/unwind_with_execinfo.cpp
|
src/unwind/unwind_with_execinfo.cpp
|
||||||
src/unwind/unwind_with_nothing.cpp
|
src/unwind/unwind_with_nothing.cpp
|
||||||
src/unwind/unwind_with_unwind.cpp
|
src/unwind/unwind_with_unwind.cpp
|
||||||
|
|||||||
@ -8,6 +8,36 @@
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
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);
|
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 cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace addr2line {
|
||||||
#if IS_LINUX || IS_APPLE
|
#if IS_LINUX || IS_APPLE
|
||||||
bool has_addr2line() {
|
bool has_addr2line() {
|
||||||
static std::mutex mutex;
|
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
|
// 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`.
|
// on macos when looking up the shared object containing `start`.
|
||||||
if(!entry.obj_path.empty()) {
|
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 {
|
try {
|
||||||
entries[entry.obj_path].emplace_back(
|
entries[entry.obj_path].emplace_back(
|
||||||
to_hex(entry.obj_address),
|
to_hex(entry.obj_address),
|
||||||
@ -280,7 +286,10 @@ namespace cpptrace {
|
|||||||
filename_end != std::string::npos,
|
filename_end != std::string::npos,
|
||||||
"Unexpected edge case while processing addr2line/atos output"
|
"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_start = filename_end + 1;
|
||||||
const std::size_t line_end = line.find(")", filename_end);
|
const std::size_t line_end = line.find(")", filename_end);
|
||||||
internal_verify(
|
internal_verify(
|
||||||
@ -330,6 +339,7 @@ namespace cpptrace {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace dbghelp {
|
||||||
|
|
||||||
// SymFromAddr only returns the function's name. In order to get information about parameters,
|
// 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
|
// important for C++ stack traces where functions may be overloaded, we have to manually use
|
||||||
// Windows DIA to walk debug info structures. Resources:
|
// 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>
|
template<typename T, IMAGEHLP_SYMBOL_TYPE_INFO SymType, bool FAILABLE = false>
|
||||||
T get_info(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
T get_info(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
||||||
T info;
|
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) {
|
if(FAILABLE) {
|
||||||
return (T)-1;
|
return (T)-1;
|
||||||
} else {
|
} else {
|
||||||
@ -73,14 +83,20 @@ namespace cpptrace {
|
|||||||
template<IMAGEHLP_SYMBOL_TYPE_INFO SymType, bool FAILABLE = false>
|
template<IMAGEHLP_SYMBOL_TYPE_INFO SymType, bool FAILABLE = false>
|
||||||
std::string get_info_wchar(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
std::string get_info_wchar(ULONG type_index, HANDLE proc, ULONG64 modbase) {
|
||||||
WCHAR* info;
|
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(
|
throw std::logic_error(
|
||||||
std::string("SymGetTypeInfo failed: ")
|
std::string("SymGetTypeInfo failed: ")
|
||||||
+ std::system_error(GetLastError(), std::system_category()).what()
|
+ 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
|
// special case to properly free a buffer and convert string to narrow chars, only used for
|
||||||
static_assert(SymType == IMAGEHLP_SYMBOL_TYPE_INFO::TI_GET_SYMNAME, "get_info_wchar called with unexpected IMAGEHLP_SYMBOL_TYPE_INFO");
|
// 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::wstring wstr(info);
|
||||||
std::string str;
|
std::string str;
|
||||||
str.reserve(wstr.size());
|
str.reserve(wstr.size());
|
||||||
@ -210,7 +226,8 @@ namespace cpptrace {
|
|||||||
modbase
|
modbase
|
||||||
);
|
);
|
||||||
int n_ignore = class_parent_id != (DWORD)-1; // ignore this param
|
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
|
// return type
|
||||||
const auto return_type = lookup_type(return_type_id, proc, modbase);
|
const auto return_type = lookup_type(return_type_id, proc, modbase);
|
||||||
if(n_children == 0) {
|
if(n_children == 0) {
|
||||||
@ -225,7 +242,9 @@ namespace cpptrace {
|
|||||||
if(
|
if(
|
||||||
!SymGetTypeInfo(
|
!SymGetTypeInfo(
|
||||||
proc, modbase, type_index,
|
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
|
children
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@ -256,10 +275,14 @@ namespace cpptrace {
|
|||||||
case SymTagEnum::SymTagEnum:
|
case SymTagEnum::SymTagEnum:
|
||||||
case SymTagEnum::SymTagUDT:
|
case SymTagEnum::SymTagUDT:
|
||||||
case SymTagEnum::SymTagBaseClass:
|
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:
|
default:
|
||||||
return {
|
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,
|
proc,
|
||||||
symbol->ModBase
|
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);
|
SymEnumSymbols(proc, 0, nullptr, enumerator_callback, &fi);
|
||||||
std::string signature = symbol->Name + std::string("(") + fi.str + ")";
|
std::string signature = symbol->Name + std::string("(") + fi.str + ")";
|
||||||
// There's a phenomina with DIA not inserting commas after template parameters. Fix them here.
|
// There's a phenomina with DIA not inserting commas after template parameters. Fix them here.
|
||||||
@ -393,6 +423,7 @@ namespace cpptrace {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace libdl {
|
||||||
stacktrace_frame resolve_frame(const void* addr) {
|
stacktrace_frame resolve_frame(const void* addr) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
if(dladdr(addr, &info)) { // thread-safe
|
if(dladdr(addr, &info)) { // thread-safe
|
||||||
@ -41,6 +42,7 @@ namespace cpptrace {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace libbacktrace {
|
||||||
int full_callback(void* data, uintptr_t address, const char* file, int line, const char* symbol) {
|
int full_callback(void* data, uintptr_t address, const char* file, int line, const char* symbol) {
|
||||||
stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
|
stacktrace_frame& frame = *static_cast<stacktrace_frame*>(data);
|
||||||
if(line == 0) {
|
if(line == 0) {
|
||||||
@ -89,6 +90,7 @@ namespace cpptrace {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -182,6 +182,7 @@ static int dwarf4_ranges(
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace libdwarf {
|
||||||
// printbugging as we go
|
// printbugging as we go
|
||||||
constexpr bool dump_dwarf = false;
|
constexpr bool dump_dwarf = false;
|
||||||
|
|
||||||
@ -614,7 +615,13 @@ namespace cpptrace {
|
|||||||
return name.find("_Z") || name.find("?h@@");
|
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);
|
assert(die.get_tag() == DW_TAG_subprogram);
|
||||||
Dwarf_Attribute attr;
|
Dwarf_Attribute attr;
|
||||||
int ret = dwarf_attr(die.get(), DW_AT_linkage_name, &attr, nullptr);
|
int ret = dwarf_attr(die.get(), DW_AT_linkage_name, &attr, nullptr);
|
||||||
@ -676,7 +683,13 @@ namespace cpptrace {
|
|||||||
frame.symbol = name + "(" + join(params, ", ") + ")";*/
|
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(
|
walk_die_list(
|
||||||
dbg,
|
dbg,
|
||||||
die,
|
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_Unsigned version;
|
||||||
Dwarf_Small table_count;
|
Dwarf_Small table_count;
|
||||||
Dwarf_Line_Context ctxt;
|
Dwarf_Line_Context ctxt;
|
||||||
@ -898,6 +917,7 @@ namespace cpptrace {
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
namespace nothing {
|
||||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
std::vector<stacktrace_frame> resolve_frames(const std::vector<void*>& frames) {
|
||||||
return std::vector<stacktrace_frame>(frames.size(), {
|
return std::vector<stacktrace_frame>(frames.size(), {
|
||||||
0,
|
0,
|
||||||
@ -17,6 +18,7 @@ namespace cpptrace {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user