diff --git a/CHANGELOG.md b/CHANGELOG.md index a3f379e72b..b27e5fcb3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +**Features**: + +- Native/Linux: symbolicate stack frames in the crash daemon. ([#1747](https://github.com/getsentry/sentry-native/pull/1747)) + **Fixes**: - Native/macOS: fix module `image_size` computation, which could have caused the symbolicator to misattribute every frame to the lowest-addressed image (typically `dyld` or `libsystem`). ([#1740](https://github.com/getsentry/sentry-native/pull/1740)) diff --git a/CMakeLists.txt b/CMakeLists.txt index 76b2377197..42e5f4d684 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -670,6 +670,10 @@ endif() if(SENTRY_WITH_LIBUNWIND) if(LINUX) + # Build remote unwinding support for the native backend's crash daemon + if(SENTRY_BACKEND_NATIVE) + set(LIBUNWIND_BUILD_REMOTE TRUE) + endif() # Use vendored libunwind add_subdirectory(vendor/libunwind) target_link_libraries(sentry PRIVATE unwind) @@ -835,6 +839,10 @@ elseif(SENTRY_BACKEND_NATIVE) SENTRY_BUILD_STATIC ) + if(SENTRY_WITH_LIBUNWIND AND LINUX) + target_compile_definitions(sentry-crash PRIVATE SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE) + endif() + # Copy include directories from sentry target target_include_directories(sentry-crash PRIVATE ${PROJECT_SOURCE_DIR}/include @@ -874,7 +882,9 @@ elseif(SENTRY_BACKEND_NATIVE) endif() if(SENTRY_WITH_LIBUNWIND AND LINUX) - target_link_libraries(sentry-crash PRIVATE unwind) + # Use unwind_remote for the daemon (includes ptrace accessors + # for remote DWARF unwinding of the crashed process) + target_link_libraries(sentry-crash PRIVATE unwind_remote) endif() # Make sentry library depend on crash daemon so it's always built together diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6086dbaafb..317f7b3ea9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -171,6 +171,13 @@ elseif(SENTRY_BACKEND_NATIVE) backends/native/minidump/sentry_minidump_writer.h ) + # Remote unwinding (Linux only — uses libunwind ptrace accessors) + if(LINUX) + sentry_target_sources_cwd(sentry + unwinder/sentry_unwinder_libunwind_remote.c + ) + endif() + # Platform-specific minidump writers if(LINUX OR ANDROID) sentry_target_sources_cwd(sentry diff --git a/src/backends/native/sentry_crash_daemon.c b/src/backends/native/sentry_crash_daemon.c index b440aa1d29..d9a42d1024 100644 --- a/src/backends/native/sentry_crash_daemon.c +++ b/src/backends/native/sentry_crash_daemon.c @@ -47,6 +47,9 @@ # include # include # endif +# if defined(SENTRY_PLATFORM_LINUX) +# include "unwinder/sentry_unwinder.h" +# endif #elif defined(SENTRY_PLATFORM_WINDOWS) # include # include @@ -544,6 +547,24 @@ build_registers_from_ctx(const sentry_crash_context_t *ctx, size_t thread_idx) return registers; } +#if defined(SENTRY_PLATFORM_LINUX) +static sentry_value_t +build_registers_from_remote_registers( + const sentry_remote_registers_t *remote_registers) +{ + sentry_value_t registers = sentry_value_new_object(); + + for (size_t i = 0; i < remote_registers->count; i++) { + const sentry_remote_register_t *remote_register + = &remote_registers->values[i]; + sentry_value_set_by_key(registers, remote_register->name, + sentry__value_new_addr(remote_register->value)); + } + + return registers; +} +#endif + /** * Maximum number of frames to unwind */ @@ -900,10 +921,88 @@ build_stacktrace_for_thread( sentry_value_t temp_frames[MAX_STACK_FRAMES]; int frame_count = 0; +#if defined(SENTRY_PLATFORM_LINUX) + // Remote DWARF unwinding via libunwind ptrace accessors. Do not attach to + // the crashed thread from the daemon; use the saved fault context below. + { + pid_t tid = 0; + if (thread_idx == SIZE_MAX || thread_idx == 0) { + tid = ctx->crashed_tid; + } else if (thread_idx < ctx->platform.num_threads) { + tid = ctx->platform.threads[thread_idx].tid; + } + + bool is_crashed_thread + = thread_idx == SIZE_MAX || tid == ctx->crashed_tid; + + if (tid > 0 && !is_crashed_thread) { + sentry_remote_registers_t registers = { 0 }; + sentry_remote_frame_t *remote_frames + = sentry_malloc(sizeof(*remote_frames) * MAX_STACK_FRAMES); + size_t remote_count = remote_frames + ? sentry__unwind_stack_from_thread( + tid, remote_frames, MAX_STACK_FRAMES, ®isters) + : 0; + + if (remote_count > 0) { + SENTRY_DEBUGF("Remote unwound %zu frames for thread %d", + remote_count, tid); + + for (size_t i = 0; + i < remote_count && frame_count < MAX_STACK_FRAMES; i++) { + if (remote_frames[i].ip == 0 + || !is_valid_code_addr(remote_frames[i].ip)) { + continue; + } + temp_frames[frame_count] = sentry_value_new_object(); + sentry_value_set_by_key(temp_frames[frame_count], + "instruction_addr", + sentry__value_new_addr(remote_frames[i].ip)); + // Trust describes the unwind source, not the emitted + // frame index. If the initial cursor frame is filtered + // out, the next emitted frame was still reached via CFI. + sentry_value_set_by_key(temp_frames[frame_count], "trust", + sentry_value_new_string(i == 0 ? "context" : "cfi")); + enrich_frame_with_module_info( + ctx, temp_frames[frame_count], remote_frames[i].ip); + if (remote_frames[i].symbol[0]) { + sentry_value_set_by_key(temp_frames[frame_count], + "function", + sentry_value_new_string(remote_frames[i].symbol)); + } + frame_count++; + } + + if (frame_count > 0) { + if (stack_buf) { + sentry_free(stack_buf); + } + + for (int i = frame_count - 1; i >= 0; i--) { + sentry_value_append(frames, temp_frames[i]); + } + sentry_value_set_by_key(stacktrace, "frames", frames); + if (registers.count > 0) { + sentry_value_set_by_key(stacktrace, "registers", + build_registers_from_remote_registers(®isters)); + } + sentry_free(remote_frames); + return stacktrace; + } + } + + if (remote_frames) { + sentry_free(remote_frames); + } + } + } + // Fall through to pre-captured backtrace or FP-walking if remote + // unwinding failed +#endif + #if defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_ANDROID) - // Use pre-captured libunwind backtrace if available (DWARF-based, works - // without frame pointers). This is preferred over FP-based walking for - // the crashed thread. + // Fallback: use pre-captured libunwind backtrace if available + // (DWARF-based, works without frame pointers). if (ctx->platform.backtrace_count > 0 && (thread_idx == SIZE_MAX || thread_idx == 0)) { SENTRY_DEBUGF("Using pre-captured libunwind backtrace (%zu frames)", @@ -919,6 +1018,9 @@ build_stacktrace_for_thread( temp_frames[frame_count] = sentry_value_new_object(); sentry_value_set_by_key(temp_frames[frame_count], "instruction_addr", sentry__value_new_addr(frame_ip)); + // Trust describes the unwind source, not the emitted frame index. + // If the initial cursor frame is filtered out, the next emitted + // frame was still reached via CFI. sentry_value_set_by_key(temp_frames[frame_count], "trust", sentry_value_new_string(i == 0 ? "context" : "cfi")); enrich_frame_with_module_info( diff --git a/src/unwinder/sentry_unwinder.c b/src/unwinder/sentry_unwinder.c index 09664d0156..8424236e90 100644 --- a/src/unwinder/sentry_unwinder.c +++ b/src/unwinder/sentry_unwinder.c @@ -1,3 +1,4 @@ +#include "sentry_unwinder.h" #include "sentry_boot.h" #define DEFINE_UNWINDER(Func) \ @@ -19,6 +20,24 @@ DEFINE_UNWINDER(libunwind); DEFINE_UNWINDER(libunwind_mac); DEFINE_UNWINDER(psunwind); +#if defined(SENTRY_PLATFORM_LINUX) +# define DEFINE_THREAD_UNWINDER(Func) \ + size_t sentry__unwind_stack_from_thread_##Func(pid_t tid, \ + sentry_remote_frame_t *frames, size_t max_frames, \ + sentry_remote_registers_t *registers) + +# define TRY_THREAD_UNWINDER(Func) \ + do { \ + size_t rv = sentry__unwind_stack_from_thread_##Func( \ + tid, frames, max_frames, registers); \ + if (rv > 0) { \ + return rv; \ + } \ + } while (0) + +DEFINE_THREAD_UNWINDER(libunwind_remote); +#endif + static size_t unwind_stack( void *addr, const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames) @@ -56,3 +75,19 @@ sentry_unwind_stack_from_ucontext( { return unwind_stack(NULL, uctx, stacktrace_out, max_len); } + +#if defined(SENTRY_PLATFORM_LINUX) +size_t +sentry__unwind_stack_from_thread(pid_t tid, sentry_remote_frame_t *frames, + size_t max_frames, sentry_remote_registers_t *registers) +{ + (void)tid; + (void)frames; + (void)max_frames; + (void)registers; +# ifdef SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE + TRY_THREAD_UNWINDER(libunwind_remote); +# endif + return 0; +} +#endif diff --git a/src/unwinder/sentry_unwinder.h b/src/unwinder/sentry_unwinder.h index 889d20ca18..09b83b77e1 100644 --- a/src/unwinder/sentry_unwinder.h +++ b/src/unwinder/sentry_unwinder.h @@ -1,8 +1,43 @@ #ifndef SENTRY_UNWINDER_H_INCLUDED #define SENTRY_UNWINDER_H_INCLUDED +#include "sentry_boot.h" + +#include + typedef struct { uintptr_t lo, hi; } mem_range_t; +#if defined(SENTRY_PLATFORM_LINUX) + +# include +# include + +# define SENTRY_REMOTE_UNWIND_MAX_REGISTER_NAME 16 +# define SENTRY_REMOTE_UNWIND_MAX_REGISTERS 64 +# define SENTRY_REMOTE_UNWIND_MAX_SYMBOL 256 + +typedef struct { + char name[SENTRY_REMOTE_UNWIND_MAX_REGISTER_NAME]; + uint64_t value; +} sentry_remote_register_t; + +typedef struct { + uint64_t ip; + char symbol[SENTRY_REMOTE_UNWIND_MAX_SYMBOL]; + uint64_t symbol_offset; +} sentry_remote_frame_t; + +typedef struct { + size_t count; + sentry_remote_register_t values[SENTRY_REMOTE_UNWIND_MAX_REGISTERS]; +} sentry_remote_registers_t; + +size_t sentry__unwind_stack_from_thread(pid_t tid, + sentry_remote_frame_t *frames, size_t max_frames, + sentry_remote_registers_t *registers); + +#endif + #endif // SENTRY_UNWINDER_H_INCLUDED diff --git a/src/unwinder/sentry_unwinder_libunwind_remote.c b/src/unwinder/sentry_unwinder_libunwind_remote.c new file mode 100644 index 0000000000..99bb8bb854 --- /dev/null +++ b/src/unwinder/sentry_unwinder_libunwind_remote.c @@ -0,0 +1,175 @@ +// Remote stack unwinding via libunwind ptrace accessors. +// This file must NOT define UNW_LOCAL_ONLY so that unw_init_remote() +// and other generic (_U prefix) symbols are used. +// +// Only compiled into sentry-crash daemon +// (SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE). +// The sentry library compiles this file too (shared sources) but the +// function body is empty without the define. + +#include "sentry_boot.h" +#include "sentry_string.h" +#include "sentry_unwinder.h" + +#ifdef SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE + +# include "sentry_logger.h" + +# include +# include +# include +# include + +# include +# include + +static int +format_register_name(char *dst, size_t dst_len, unw_regnum_t reg) +{ + const char *name = unw_regname(reg); + if (!name || strcmp(name, "???") == 0) { + return 0; + } + + size_t len = strlen(name); + if (len == 0 || len >= dst_len) { + return 0; + } + + memcpy(dst, name, len + 1); + sentry__string_ascii_lower(dst); + return 1; +} + +static void +capture_registers(unw_cursor_t *cursor, sentry_remote_registers_t *registers) +{ + if (!registers) { + return; + } + + for (unw_regnum_t reg = 0; reg <= UNW_REG_LAST + && registers->count < SENTRY_REMOTE_UNWIND_MAX_REGISTERS; + reg++) { + unw_word_t value = 0; + if (unw_get_reg(cursor, reg, &value) < 0) { + continue; + } + + sentry_remote_register_t *remote_register + = ®isters->values[registers->count]; + if (!format_register_name( + remote_register->name, sizeof(remote_register->name), reg)) { + continue; + } + + remote_register->value = (uint64_t)value; + registers->count++; + } +} + +size_t +sentry__unwind_stack_from_thread_libunwind_remote(pid_t tid, + sentry_remote_frame_t *frames, size_t max_frames, + sentry_remote_registers_t *registers) +{ + if (registers) { + memset(registers, 0, sizeof(*registers)); + } + + if (ptrace(PTRACE_ATTACH, tid, NULL, NULL) != 0) { + SENTRY_WARNF("remote_unwind: ptrace attach failed for %d: %s", tid, + strerror(errno)); + return 0; + } + + int status; + if (waitpid(tid, &status, __WALL) < 0) { + SENTRY_WARNF( + "remote_unwind: waitpid failed for %d: %s", tid, strerror(errno)); + ptrace(PTRACE_DETACH, tid, NULL, NULL); + return 0; + } + if (!WIFSTOPPED(status)) { + SENTRY_WARNF( + "remote_unwind: thread %d did not stop after attach: status=%d", + tid, status); + ptrace(PTRACE_DETACH, tid, NULL, NULL); + return 0; + } + + size_t n = 0; + + unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, 0); + if (!as) { + SENTRY_WARN("remote_unwind: unw_create_addr_space failed"); + goto detach; + } + + void *upt = _UPT_create(tid); + if (!upt) { + SENTRY_WARN("remote_unwind: _UPT_create failed"); + unw_destroy_addr_space(as); + goto detach; + } + + unw_cursor_t cursor; + int ret = unw_init_remote(&cursor, as, upt); + if (ret < 0) { + SENTRY_WARNF("remote_unwind: unw_init_remote failed: %d", ret); + _UPT_destroy(upt); + unw_destroy_addr_space(as); + goto detach; + } + + capture_registers(&cursor, registers); + + while (n < max_frames) { + unw_word_t ip = 0; + if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0 || ip == 0) { + break; + } + + frames[n].ip = (uint64_t)ip; + frames[n].symbol[0] = '\0'; + frames[n].symbol_offset = 0; + + unw_word_t off = 0; + if (unw_get_proc_name( + &cursor, frames[n].symbol, sizeof(frames[n].symbol), &off) + == 0) { + frames[n].symbol_offset = (uint64_t)off; + } + + n++; + + if (unw_step(&cursor) <= 0) { + break; + } + } + + _UPT_destroy(upt); + unw_destroy_addr_space(as); + +detach: + ptrace(PTRACE_DETACH, tid, NULL, NULL); + + SENTRY_DEBUGF("Remote unwound %zu frames for thread %d", n, tid); + return n; +} + +#else /* !SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE */ + +size_t +sentry__unwind_stack_from_thread_libunwind_remote(pid_t tid, + sentry_remote_frame_t *frames, size_t max_frames, + sentry_remote_registers_t *registers) +{ + (void)tid; + (void)frames; + (void)max_frames; + (void)registers; + return 0; +} + +#endif /* SENTRY_WITH_UNWINDER_LIBUNWIND_REMOTE */ diff --git a/vendor/libunwind/CMakeLists.txt b/vendor/libunwind/CMakeLists.txt index 6a684f0c95..4c8b4c1d38 100644 --- a/vendor/libunwind/CMakeLists.txt +++ b/vendor/libunwind/CMakeLists.txt @@ -1,5 +1,7 @@ # CMakeLists.txt for vendored libunwind (Linux only; x86_64, aarch64, x86, arm) -# This builds only the local unwinding library (libunwind.a equivalent) +# Builds the local unwinding library (libunwind.a equivalent). +# When LIBUNWIND_BUILD_REMOTE is set, also builds unwind_remote with +# generic (G-prefix) sources and ptrace accessors for remote unwinding. # Vendored libunwind - built as a subdirectory of the main project. # Enable ASM for the .S sources without a nested project() call. @@ -289,3 +291,188 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") endif() target_link_libraries(unwind PRIVATE ${CMAKE_DL_LIBS} pthread) + +# --- Remote unwinding support (optional, for native backend daemon) --- +if(LIBUNWIND_BUILD_REMOTE) + +# Generic (G-prefix) sources — compiled WITHOUT UNW_LOCAL_ONLY. +# Produce _U_ symbols that coexist with the _UL_ local symbols. +set(UNWIND_GENERIC_MI_SOURCES + ${LIBUNWIND_SRC}/mi/Gaddress_validator.c + ${LIBUNWIND_SRC}/mi/Gdestroy_addr_space.c + ${LIBUNWIND_SRC}/mi/Gdyn-extract.c + ${LIBUNWIND_SRC}/mi/Gdyn-remote.c + ${LIBUNWIND_SRC}/mi/Gfind_dynamic_proc_info.c + ${LIBUNWIND_SRC}/mi/Gget_accessors.c + ${LIBUNWIND_SRC}/mi/Gget_elf_filename.c + ${LIBUNWIND_SRC}/mi/Gget_fpreg.c + ${LIBUNWIND_SRC}/mi/Gget_proc_info_by_ip.c + ${LIBUNWIND_SRC}/mi/Gget_proc_name.c + ${LIBUNWIND_SRC}/mi/Gget_reg.c + ${LIBUNWIND_SRC}/mi/Gis_plt_entry.c + ${LIBUNWIND_SRC}/mi/Gput_dynamic_unwind_info.c + ${LIBUNWIND_SRC}/mi/Gset_cache_size.c + ${LIBUNWIND_SRC}/mi/Gset_caching_policy.c + ${LIBUNWIND_SRC}/mi/Gset_fpreg.c + ${LIBUNWIND_SRC}/mi/Gset_iterate_phdr_function.c + ${LIBUNWIND_SRC}/mi/Gset_reg.c +) + +set(UNWIND_GENERIC_DWARF_SOURCES + ${LIBUNWIND_SRC}/dwarf/Gexpr.c + ${LIBUNWIND_SRC}/dwarf/Gfde.c + ${LIBUNWIND_SRC}/dwarf/Gfind_proc_info-lsb.c + ${LIBUNWIND_SRC}/dwarf/Gfind_unwind_table.c + ${LIBUNWIND_SRC}/dwarf/Gget_proc_info_in_range.c + ${LIBUNWIND_SRC}/dwarf/Gparser.c + ${LIBUNWIND_SRC}/dwarf/Gpe.c +) + +if(UNWIND_ARCH STREQUAL "x86_64") + set(UNWIND_GENERIC_ARCH_SOURCES + ${LIBUNWIND_SRC}/x86_64/Gos-linux.c + ${LIBUNWIND_SRC}/x86_64/Gapply_reg_state.c + ${LIBUNWIND_SRC}/x86_64/Gcreate_addr_space.c + ${LIBUNWIND_SRC}/x86_64/Gget_proc_info.c + ${LIBUNWIND_SRC}/x86_64/Gget_save_loc.c + ${LIBUNWIND_SRC}/x86_64/Gglobal.c + ${LIBUNWIND_SRC}/x86_64/Ginit.c + ${LIBUNWIND_SRC}/x86_64/Ginit_local.c + ${LIBUNWIND_SRC}/x86_64/Ginit_remote.c + ${LIBUNWIND_SRC}/x86_64/Gregs.c + ${LIBUNWIND_SRC}/x86_64/Greg_states_iterate.c + ${LIBUNWIND_SRC}/x86_64/Gresume.c + ${LIBUNWIND_SRC}/x86_64/Gstash_frame.c + ${LIBUNWIND_SRC}/x86_64/Gstep.c + ${LIBUNWIND_SRC}/x86_64/Gtrace.c + ) +elseif(UNWIND_ARCH STREQUAL "aarch64") + set(UNWIND_GENERIC_ARCH_SOURCES + ${LIBUNWIND_SRC}/aarch64/Gos-linux.c + ${LIBUNWIND_SRC}/aarch64/Gapply_reg_state.c + ${LIBUNWIND_SRC}/aarch64/Gcreate_addr_space.c + ${LIBUNWIND_SRC}/aarch64/Gget_proc_info.c + ${LIBUNWIND_SRC}/aarch64/Gget_save_loc.c + ${LIBUNWIND_SRC}/aarch64/Gglobal.c + ${LIBUNWIND_SRC}/aarch64/Ginit.c + ${LIBUNWIND_SRC}/aarch64/Ginit_local.c + ${LIBUNWIND_SRC}/aarch64/Ginit_remote.c + ${LIBUNWIND_SRC}/aarch64/Gis_signal_frame.c + ${LIBUNWIND_SRC}/aarch64/Gregs.c + ${LIBUNWIND_SRC}/aarch64/Greg_states_iterate.c + ${LIBUNWIND_SRC}/aarch64/Gresume.c + ${LIBUNWIND_SRC}/aarch64/Gstash_frame.c + ${LIBUNWIND_SRC}/aarch64/Gstep.c + ${LIBUNWIND_SRC}/aarch64/Gtrace.c + ${LIBUNWIND_SRC}/aarch64/Gstrip_ptrauth_insn_mask.c + ) +elseif(UNWIND_ARCH STREQUAL "x86") + set(UNWIND_GENERIC_ARCH_SOURCES + ${LIBUNWIND_SRC}/x86/Gos-linux.c + ${LIBUNWIND_SRC}/x86/Gapply_reg_state.c + ${LIBUNWIND_SRC}/x86/Gcreate_addr_space.c + ${LIBUNWIND_SRC}/x86/Gget_proc_info.c + ${LIBUNWIND_SRC}/x86/Gget_save_loc.c + ${LIBUNWIND_SRC}/x86/Gglobal.c + ${LIBUNWIND_SRC}/x86/Ginit.c + ${LIBUNWIND_SRC}/x86/Ginit_local.c + ${LIBUNWIND_SRC}/x86/Ginit_remote.c + ${LIBUNWIND_SRC}/x86/Gregs.c + ${LIBUNWIND_SRC}/x86/Greg_states_iterate.c + ${LIBUNWIND_SRC}/x86/Gresume.c + ${LIBUNWIND_SRC}/x86/Gstep.c + ) +elseif(UNWIND_ARCH STREQUAL "arm") + set(UNWIND_GENERIC_ARCH_SOURCES + ${LIBUNWIND_SRC}/arm/Gos-linux.c + ${LIBUNWIND_SRC}/arm/Gapply_reg_state.c + ${LIBUNWIND_SRC}/arm/Gcreate_addr_space.c + ${LIBUNWIND_SRC}/arm/Gex_tables.c + ${LIBUNWIND_SRC}/arm/Gget_proc_info.c + ${LIBUNWIND_SRC}/arm/Gget_save_loc.c + ${LIBUNWIND_SRC}/arm/Gglobal.c + ${LIBUNWIND_SRC}/arm/Ginit.c + ${LIBUNWIND_SRC}/arm/Ginit_local.c + ${LIBUNWIND_SRC}/arm/Ginit_remote.c + ${LIBUNWIND_SRC}/arm/Gregs.c + ${LIBUNWIND_SRC}/arm/Greg_states_iterate.c + ${LIBUNWIND_SRC}/arm/Gresume.c + ${LIBUNWIND_SRC}/arm/Gstash_frame.c + ${LIBUNWIND_SRC}/arm/Gstep.c + ${LIBUNWIND_SRC}/arm/Gtrace.c + ) +endif() + +# Ptrace accessor library (_UPT_* functions for remote unwinding via ptrace) +set(UNWIND_PTRACE_SOURCES + ${LIBUNWIND_SRC}/ptrace/_UPT_accessors.c + ${LIBUNWIND_SRC}/ptrace/_UPT_access_fpreg.c + ${LIBUNWIND_SRC}/ptrace/_UPT_access_mem.c + ${LIBUNWIND_SRC}/ptrace/_UPT_access_reg.c + ${LIBUNWIND_SRC}/ptrace/_UPT_create.c + ${LIBUNWIND_SRC}/ptrace/_UPT_destroy.c + ${LIBUNWIND_SRC}/ptrace/_UPT_elf.c + ${LIBUNWIND_SRC}/ptrace/_UPT_find_proc_info.c + ${LIBUNWIND_SRC}/ptrace/_UPT_get_dyn_info_list_addr.c + ${LIBUNWIND_SRC}/ptrace/_UPT_get_elf_filename.c + ${LIBUNWIND_SRC}/ptrace/_UPT_get_proc_name.c + ${LIBUNWIND_SRC}/ptrace/_UPT_ptrauth_insn_mask.c + ${LIBUNWIND_SRC}/ptrace/_UPT_put_unwind_info.c + ${LIBUNWIND_SRC}/ptrace/_UPT_reg_offset.c + ${LIBUNWIND_SRC}/ptrace/_UPT_resume.c +) + +# unwind_remote: superset of unwind (local + generic + ptrace) +add_library(unwind_remote STATIC + ${UNWIND_COMMON_SOURCES} + ${UNWIND_LOCAL_SOURCES} + ${UNWIND_DWARF_LOCAL_SOURCES} + ${UNWIND_ELF_SOURCES} + ${UNWIND_ARCH_SOURCES} + ${UNWIND_GENERIC_MI_SOURCES} + ${UNWIND_GENERIC_DWARF_SOURCES} + ${UNWIND_GENERIC_ARCH_SOURCES} + ${UNWIND_PTRACE_SOURCES} +) + +target_include_directories(unwind_remote + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/include + ${LIBUNWIND_INC} + ${LIBUNWIND_SRC} + PUBLIC + $ + $ +) + +if(UNWIND_ARCH STREQUAL "x86_64") + target_include_directories(unwind_remote PRIVATE ${LIBUNWIND_INC}/tdep-x86_64) + target_compile_definitions(unwind_remote PRIVATE UNW_TARGET_X86_64=1) +elseif(UNWIND_ARCH STREQUAL "aarch64") + target_include_directories(unwind_remote PRIVATE ${LIBUNWIND_INC}/tdep-aarch64) + target_compile_definitions(unwind_remote PRIVATE UNW_TARGET_AARCH64=1) +elseif(UNWIND_ARCH STREQUAL "x86") + target_include_directories(unwind_remote PRIVATE ${LIBUNWIND_INC}/tdep-x86) + target_compile_definitions(unwind_remote PRIVATE UNW_TARGET_X86=1) +elseif(UNWIND_ARCH STREQUAL "arm") + target_include_directories(unwind_remote PRIVATE ${LIBUNWIND_INC}/tdep-arm) + target_compile_definitions(unwind_remote PRIVATE UNW_TARGET_ARM=1) +endif() + +target_compile_definitions(unwind_remote PRIVATE + HAVE_CONFIG_H + _GNU_SOURCE +) + +set_target_properties(unwind_remote PROPERTIES + C_STANDARD 99 + POSITION_INDEPENDENT_CODE ON +) + +if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(unwind_remote PRIVATE -w) +endif() + +target_link_libraries(unwind_remote PRIVATE ${CMAKE_DL_LIBS} pthread) + +endif() # LIBUNWIND_BUILD_REMOTE diff --git a/vendor/libunwind/VENDORING.md b/vendor/libunwind/VENDORING.md index e54786ce63..4b1960eb9e 100644 --- a/vendor/libunwind/VENDORING.md +++ b/vendor/libunwind/VENDORING.md @@ -9,8 +9,18 @@ ## Purpose libunwind is vendored so the sentry-native SDK can perform stack unwinding on -Linux without requiring users to install any external packages. Only the -**local** unwinding functionality is needed. +Linux without requiring users to install any external packages. + +Two CMake targets are provided: + +- **`unwind`** — local unwinding only (`L`-prefix sources, `_UL*` symbols). + Used by the main `sentry` library and the inproc backend. +- **`unwind_remote`** — local + remote unwinding (`L`-prefix + `G`-prefix + sources + `src/ptrace/` accessors, `_UL*` + `_U*` + `_UPT_*` symbols). + Only built when `LIBUNWIND_BUILD_REMOTE` is set (i.e., native backend on + Linux). Used by the `sentry-crash` daemon for out-of-process DWARF + unwinding and symbol name resolution via `unw_init_remote()` / + `unw_get_proc_name()`. ## Supported Architectures (built by CMake) @@ -65,15 +75,13 @@ Source and include directories for architectures sentry-native does not target: ### 4. Unused feature modules -These are separate `libunwind` "accessor" libraries for non-local unwinding use -cases. sentry-native only uses local unwinding (unwinding the current process -in-process), so none of these are needed: +These are separate `libunwind` "accessor" libraries that are not needed by +sentry-native: | Directory | Purpose | Why removed | |-----------------|-------------------------------------|-----------------------------------| | `src/coredump/` | Unwinding from a coredump file | Not a live-process use case | | `src/nto/` | QNX Neutrino ptrace-based unwinding | QNX is not a sentry-native target | -| `src/ptrace/` | Remote unwinding via `ptrace()` | Only local unwinding is needed | | `src/setjmp/` | `setjmp`/`longjmp` wrappers | Not relevant for crash reporting | ### What is kept but NOT built @@ -140,8 +148,8 @@ both GCC and Clang. 3. Delete and re-copy these directories from the new tarball, **excluding** the removed architecture dirs listed above: - - `src/` — keep only: `aarch64/`, `arm/`, `dwarf/`, `mi/`, `riscv/`, - `unwind/`, `x86/`, `x86_64/`, and top-level `.c` / `.h` files + - `src/` — keep only: `aarch64/`, `arm/`, `dwarf/`, `mi/`, `ptrace/`, + `riscv/`, `unwind/`, `x86/`, `x86_64/`, and top-level `.c` / `.h` files (`src/unwind/` is kept for reference but **not compiled** — do not add it to `CMakeLists.txt`) - `include/` — keep only: `tdep/`, `tdep-aarch64/`, `tdep-arm/`, diff --git a/vendor/libunwind/src/ptrace/_UPT_access_fpreg.c b/vendor/libunwind/src/ptrace/_UPT_access_fpreg.c new file mode 100644 index 0000000000..7d8eee83d8 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_access_fpreg.c @@ -0,0 +1,146 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if HAVE_DECL_PTRACE_POKEUSER || defined(HAVE_TTRACE) +int +_UPT_access_fpreg (unw_addr_space_t as UNUSED, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + unw_word_t *wp = (unw_word_t *) val; + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + int i; + + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + return -UNW_EBADREG; + + errno = 0; + if (write) + for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg] + i * sizeof(wp[i]), + wp[i]); +#endif + if (errno) + return -UNW_EBADREG; + } + else + for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + wp[i] = ptrace (PTRACE_PEEKUSER, pid, + _UPT_reg_offset[reg] + i * sizeof(wp[i]), 0); +#endif + if (errno) + return -UNW_EBADREG; + } + return 0; +} +#elif HAVE_DECL_PT_GETFPREGS +int +_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + fpregset_t fpreg; + +#if defined(__amd64__) + if (1) /* XXXKIB */ + return -UNW_EBADREG; +#elif defined(__i386__) + if ((unsigned) reg < UNW_X86_ST0 || (unsigned) reg > UNW_X86_ST7) + return -UNW_EBADREG; +#elif defined(__arm__) + if ((unsigned) reg < UNW_ARM_F0 || (unsigned) reg > UNW_ARM_F7) + return -UNW_EBADREG; +#elif defined(__aarch64__) + if ((unsigned) reg < UNW_AARCH64_V0 || (unsigned) reg > UNW_AARCH64_V31) + return -UNW_EBADREG; +#elif defined(__powerpc64__) + if ((unsigned) reg < UNW_PPC64_F0 || (unsigned) reg > UNW_PPC64_F31) + return -UNW_EBADREG; +#elif defined(__powerpc__) + if ((unsigned) reg < UNW_PPC32_F0 || (unsigned) reg > UNW_PPC32_F31) + return -UNW_EBADREG; +#else +#error Fix me +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + return -UNW_EBADREG; + + if (ptrace(PT_GETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) + return -UNW_EBADREG; + if (write) { +#if defined(__amd64__) + memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__arm__) +# if __FreeBSD_version >= 1400079 + memcpy(&fpreg.fpr_r[reg], val, sizeof(unw_fpreg_t)); +# else + memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t)); +# endif +#elif defined(__aarch64__) + memcpy(&fpreg.fp_q[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__powerpc__) + memcpy(&fpreg.fpreg[reg], val, sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + if (ptrace(PT_SETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) + return -UNW_EBADREG; + } else +#if defined(__amd64__) + memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t)); +#elif defined(__arm__) +# if __FreeBSD_version >= 1400079 + memcpy(&fpreg.fpr_r[reg], val, sizeof(unw_fpreg_t)); +# else + memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t)); +# endif +#elif defined(__aarch64__) + memcpy(val, &fpreg.fp_q[reg], sizeof(unw_fpreg_t)); +#elif defined(__powerpc__) + memcpy(val, &fpreg.fpreg[reg], sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + return 0; +} +#else +#error Fix me +#endif diff --git a/vendor/libunwind/src/ptrace/_UPT_access_mem.c b/vendor/libunwind/src/ptrace/_UPT_access_mem.c new file mode 100644 index 0000000000..5892982cd7 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_access_mem.c @@ -0,0 +1,123 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if HAVE_DECL_PTRACE_POKEDATA || defined(HAVE_TTRACE) +int +_UPT_access_mem (unw_addr_space_t as UNUSED, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + int i, end; + unw_word_t tmp_val; + + if (!ui) + return -UNW_EINVAL; + + pid_t pid = ui->pid; + + // Some 32-bit archs have to define a 64-bit unw_word_t. + // Callers of this function therefore expect a 64-bit + // return value, but ptrace only returns a 32-bit value + // in such cases. + if (sizeof(long) == 4 && sizeof(unw_word_t) == 8) + end = 2; + else + end = 1; + + for (i = 0; i < end; i++) + { + unw_word_t tmp_addr = i == 0 ? addr : addr + 4; + + errno = 0; + if (write) + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + tmp_val = i == 0 ? *val : *val >> 32; +#else + tmp_val = i == 0 && end == 2 ? *val >> 32 : *val; +#endif + + Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val); + if (errno) + return -UNW_EINVAL; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0); + + if (i == 0) + *val = 0; + +#if __BYTE_ORDER == __LITTLE_ENDIAN + *val |= tmp_val << (i * 32); +#else + *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val; +#endif + + if (errno) + return -UNW_EINVAL; +#endif + Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val); + } + } + return 0; +} +#elif HAVE_DECL_PT_IO +int +_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + if (!ui) + return -UNW_EINVAL; + pid_t pid = ui->pid; + struct ptrace_io_desc iod; + + iod.piod_offs = (void *)addr; + iod.piod_addr = val; + iod.piod_len = sizeof(*val); + iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; + if (write) + Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val); + if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1) + return -UNW_EINVAL; + if (!write) + Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val); + return 0; +} +#else +#error Fix me +#endif diff --git a/vendor/libunwind/src/ptrace/_UPT_access_reg.c b/vendor/libunwind/src/ptrace/_UPT_access_reg.c new file mode 100644 index 0000000000..316ad19b8a --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_access_reg.c @@ -0,0 +1,402 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 +# include +# ifdef HAVE_ASM_PTRACE_OFFSETS_H +# include +# endif +# include "tdep-ia64/rse.h" +#endif + +#if HAVE_DECL_PTRACE_SETREGSET && (defined(__linux__) && !defined(UNW_TARGET_X86)) +#include +int +_UPT_access_reg (unw_addr_space_t as UNUSED, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + struct iovec loc; + +#if UNW_DEBUG + Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n", + unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + + loc.iov_base = ®s; + loc.iov_len = sizeof(regs); + + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + +badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#elif (HAVE_DECL_PTRACE_POKEUSER || defined(HAVE_TTRACE)) && (defined(__linux__) && !defined(UNW_TARGET_X86)) +int +_UPT_access_reg (UNUSED unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + +#if UNW_DEBUG + Debug(16, "using pokeuser: reg: %s [%u], val: %lx, write: %d\n", unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val); +#endif + +#if UNW_TARGET_IA64 + if ((unsigned) reg - UNW_IA64_NAT < 32) + { + unsigned long nat_bits, mask; + + /* The Linux ptrace represents the statc NaT bits as a single word. */ + mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT); + errno = 0; +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0); + if (errno) + goto badreg; +#endif + + if (write) + { + if (*val) + nat_bits |= mask; + else + nat_bits &= ~mask; +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits); + if (errno) + goto badreg; +#endif + } + goto out; + } + else + switch (reg) + { + case UNW_IA64_GR + 0: + if (write) + goto badreg; + *val = 0; + return 0; + + case UNW_REG_IP: + { + unsigned long ip, psr; + + /* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */ +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0); + if (errno) + goto badreg; +#endif + if (write) + { + ip = *val & ~0xfUL; + psr = (psr & ~0x3UL << 41) | (*val & 0x3); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip); + ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr); + if (errno) + goto badreg; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0); + if (errno) + goto badreg; +#endif + *val = ip + ((psr >> 41) & 0x3); + } + goto out; + } + + case UNW_IA64_AR_BSPSTORE: + reg = UNW_IA64_AR_BSP; + break; + + case UNW_IA64_AR_BSP: + case UNW_IA64_BSP: + { + unsigned long sof, cfm, bsp; + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + /* Account for the fact that ptrace() expects bsp to point + _after_ the current register frame. */ + errno = 0; + cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); + if (errno) + goto badreg; +#endif + sof = (cfm & 0x7f); + + if (write) + { + bsp = rse_skip_regs (*val, sof); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp); + if (errno) + goto badreg; +#endif + } + else + { +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); + if (errno) + goto badreg; +#endif + *val = rse_skip_regs (bsp, -sof); + } + goto out; + } + + case UNW_IA64_CFM: + /* If we change CFM, we need to adjust ptrace's notion of bsp + accordingly, so that the real bsp remains unchanged. */ + if (write) + { + unsigned long new_sof, old_sof, cfm, bsp; + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); + cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); +#endif + if (errno) + goto badreg; + old_sof = (cfm & 0x7f); + new_sof = (*val & 0x7f); + if (old_sof != new_sof) + { + bsp = rse_skip_regs (bsp, -old_sof + new_sof); +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0); + if (errno) + goto badreg; +#endif + } +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val); + if (errno) + goto badreg; +#endif + goto out; + } + break; + } +#endif /* End of IA64 */ + +#if UNW_TARGET_RISCV + if (reg == UNW_RISCV_X0) { + if (write) + goto badreg; + + *val = 0; + return 0; + } +#endif /* End of RISCV */ + + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { +#if UNW_DEBUG + Debug(2, "register out of range: >= %zu / %zu\n", sizeof(_UPT_reg_offset), sizeof(_UPT_reg_offset[0])); +#endif + errno = EINVAL; + goto badreg; + } + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#else + errno = 0; + if (write) + ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val); + else { +#if UNW_DEBUG + Debug(16, "ptrace PEEKUSER pid: %lu , reg: %lu , offs: %lu\n", (unsigned long)pid, (unsigned long)reg, + (unsigned long)_UPT_reg_offset[reg]); +#endif + *val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0); + } + if (errno) { +#if UNW_DEBUG + Debug(2, "ptrace failure\n"); +#endif + goto badreg; + } +#endif + +#ifdef UNW_TARGET_IA64 + out: +#endif +#if UNW_DEBUG + if (!write) + Debug (16, "%s[%u] -> %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + return 0; + + badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#elif defined(HAVE_DECL_PT_GETREGS) && defined(__linux__) +# include + +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + struct user_regs_struct regs; + char *r; + +#if UNW_DEBUG + Debug(16, "using getregs: reg: %s [%u], val: %lx, write: %u\n", unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace(PT_GETREGS, pid, NULL, ®s) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PT_SETREGS, pid, NULL, ®s) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + + badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} + +#elif defined(HAVE_DECL_PT_GETREGS) && defined(__FreeBSD__) +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + +#if UNW_DEBUG + Debug(16, "using getregs: reg: %s [%u], val: %lx, write: %u\n", unw_regname(reg), (unsigned) reg, (long) val, write); + + if (write) + Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); +#endif + + if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) + { + errno = EINVAL; + goto badreg; + } + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace(PT_GETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PT_SETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + + badreg: + Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); + return -UNW_EBADREG; +} +#else +#error Port me +#endif diff --git a/vendor/libunwind/src/ptrace/_UPT_accessors.c b/vendor/libunwind/src/ptrace/_UPT_accessors.c new file mode 100644 index 0000000000..d01d8a8dcc --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_accessors.c @@ -0,0 +1,40 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +unw_accessors_t _UPT_accessors = + { + .find_proc_info = _UPT_find_proc_info, + .put_unwind_info = _UPT_put_unwind_info, + .get_dyn_info_list_addr = _UPT_get_dyn_info_list_addr, + .access_mem = _UPT_access_mem, + .access_reg = _UPT_access_reg, + .access_fpreg = _UPT_access_fpreg, + .resume = _UPT_resume, + .get_proc_name = _UPT_get_proc_name, + .get_elf_filename = _UPT_get_elf_filename, + .ptrauth_insn_mask = _UPT_ptrauth_insn_mask + }; diff --git a/vendor/libunwind/src/ptrace/_UPT_create.c b/vendor/libunwind/src/ptrace/_UPT_create.c new file mode 100644 index 0000000000..1536c27e9e --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_create.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "_UPT_internal.h" + +void * +_UPT_create (pid_t pid) +{ + struct UPT_info *ui = malloc (sizeof (struct UPT_info)); + + mi_init (); + + if (!ui) + return NULL; + + memset (ui, 0, sizeof (*ui)); + ui->pid = pid; + ui->edi.di_cache.format = -1; + ui->edi.di_debug.format = -1; +#if UNW_TARGET_IA64 + ui->edi.ktab.format = -1; +#endif + return ui; +} diff --git a/vendor/libunwind/src/ptrace/_UPT_destroy.c b/vendor/libunwind/src/ptrace/_UPT_destroy.c new file mode 100644 index 0000000000..edb664ce12 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_destroy.c @@ -0,0 +1,34 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +void +_UPT_destroy (void *ptr) +{ + struct UPT_info *ui = (struct UPT_info *) ptr; + invalidate_edi (&ui->edi); + free (ptr); +} diff --git a/vendor/libunwind/src/ptrace/_UPT_elf.c b/vendor/libunwind/src/ptrace/_UPT_elf.c new file mode 100644 index 0000000000..efc43b578b --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_elf.c @@ -0,0 +1,5 @@ +/* We need to get a separate copy of the ELF-code into + libunwind-ptrace since it cannot (and must not) have any ELF + dependencies on libunwind. */ +#include "libunwind_i.h" /* get ELFCLASS defined */ +#include "../elfxx.c" diff --git a/vendor/libunwind/src/ptrace/_UPT_find_proc_info.c b/vendor/libunwind/src/ptrace/_UPT_find_proc_info.c new file mode 100644 index 0000000000..0450b0847b --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_find_proc_info.c @@ -0,0 +1,145 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include + +#include + +#include "_UPT_internal.h" + +static int +get_unwind_info (struct elf_dyn_info *edi, pid_t pid, unw_addr_space_t as, unw_word_t ip) +{ + unsigned long segbase, mapoff; + char path[PATH_MAX]; + +#if UNW_TARGET_IA64 && defined(__linux__) + if (!edi->ktab.start_ip && _Uia64_get_kernel_table (&edi->ktab) < 0) + return -UNW_ENOINFO; + + if (edi->ktab.format != -1 && ip >= edi->ktab.start_ip && ip < edi->ktab.end_ip) + return 0; +#endif + + if ((edi->di_cache.format != -1 + && ip >= edi->di_cache.start_ip && ip < edi->di_cache.end_ip) +#if UNW_TARGET_ARM + || (edi->di_debug.format != -1 + && ip >= edi->di_arm.start_ip && ip < edi->di_arm.end_ip) +#endif + || (edi->di_debug.format != -1 + && ip >= edi->di_debug.start_ip && ip < edi->di_debug.end_ip)) + return 0; + + invalidate_edi(edi); + + if (tdep_get_elf_image (&edi->ei, pid, ip, &segbase, &mapoff, path, + sizeof(path)) < 0) + return -UNW_ENOINFO; + + /* Here, SEGBASE is the starting-address of the (mmap'ped) segment + which covers the IP we're looking for. */ + if (tdep_find_unwind_table (edi, as, path, segbase, mapoff, ip) < 0) + return -UNW_ENOINFO; + + /* This can happen in corner cases where dynamically generated + code falls into the same page that contains the data-segment + and the page-offset of the code is within the first page of + the executable. */ + if (edi->di_cache.format != -1 + && (ip < edi->di_cache.start_ip || ip >= edi->di_cache.end_ip)) + edi->di_cache.format = -1; + + if (edi->di_debug.format != -1 + && (ip < edi->di_debug.start_ip || ip >= edi->di_debug.end_ip)) + edi->di_debug.format = -1; + + if (edi->di_cache.format == -1 +#if UNW_TARGET_ARM + && edi->di_arm.format == -1 +#endif + && edi->di_debug.format == -1) + return -UNW_ENOINFO; + + return 0; +} + +int +_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + struct UPT_info *ui = arg; + int ret = -UNW_ENOINFO; + + if (get_unwind_info (&ui->edi, ui->pid, as, ip) < 0) + return -UNW_ENOINFO; + +#if UNW_TARGET_IA64 + if (ui->edi.ktab.format != -1) + { + /* The kernel unwind table resides in local memory, so we have + to use the local address space to search it. Since + _UPT_put_unwind_info() has no easy way of detecting this + case, we simply make a copy of the unwind-info, so + _UPT_put_unwind_info() can always free() the unwind-info + without ill effects. */ + ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi, + need_unwind_info, arg); + if (ret >= 0) + { + if (!need_unwind_info) + pi->unwind_info = NULL; + else + { + void *mem = malloc (pi->unwind_info_size); + + if (!mem) + return -UNW_ENOMEM; + memcpy (mem, pi->unwind_info, pi->unwind_info_size); + pi->unwind_info = mem; + } + } + } +#endif + + if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache, + pi, need_unwind_info, arg); + + if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi, + need_unwind_info, arg); + +#if UNW_TARGET_ARM + if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1) + ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi, + need_unwind_info, arg); +#endif + + return ret; +} diff --git a/vendor/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c b/vendor/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c new file mode 100644 index 0000000000..3156acfdaf --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c @@ -0,0 +1,112 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#if UNW_TARGET_IA64 && defined(__linux__) +# include "elf64.h" +# include "os-linux.h" + +static inline int +get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, + int *countp) +{ + unsigned long lo, hi, off; + struct UPT_info *ui = arg; + struct map_iterator mi; + char path[PATH_MAX]; + unw_word_t res; + int count = 0; + + maps_init (&mi, ui->pid); + while (maps_next (&mi, &lo, &hi, &off, NULL)) + { + if (off) + continue; + + invalidate_edi(&ui->edi); + + if (elf_map_image (&ui->edi.ei, path) < 0) + /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ + continue; + + Debug (16, "checking object %s\n", path); + + if (tdep_find_unwind_table (&ui->edi, as, path, lo, off, 0) > 0) + { + res = _Uia64_find_dyn_list (as, &ui->edi.di_cache, arg); + if (res && count++ == 0) + { + Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); + *dil_addr = res; + } + } + } + maps_close (&mi); + *countp = count; + return 0; +} + +#else + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static inline int +get_list_addr (unw_addr_space_t as UNUSED, + unw_word_t *dil_addr UNUSED, + void *arg UNUSED, + int *countp) +{ +# warning Implement get_list_addr(), please. + *countp = 0; + return 0; +} + +#endif + +int +_UPT_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, + void *arg) +{ + int count, ret; + + Debug (12, "looking for dyn_info list\n"); + + if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) + return ret; + + /* If multiple dynamic-info list addresses are found, we would have + to determine which was is the one actually in use (since the + dynamic name resolution algorithm will pick one "winner"). + Perhaps we'd have to track them all until we find one that's + non-empty. Hopefully, this case simply will never arise, since + only libunwind defines the dynamic info list head. */ + assert (count <= 1); + + return (count > 0) ? 0 : -UNW_ENOINFO; +} diff --git a/vendor/libunwind/src/ptrace/_UPT_get_elf_filename.c b/vendor/libunwind/src/ptrace/_UPT_get_elf_filename.c new file mode 100644 index 0000000000..401de3d181 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_get_elf_filename.c @@ -0,0 +1,38 @@ +/* + * This file is part of libunwind. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "_UPT_internal.h" + +int +_UPT_get_elf_filename (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, void *arg) +{ + struct UPT_info *ui = arg; + +#if UNW_ELF_CLASS == UNW_ELFCLASS64 + return _Uelf64_get_elf_filename (as, ui->pid, ip, buf, buf_len, offp); +#elif UNW_ELF_CLASS == UNW_ELFCLASS32 + return _Uelf32_get_elf_filename (as, ui->pid, ip, buf, buf_len, offp); +#else + return -UNW_ENOINFO; +#endif +} diff --git a/vendor/libunwind/src/ptrace/_UPT_get_proc_name.c b/vendor/libunwind/src/ptrace/_UPT_get_proc_name.c new file mode 100644 index 0000000000..4fc93e7477 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_get_proc_name.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Copyright (C) 2007 David Mosberger-Tang + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +int +_UPT_get_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, void *arg) +{ + struct UPT_info *ui = arg; + +#if UNW_ELF_CLASS == UNW_ELFCLASS64 + return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); +#elif UNW_ELF_CLASS == UNW_ELFCLASS32 + return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); +#else + return -UNW_ENOINFO; +#endif +} diff --git a/vendor/libunwind/src/ptrace/_UPT_internal.h b/vendor/libunwind/src/ptrace/_UPT_internal.h new file mode 100644 index 0000000000..5cef2573ee --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_internal.h @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003, 2005 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _UPT_internal_h +#define _UPT_internal_h + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PTRACE_H +#include +#endif +#ifdef HAVE_SYS_PROCFS_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "libunwind_i.h" + +struct UPT_info + { + pid_t pid; /* the process-id of the child we're unwinding */ + struct elf_dyn_info edi; + }; + +extern const int _UPT_reg_offset[UNW_REG_LAST + 1]; + +#endif /* _UPT_internal_h */ diff --git a/vendor/libunwind/src/ptrace/_UPT_ptrauth_insn_mask.c b/vendor/libunwind/src/ptrace/_UPT_ptrauth_insn_mask.c new file mode 100644 index 0000000000..f402cb5553 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_ptrauth_insn_mask.c @@ -0,0 +1,58 @@ +/* +* This file is part of libunwind. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "_UPT_internal.h" + +#if defined(UNW_TARGET_AARCH64) && defined(NT_ARM_PAC_MASK) + +unw_word_t _UPT_ptrauth_insn_mask (UNUSED unw_addr_space_t as, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + int ret; + struct iovec iovec; + uint64_t regset[2] = {0, 0}; + + iovec.iov_base = ®set; + iovec.iov_len = sizeof (regset); + + ret = ptrace (PTRACE_GETREGSET, pid, NT_ARM_PAC_MASK, &iovec); + if (ret != 0) + { + Debug (12, "Failed to fetch ptrauth instruction mask"); + return 0; + } + + // regset[0] => data_mask + // regset[1] => insn_mask + return regset[1]; +} + +#else + +unw_word_t _UPT_ptrauth_insn_mask (UNUSED unw_addr_space_t as, UNUSED void *arg) +{ + return 0; +} + +#endif + diff --git a/vendor/libunwind/src/ptrace/_UPT_put_unwind_info.c b/vendor/libunwind/src/ptrace/_UPT_put_unwind_info.c new file mode 100644 index 0000000000..54989a769a --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_put_unwind_info.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +void +_UPT_put_unwind_info (unw_addr_space_t as UNUSED, unw_proc_info_t *pi, void *arg UNUSED) +{ + if (!pi->unwind_info) + return; + free (pi->unwind_info); + pi->unwind_info = NULL; +} diff --git a/vendor/libunwind/src/ptrace/_UPT_reg_offset.c b/vendor/libunwind/src/ptrace/_UPT_reg_offset.c new file mode 100644 index 0000000000..02e0ec6d89 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_reg_offset.c @@ -0,0 +1,740 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + Copyright (C) 2013 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +#include + +#ifdef HAVE_ASM_PTRACE_H +# include +#endif + +#ifdef HAVE_ASM_PTRACE_OFFSETS_H +# include +#endif + +#if defined(__powerpc__) && defined(__FreeBSD__) +#define PT_R0 0 +#define PT_R1 1 +#define PT_R2 2 +#define PT_R3 3 +#define PT_R4 4 +#define PT_R5 5 +#define PT_R6 6 +#define PT_R7 7 +#define PT_R8 8 +#define PT_R9 9 +#define PT_R10 10 +#define PT_R11 11 +#define PT_R12 12 +#define PT_R13 13 +#define PT_R14 14 +#define PT_R15 15 +#define PT_R16 16 +#define PT_R17 17 +#define PT_R18 18 +#define PT_R19 19 +#define PT_R20 20 +#define PT_R21 21 +#define PT_R22 22 +#define PT_R23 23 +#define PT_R24 24 +#define PT_R25 25 +#define PT_R26 26 +#define PT_R27 27 +#define PT_R28 28 +#define PT_R29 29 +#define PT_R30 30 +#define PT_R31 31 +#define PT_NIP 32 +#define PT_CCR 33 +#define PT_CTR 35 +#define PT_LNK 36 +#define PT_XER 37 +#define PT_FPR0 48 +#define PT_FPSCR (PT_FPR0 + 2*32 + 1) +#define PT_VR0 82 +#define PT_VSCR (PT_VR0 + 32*2 + 1) +#define PT_VRSAVE (PT_VR0 + 33*2) +#endif + +const int _UPT_reg_offset[UNW_REG_LAST + 1] = + { +#ifdef HAVE_ASM_PTRACE_OFFSETS_H +# ifndef PT_AR_CSD +# define PT_AR_CSD -1 /* this was introduced with rev 2.1 of ia64 */ +# endif + + [UNW_IA64_GR + 0] = -1, [UNW_IA64_GR + 1] = PT_R1, + [UNW_IA64_GR + 2] = PT_R2, [UNW_IA64_GR + 3] = PT_R3, + [UNW_IA64_GR + 4] = PT_R4, [UNW_IA64_GR + 5] = PT_R5, + [UNW_IA64_GR + 6] = PT_R6, [UNW_IA64_GR + 7] = PT_R7, + [UNW_IA64_GR + 8] = PT_R8, [UNW_IA64_GR + 9] = PT_R9, + [UNW_IA64_GR + 10] = PT_R10, [UNW_IA64_GR + 11] = PT_R11, + [UNW_IA64_GR + 12] = PT_R12, [UNW_IA64_GR + 13] = PT_R13, + [UNW_IA64_GR + 14] = PT_R14, [UNW_IA64_GR + 15] = PT_R15, + [UNW_IA64_GR + 16] = PT_R16, [UNW_IA64_GR + 17] = PT_R17, + [UNW_IA64_GR + 18] = PT_R18, [UNW_IA64_GR + 19] = PT_R19, + [UNW_IA64_GR + 20] = PT_R20, [UNW_IA64_GR + 21] = PT_R21, + [UNW_IA64_GR + 22] = PT_R22, [UNW_IA64_GR + 23] = PT_R23, + [UNW_IA64_GR + 24] = PT_R24, [UNW_IA64_GR + 25] = PT_R25, + [UNW_IA64_GR + 26] = PT_R26, [UNW_IA64_GR + 27] = PT_R27, + [UNW_IA64_GR + 28] = PT_R28, [UNW_IA64_GR + 29] = PT_R29, + [UNW_IA64_GR + 30] = PT_R30, [UNW_IA64_GR + 31] = PT_R31, + + [UNW_IA64_NAT+ 0] = -1, [UNW_IA64_NAT+ 1] = PT_NAT_BITS, + [UNW_IA64_NAT+ 2] = PT_NAT_BITS, [UNW_IA64_NAT+ 3] = PT_NAT_BITS, + [UNW_IA64_NAT+ 4] = PT_NAT_BITS, [UNW_IA64_NAT+ 5] = PT_NAT_BITS, + [UNW_IA64_NAT+ 6] = PT_NAT_BITS, [UNW_IA64_NAT+ 7] = PT_NAT_BITS, + [UNW_IA64_NAT+ 8] = PT_NAT_BITS, [UNW_IA64_NAT+ 9] = PT_NAT_BITS, + [UNW_IA64_NAT+ 10] = PT_NAT_BITS, [UNW_IA64_NAT+ 11] = PT_NAT_BITS, + [UNW_IA64_NAT+ 12] = PT_NAT_BITS, [UNW_IA64_NAT+ 13] = PT_NAT_BITS, + [UNW_IA64_NAT+ 14] = PT_NAT_BITS, [UNW_IA64_NAT+ 15] = PT_NAT_BITS, + [UNW_IA64_NAT+ 16] = PT_NAT_BITS, [UNW_IA64_NAT+ 17] = PT_NAT_BITS, + [UNW_IA64_NAT+ 18] = PT_NAT_BITS, [UNW_IA64_NAT+ 19] = PT_NAT_BITS, + [UNW_IA64_NAT+ 20] = PT_NAT_BITS, [UNW_IA64_NAT+ 21] = PT_NAT_BITS, + [UNW_IA64_NAT+ 22] = PT_NAT_BITS, [UNW_IA64_NAT+ 23] = PT_NAT_BITS, + [UNW_IA64_NAT+ 24] = PT_NAT_BITS, [UNW_IA64_NAT+ 25] = PT_NAT_BITS, + [UNW_IA64_NAT+ 26] = PT_NAT_BITS, [UNW_IA64_NAT+ 27] = PT_NAT_BITS, + [UNW_IA64_NAT+ 28] = PT_NAT_BITS, [UNW_IA64_NAT+ 29] = PT_NAT_BITS, + [UNW_IA64_NAT+ 30] = PT_NAT_BITS, [UNW_IA64_NAT+ 31] = PT_NAT_BITS, + + [UNW_IA64_FR + 0] = -1, [UNW_IA64_FR + 1] = -1, + [UNW_IA64_FR + 2] = PT_F2, [UNW_IA64_FR + 3] = PT_F3, + [UNW_IA64_FR + 4] = PT_F4, [UNW_IA64_FR + 5] = PT_F5, + [UNW_IA64_FR + 6] = PT_F6, [UNW_IA64_FR + 7] = PT_F7, + [UNW_IA64_FR + 8] = PT_F8, [UNW_IA64_FR + 9] = PT_F9, + [UNW_IA64_FR + 10] = PT_F10, [UNW_IA64_FR + 11] = PT_F11, + [UNW_IA64_FR + 12] = PT_F12, [UNW_IA64_FR + 13] = PT_F13, + [UNW_IA64_FR + 14] = PT_F14, [UNW_IA64_FR + 15] = PT_F15, + [UNW_IA64_FR + 16] = PT_F16, [UNW_IA64_FR + 17] = PT_F17, + [UNW_IA64_FR + 18] = PT_F18, [UNW_IA64_FR + 19] = PT_F19, + [UNW_IA64_FR + 20] = PT_F20, [UNW_IA64_FR + 21] = PT_F21, + [UNW_IA64_FR + 22] = PT_F22, [UNW_IA64_FR + 23] = PT_F23, + [UNW_IA64_FR + 24] = PT_F24, [UNW_IA64_FR + 25] = PT_F25, + [UNW_IA64_FR + 26] = PT_F26, [UNW_IA64_FR + 27] = PT_F27, + [UNW_IA64_FR + 28] = PT_F28, [UNW_IA64_FR + 29] = PT_F29, + [UNW_IA64_FR + 30] = PT_F30, [UNW_IA64_FR + 31] = PT_F31, + [UNW_IA64_FR + 32] = PT_F32, [UNW_IA64_FR + 33] = PT_F33, + [UNW_IA64_FR + 34] = PT_F34, [UNW_IA64_FR + 35] = PT_F35, + [UNW_IA64_FR + 36] = PT_F36, [UNW_IA64_FR + 37] = PT_F37, + [UNW_IA64_FR + 38] = PT_F38, [UNW_IA64_FR + 39] = PT_F39, + [UNW_IA64_FR + 40] = PT_F40, [UNW_IA64_FR + 41] = PT_F41, + [UNW_IA64_FR + 42] = PT_F42, [UNW_IA64_FR + 43] = PT_F43, + [UNW_IA64_FR + 44] = PT_F44, [UNW_IA64_FR + 45] = PT_F45, + [UNW_IA64_FR + 46] = PT_F46, [UNW_IA64_FR + 47] = PT_F47, + [UNW_IA64_FR + 48] = PT_F48, [UNW_IA64_FR + 49] = PT_F49, + [UNW_IA64_FR + 50] = PT_F50, [UNW_IA64_FR + 51] = PT_F51, + [UNW_IA64_FR + 52] = PT_F52, [UNW_IA64_FR + 53] = PT_F53, + [UNW_IA64_FR + 54] = PT_F54, [UNW_IA64_FR + 55] = PT_F55, + [UNW_IA64_FR + 56] = PT_F56, [UNW_IA64_FR + 57] = PT_F57, + [UNW_IA64_FR + 58] = PT_F58, [UNW_IA64_FR + 59] = PT_F59, + [UNW_IA64_FR + 60] = PT_F60, [UNW_IA64_FR + 61] = PT_F61, + [UNW_IA64_FR + 62] = PT_F62, [UNW_IA64_FR + 63] = PT_F63, + [UNW_IA64_FR + 64] = PT_F64, [UNW_IA64_FR + 65] = PT_F65, + [UNW_IA64_FR + 66] = PT_F66, [UNW_IA64_FR + 67] = PT_F67, + [UNW_IA64_FR + 68] = PT_F68, [UNW_IA64_FR + 69] = PT_F69, + [UNW_IA64_FR + 70] = PT_F70, [UNW_IA64_FR + 71] = PT_F71, + [UNW_IA64_FR + 72] = PT_F72, [UNW_IA64_FR + 73] = PT_F73, + [UNW_IA64_FR + 74] = PT_F74, [UNW_IA64_FR + 75] = PT_F75, + [UNW_IA64_FR + 76] = PT_F76, [UNW_IA64_FR + 77] = PT_F77, + [UNW_IA64_FR + 78] = PT_F78, [UNW_IA64_FR + 79] = PT_F79, + [UNW_IA64_FR + 80] = PT_F80, [UNW_IA64_FR + 81] = PT_F81, + [UNW_IA64_FR + 82] = PT_F82, [UNW_IA64_FR + 83] = PT_F83, + [UNW_IA64_FR + 84] = PT_F84, [UNW_IA64_FR + 85] = PT_F85, + [UNW_IA64_FR + 86] = PT_F86, [UNW_IA64_FR + 87] = PT_F87, + [UNW_IA64_FR + 88] = PT_F88, [UNW_IA64_FR + 89] = PT_F89, + [UNW_IA64_FR + 90] = PT_F90, [UNW_IA64_FR + 91] = PT_F91, + [UNW_IA64_FR + 92] = PT_F92, [UNW_IA64_FR + 93] = PT_F93, + [UNW_IA64_FR + 94] = PT_F94, [UNW_IA64_FR + 95] = PT_F95, + [UNW_IA64_FR + 96] = PT_F96, [UNW_IA64_FR + 97] = PT_F97, + [UNW_IA64_FR + 98] = PT_F98, [UNW_IA64_FR + 99] = PT_F99, + [UNW_IA64_FR +100] = PT_F100, [UNW_IA64_FR +101] = PT_F101, + [UNW_IA64_FR +102] = PT_F102, [UNW_IA64_FR +103] = PT_F103, + [UNW_IA64_FR +104] = PT_F104, [UNW_IA64_FR +105] = PT_F105, + [UNW_IA64_FR +106] = PT_F106, [UNW_IA64_FR +107] = PT_F107, + [UNW_IA64_FR +108] = PT_F108, [UNW_IA64_FR +109] = PT_F109, + [UNW_IA64_FR +110] = PT_F110, [UNW_IA64_FR +111] = PT_F111, + [UNW_IA64_FR +112] = PT_F112, [UNW_IA64_FR +113] = PT_F113, + [UNW_IA64_FR +114] = PT_F114, [UNW_IA64_FR +115] = PT_F115, + [UNW_IA64_FR +116] = PT_F116, [UNW_IA64_FR +117] = PT_F117, + [UNW_IA64_FR +118] = PT_F118, [UNW_IA64_FR +119] = PT_F119, + [UNW_IA64_FR +120] = PT_F120, [UNW_IA64_FR +121] = PT_F121, + [UNW_IA64_FR +122] = PT_F122, [UNW_IA64_FR +123] = PT_F123, + [UNW_IA64_FR +124] = PT_F124, [UNW_IA64_FR +125] = PT_F125, + [UNW_IA64_FR +126] = PT_F126, [UNW_IA64_FR +127] = PT_F127, + + [UNW_IA64_AR + 0] = -1, [UNW_IA64_AR + 1] = -1, + [UNW_IA64_AR + 2] = -1, [UNW_IA64_AR + 3] = -1, + [UNW_IA64_AR + 4] = -1, [UNW_IA64_AR + 5] = -1, + [UNW_IA64_AR + 6] = -1, [UNW_IA64_AR + 7] = -1, + [UNW_IA64_AR + 8] = -1, [UNW_IA64_AR + 9] = -1, + [UNW_IA64_AR + 10] = -1, [UNW_IA64_AR + 11] = -1, + [UNW_IA64_AR + 12] = -1, [UNW_IA64_AR + 13] = -1, + [UNW_IA64_AR + 14] = -1, [UNW_IA64_AR + 15] = -1, + [UNW_IA64_AR + 16] = PT_AR_RSC, [UNW_IA64_AR + 17] = PT_AR_BSP, + [UNW_IA64_AR + 18] = PT_AR_BSPSTORE,[UNW_IA64_AR + 19] = PT_AR_RNAT, + [UNW_IA64_AR + 20] = -1, [UNW_IA64_AR + 21] = -1, + [UNW_IA64_AR + 22] = -1, [UNW_IA64_AR + 23] = -1, + [UNW_IA64_AR + 24] = -1, [UNW_IA64_AR + 25] = PT_AR_CSD, + [UNW_IA64_AR + 26] = -1, [UNW_IA64_AR + 27] = -1, + [UNW_IA64_AR + 28] = -1, [UNW_IA64_AR + 29] = -1, + [UNW_IA64_AR + 30] = -1, [UNW_IA64_AR + 31] = -1, + [UNW_IA64_AR + 32] = PT_AR_CCV, [UNW_IA64_AR + 33] = -1, + [UNW_IA64_AR + 34] = -1, [UNW_IA64_AR + 35] = -1, + [UNW_IA64_AR + 36] = PT_AR_UNAT, [UNW_IA64_AR + 37] = -1, + [UNW_IA64_AR + 38] = -1, [UNW_IA64_AR + 39] = -1, + [UNW_IA64_AR + 40] = PT_AR_FPSR, [UNW_IA64_AR + 41] = -1, + [UNW_IA64_AR + 42] = -1, [UNW_IA64_AR + 43] = -1, + [UNW_IA64_AR + 44] = -1, [UNW_IA64_AR + 45] = -1, + [UNW_IA64_AR + 46] = -1, [UNW_IA64_AR + 47] = -1, + [UNW_IA64_AR + 48] = -1, [UNW_IA64_AR + 49] = -1, + [UNW_IA64_AR + 50] = -1, [UNW_IA64_AR + 51] = -1, + [UNW_IA64_AR + 52] = -1, [UNW_IA64_AR + 53] = -1, + [UNW_IA64_AR + 54] = -1, [UNW_IA64_AR + 55] = -1, + [UNW_IA64_AR + 56] = -1, [UNW_IA64_AR + 57] = -1, + [UNW_IA64_AR + 58] = -1, [UNW_IA64_AR + 59] = -1, + [UNW_IA64_AR + 60] = -1, [UNW_IA64_AR + 61] = -1, + [UNW_IA64_AR + 62] = -1, [UNW_IA64_AR + 63] = -1, + [UNW_IA64_AR + 64] = PT_AR_PFS, [UNW_IA64_AR + 65] = PT_AR_LC, + [UNW_IA64_AR + 66] = PT_AR_EC, [UNW_IA64_AR + 67] = -1, + [UNW_IA64_AR + 68] = -1, [UNW_IA64_AR + 69] = -1, + [UNW_IA64_AR + 70] = -1, [UNW_IA64_AR + 71] = -1, + [UNW_IA64_AR + 72] = -1, [UNW_IA64_AR + 73] = -1, + [UNW_IA64_AR + 74] = -1, [UNW_IA64_AR + 75] = -1, + [UNW_IA64_AR + 76] = -1, [UNW_IA64_AR + 77] = -1, + [UNW_IA64_AR + 78] = -1, [UNW_IA64_AR + 79] = -1, + [UNW_IA64_AR + 80] = -1, [UNW_IA64_AR + 81] = -1, + [UNW_IA64_AR + 82] = -1, [UNW_IA64_AR + 83] = -1, + [UNW_IA64_AR + 84] = -1, [UNW_IA64_AR + 85] = -1, + [UNW_IA64_AR + 86] = -1, [UNW_IA64_AR + 87] = -1, + [UNW_IA64_AR + 88] = -1, [UNW_IA64_AR + 89] = -1, + [UNW_IA64_AR + 90] = -1, [UNW_IA64_AR + 91] = -1, + [UNW_IA64_AR + 92] = -1, [UNW_IA64_AR + 93] = -1, + [UNW_IA64_AR + 94] = -1, [UNW_IA64_AR + 95] = -1, + [UNW_IA64_AR + 96] = -1, [UNW_IA64_AR + 97] = -1, + [UNW_IA64_AR + 98] = -1, [UNW_IA64_AR + 99] = -1, + [UNW_IA64_AR +100] = -1, [UNW_IA64_AR +101] = -1, + [UNW_IA64_AR +102] = -1, [UNW_IA64_AR +103] = -1, + [UNW_IA64_AR +104] = -1, [UNW_IA64_AR +105] = -1, + [UNW_IA64_AR +106] = -1, [UNW_IA64_AR +107] = -1, + [UNW_IA64_AR +108] = -1, [UNW_IA64_AR +109] = -1, + [UNW_IA64_AR +110] = -1, [UNW_IA64_AR +111] = -1, + [UNW_IA64_AR +112] = -1, [UNW_IA64_AR +113] = -1, + [UNW_IA64_AR +114] = -1, [UNW_IA64_AR +115] = -1, + [UNW_IA64_AR +116] = -1, [UNW_IA64_AR +117] = -1, + [UNW_IA64_AR +118] = -1, [UNW_IA64_AR +119] = -1, + [UNW_IA64_AR +120] = -1, [UNW_IA64_AR +121] = -1, + [UNW_IA64_AR +122] = -1, [UNW_IA64_AR +123] = -1, + [UNW_IA64_AR +124] = -1, [UNW_IA64_AR +125] = -1, + [UNW_IA64_AR +126] = -1, [UNW_IA64_AR +127] = -1, + + [UNW_IA64_BR + 0] = PT_B0, [UNW_IA64_BR + 1] = PT_B1, + [UNW_IA64_BR + 2] = PT_B2, [UNW_IA64_BR + 3] = PT_B3, + [UNW_IA64_BR + 4] = PT_B4, [UNW_IA64_BR + 5] = PT_B5, + [UNW_IA64_BR + 6] = PT_B6, [UNW_IA64_BR + 7] = PT_B7, + + [UNW_IA64_PR] = PT_PR, + [UNW_IA64_CFM] = PT_CFM, + [UNW_IA64_IP] = PT_CR_IIP +#elif defined(HAVE_TTRACE) +# warning No support for ttrace() yet. +#elif defined(UNW_TARGET_HPPA) + [UNW_HPPA_GR + 0] = 0x000, [UNW_HPPA_GR + 1] = 0x004, + [UNW_HPPA_GR + 2] = 0x008, [UNW_HPPA_GR + 3] = 0x00c, + [UNW_HPPA_GR + 4] = 0x010, [UNW_HPPA_GR + 5] = 0x014, + [UNW_HPPA_GR + 6] = 0x018, [UNW_HPPA_GR + 7] = 0x01c, + [UNW_HPPA_GR + 8] = 0x020, [UNW_HPPA_GR + 9] = 0x024, + [UNW_HPPA_GR + 10] = 0x028, [UNW_HPPA_GR + 11] = 0x02c, + [UNW_HPPA_GR + 12] = 0x030, [UNW_HPPA_GR + 13] = 0x034, + [UNW_HPPA_GR + 14] = 0x038, [UNW_HPPA_GR + 15] = 0x03c, + [UNW_HPPA_GR + 16] = 0x040, [UNW_HPPA_GR + 17] = 0x044, + [UNW_HPPA_GR + 18] = 0x048, [UNW_HPPA_GR + 19] = 0x04c, + [UNW_HPPA_GR + 20] = 0x050, [UNW_HPPA_GR + 21] = 0x054, + [UNW_HPPA_GR + 22] = 0x058, [UNW_HPPA_GR + 23] = 0x05c, + [UNW_HPPA_GR + 24] = 0x060, [UNW_HPPA_GR + 25] = 0x064, + [UNW_HPPA_GR + 26] = 0x068, [UNW_HPPA_GR + 27] = 0x06c, + [UNW_HPPA_GR + 28] = 0x070, [UNW_HPPA_GR + 29] = 0x074, + [UNW_HPPA_GR + 30] = 0x078, [UNW_HPPA_GR + 31] = 0x07c, + + [UNW_HPPA_FR + 0] = 0x080, [UNW_HPPA_FR + 1] = 0x088, + [UNW_HPPA_FR + 2] = 0x090, [UNW_HPPA_FR + 3] = 0x098, + [UNW_HPPA_FR + 4] = 0x0a0, [UNW_HPPA_FR + 5] = 0x0a8, + [UNW_HPPA_FR + 6] = 0x0b0, [UNW_HPPA_FR + 7] = 0x0b8, + [UNW_HPPA_FR + 8] = 0x0c0, [UNW_HPPA_FR + 9] = 0x0c8, + [UNW_HPPA_FR + 10] = 0x0d0, [UNW_HPPA_FR + 11] = 0x0d8, + [UNW_HPPA_FR + 12] = 0x0e0, [UNW_HPPA_FR + 13] = 0x0e8, + [UNW_HPPA_FR + 14] = 0x0f0, [UNW_HPPA_FR + 15] = 0x0f8, + [UNW_HPPA_FR + 16] = 0x100, [UNW_HPPA_FR + 17] = 0x108, + [UNW_HPPA_FR + 18] = 0x110, [UNW_HPPA_FR + 19] = 0x118, + [UNW_HPPA_FR + 20] = 0x120, [UNW_HPPA_FR + 21] = 0x128, + [UNW_HPPA_FR + 22] = 0x130, [UNW_HPPA_FR + 23] = 0x138, + [UNW_HPPA_FR + 24] = 0x140, [UNW_HPPA_FR + 25] = 0x148, + [UNW_HPPA_FR + 26] = 0x150, [UNW_HPPA_FR + 27] = 0x158, + [UNW_HPPA_FR + 28] = 0x160, [UNW_HPPA_FR + 29] = 0x168, + [UNW_HPPA_FR + 30] = 0x170, [UNW_HPPA_FR + 31] = 0x178, + + [UNW_HPPA_IP] = 0x1a8 /* IAOQ[0] */ +#elif defined(UNW_TARGET_X86) +#if defined __FreeBSD__ +#define UNW_R_OFF(R, r) \ + [UNW_X86_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(EAX, eax) + UNW_R_OFF(EDX, edx) + UNW_R_OFF(ECX, ecx) + UNW_R_OFF(EBX, ebx) + UNW_R_OFF(ESI, esi) + UNW_R_OFF(EDI, edi) + UNW_R_OFF(EBP, ebp) + UNW_R_OFF(ESP, esp) + UNW_R_OFF(EIP, eip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, eflags) +// UNW_R_OFF(SS, ss) +#elif defined __linux__ + [UNW_X86_EAX] = 0x18, + [UNW_X86_EBX] = 0x00, + [UNW_X86_ECX] = 0x04, + [UNW_X86_EDX] = 0x08, + [UNW_X86_ESI] = 0x0c, + [UNW_X86_EDI] = 0x10, + [UNW_X86_EBP] = 0x14, + [UNW_X86_EIP] = 0x30, + [UNW_X86_ESP] = 0x3c +/* CS = 0x34, */ +/* DS = 0x1c, */ +/* ES = 0x20, */ +/* FS = 0x24, */ +/* GS = 0x28, */ +/* ORIG_EAX = 0x2c, */ +/* EFLAGS = 0x38, */ +/* SS = 0x40 */ +#else +#error Port me +#endif +#elif defined(UNW_TARGET_X86_64) +#if defined __FreeBSD__ +#define UNW_R_OFF(R, r) \ + [UNW_X86_64_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(RAX, rax) + UNW_R_OFF(RDX, rdx) + UNW_R_OFF(RCX, rcx) + UNW_R_OFF(RBX, rbx) + UNW_R_OFF(RSI, rsi) + UNW_R_OFF(RDI, rdi) + UNW_R_OFF(RBP, rbp) + UNW_R_OFF(RSP, rsp) + UNW_R_OFF(R8, r8) + UNW_R_OFF(R9, r9) + UNW_R_OFF(R10, r10) + UNW_R_OFF(R11, r11) + UNW_R_OFF(R12, r12) + UNW_R_OFF(R13, r13) + UNW_R_OFF(R14, r14) + UNW_R_OFF(R15, r15) + UNW_R_OFF(RIP, rip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, rflags) +// UNW_R_OFF(SS, ss) +#undef UNW_R_OFF +#elif defined __linux__ + [UNW_X86_64_RAX] = 0x50, + [UNW_X86_64_RDX] = 0x60, + [UNW_X86_64_RCX] = 0x58, + [UNW_X86_64_RBX] = 0x28, + [UNW_X86_64_RSI] = 0x68, + [UNW_X86_64_RDI] = 0x70, + [UNW_X86_64_RBP] = 0x20, + [UNW_X86_64_RSP] = 0x98, + [UNW_X86_64_R8] = 0x48, + [UNW_X86_64_R9] = 0x40, + [UNW_X86_64_R10] = 0x38, + [UNW_X86_64_R11] = 0x30, + [UNW_X86_64_R12] = 0x18, + [UNW_X86_64_R13] = 0x10, + [UNW_X86_64_R14] = 0x08, + [UNW_X86_64_R15] = 0x00, + [UNW_X86_64_RIP] = 0x80 +// [UNW_X86_64_CS] = 0x88, +// [UNW_X86_64_EFLAGS] = 0x90, +// [UNW_X86_64_RSP] = 0x98, +// [UNW_X86_64_SS] = 0xa0 +#else +#error Port me +#endif +#elif defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64) + +#define UNW_REG_SLOT_SIZE sizeof(unsigned long) +#define UNW_PPC_R(v) ((v) * UNW_REG_SLOT_SIZE) +#define UNW_PPC_PT(p) UNW_PPC_R(PT_##p) + +#define UNW_FP_OFF(b, i) \ + [UNW_PPC##b##_F##i] = UNW_PPC_R(PT_FPR0 + i * 8/UNW_REG_SLOT_SIZE) + +#define UNW_R_OFF(b, i) \ + [UNW_PPC##b##_R##i] = UNW_PPC_R(PT_R##i) + +#define UNW_PPC_REGS(b) \ + UNW_R_OFF(b, 0), \ + UNW_R_OFF(b, 1), \ + UNW_R_OFF(b, 2), \ + UNW_R_OFF(b, 3), \ + UNW_R_OFF(b, 4), \ + UNW_R_OFF(b, 5), \ + UNW_R_OFF(b, 6), \ + UNW_R_OFF(b, 7), \ + UNW_R_OFF(b, 8), \ + UNW_R_OFF(b, 9), \ + UNW_R_OFF(b, 10), \ + UNW_R_OFF(b, 11), \ + UNW_R_OFF(b, 12), \ + UNW_R_OFF(b, 13), \ + UNW_R_OFF(b, 14), \ + UNW_R_OFF(b, 15), \ + UNW_R_OFF(b, 16), \ + UNW_R_OFF(b, 17), \ + UNW_R_OFF(b, 18), \ + UNW_R_OFF(b, 19), \ + UNW_R_OFF(b, 20), \ + UNW_R_OFF(b, 21), \ + UNW_R_OFF(b, 22), \ + UNW_R_OFF(b, 23), \ + UNW_R_OFF(b, 24), \ + UNW_R_OFF(b, 25), \ + UNW_R_OFF(b, 26), \ + UNW_R_OFF(b, 27), \ + UNW_R_OFF(b, 28), \ + UNW_R_OFF(b, 29), \ + UNW_R_OFF(b, 30), \ + UNW_R_OFF(b, 31), \ + \ + [UNW_PPC##b##_CTR] = UNW_PPC_PT(CTR), \ + [UNW_PPC##b##_XER] = UNW_PPC_PT(XER), \ + [UNW_PPC##b##_LR] = UNW_PPC_PT(LNK), \ + \ + UNW_FP_OFF(b, 0), \ + UNW_FP_OFF(b, 1), \ + UNW_FP_OFF(b, 2), \ + UNW_FP_OFF(b, 3), \ + UNW_FP_OFF(b, 4), \ + UNW_FP_OFF(b, 5), \ + UNW_FP_OFF(b, 6), \ + UNW_FP_OFF(b, 7), \ + UNW_FP_OFF(b, 8), \ + UNW_FP_OFF(b, 9), \ + UNW_FP_OFF(b, 10), \ + UNW_FP_OFF(b, 11), \ + UNW_FP_OFF(b, 12), \ + UNW_FP_OFF(b, 13), \ + UNW_FP_OFF(b, 14), \ + UNW_FP_OFF(b, 15), \ + UNW_FP_OFF(b, 16), \ + UNW_FP_OFF(b, 17), \ + UNW_FP_OFF(b, 18), \ + UNW_FP_OFF(b, 19), \ + UNW_FP_OFF(b, 20), \ + UNW_FP_OFF(b, 21), \ + UNW_FP_OFF(b, 22), \ + UNW_FP_OFF(b, 23), \ + UNW_FP_OFF(b, 24), \ + UNW_FP_OFF(b, 25), \ + UNW_FP_OFF(b, 26), \ + UNW_FP_OFF(b, 27), \ + UNW_FP_OFF(b, 28), \ + UNW_FP_OFF(b, 29), \ + UNW_FP_OFF(b, 30), \ + UNW_FP_OFF(b, 31) + +#define UNW_PPC32_REGS \ + [UNW_PPC32_FPSCR] = UNW_PPC_PT(FPSCR), \ + [UNW_PPC32_CCR] = UNW_PPC_PT(CCR) + +#define UNW_VR_OFF(i) \ + [UNW_PPC64_V##i] = UNW_PPC_R(PT_VR0 + i * 2) + +#define UNW_PPC64_REGS \ + [UNW_PPC64_NIP] = UNW_PPC_PT(NIP), \ + [UNW_PPC64_FRAME_POINTER] = -1, \ + [UNW_PPC64_ARG_POINTER] = -1, \ + [UNW_PPC64_CR0] = -1, \ + [UNW_PPC64_CR1] = -1, \ + [UNW_PPC64_CR2] = -1, \ + [UNW_PPC64_CR3] = -1, \ + [UNW_PPC64_CR4] = -1, \ + [UNW_PPC64_CR5] = -1, \ + [UNW_PPC64_CR6] = -1, \ + [UNW_PPC64_CR7] = -1, \ + [UNW_PPC64_VRSAVE] = UNW_PPC_PT(VRSAVE), \ + [UNW_PPC64_VSCR] = UNW_PPC_PT(VSCR), \ + [UNW_PPC64_SPE_ACC] = -1, \ + [UNW_PPC64_SPEFSCR] = -1, \ + UNW_VR_OFF(0), \ + UNW_VR_OFF(1), \ + UNW_VR_OFF(2), \ + UNW_VR_OFF(3), \ + UNW_VR_OFF(4), \ + UNW_VR_OFF(5), \ + UNW_VR_OFF(6), \ + UNW_VR_OFF(7), \ + UNW_VR_OFF(8), \ + UNW_VR_OFF(9), \ + UNW_VR_OFF(10), \ + UNW_VR_OFF(11), \ + UNW_VR_OFF(12), \ + UNW_VR_OFF(13), \ + UNW_VR_OFF(14), \ + UNW_VR_OFF(15), \ + UNW_VR_OFF(16), \ + UNW_VR_OFF(17), \ + UNW_VR_OFF(18), \ + UNW_VR_OFF(19), \ + UNW_VR_OFF(20), \ + UNW_VR_OFF(21), \ + UNW_VR_OFF(22), \ + UNW_VR_OFF(23), \ + UNW_VR_OFF(24), \ + UNW_VR_OFF(25), \ + UNW_VR_OFF(26), \ + UNW_VR_OFF(27), \ + UNW_VR_OFF(28), \ + UNW_VR_OFF(29), \ + UNW_VR_OFF(30), \ + UNW_VR_OFF(31) + +#if defined(UNW_TARGET_PPC32) + UNW_PPC_REGS(32), + UNW_PPC32_REGS, +#else + UNW_PPC_REGS(64), + UNW_PPC64_REGS, +#endif + +#elif defined(UNW_TARGET_ARM) +#if defined(__linux__) || defined(__FreeBSD__) + [UNW_ARM_R0] = 0x00, + [UNW_ARM_R1] = 0x04, + [UNW_ARM_R2] = 0x08, + [UNW_ARM_R3] = 0x0c, + [UNW_ARM_R4] = 0x10, + [UNW_ARM_R5] = 0x14, + [UNW_ARM_R6] = 0x18, + [UNW_ARM_R7] = 0x1c, + [UNW_ARM_R8] = 0x20, + [UNW_ARM_R9] = 0x24, + [UNW_ARM_R10] = 0x28, + [UNW_ARM_R11] = 0x2c, + [UNW_ARM_R12] = 0x30, + [UNW_ARM_R13] = 0x34, + [UNW_ARM_R14] = 0x38, + [UNW_ARM_R15] = 0x3c, +#else +#error Fix me +#endif +#elif defined(UNW_TARGET_MIPS) + [UNW_MIPS_R0] = 0, + [UNW_MIPS_R1] = 1, + [UNW_MIPS_R2] = 2, + [UNW_MIPS_R3] = 3, + [UNW_MIPS_R4] = 4, + [UNW_MIPS_R5] = 5, + [UNW_MIPS_R6] = 6, + [UNW_MIPS_R7] = 7, + [UNW_MIPS_R8] = 8, + [UNW_MIPS_R9] = 9, + [UNW_MIPS_R10] = 10, + [UNW_MIPS_R11] = 11, + [UNW_MIPS_R12] = 12, + [UNW_MIPS_R13] = 13, + [UNW_MIPS_R14] = 14, + [UNW_MIPS_R15] = 15, + [UNW_MIPS_R16] = 16, + [UNW_MIPS_R17] = 17, + [UNW_MIPS_R18] = 18, + [UNW_MIPS_R19] = 19, + [UNW_MIPS_R20] = 20, + [UNW_MIPS_R21] = 21, + [UNW_MIPS_R22] = 22, + [UNW_MIPS_R23] = 23, + [UNW_MIPS_R24] = 24, + [UNW_MIPS_R25] = 25, + [UNW_MIPS_R26] = 26, + [UNW_MIPS_R27] = 27, + [UNW_MIPS_R28] = 28, + [UNW_MIPS_R29] = 29, + [UNW_MIPS_R30] = 30, + [UNW_MIPS_R31] = 31, + [UNW_MIPS_PC] = 64, +#elif defined(UNW_TARGET_SH) +#elif defined(UNW_TARGET_AARCH64) + [UNW_AARCH64_X0] = 0x00, + [UNW_AARCH64_X1] = 0x08, + [UNW_AARCH64_X2] = 0x10, + [UNW_AARCH64_X3] = 0x18, + [UNW_AARCH64_X4] = 0x20, + [UNW_AARCH64_X5] = 0x28, + [UNW_AARCH64_X6] = 0x30, + [UNW_AARCH64_X7] = 0x38, + [UNW_AARCH64_X8] = 0x40, + [UNW_AARCH64_X9] = 0x48, + [UNW_AARCH64_X10] = 0x50, + [UNW_AARCH64_X11] = 0x58, + [UNW_AARCH64_X12] = 0x60, + [UNW_AARCH64_X13] = 0x68, + [UNW_AARCH64_X14] = 0x70, + [UNW_AARCH64_X15] = 0x78, + [UNW_AARCH64_X16] = 0x80, + [UNW_AARCH64_X17] = 0x88, + [UNW_AARCH64_X18] = 0x90, + [UNW_AARCH64_X19] = 0x98, + [UNW_AARCH64_X20] = 0xa0, + [UNW_AARCH64_X21] = 0xa8, + [UNW_AARCH64_X22] = 0xb0, + [UNW_AARCH64_X23] = 0xb8, + [UNW_AARCH64_X24] = 0xc0, + [UNW_AARCH64_X25] = 0xc8, + [UNW_AARCH64_X26] = 0xd0, + [UNW_AARCH64_X27] = 0xd8, + [UNW_AARCH64_X28] = 0xe0, + [UNW_AARCH64_X29] = 0xe8, + [UNW_AARCH64_X30] = 0xf0, + [UNW_AARCH64_SP] = 0xf8, + [UNW_AARCH64_PC] = 0x100, + [UNW_AARCH64_PSTATE] = 0x108 +#elif defined(UNW_TARGET_S390X) + [UNW_S390X_R0] = 0x10, + [UNW_S390X_R1] = 0x18, + [UNW_S390X_R2] = 0x20, + [UNW_S390X_R3] = 0x28, + [UNW_S390X_R4] = 0x30, + [UNW_S390X_R5] = 0x38, + [UNW_S390X_R6] = 0x40, + [UNW_S390X_R7] = 0x48, + [UNW_S390X_R8] = 0x50, + [UNW_S390X_R9] = 0x58, + [UNW_S390X_R10] = 0x60, + [UNW_S390X_R11] = 0x68, + [UNW_S390X_R12] = 0x70, + [UNW_S390X_R13] = 0x78, + [UNW_S390X_R14] = 0x80, + [UNW_S390X_R15] = 0x88, + [UNW_S390X_F0] = 0xe0, + [UNW_S390X_F1] = 0xe8, + [UNW_S390X_F2] = 0xf0, + [UNW_S390X_F3] = 0xf8, + [UNW_S390X_F4] = 0x100, + [UNW_S390X_F5] = 0x108, + [UNW_S390X_F6] = 0x110, + [UNW_S390X_F7] = 0x118, + [UNW_S390X_F8] = 0x120, + [UNW_S390X_F9] = 0x128, + [UNW_S390X_F10] = 0x130, + [UNW_S390X_F11] = 0x138, + [UNW_S390X_F12] = 0x140, + [UNW_S390X_F13] = 0x148, + [UNW_S390X_F14] = 0x150, + [UNW_S390X_F15] = 0x150, + [UNW_S390X_IP] = 0x08 +#elif defined(UNW_TARGET_RISCV) + +#if __riscv_xlen == 64 +# define RISCV_REG_OFFSET(x) (8*x) +#elif __riscv_xlen == 32 +# define RISCV_REG_OFFSET(x) (4*x) +#else +# error "Unsupported address size" +#endif + [UNW_RISCV_PC] = RISCV_REG_OFFSET(0), + [UNW_RISCV_X1] = RISCV_REG_OFFSET(1), + [UNW_RISCV_X2] = RISCV_REG_OFFSET(2), + [UNW_RISCV_X3] = RISCV_REG_OFFSET(3), + [UNW_RISCV_X4] = RISCV_REG_OFFSET(4), + [UNW_RISCV_X5] = RISCV_REG_OFFSET(5), + [UNW_RISCV_X6] = RISCV_REG_OFFSET(6), + [UNW_RISCV_X7] = RISCV_REG_OFFSET(7), + [UNW_RISCV_X8] = RISCV_REG_OFFSET(8), + [UNW_RISCV_X9] = RISCV_REG_OFFSET(9), + [UNW_RISCV_X10] = RISCV_REG_OFFSET(10), + [UNW_RISCV_X11] = RISCV_REG_OFFSET(11), + [UNW_RISCV_X12] = RISCV_REG_OFFSET(12), + [UNW_RISCV_X13] = RISCV_REG_OFFSET(13), + [UNW_RISCV_X14] = RISCV_REG_OFFSET(14), + [UNW_RISCV_X15] = RISCV_REG_OFFSET(15), + [UNW_RISCV_X16] = RISCV_REG_OFFSET(16), + [UNW_RISCV_X17] = RISCV_REG_OFFSET(17), + [UNW_RISCV_X18] = RISCV_REG_OFFSET(18), + [UNW_RISCV_X19] = RISCV_REG_OFFSET(19), + [UNW_RISCV_X20] = RISCV_REG_OFFSET(20), + [UNW_RISCV_X21] = RISCV_REG_OFFSET(21), + [UNW_RISCV_X22] = RISCV_REG_OFFSET(22), + [UNW_RISCV_X23] = RISCV_REG_OFFSET(23), + [UNW_RISCV_X24] = RISCV_REG_OFFSET(24), + [UNW_RISCV_X25] = RISCV_REG_OFFSET(25), + [UNW_RISCV_X26] = RISCV_REG_OFFSET(26), + [UNW_RISCV_X27] = RISCV_REG_OFFSET(27), + [UNW_RISCV_X28] = RISCV_REG_OFFSET(28), + [UNW_RISCV_X29] = RISCV_REG_OFFSET(29), + [UNW_RISCV_X30] = RISCV_REG_OFFSET(30), + [UNW_RISCV_X31] = RISCV_REG_OFFSET(31), +#elif defined(UNW_TARGET_LOONGARCH64) +# include + + [UNW_LOONGARCH64_R0] = LOONGARCH_EF_R0, + [UNW_LOONGARCH64_R1] = LOONGARCH_EF_R1, + [UNW_LOONGARCH64_R2] = LOONGARCH_EF_R2, + [UNW_LOONGARCH64_R3] = LOONGARCH_EF_R3, + [UNW_LOONGARCH64_R4] = LOONGARCH_EF_R4, + [UNW_LOONGARCH64_R5] = LOONGARCH_EF_R5, + [UNW_LOONGARCH64_R6] = LOONGARCH_EF_R6, + [UNW_LOONGARCH64_R7] = LOONGARCH_EF_R7, + [UNW_LOONGARCH64_R8] = LOONGARCH_EF_R8, + [UNW_LOONGARCH64_R9] = LOONGARCH_EF_R9, + [UNW_LOONGARCH64_R10] = LOONGARCH_EF_R10, + [UNW_LOONGARCH64_R11] = LOONGARCH_EF_R11, + [UNW_LOONGARCH64_R12] = LOONGARCH_EF_R12, + [UNW_LOONGARCH64_R13] = LOONGARCH_EF_R13, + [UNW_LOONGARCH64_R14] = LOONGARCH_EF_R14, + [UNW_LOONGARCH64_R15] = LOONGARCH_EF_R15, + [UNW_LOONGARCH64_R16] = LOONGARCH_EF_R16, + [UNW_LOONGARCH64_R17] = LOONGARCH_EF_R17, + [UNW_LOONGARCH64_R18] = LOONGARCH_EF_R18, + [UNW_LOONGARCH64_R19] = LOONGARCH_EF_R19, + [UNW_LOONGARCH64_R20] = LOONGARCH_EF_R20, + [UNW_LOONGARCH64_R21] = LOONGARCH_EF_R21, + [UNW_LOONGARCH64_R22] = LOONGARCH_EF_R22, + [UNW_LOONGARCH64_R23] = LOONGARCH_EF_R23, + [UNW_LOONGARCH64_R24] = LOONGARCH_EF_R24, + [UNW_LOONGARCH64_R25] = LOONGARCH_EF_R25, + [UNW_LOONGARCH64_R26] = LOONGARCH_EF_R26, + [UNW_LOONGARCH64_R27] = LOONGARCH_EF_R27, + [UNW_LOONGARCH64_R28] = LOONGARCH_EF_R28, + [UNW_LOONGARCH64_R29] = LOONGARCH_EF_R29, + [UNW_LOONGARCH64_R30] = LOONGARCH_EF_R30, + [UNW_LOONGARCH64_R31] = LOONGARCH_EF_R31, + [UNW_LOONGARCH64_PC] = LOONGARCH_EF_CSR_ERA +#else +# error Fix me. +#endif + }; diff --git a/vendor/libunwind/src/ptrace/_UPT_resume.c b/vendor/libunwind/src/ptrace/_UPT_resume.c new file mode 100644 index 0000000000..9ca5224cd8 --- /dev/null +++ b/vendor/libunwind/src/ptrace/_UPT_resume.c @@ -0,0 +1,42 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "_UPT_internal.h" + +int +_UPT_resume (unw_addr_space_t as UNUSED, unw_cursor_t *c UNUSED, void *arg) +{ + struct UPT_info *ui = arg; + + mi_init (); + +#ifdef HAVE_TTRACE +# warning No support for ttrace() yet. +#elif HAVE_DECL_PTRACE_CONT + return ptrace (PTRACE_CONT, ui->pid, 0, 0); +#elif HAVE_DECL_PT_CONTINUE + return ptrace(PT_CONTINUE, ui->pid, (caddr_t)1, 0); +#endif +}