Emscripten experimentation
This commit is contained in:
parent
04b85a0dfa
commit
da533c0ef0
@ -66,7 +66,40 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ========================================== Platform Support and Auto-config ==========================================
|
# ========================================== Platform Support and Auto-config ==========================================
|
||||||
include(cmake/Autoconfig.cmake)
|
if(NOT EMSCRIPTEN)
|
||||||
|
include(cmake/Autoconfig.cmake)
|
||||||
|
else()
|
||||||
|
if(
|
||||||
|
CPPTRACE_UNWIND_WITH_UNWIND OR
|
||||||
|
CPPTRACE_UNWIND_WITH_LIBUNWIND OR
|
||||||
|
CPPTRACE_UNWIND_WITH_EXECINFO OR
|
||||||
|
CPPTRACE_UNWIND_WITH_WINAPI OR
|
||||||
|
CPPTRACE_UNWIND_WITH_DBGHELP OR
|
||||||
|
CPPTRACE_UNWIND_WITH_NOTHING
|
||||||
|
)
|
||||||
|
message(FATAL_ERROR "Cpptrace config error: Unwinding back-end may not be specified under emscripten.")
|
||||||
|
endif()
|
||||||
|
if(
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE OR
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_LIBDL OR
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE OR
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF OR
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_DBGHELP OR
|
||||||
|
CPPTRACE_GET_SYMBOLS_WITH_NOTHING
|
||||||
|
)
|
||||||
|
message(FATAL_ERROR "Cpptrace config error: Symbol back-end may not be specified under emscripten.")
|
||||||
|
endif()
|
||||||
|
if(
|
||||||
|
CPPTRACE_DEMANGLE_WITH_CXXABI OR
|
||||||
|
CPPTRACE_DEMANGLE_WITH_WINAPI OR
|
||||||
|
CPPTRACE_DEMANGLE_WITH_NOTHING
|
||||||
|
)
|
||||||
|
message(FATAL_ERROR "Cpptrace config error: Demangling back-end may not be specified under emscripten.")
|
||||||
|
endif()
|
||||||
|
set(CPPTRACE_UNWIND_WITH_NOTHING On)
|
||||||
|
set(CPPTRACE_GET_SYMBOLS_WITH_NOTHING On)
|
||||||
|
set(CPPTRACE_DEMANGLE_WITH_NOTHING On)
|
||||||
|
endif()
|
||||||
|
|
||||||
# =================================================== Library Setup ====================================================
|
# =================================================== Library Setup ====================================================
|
||||||
|
|
||||||
@ -469,6 +502,13 @@ if(CPPTRACE_DEMANGLE_WITH_NOTHING)
|
|||||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_DEMANGLE_WITH_NOTHING)
|
target_compile_definitions(${target_name} PUBLIC CPPTRACE_DEMANGLE_WITH_NOTHING)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Emscripten
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_definitions(${target_name} PUBLIC CPPTRACE_EMSCRIPTEN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Other options
|
||||||
|
|
||||||
if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "")
|
if(NOT "${CPPTRACE_BACKTRACE_PATH}" STREQUAL "")
|
||||||
target_compile_definitions(${target_name} PUBLIC CPPTRACE_BACKTRACE_PATH=${CPPTRACE_BACKTRACE_PATH})
|
target_compile_definitions(${target_name} PUBLIC CPPTRACE_BACKTRACE_PATH=${CPPTRACE_BACKTRACE_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -68,7 +68,7 @@ namespace detail {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else // Windows
|
#elif IS_WINDOWS
|
||||||
Result<std::uintptr_t, internal_error> get_module_image_base(const std::string& object_path) {
|
Result<std::uintptr_t, internal_error> get_module_image_base(const std::string& object_path) {
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|||||||
@ -107,7 +107,7 @@ namespace detail {
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#elif IS_WINDOWS
|
||||||
std::string get_module_name(HMODULE handle) {
|
std::string get_module_name(HMODULE handle) {
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
@ -153,6 +153,10 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
#elif IS_EMSCRIPTEN
|
||||||
|
object_frame get_frame_object_info(frame_ptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<object_frame> get_frames_object_info(const std::vector<frame_ptr>& addresses) {
|
std::vector<object_frame> get_frames_object_info(const std::vector<frame_ptr>& addresses) {
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
object_frame get_frame_object_info(frame_ptr address);
|
object_frame get_frame_object_info(frame_ptr address);
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "binary/object.hpp"
|
#include "binary/object.hpp"
|
||||||
#include "binary/safe_dl.hpp"
|
#include "binary/safe_dl.hpp"
|
||||||
#include "snippets/snippet.hpp"
|
#include "snippets/snippet.hpp"
|
||||||
|
#include "platform/emscripten.hpp"
|
||||||
|
|
||||||
namespace cpptrace {
|
namespace cpptrace {
|
||||||
CPPTRACE_FORCE_NO_INLINE
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
@ -396,12 +397,16 @@ namespace cpptrace {
|
|||||||
CPPTRACE_FORCE_NO_INLINE
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
stacktrace generate_trace(std::size_t skip, std::size_t max_depth) {
|
stacktrace generate_trace(std::size_t skip, std::size_t max_depth) {
|
||||||
try {
|
try {
|
||||||
|
#if IS_EMSCRIPTEN
|
||||||
|
return detail::generate_emscripten_trace(skip + 1, max_depth);
|
||||||
|
#else
|
||||||
std::vector<frame_ptr> frames = detail::capture_frames(skip + 1, max_depth);
|
std::vector<frame_ptr> frames = detail::capture_frames(skip + 1, max_depth);
|
||||||
std::vector<stacktrace_frame> trace = detail::resolve_frames(frames);
|
std::vector<stacktrace_frame> trace = detail::resolve_frames(frames);
|
||||||
for(auto& frame : trace) {
|
for(auto& frame : trace) {
|
||||||
frame.symbol = detail::demangle(frame.symbol);
|
frame.symbol = detail::demangle(frame.symbol);
|
||||||
}
|
}
|
||||||
return {std::move(trace)};
|
return {std::move(trace)};
|
||||||
|
#endif
|
||||||
} catch(...) { // NOSONAR
|
} catch(...) { // NOSONAR
|
||||||
if(!detail::should_absorb_trace_exceptions()) {
|
if(!detail::should_absorb_trace_exceptions()) {
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
33
src/platform/emscripten.hpp
Normal file
33
src/platform/emscripten.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef EMSCRIPTEN_HPP
|
||||||
|
#define EMSCRIPTEN_HPP
|
||||||
|
|
||||||
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
|
#if IS_EMSCRIPTEN
|
||||||
|
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "utils/microfmt.hpp"
|
||||||
|
|
||||||
|
namespace cpptrace {
|
||||||
|
namespace detail {
|
||||||
|
CPPTRACE_FORCE_NO_INLINE
|
||||||
|
stacktrace generate_emscripten_trace(std::size_t skip, std::size_t max_depth) {
|
||||||
|
int estimated_size = emscripten_get_callstack(0, nullptr, 0);
|
||||||
|
VERIFY(estimated_size >= 0);
|
||||||
|
// "Note that this might be fully accurate since subsequent calls will carry different line numbers, so it is
|
||||||
|
// best to allocate a few bytes extra to be safe."
|
||||||
|
// Thanks, emscripten
|
||||||
|
const auto max_size = estimated_size + 1000;
|
||||||
|
// actually do the trace now
|
||||||
|
std::unique_ptr<char[]> buffer(new char[max_size]);
|
||||||
|
emscripten_get_callstack(0, buffer.get(), max_size);
|
||||||
|
microfmt::print("{}\n", buffer.get());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -14,6 +14,9 @@
|
|||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#undef IS_APPLE
|
#undef IS_APPLE
|
||||||
#define IS_APPLE 1
|
#define IS_APPLE 1
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
#undef IS_EMSCRIPTEN
|
||||||
|
#define IS_EMSCRIPTEN 1
|
||||||
#else
|
#else
|
||||||
#error "Unexpected platform"
|
#error "Unexpected platform"
|
||||||
#endif
|
#endif
|
||||||
@ -32,7 +35,7 @@
|
|||||||
#undef IS_MSVC
|
#undef IS_MSVC
|
||||||
#define IS_MSVC 1
|
#define IS_MSVC 1
|
||||||
#else
|
#else
|
||||||
#error "Unsupported compiler"
|
// #error "Unsupported compiler"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IS_LIBSTDCXX 0
|
#define IS_LIBSTDCXX 0
|
||||||
|
|||||||
@ -84,7 +84,9 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames) {
|
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames) {
|
||||||
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) && defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
|
#if IS_EMSCRIPTEN
|
||||||
|
return {}; // TODO
|
||||||
|
#elif defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) && defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
|
||||||
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(frames);
|
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(frames);
|
||||||
fill_blanks(trace, dbghelp::resolve_frames);
|
fill_blanks(trace, dbghelp::resolve_frames);
|
||||||
return trace;
|
return trace;
|
||||||
@ -120,7 +122,9 @@ namespace detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
std::vector<stacktrace_frame> resolve_frames(const std::vector<frame_ptr>& frames) {
|
||||||
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) \
|
#if IS_EMSCRIPTEN
|
||||||
|
return {}; // TODO
|
||||||
|
#elif defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) \
|
||||||
|| defined(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
|| defined(CPPTRACE_GET_SYMBOLS_WITH_ADDR2LINE)
|
||||||
auto dlframes = get_frames_object_info(frames);
|
auto dlframes = get_frames_object_info(frames);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
void trace() {
|
void trace() {
|
||||||
cpptrace::generate_trace().print();
|
cpptrace::generate_trace().print();
|
||||||
cpptrace::generate_trace().print_with_snippets();
|
cpptrace::generate_trace().print_with_snippets();
|
||||||
throw cpptrace::logic_error("foobar");
|
// throw cpptrace::logic_error("foobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo(int n) {
|
void foo(int n) {
|
||||||
|
|||||||
@ -25,7 +25,7 @@ CPPTRACE_FORCE_NO_INLINE static void raw_trace_basic() {
|
|||||||
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_basic) + 90);
|
EXPECT_LE(raw_trace.frames[0], reinterpret_cast<uintptr_t>(raw_trace_basic) + 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_basic_precise() {
|
CPPTRACE_FORCE_NO_INLINE void raw_trace_basic_precise() {
|
||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
@ -46,7 +46,7 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_basic_precise() {
|
|||||||
|
|
||||||
TEST(RawTrace, Basic) {
|
TEST(RawTrace, Basic) {
|
||||||
raw_trace_basic();
|
raw_trace_basic();
|
||||||
#ifndef _MSC_VER
|
#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
|
||||||
raw_trace_basic_precise();
|
raw_trace_basic_precise();
|
||||||
#endif
|
#endif
|
||||||
[[maybe_unused]] volatile int x = 0; // prevent raw_trace_basic_precise() above being a jmp
|
[[maybe_unused]] volatile int x = 0; // prevent raw_trace_basic_precise() above being a jmp
|
||||||
@ -80,7 +80,7 @@ CPPTRACE_FORCE_NO_INLINE void record_parent(uintptr_t low_bound, uintptr_t high_
|
|||||||
parents.insert(parents.begin(), {low_bound, high_bound});
|
parents.insert(parents.begin(), {low_bound, high_bound});
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
|
||||||
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_3() {
|
CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_3() {
|
||||||
a:
|
a:
|
||||||
auto raw_trace = cpptrace::generate_raw_trace();
|
auto raw_trace = cpptrace::generate_raw_trace();
|
||||||
@ -161,7 +161,7 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_1() {
|
|||||||
TEST(RawTrace, MultipleCalls) {
|
TEST(RawTrace, MultipleCalls) {
|
||||||
parents.clear();
|
parents.clear();
|
||||||
raw_trace_multi_1();
|
raw_trace_multi_1();
|
||||||
#ifndef _MSC_VER
|
#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
|
||||||
raw_trace_multi_precise_1();
|
raw_trace_multi_precise_1();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user