diff --git a/add-loongarch-support-not-upstream-modified.patch b/add-loongarch-support-not-upstream-modified.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e9451baf33f1100569073c1bf694a75f9c4b36f --- /dev/null +++ b/add-loongarch-support-not-upstream-modified.patch @@ -0,0 +1,476 @@ +From 8ef1866b4ff653857564e004d1b7bb12d536b20c Mon Sep 17 00:00:00 2001 +From: herengui +Date: Mon, 28 Aug 2023 16:12:18 +0800 +Subject: [PATCH 1/2] libunwind add loongarch64 support + +Signed-off-by: herengui +--- + Makefile.am | 6 +++++ + README | 2 ++ + config/config.guess | 3 +++ + config/config.sub | 1 + + configure.ac | 7 +++-- + include/libunwind.h | 4 ++- + include/libunwind.h.in | 2 ++ + include/tdep/dwarf-config.h | 2 ++ + include/tdep/jmpbuf.h | 2 ++ + include/tdep/libunwind_i.h | 4 ++- + include/tdep/libunwind_i.h.in | 2 ++ + src/Makefile.am | 38 ++++++++++++++++++++++++++++ + src/coredump/_UCD_access_reg_linux.c | 37 +++++++++++++++++++++++++++ + src/ptrace/_UPT_reg_offset.c | 26 +++++++++++++++++++ + tests/Makefile.am | 4 +++ + tests/Makefile.in | 4 +++ + tests/check-namespace.sh.in | 21 ++++++++++++++- + tests/run-coredump-unwind | 1 + + 18 files changed, 161 insertions(+), 5 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 9bb2413..3b7566f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -44,6 +44,9 @@ endif + if ARCH_S390X + include_HEADERS += include/libunwind-s390x.h + endif ++if ARCH_LOONGARCH64 ++include_HEADERS += include/libunwind-loongarch64.h ++endif + if ARCH_RISCV + include_HEADERS += include/libunwind-riscv.h + endif +@@ -79,6 +82,9 @@ noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ + include/tdep-ia64/libunwind_i.h include/tdep-ia64/script.h \ + include/tdep-hppa/libunwind_i.h \ + include/tdep-hppa/jmpbuf.h include/tdep-hppa/dwarf-config.h \ ++ include/tdep-loongarch64/dwarf-config.h \ ++ include/tdep-loongarch64/jmpbuf.h \ ++ include/tdep-loongarch64/libunwind_i.h \ + include/tdep-mips/libunwind_i.h \ + include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \ + include/tdep-tilegx/libunwind_i.h \ +diff --git a/README b/README +index 9427144..9d0e30d 100644 +--- a/README ++++ b/README +@@ -16,6 +16,7 @@ This library supports several architecture/operating-system combinations: + | Linux | IA-64 | ✓ | + | Linux | PARISC | Works well, but C library missing unwind-info | + | Linux | Tilegx | 64-bit mode only | ++| Linux | LoongArch | 64-bit only | + | Linux | MIPS | Newly added | + | Linux | RISC-V | 64-bit only | + | HP-UX | IA-64 | Mostly works, but known to have serious limitations | +@@ -41,6 +42,7 @@ such dependencies + | arm | p | | + | hppa | p | p | + | ia64 | p | r | ++| loongarch | p | | + | mips | p | | + | ppc32 | r | | + | ppc64 | r | r | +diff --git a/config/config.guess b/config/config.guess +index f50dcdb..49cd5b2 100755 +--- a/config/config.guess ++++ b/config/config.guess +@@ -964,6 +964,9 @@ EOF + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; ++ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; +diff --git a/config/config.sub b/config/config.sub +index 1d8e98b..92eca01 100755 +--- a/config/config.sub ++++ b/config/config.sub +@@ -265,6 +265,7 @@ case $basic_machine in + | k1om \ + | le32 | le64 \ + | lm32 \ ++ | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ +diff --git a/configure.ac b/configure.ac +index 2893f0c..5e450b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -97,6 +97,7 @@ AC_DEFUN([SET_ARCH],[ + [sh*],[$2=sh], + [amd64],[$2=x86_64], + [tile*],[$2=tilegx], ++ [loongarch64*],[$2=loongarch64], + [riscv*],[$2=riscv], + [$2=$1]) + ]) dnl SET_ARCH +@@ -120,7 +121,7 @@ esac + + AC_ARG_ENABLE(coredump, + AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),, +- [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|riscv*], [enable_coredump=yes], [enable_coredump=no])] ++ [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|loongarch64], [enable_coredump=yes], [enable_coredump=no])] + ) + + AC_MSG_CHECKING([if we should build libunwind-coredump]) +@@ -180,6 +181,7 @@ AM_CONDITIONAL(ARCH_AARCH64, test x$target_arch = xaarch64) + AM_CONDITIONAL(ARCH_ARM, test x$target_arch = xarm) + AM_CONDITIONAL(ARCH_IA64, test x$target_arch = xia64) + AM_CONDITIONAL(ARCH_HPPA, test x$target_arch = xhppa) ++AM_CONDITIONAL(ARCH_LOONGARCH64, test x$target_arch = xloongarch64) + AM_CONDITIONAL(ARCH_MIPS, test x$target_arch = xmips) + AM_CONDITIONAL(ARCH_X86, test x$target_arch = xx86) + AM_CONDITIONAL(ARCH_X86_64, test x$target_arch = xx86_64) +@@ -199,7 +201,7 @@ AC_MSG_CHECKING([for ELF helper width]) + case "${target_arch}" in + (arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);; + (aarch64|ia64|ppc64|x86_64|s390x|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);; +-(mips|riscv) use_elfxx=yes; AC_MSG_RESULT([xx]);; ++(mips|riscv|loongarch64) use_elfxx=yes; AC_MSG_RESULT([xx]);; + *) AC_MSG_ERROR([Unknown ELF target: ${target_arch}]) + esac + AM_CONDITIONAL(USE_ELF32, [test x$use_elf32 = xyes]) +@@ -245,6 +247,7 @@ case $target_arch in + arm*) enable_cxx_exceptions=no;; + mips*) enable_cxx_exceptions=no;; + tile*) enable_cxx_exceptions=no;; ++ loongarch*) enable_cxx_exceptions=no;; + s390x*) enable_cxx_exceptions=no;; + *) enable_cxx_exceptions=yes;; + esac +diff --git a/include/libunwind.h b/include/libunwind.h +index 40f485d..421d601 100644 +--- a/include/libunwind.h ++++ b/include/libunwind.h +@@ -27,6 +27,8 @@ + # include "libunwind-tilegx.h" + #elif defined __s390x__ + # include "libunwind-s390x.h" ++#elif defined __loongarch64 ++# include "libunwind-loongarch64.h" + #elif defined __riscv || defined __riscv__ + # include "libunwind-riscv.h" + #else +@@ -35,6 +37,6 @@ + + #else /* UNW_REMOTE_ONLY */ + +-# include "libunwind-x86_64.h" ++# include "libunwind-loongarch64.h" + + #endif /* UNW_REMOTE_ONLY */ +diff --git a/include/libunwind.h.in b/include/libunwind.h.in +index dfea766..1ba5401 100644 +--- a/include/libunwind.h.in ++++ b/include/libunwind.h.in +@@ -27,6 +27,8 @@ + # include "libunwind-tilegx.h" + #elif defined __s390x__ + # include "libunwind-s390x.h" ++#elif defined __loongarch64 ++# include "libunwind-loongarch64.h" + #elif defined __riscv || defined __riscv__ + # include "libunwind-riscv.h" + #else +diff --git a/include/tdep/dwarf-config.h b/include/tdep/dwarf-config.h +index 0cfd079..d367756 100644 +--- a/include/tdep/dwarf-config.h ++++ b/include/tdep/dwarf-config.h +@@ -25,6 +25,8 @@ + # include "tdep-x86_64/dwarf-config.h" + #elif defined __tilegx__ + # include "tdep-tilegx/dwarf-config.h" ++#elif defined __loongarch64 ++# include "tdep-loongarch64/dwarf-config.h" + #elif defined __riscv || defined __riscv__ + # include "tdep-riscv/dwarf-config.h" + #else +diff --git a/include/tdep/jmpbuf.h b/include/tdep/jmpbuf.h +index 77d35c3..22d9f26 100644 +--- a/include/tdep/jmpbuf.h ++++ b/include/tdep/jmpbuf.h +@@ -23,6 +23,8 @@ + # include "tdep-x86_64/jmpbuf.h" + #elif defined __tilegx__ + # include "tdep-tilegx/jmpbuf.h" ++#elif defined __loongarch64 ++# include "tdep-loongarch64/jmpbuf.h" + #elif defined __riscv || defined __riscv__ + # include "tdep-riscv/jmpbuf.h" + #else +diff --git a/include/tdep/libunwind_i.h b/include/tdep/libunwind_i.h +index efd4f87..bfb89bf 100644 +--- a/include/tdep/libunwind_i.h ++++ b/include/tdep/libunwind_i.h +@@ -27,6 +27,8 @@ + # include "tdep-tilegx/libunwind_i.h" + #elif defined __s390x__ + # include "tdep-s390x/libunwind_i.h" ++#elif defined __loongarch64 ++# include "tdep-loongarch64/libunwind_i.h" + #elif defined __riscv || defined __riscv__ + # include "tdep-riscv/libunwind_i.h" + #else +@@ -36,6 +38,6 @@ + + #else /* UNW_REMOTE_ONLY */ + +-# include "tdep-x86_64/libunwind_i.h" ++# include "tdep-loongarch64/libunwind_i.h" + + #endif /* UNW_REMOTE_ONLY */ +diff --git a/include/tdep/libunwind_i.h.in b/include/tdep/libunwind_i.h.in +index a40f7cf..1e0a247 100644 +--- a/include/tdep/libunwind_i.h.in ++++ b/include/tdep/libunwind_i.h.in +@@ -27,6 +27,8 @@ + # include "tdep-tilegx/libunwind_i.h" + #elif defined __s390x__ + # include "tdep-s390x/libunwind_i.h" ++#elif defined __loongarch64 ++# include "tdep-loongarch64/libunwind_i.h" + #elif defined __riscv || defined __riscv__ + # include "tdep-riscv/libunwind_i.h" + #else +diff --git a/src/Makefile.am b/src/Makefile.am +index 2b5b029..9afd58f 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -360,6 +360,31 @@ libunwind_riscv_la_SOURCES_riscv = $(libunwind_la_SOURCES_riscv_common) \ + riscv/Gglobal.c riscv/Ginit.c riscv/Ginit_local.c riscv/Ginit_remote.c \ + riscv/Gis_signal_frame.c riscv/Gregs.c riscv/Gresume.c riscv/Gstep.c + ++# The list of files that go info libunwind and libunwind-loongarch64: ++noinst_HEADERS += loongarch64/init.h loongarch64/offsets.h loongarch64/unwind_i.h ++libunwind_la_SOURCES_loongarch64_common = $(libunwind_la_SOURCES_common) \ ++ loongarch64/is_fpreg.c loongarch64/regname.c ++ ++# The list of files that go into libunwind: ++libunwind_la_SOURCES_loongarch64 = $(libunwind_la_SOURCES_loongarch64_common) \ ++ $(libunwind_la_SOURCES_local) \ ++ loongarch64/getcontext.S \ ++ loongarch64/Lapply_reg_state.c loongarch64/Lreg_states_iterate.c \ ++ loongarch64/Lcreate_addr_space.c loongarch64/Lget_proc_info.c \ ++ loongarch64/Lget_save_loc.c loongarch64/Lglobal.c loongarch64/Linit.c \ ++ loongarch64/Linit_local.c loongarch64/Linit_remote.c \ ++ loongarch64/Lis_signal_frame.c loongarch64/Lregs.c \ ++ loongarch64/Lresume.c loongarch64/Lstep.c ++ ++libunwind_loongarch64_la_SOURCES_loongarch64 = $(libunwind_la_SOURCES_loongarch64_common) \ ++ $(libunwind_la_SOURCES_generic) \ ++ loongarch64/Gapply_reg_state.c loongarch64/Greg_states_iterate.c \ ++ loongarch64/Gcreate_addr_space.c loongarch64/Gget_proc_info.c \ ++ loongarch64/Gget_save_loc.c loongarch64/Gglobal.c loongarch64/Ginit.c \ ++ loongarch64/Ginit_local.c loongarch64/Ginit_remote.c \ ++ loongarch64/Gis_signal_frame.c loongarch64/Gregs.c \ ++ loongarch64/Gresume.c loongarch64/Gstep.c ++ + # The list of files that go both into libunwind and libunwind-x86: + noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h + libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ +@@ -662,6 +687,18 @@ if !REMOTE_ONLY + endif + libunwind_setjmp_la_SOURCES += tilegx/siglongjmp.S + else ++if ARCH_LOONGARCH64 ++ lib_LTLIBRARIES += libunwind-loongarch64.la ++ libunwind_la_SOURCES = $(libunwind_la_SOURCES_loongarch64) ++ libunwind_loongarch64_la_SOURCES = $(libunwind_loongarch64_la_SOURCES_loongarch64) ++ libunwind_loongarch64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) ++ libunwind_loongarch64_la_LIBADD = libunwind-dwarf-generic.la ++ libunwind_loongarch64_la_LIBADD += libunwind-elf64.la ++if !REMOTE_ONLY ++ libunwind_loongarch64_la_LIBADD += libunwind.la -lc ++endif ++ libunwind_setjmp_la_SOURCES += loongarch64/siglongjmp.S ++else + if ARCH_RISCV + lib_LTLIBRARIES += libunwind-riscv.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_riscv) +@@ -752,6 +789,7 @@ endif # ARCH_PPC32 + endif # ARCH_X86_64 + endif # ARCH_X86 + endif # ARCH_RISCV ++endif # ARCH_LOONGARCH64 + endif # ARCH_TILEGX + endif # ARCH_MIPS + endif # ARCH_HPPA +diff --git a/src/coredump/_UCD_access_reg_linux.c b/src/coredump/_UCD_access_reg_linux.c +index 27eef12..f22d164 100644 +--- a/src/coredump/_UCD_access_reg_linux.c ++++ b/src/coredump/_UCD_access_reg_linux.c +@@ -57,6 +57,43 @@ _UCD_access_reg (unw_addr_space_t as, + #elif defined(UNW_TARGET_S390X) + if (regnum > UNW_S390X_R15) + goto badreg; ++#elif defined(UNW_TARGET_LOONGARCH64) ++# include ++ ++ static const uint8_t remap_regs[] = ++ { ++ [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_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, ++ }; + #elif defined(UNW_TARGET_IA64) || defined(UNW_TARGET_HPPA) || defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64) + if (regnum >= ARRAY_SIZE(ui->prstatus->pr_reg)) + goto badreg; +diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c +index b7dd3b7..80a072e 100644 +--- a/src/ptrace/_UPT_reg_offset.c ++++ b/src/ptrace/_UPT_reg_offset.c +@@ -713,6 +713,32 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] = + [UNW_S390X_F14] = 0x150, + [UNW_S390X_F15] = 0x150, + [UNW_S390X_IP] = 0x08 ++#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, + #elif defined(UNW_TARGET_RISCV) + + #if __riscv_xlen == 64 +diff --git a/tests/Makefile.am b/tests/Makefile.am +index c783fc3..b513c72 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -120,6 +120,10 @@ if ARCH_RISCV + XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) + endif + ++if ARCH_LOONGARCH64 ++XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) ++endif ++ + if ARCH_ARM + # ARM Linux kernel >=2.6.39 removed PTRACE_SINGLESTEP emulation + XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) +diff --git a/tests/Makefile.in b/tests/Makefile.in +index 6b4587b..359f815 100644 +--- a/tests/Makefile.in ++++ b/tests/Makefile.in +@@ -136,6 +136,10 @@ XFAIL_TESTS = $(am__append_17) $(am__append_18) $(am__append_19) \ + # ptrace gives EBADREG when testing, + # but generally everything else works. + @NO_PTRACE_TEST_TRUE@am__append_20 = run-ptrace-mapper test-ptrace Ltest-init-local-signal ++ ++XFAIL_TESTS = $(am__append_20) ++@ARCH_LOONGARCH64_TRUE@am__append_20 = $(XFAIL_TESTS_PTRACE_SINGLESTEP) ++ + noinst_PROGRAMS = $(am__EXEEXT_11) $(am__EXEEXT_15) $(am__EXEEXT_18) + subdir = tests + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in +index f9201a2..3291c8a 100644 +--- a/tests/check-namespace.sh.in ++++ b/tests/check-namespace.sh.in +@@ -86,6 +86,13 @@ filter_misc () { + ignore _gp + fi + ++ if [ ${plat} = "loongarch64" ]; then ++ ignore _fbss ++ ignore _fdata ++ ignore _ftext ++ ignore _gp ++ fi ++ + if [ ${os} == "solaris2.11" ]; then + ignore _PROCEDURE_LINKAGE_TABLE_ + ignore _etext +@@ -189,7 +196,12 @@ check_local_unw_abi () { + match _UL${plat}_dwarf_find_unwind_table + match _U${plat}_setcontext + ;; +- ++ loongarch64) ++ match _U${plat}_getcontext ++ match _U${plat}_is_fpreg ++ match _UL${plat}_dwarf_search_unwind_table ++ match _UL${plat}_dwarf_find_unwind_table ++ ;; + *) + match _U${plat}_is_fpreg + match _UL${plat}_dwarf_search_unwind_table +@@ -303,6 +315,13 @@ check_generic_unw_abi () { + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; ++ loongarch64) ++ match _U${plat}_get_elf_image ++ match _U${plat}_get_exe_image_path ++ match _U${plat}_is_fpreg ++ match _U${plat}_dwarf_search_unwind_table ++ match _U${plat}_dwarf_find_unwind_table ++ ;; + *) + match _U${plat}_is_fpreg + match _U${plat}_dwarf_search_unwind_table +diff --git a/tests/run-coredump-unwind b/tests/run-coredump-unwind +index 0c2b28c..690362b 100755 +--- a/tests/run-coredump-unwind ++++ b/tests/run-coredump-unwind +@@ -22,6 +22,7 @@ add_minidebug() + comm -13 "$dynsyms" "$funcsyms" > "$keep_symbols" + # Copy the full debuginfo, keeping only a minumal set of symbols and removing some unnecessary sections + objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols="$keep_symbols" "$debuginfo" "$mini_debuginfo" &> /dev/null ++ wait + #Inject the compressed data into the .gnu_debugdata section of the original binary + xz "$mini_debuginfo" + mini_debuginfo="${mini_debuginfo}.xz" +-- +2.41.0 + diff --git a/add-loongarch-support-not-upstream-new.patch b/add-loongarch-support-not-upstream-new.patch new file mode 100644 index 0000000000000000000000000000000000000000..0c44ecc8ec828ec31474342396604db0592ac61e --- /dev/null +++ b/add-loongarch-support-not-upstream-new.patch @@ -0,0 +1,2523 @@ +From c00817efd9ced15a917b8ab429a42f5b4297840b Mon Sep 17 00:00:00 2001 +From: herengui +Date: Mon, 28 Aug 2023 16:12:50 +0800 +Subject: [PATCH 2/2] libunwind loongarch64 architecture resources + +Signed-off-by: herengui +--- + include/libunwind-loongarch64.h | 139 ++++++++ + include/tdep-loongarch64/dwarf-config.h | 59 ++++ + include/tdep-loongarch64/jmpbuf.h | 34 ++ + include/tdep-loongarch64/libunwind_i.h | 250 +++++++++++++++ + src/loongarch64/Gapply_reg_state.c | 37 +++ + src/loongarch64/Gcreate_addr_space.c | 52 +++ + src/loongarch64/Gget_proc_info.c | 44 +++ + src/loongarch64/Gget_save_loc.c | 101 ++++++ + src/loongarch64/Gglobal.c | 58 ++++ + src/loongarch64/Ginit.c | 405 ++++++++++++++++++++++++ + src/loongarch64/Ginit_local.c | 80 +++++ + src/loongarch64/Ginit_remote.c | 56 ++++ + src/loongarch64/Gis_signal_frame.c | 71 +++++ + src/loongarch64/Greg_states_iterate.c | 37 +++ + src/loongarch64/Gregs.c | 109 +++++++ + src/loongarch64/Gresume.c | 126 ++++++++ + src/loongarch64/Gstep.c | 144 +++++++++ + src/loongarch64/Lapply_reg_state.c | 5 + + src/loongarch64/Lcreate_addr_space.c | 5 + + src/loongarch64/Lget_proc_info.c | 5 + + src/loongarch64/Lget_save_loc.c | 5 + + src/loongarch64/Lglobal.c | 5 + + src/loongarch64/Linit.c | 5 + + src/loongarch64/Linit_local.c | 5 + + src/loongarch64/Linit_remote.c | 5 + + src/loongarch64/Lis_signal_frame.c | 5 + + src/loongarch64/Lreg_states_iterate.c | 5 + + src/loongarch64/Lregs.c | 5 + + src/loongarch64/Lresume.c | 5 + + src/loongarch64/Lstep.c | 5 + + src/loongarch64/getcontext.S | 61 ++++ + src/loongarch64/init.h | 64 ++++ + src/loongarch64/is_fpreg.c | 35 ++ + src/loongarch64/offsets.h | 50 +++ + src/loongarch64/regname.c | 50 +++ + src/loongarch64/siglongjmp.S | 8 + + src/loongarch64/unwind_i.h | 43 +++ + 37 files changed, 2178 insertions(+) + create mode 100644 include/libunwind-loongarch64.h + create mode 100644 include/tdep-loongarch64/dwarf-config.h + create mode 100644 include/tdep-loongarch64/jmpbuf.h + create mode 100644 include/tdep-loongarch64/libunwind_i.h + create mode 100644 src/loongarch64/Gapply_reg_state.c + create mode 100644 src/loongarch64/Gcreate_addr_space.c + create mode 100644 src/loongarch64/Gget_proc_info.c + create mode 100644 src/loongarch64/Gget_save_loc.c + create mode 100644 src/loongarch64/Gglobal.c + create mode 100644 src/loongarch64/Ginit.c + create mode 100644 src/loongarch64/Ginit_local.c + create mode 100644 src/loongarch64/Ginit_remote.c + create mode 100644 src/loongarch64/Gis_signal_frame.c + create mode 100644 src/loongarch64/Greg_states_iterate.c + create mode 100644 src/loongarch64/Gregs.c + create mode 100644 src/loongarch64/Gresume.c + create mode 100644 src/loongarch64/Gstep.c + create mode 100644 src/loongarch64/Lapply_reg_state.c + create mode 100644 src/loongarch64/Lcreate_addr_space.c + create mode 100644 src/loongarch64/Lget_proc_info.c + create mode 100644 src/loongarch64/Lget_save_loc.c + create mode 100644 src/loongarch64/Lglobal.c + create mode 100644 src/loongarch64/Linit.c + create mode 100644 src/loongarch64/Linit_local.c + create mode 100644 src/loongarch64/Linit_remote.c + create mode 100644 src/loongarch64/Lis_signal_frame.c + create mode 100644 src/loongarch64/Lreg_states_iterate.c + create mode 100644 src/loongarch64/Lregs.c + create mode 100644 src/loongarch64/Lresume.c + create mode 100644 src/loongarch64/Lstep.c + create mode 100644 src/loongarch64/getcontext.S + create mode 100644 src/loongarch64/init.h + create mode 100644 src/loongarch64/is_fpreg.c + create mode 100644 src/loongarch64/offsets.h + create mode 100644 src/loongarch64/regname.c + create mode 100644 src/loongarch64/siglongjmp.S + create mode 100644 src/loongarch64/unwind_i.h + +diff --git a/include/libunwind-loongarch64.h b/include/libunwind-loongarch64.h +new file mode 100644 +index 0000000..eb4cfd8 +--- /dev/null ++++ b/include/libunwind-loongarch64.h +@@ -0,0 +1,139 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2001-2004 Hewlett-Packard Co ++ Contributed by David Mosberger-Tang ++ Copyright (C) 2021 Loongson Technology Corporation 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. */ ++ ++#ifndef LIBUNWIND_H ++#define LIBUNWIND_H ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++extern "C" { ++#endif ++ ++#include ++#include ++ ++#define UNW_TARGET loongarch64 ++#define UNW_TARGET_LOONGARCH64 1 ++ ++#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ ++ ++/* This needs to be big enough to accommodate "struct cursor", while ++ leaving some slack for future expansion. Changing this value will ++ require recompiling all users of this library. Stack allocation is ++ relatively cheap and unwind-state copying is relatively rare, so we ++ want to err on making it rather too big than too small. */ ++ ++/* FIXME for LoongArch64. Too big? What do other things use for similar tasks? */ ++#define UNW_TDEP_CURSOR_LEN 4096 ++ ++typedef uint64_t unw_word_t; ++typedef int64_t unw_sword_t; ++ ++typedef long double unw_tdep_fpreg_t; ++ ++typedef enum ++ { ++ UNW_LOONGARCH64_R0, ++ UNW_LOONGARCH64_R1, ++ UNW_LOONGARCH64_R2, ++ UNW_LOONGARCH64_R3, ++ UNW_LOONGARCH64_R4, ++ UNW_LOONGARCH64_R5, ++ UNW_LOONGARCH64_R6, ++ UNW_LOONGARCH64_R7, ++ UNW_LOONGARCH64_R8, ++ UNW_LOONGARCH64_R9, ++ UNW_LOONGARCH64_R10, ++ UNW_LOONGARCH64_R11, ++ UNW_LOONGARCH64_R12, ++ UNW_LOONGARCH64_R13, ++ UNW_LOONGARCH64_R14, ++ UNW_LOONGARCH64_R15, ++ UNW_LOONGARCH64_R16, ++ UNW_LOONGARCH64_R17, ++ UNW_LOONGARCH64_R18, ++ UNW_LOONGARCH64_R19, ++ UNW_LOONGARCH64_R20, ++ UNW_LOONGARCH64_R21, ++ UNW_LOONGARCH64_R22, ++ UNW_LOONGARCH64_R23, ++ UNW_LOONGARCH64_R24, ++ UNW_LOONGARCH64_R25, ++ UNW_LOONGARCH64_R26, ++ UNW_LOONGARCH64_R27, ++ UNW_LOONGARCH64_R28, ++ UNW_LOONGARCH64_R29, ++ UNW_LOONGARCH64_R30, ++ UNW_LOONGARCH64_R31, ++ ++ UNW_LOONGARCH64_PC = 33, ++ ++ /* FIXME: Other registers! */ ++ ++ /* For LoongArch64, the CFA is the value of SP (r3) at the call site in the ++ previous frame. */ ++ UNW_LOONGARCH64_CFA, ++ ++ UNW_TDEP_LAST_REG = UNW_LOONGARCH64_PC, ++ ++ UNW_TDEP_IP = UNW_LOONGARCH64_R1, ++ UNW_TDEP_SP = UNW_LOONGARCH64_R3, ++ UNW_TDEP_EH = UNW_LOONGARCH64_R0 /* FIXME. */ ++ } ++loongarch64_regnum_t; ++ ++#define UNW_TDEP_NUM_EH_REGS 4 ++ ++typedef struct unw_tdep_save_loc ++ { ++ /* Additional target-dependent info on a save location. */ ++ char unused; ++ } ++unw_tdep_save_loc_t; ++ ++/* On LoongArch64, we can directly use ucontext_t as the unwind context. */ ++typedef ucontext_t unw_tdep_context_t; ++ ++typedef struct ++ { ++ /* no loongarch64-specific auxiliary proc-info */ ++ char unused; ++ } ++unw_tdep_proc_info_t; ++ ++#include "libunwind-dynamic.h" ++#include "libunwind-common.h" ++ ++#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) ++extern int unw_tdep_getcontext (ucontext_t *uc); ++ ++#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) ++extern int unw_tdep_is_fpreg (int); ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++} ++#endif ++ ++#endif /* LIBUNWIND_H */ +\ No newline at end of file +diff --git a/include/tdep-loongarch64/dwarf-config.h b/include/tdep-loongarch64/dwarf-config.h +new file mode 100644 +index 0000000..a8b309b +--- /dev/null ++++ b/include/tdep-loongarch64/dwarf-config.h +@@ -0,0 +1,59 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2012 Tommi Rantala ++ Copyright (C) 2021 Loongson Technology Corporation 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. */ ++ ++#ifndef dwarf_config_h ++#define dwarf_config_h ++ ++/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not ++ explicitly defined. ++ Number of hardware registers. We have: ++ - 32 integer registers ++ - 32 floating point registers ++ - 8 condition code registers ++ - 2 fake registers: ++ - ARG_POINTER_REGNUM ++ - FRAME_POINTER_REGNUM */ ++#define DWARF_NUM_PRESERVED_REGS 74 ++ ++#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) ++ ++/* Not big-endian. */ ++#define dwarf_is_big_endian(addr_space) 0 ++ ++/* Convert a pointer to a dwarf_cursor structure to a pointer to ++ unw_cursor_t. */ ++#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) ++ ++typedef struct dwarf_loc ++ { ++ unw_word_t val; ++#ifndef UNW_LOCAL_ONLY ++ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ ++#endif ++ } ++dwarf_loc_t; ++ ++#endif /* dwarf_config_h */ +\ No newline at end of file +diff --git a/include/tdep-loongarch64/jmpbuf.h b/include/tdep-loongarch64/jmpbuf.h +new file mode 100644 +index 0000000..38900a9 +--- /dev/null ++++ b/include/tdep-loongarch64/jmpbuf.h +@@ -0,0 +1,34 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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. */ ++ ++/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ ++ ++/* https://github.com/loongson/glibc/blob/loongarch_2_33/sysdeps/loongarch/setjmp.S ++ https://github.com/loongson/glibc/blob/loongarch_2_33/sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h */ ++ ++#define JB_SP 1 ++#define JB_RP 0 ++#define JB_MASK_SAVED (168>>3) ++#define JB_MASK (176>>3) +\ No newline at end of file +diff --git a/include/tdep-loongarch64/libunwind_i.h b/include/tdep-loongarch64/libunwind_i.h +new file mode 100644 +index 0000000..3c2852c +--- /dev/null ++++ b/include/tdep-loongarch64/libunwind_i.h +@@ -0,0 +1,250 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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. */ ++ ++#ifndef LOONGARCH64_LIBUNWIND_I_H ++#define LOONGARCH64_LIBUNWIND_I_H ++ ++/* Target-dependent definitions that are internal to libunwind but need ++ to be shared with target-independent code. */ ++ ++#include ++#include ++#include "elf64.h" ++#include "mempool.h" ++#include "dwarf.h" ++ ++typedef struct ++ { ++ /* no loongarch64-specific fast trace */ ++ } ++unw_tdep_frame_t; ++ ++struct unw_addr_space ++ { ++ struct unw_accessors acc; ++ ++ unw_caching_policy_t caching_policy; ++ _Atomic uint32_t cache_generation; ++ unw_word_t dyn_generation; /* see dyn-common.h */ ++ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ ++ struct dwarf_rs_cache global_cache; ++ struct unw_debug_frame_list *debug_frames; ++}; ++ ++/* LoongArch64 supports only little-endian. */ ++#define tdep_big_endian(as) 0 ++ ++struct cursor ++ { ++ struct dwarf_cursor dwarf; /* must be first */ ++ ++ enum ++ { ++ LOONGARCH64_SCF_NONE, ++ LOONGARCH64_SCF_LINUX_RT_SIGFRAME, ++ } ++ sigcontext_format; ++ unw_word_t sigcontext_addr; ++ unw_word_t sigcontext_sp; ++ unw_word_t sigcontext_pc; ++ int validate; ++ ucontext_t *uc; ++ }; ++ ++static inline ucontext_t * ++dwarf_get_uc(const struct dwarf_cursor *cursor) ++{ ++ const struct cursor *c = (struct cursor *) cursor->as_arg; ++ return c->uc; ++} ++ ++#define DWARF_GET_LOC(l) ((l).val) ++ ++#ifdef UNW_LOCAL_ONLY ++# define DWARF_NULL_LOC DWARF_LOC (0, 0) ++# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) ++# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) ++# define DWARF_IS_REG_LOC(l) 0 ++# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ ++ tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) ++# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) ++# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ ++ tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) ++ ++/* FIXME: Implement these for the LoongArch64 FPU. */ ++static inline int ++dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) ++{ ++ return 0; ++} ++ ++static inline int ++dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) ++{ ++ return 0; ++} ++ ++static inline int ++dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *val = *(unw_word_t *) (intptr_t) DWARF_GET_LOC (loc); ++ return 0; ++} ++ ++static inline int ++dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *(unw_word_t *) (intptr_t) DWARF_GET_LOC (loc) = val; ++ return 0; ++} ++ ++#else /* !UNW_LOCAL_ONLY */ ++# define DWARF_LOC_TYPE_FP (1 << 0) ++# define DWARF_LOC_TYPE_REG (1 << 1) ++# define DWARF_NULL_LOC DWARF_LOC (0, 0) ++# define DWARF_IS_NULL_LOC(l) \ ++ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) ++# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) ++# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) ++# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) ++# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) ++# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) ++# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ ++ | DWARF_LOC_TYPE_FP)) ++ ++/* FIXME: Implement these for the LoongArch64 FPU. */ ++static inline int ++dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) ++{ ++ return 0; ++} ++ ++static inline int ++dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) ++{ ++ return 0; ++} ++ ++static inline int ++dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) ++{ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ /* If a code-generator were to save a value of type unw_word_t in a ++ * floating-point register, we would have to support this case. I ++ * suppose it could happen with MMX registers, but does it really ++ * happen? */ ++ assert (!DWARF_IS_FP_LOC (loc)); ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, ++ 0, c->as_arg); ++ else ++ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, ++ 0, c->as_arg); ++} ++ ++static inline int ++dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) ++{ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ /* If a code-generator were to save a value of type unw_word_t in a ++ * floating-point register, we would have to support this case. I ++ * suppose it could happen with MMX registers, but does it really ++ * happen? */ ++ assert (!DWARF_IS_FP_LOC (loc)); ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, ++ 1, c->as_arg); ++ else ++ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, ++ 1, c->as_arg); ++} ++ ++#endif /* !UNW_LOCAL_ONLY */ ++ ++#define tdep_getcontext_trace unw_getcontext ++#define tdep_init_done UNW_OBJ(init_done) ++#define tdep_init UNW_OBJ(init) ++/* Platforms that support UNW_INFO_FORMAT_TABLE need to define ++ tdep_search_unwind_table. */ ++#define tdep_search_unwind_table dwarf_search_unwind_table ++#define tdep_find_unwind_table dwarf_find_unwind_table ++#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) ++#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) ++#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) ++#define tdep_access_reg UNW_OBJ(access_reg) ++#define tdep_access_fpreg UNW_OBJ(access_fpreg) ++#define tdep_fetch_frame(c,ip,n) do {} while(0) ++#define tdep_cache_frame(c) 0 ++#define tdep_reuse_frame(c,rs) do {} while(0) ++#define tdep_stash_frame(c,rs) do {} while(0) ++#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) ++ ++#ifdef UNW_LOCAL_ONLY ++# define tdep_find_proc_info(c,ip,n) \ ++ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ ++ (c)->as_arg) ++# define tdep_put_unwind_info(as,pi,arg) \ ++ dwarf_put_unwind_info((as), (pi), (arg)) ++#else ++# define tdep_find_proc_info(c,ip,n) \ ++ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ ++ (c)->as_arg) ++# define tdep_put_unwind_info(as,pi,arg) \ ++ (*(as)->acc.put_unwind_info)((as), (pi), (arg)) ++#endif ++ ++#define tdep_get_as(c) ((c)->dwarf.as) ++#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) ++#define tdep_get_ip(c) ((c)->dwarf.ip) ++ ++extern int tdep_init_done; ++#define tdep_init_mem_validate UNW_OBJ(init_mem_validate) ++ ++extern void tdep_init (void); ++extern void tdep_init_mem_validate (void); ++extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, ++ unw_dyn_info_t *di, unw_proc_info_t *pi, ++ int need_unwind_info, void *arg); ++extern void *tdep_uc_addr (ucontext_t *uc, int reg); ++extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, ++ unsigned long *segbase, unsigned long *mapoff, ++ char *path, size_t pathlen); ++extern void tdep_get_exe_image_path (char *path); ++extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, ++ unw_word_t *valp, int write); ++extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, ++ unw_fpreg_t *valp, int write); ++ ++#endif /* LOONGARCH64_LIBUNWIND_I_H */ +\ No newline at end of file +diff --git a/src/loongarch64/Gapply_reg_state.c b/src/loongarch64/Gapply_reg_state.c +new file mode 100644 +index 0000000..9b63ac8 +--- /dev/null ++++ b/src/loongarch64/Gapply_reg_state.c +@@ -0,0 +1,37 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. ++ Contributed by David Mosberger-Tang ++ ++ Modified for x86_64 by Max Asbock ++ ++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 "unwind_i.h" ++ ++int ++unw_apply_reg_state (unw_cursor_t *cursor, ++ void *reg_states_data) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gcreate_addr_space.c b/src/loongarch64/Gcreate_addr_space.c +new file mode 100644 +index 0000000..4ede55e +--- /dev/null ++++ b/src/loongarch64/Gcreate_addr_space.c +@@ -0,0 +1,52 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 ++ ++#include "unwind_i.h" ++ ++unw_addr_space_t ++unw_create_addr_space (unw_accessors_t *a, int byte_order) ++{ ++#ifdef UNW_LOCAL_ONLY ++ return NULL; ++#else ++ unw_addr_space_t as; ++ ++ /* LoongArch64 supports only little-endian. */ ++ if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) ++ return NULL; ++ ++ as = malloc (sizeof (*as)); ++ if (!as) ++ return NULL; ++ ++ memset (as, 0, sizeof (*as)); ++ ++ as->acc = *a; ++ ++ return as; ++#endif ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gget_proc_info.c b/src/loongarch64/Gget_proc_info.c +new file mode 100644 +index 0000000..96699c8 +--- /dev/null ++++ b/src/loongarch64/Gget_proc_info.c +@@ -0,0 +1,44 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++int ++unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ int ret; ++ ++ ret = dwarf_make_proc_info (&c->dwarf); ++ if (ret < 0) { ++ /* Construct a dummy proc info if Dwarf failed */ ++ memset (pi, 0, sizeof (*pi)); ++ pi->start_ip = c->dwarf.ip; ++ pi->end_ip = c->dwarf.ip + 4; ++ return 0; ++ } ++ ++ *pi = c->dwarf.pi; ++ return 0; ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gget_save_loc.c b/src/loongarch64/Gget_save_loc.c +new file mode 100644 +index 0000000..536fa3c +--- /dev/null ++++ b/src/loongarch64/Gget_save_loc.c +@@ -0,0 +1,101 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++ ++/* FIXME for LoongArch64. */ ++ ++int ++unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ dwarf_loc_t loc; ++ ++ loc = DWARF_NULL_LOC; /* default to "not saved" */ ++ ++ switch (reg) ++ { ++ case UNW_LOONGARCH64_R0: ++ case UNW_LOONGARCH64_R1: ++ case UNW_LOONGARCH64_R2: ++ case UNW_LOONGARCH64_R3: ++ case UNW_LOONGARCH64_R4: ++ case UNW_LOONGARCH64_R5: ++ case UNW_LOONGARCH64_R6: ++ case UNW_LOONGARCH64_R7: ++ case UNW_LOONGARCH64_R8: ++ case UNW_LOONGARCH64_R9: ++ case UNW_LOONGARCH64_R10: ++ case UNW_LOONGARCH64_R11: ++ case UNW_LOONGARCH64_R12: ++ case UNW_LOONGARCH64_R13: ++ case UNW_LOONGARCH64_R14: ++ case UNW_LOONGARCH64_R15: ++ case UNW_LOONGARCH64_R16: ++ case UNW_LOONGARCH64_R17: ++ case UNW_LOONGARCH64_R18: ++ case UNW_LOONGARCH64_R19: ++ case UNW_LOONGARCH64_R20: ++ case UNW_LOONGARCH64_R21: ++ case UNW_LOONGARCH64_R22: ++ case UNW_LOONGARCH64_R23: ++ case UNW_LOONGARCH64_R24: ++ case UNW_LOONGARCH64_R25: ++ case UNW_LOONGARCH64_R26: ++ case UNW_LOONGARCH64_R27: ++ case UNW_LOONGARCH64_R28: ++ case UNW_LOONGARCH64_R29: ++ case UNW_LOONGARCH64_R30: ++ case UNW_LOONGARCH64_R31: ++ case UNW_LOONGARCH64_PC: ++ loc = c->dwarf.loc[reg - UNW_LOONGARCH64_R0]; ++ break; ++ ++ default: ++ break; ++ } ++ ++ memset (sloc, 0, sizeof (*sloc)); ++ ++ if (DWARF_IS_NULL_LOC (loc)) ++ { ++ sloc->type = UNW_SLT_NONE; ++ return 0; ++ } ++ ++#if !defined(UNW_LOCAL_ONLY) ++ if (DWARF_IS_REG_LOC (loc)) ++ { ++ sloc->type = UNW_SLT_REG; ++ sloc->u.regnum = DWARF_GET_LOC (loc); ++ } ++ else ++#endif ++ { ++ sloc->type = UNW_SLT_MEMORY; ++ sloc->u.addr = DWARF_GET_LOC (loc); ++ } ++ return 0; ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gglobal.c b/src/loongarch64/Gglobal.c +new file mode 100644 +index 0000000..a475df0 +--- /dev/null ++++ b/src/loongarch64/Gglobal.c +@@ -0,0 +1,58 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++#include "dwarf_i.h" ++ ++HIDDEN define_lock (loongarch64_lock); ++HIDDEN int tdep_init_done; ++ ++HIDDEN void ++tdep_init (void) ++{ ++ intrmask_t saved_mask; ++ ++ sigfillset (&unwi_full_mask); ++ ++ lock_acquire (&loongarch64_lock, saved_mask); ++ { ++ if (tdep_init_done) ++ /* another thread else beat us to it... */ ++ goto out; ++ ++ mi_init (); ++ ++ dwarf_init (); ++ ++ tdep_init_mem_validate (); ++ ++#ifndef UNW_REMOTE_ONLY ++ loongarch64_local_addr_space_init (); ++#endif ++ tdep_init_done = 1; /* signal that we're initialized... */ ++ } ++ out: ++ lock_release (&loongarch64_lock, saved_mask); ++} +\ No newline at end of file +diff --git a/src/loongarch64/Ginit.c b/src/loongarch64/Ginit.c +new file mode 100644 +index 0000000..83817d1 +--- /dev/null ++++ b/src/loongarch64/Ginit.c +@@ -0,0 +1,405 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 ++#include ++#include ++#include ++#include ++ ++#include "unwind_i.h" ++ ++#ifdef UNW_REMOTE_ONLY ++ ++/* unw_local_addr_space is a NULL pointer in this case. */ ++unw_addr_space_t unw_local_addr_space; ++ ++#else /* !UNW_REMOTE_ONLY */ ++ ++static struct unw_addr_space local_addr_space; ++ ++unw_addr_space_t unw_local_addr_space = &local_addr_space; ++ ++static inline void * ++uc_addr (ucontext_t *uc, int reg) ++{ ++ if (reg >= UNW_LOONGARCH64_R0 && reg <= UNW_LOONGARCH64_R31) ++ return &uc->uc_mcontext.__gregs[reg - UNW_LOONGARCH64_R0]; ++ else if (reg == UNW_LOONGARCH64_PC) ++ return &uc->uc_mcontext.__pc; ++ else ++ return NULL; ++} ++ ++# ifdef UNW_LOCAL_ONLY ++ ++HIDDEN void * ++tdep_uc_addr (ucontext_t *uc, int reg) ++{ ++ return uc_addr (uc, reg); ++} ++ ++# endif /* UNW_LOCAL_ONLY */ ++ ++static void ++put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) ++{ ++ /* it's a no-op */ ++} ++ ++static int ++get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, ++ void *arg) ++{ ++#ifndef UNW_LOCAL_ONLY ++# pragma weak _U_dyn_info_list_addr ++ if (!_U_dyn_info_list_addr) ++ return -UNW_ENOINFO; ++#endif ++ // Access the `_U_dyn_info_list` from `LOCAL_ONLY` library, i.e. libunwind.so. ++ *dyn_info_list_addr = _U_dyn_info_list_addr (); ++ return 0; ++} ++ ++#define PAGE_SIZE 4096 ++#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) ++ ++static int mem_validate_pipe[2] = {-1, -1}; ++ ++#ifdef HAVE_PIPE2 ++static inline void ++do_pipe2 (int pipefd[2]) ++{ ++ pipe2 (pipefd, O_CLOEXEC | O_NONBLOCK); ++} ++#else ++static inline void ++set_pipe_flags (int fd) ++{ ++ int fd_flags = fcntl (fd, F_GETFD, 0); ++ int status_flags = fcntl (fd, F_GETFL, 0); ++ ++ fd_flags |= FD_CLOEXEC; ++ fcntl (fd, F_SETFD, fd_flags); ++ ++ status_flags |= O_NONBLOCK; ++ fcntl (fd, F_SETFL, status_flags); ++} ++ ++static inline void ++do_pipe2 (int pipefd[2]) ++{ ++ pipe (pipefd); ++ set_pipe_flags(pipefd[0]); ++ set_pipe_flags(pipefd[1]); ++} ++#endif ++ ++static inline void ++open_pipe (void) ++{ ++ if (mem_validate_pipe[0] != -1) ++ close (mem_validate_pipe[0]); ++ if (mem_validate_pipe[1] != -1) ++ close (mem_validate_pipe[1]); ++ ++ do_pipe2 (mem_validate_pipe); ++} ++ ++ALWAYS_INLINE ++static int ++write_validate (void *addr) ++{ ++ int ret = -1; ++ ssize_t bytes = 0; ++ ++ do ++ { ++ char buf; ++ bytes = read (mem_validate_pipe[0], &buf, 1); ++ } ++ while ( errno == EINTR ); ++ ++ int valid_read = (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK); ++ if (!valid_read) ++ { ++ // re-open closed pipe ++ open_pipe (); ++ } ++ ++ do ++ { ++ ret = write (mem_validate_pipe[1], addr, 1); ++ } ++ while ( errno == EINTR ); ++ ++ return ret; ++} ++ ++static int (*mem_validate_func) (void *addr, size_t len); ++static int msync_validate (void *addr, size_t len) ++{ ++ if (msync (addr, len, MS_ASYNC) != 0) ++ { ++ return -1; ++ } ++ ++ return write_validate (addr); ++} ++ ++#ifdef HAVE_MINCORE ++static int mincore_validate (void *addr, size_t len) ++{ ++ unsigned char mvec[2]; /* Unaligned access may cross page boundary */ ++ ++ /* mincore could fail with EAGAIN but we conservatively return -1 ++ instead of looping. */ ++ if (mincore (addr, len, (unsigned char *)mvec) != 0) ++ { ++ return -1; ++ } ++ ++ return write_validate (addr); ++} ++#endif ++ ++/* Initialise memory validation method. On linux kernels <2.6.21, ++ mincore() returns incorrect value for MAP_PRIVATE mappings, ++ such as stacks. If mincore() was available at compile time, ++ check if we can actually use it. If not, use msync() instead. */ ++HIDDEN void ++tdep_init_mem_validate (void) ++{ ++ open_pipe (); ++ ++#ifdef HAVE_MINCORE ++ unsigned char present = 1; ++ unw_word_t addr = PAGE_START((unw_word_t)&present); ++ unsigned char mvec[1]; ++ int ret; ++ while ((ret = mincore ((void*)addr, PAGE_SIZE, (unsigned char *)mvec)) == -1 && ++ errno == EAGAIN) {} ++ if (ret == 0) ++ { ++ Debug(1, "using mincore to validate memory\n"); ++ mem_validate_func = mincore_validate; ++ } ++ else ++#endif ++ { ++ Debug(1, "using msync to validate memory\n"); ++ mem_validate_func = msync_validate; ++ } ++} ++ ++/* Cache of already validated addresses */ ++#define NLGA 4 ++#if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD ++// thread-local variant ++static _Thread_local unw_word_t last_good_addr[NLGA]; ++static _Thread_local int lga_victim; ++ ++static int ++is_cached_valid_mem(unw_word_t addr) ++{ ++ int i; ++ for (i = 0; i < NLGA; i++) ++ { ++ if (addr == last_good_addr[i]) ++ return 1; ++ } ++ return 0; ++} ++ ++static void ++cache_valid_mem(unw_word_t addr) ++{ ++ int i, victim; ++ victim = lga_victim; ++ for (i = 0; i < NLGA; i++) { ++ if (last_good_addr[victim] == 0) { ++ last_good_addr[victim] = addr; ++ return; ++ } ++ victim = (victim + 1) % NLGA; ++ } ++ ++ /* All slots full. Evict the victim. */ ++ last_good_addr[victim] = addr; ++ victim = (victim + 1) % NLGA; ++ lga_victim = victim; ++} ++ ++#else ++// global, thread safe variant ++static _Atomic unw_word_t last_good_addr[NLGA]; ++static _Atomic int lga_victim; ++ ++static int ++is_cached_valid_mem(unw_word_t addr) ++{ ++ int i; ++ for (i = 0; i < NLGA; i++) ++ { ++ if (addr == atomic_load(&last_good_addr[i])) ++ return 1; ++ } ++ return 0; ++} ++ ++static void ++cache_valid_mem(unw_word_t addr) ++{ ++ int i, victim; ++ victim = atomic_load(&lga_victim); ++ unw_word_t zero = 0; ++ for (i = 0; i < NLGA; i++) { ++ if (atomic_compare_exchange_strong(&last_good_addr[victim], &zero, addr)) { ++ return; ++ } ++ victim = (victim + 1) % NLGA; ++ } ++ ++ /* All slots full. Evict the victim. */ ++ atomic_store(&last_good_addr[victim], addr); ++ victim = (victim + 1) % NLGA; ++ atomic_store(&lga_victim, victim); ++} ++#endif ++ ++static int ++validate_mem (unw_word_t addr) ++{ ++ size_t len; ++ ++ if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) ++ len = PAGE_SIZE; ++ else ++ len = PAGE_SIZE * 2; ++ ++ addr = PAGE_START(addr); ++ ++ if (addr == 0) ++ return -1; ++ ++ if (is_cached_valid_mem(addr)) ++ return 0; ++ ++ if (mem_validate_func ((void *) addr, len) == -1) ++ return -1; ++ ++ cache_valid_mem(addr); ++ ++ return 0; ++} ++ ++static int ++access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, ++ void *arg) ++{ ++ if (unlikely (write)) ++ { ++ Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); ++ *(unw_word_t *) (intptr_t) addr = *val; ++ } ++ else ++ { ++ /* validate address */ ++ const struct cursor *c = (const struct cursor *)arg; ++ if (likely (c != NULL) && unlikely (c->validate) ++ && unlikely (validate_mem (addr))) { ++ Debug (16, "mem[%016lx] -> invalid\n", addr); ++ return -1; ++ } ++ *val = *(unw_word_t *) (intptr_t) addr; ++ Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); ++ } ++ return 0; ++} ++ ++static int ++access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, ++ void *arg) ++{ ++ unw_word_t *addr; ++ ucontext_t *uc = ((struct cursor *)arg)->uc; ++ ++ if (unw_is_fpreg (reg)) ++ goto badreg; ++ ++ Debug (16, "reg = %s\n", unw_regname (reg)); ++ if (!(addr = uc_addr (uc, reg))) ++ goto badreg; ++ ++ if (write) ++ { ++ *(unw_word_t *) (intptr_t) addr = (unw_word_t) *val; ++ Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); ++ } ++ else ++ { ++ *val = (unw_word_t) *(unw_word_t *) (intptr_t) addr; ++ Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); ++ } ++ return 0; ++ ++ badreg: ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++} ++ ++static int ++access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, ++ int write, void *arg) ++{ ++ return 0; ++} ++ ++static int ++get_static_proc_name (unw_addr_space_t as, unw_word_t ip, ++ char *buf, size_t buf_len, unw_word_t *offp, ++ void *arg) ++{ ++ return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); ++} ++ ++HIDDEN void ++loongarch64_local_addr_space_init (void) ++{ ++ memset (&local_addr_space, 0, sizeof (local_addr_space)); ++ ++ local_addr_space.caching_policy = UNW_CACHE_GLOBAL; ++ local_addr_space.acc.find_proc_info = dwarf_find_proc_info; ++ local_addr_space.acc.put_unwind_info = put_unwind_info; ++ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; ++ local_addr_space.acc.access_mem = access_mem; ++ local_addr_space.acc.access_reg = access_reg; ++ local_addr_space.acc.access_fpreg = access_fpreg; ++ local_addr_space.acc.resume = loongarch64_local_resume; ++ local_addr_space.acc.get_proc_name = get_static_proc_name; ++ unw_flush_cache (&local_addr_space, 0, 0); ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ +\ No newline at end of file +diff --git a/src/loongarch64/Ginit_local.c b/src/loongarch64/Ginit_local.c +new file mode 100644 +index 0000000..dfdb49f +--- /dev/null ++++ b/src/loongarch64/Ginit_local.c +@@ -0,0 +1,80 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++#include "init.h" ++ ++#ifdef UNW_REMOTE_ONLY ++ ++int ++unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) ++{ ++ return -UNW_EINVAL; ++} ++ ++#else /* !UNW_REMOTE_ONLY */ ++ ++static int ++unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ if (!atomic_load(&tdep_init_done)) ++ tdep_init (); ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ c->dwarf.as = unw_local_addr_space; ++ c->dwarf.as_arg = c; ++ c->uc = uc; ++ c->validate = 0; ++ ++ return common_init (c, use_prev_instr); ++} ++ ++int ++unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) ++{ ++ return unw_init_local_common(cursor, uc, 1); ++} ++ ++int ++unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) ++{ ++ if (!flag) ++ { ++ return unw_init_local_common(cursor, uc, 1); ++ } ++ else if (flag == UNW_INIT_SIGNAL_FRAME) ++ { ++ return unw_init_local_common(cursor, uc, 0); ++ } ++ else ++ { ++ return -UNW_EINVAL; ++ } ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ +\ No newline at end of file +diff --git a/src/loongarch64/Ginit_remote.c b/src/loongarch64/Ginit_remote.c +new file mode 100644 +index 0000000..85f45d5 +--- /dev/null ++++ b/src/loongarch64/Ginit_remote.c +@@ -0,0 +1,56 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "init.h" ++#include "unwind_i.h" ++ ++int ++unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) ++{ ++#ifdef UNW_LOCAL_ONLY ++ return -UNW_EINVAL; ++#else /* !UNW_LOCAL_ONLY */ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ if (!tdep_init_done) ++ tdep_init (); ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ c->dwarf.as = as; ++ if (as == unw_local_addr_space) ++ { ++ c->dwarf.as_arg = c; ++ c->uc = as_arg; ++ } ++ else ++ { ++ c->dwarf.as_arg = as_arg; ++ c->uc = 0; ++ } ++ ++ return common_init (c, 0); ++#endif /* !UNW_LOCAL_ONLY */ ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gis_signal_frame.c b/src/loongarch64/Gis_signal_frame.c +new file mode 100644 +index 0000000..aa5fd54 +--- /dev/null ++++ b/src/loongarch64/Gis_signal_frame.c +@@ -0,0 +1,71 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++#include ++ ++/* ++ arch/loongarch/vdso/sigreturn.S: ++ ++ 0000000000000000 <__vdso_rt_sigreturn>: ++ 0: 03822c0b ori $r11,$r0,0x8b ++ 4: 002b0000 syscall 0x0 ++*/ ++ ++#define SIGRETURN_W0 0x03822c0b ++#define SIGRETURN_W1 0x002b0000 ++ ++int ++unw_is_signal_frame (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t w0, w1, ip; ++ unw_addr_space_t as; ++ unw_accessors_t *a; ++ void *arg; ++ int ret; ++ ++ as = c->dwarf.as; ++ a = unw_get_accessors (as); ++ arg = c->dwarf.as_arg; ++ ++ ip = c->dwarf.ip; ++ ++ /* syscall 0x0 */ ++ if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) ++ return ret; ++ ++ /* ori a7,zero,0x8b */ ++ if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) ++ return ret; ++ ++ if ((w1 & 0xffffffff) == SIGRETURN_W1 && (w0 & 0xffffffff) == SIGRETURN_W0) ++ { ++ Debug (8, "cursor at signal frame\n"); ++ return 1; ++ } ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/loongarch64/Greg_states_iterate.c b/src/loongarch64/Greg_states_iterate.c +new file mode 100644 +index 0000000..907ccb2 +--- /dev/null ++++ b/src/loongarch64/Greg_states_iterate.c +@@ -0,0 +1,37 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. ++ Contributed by David Mosberger-Tang ++ ++ Modified for x86_64 by Max Asbock ++ ++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 "unwind_i.h" ++ ++int ++unw_reg_states_iterate (unw_cursor_t *cursor, ++ unw_reg_states_callback cb, void *token) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ return dwarf_reg_states_iterate (&c->dwarf, cb, token); ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gregs.c b/src/loongarch64/Gregs.c +new file mode 100644 +index 0000000..ef0b0c6 +--- /dev/null ++++ b/src/loongarch64/Gregs.c +@@ -0,0 +1,109 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++ ++/* FIXME: The following is probably unfinished and/or at least partly bogus. */ ++ ++HIDDEN int ++tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, ++ int write) ++{ ++ dwarf_loc_t loc = DWARF_NULL_LOC; ++ ++ switch (reg) ++ { ++ case UNW_LOONGARCH64_R0: ++ case UNW_LOONGARCH64_R1: ++ case UNW_LOONGARCH64_R2: ++ ++ case UNW_LOONGARCH64_R4: ++ case UNW_LOONGARCH64_R5: ++ case UNW_LOONGARCH64_R6: ++ case UNW_LOONGARCH64_R7: ++ case UNW_LOONGARCH64_R8: ++ case UNW_LOONGARCH64_R9: ++ case UNW_LOONGARCH64_R10: ++ case UNW_LOONGARCH64_R11: ++ case UNW_LOONGARCH64_R12: ++ case UNW_LOONGARCH64_R13: ++ case UNW_LOONGARCH64_R14: ++ case UNW_LOONGARCH64_R15: ++ case UNW_LOONGARCH64_R16: ++ case UNW_LOONGARCH64_R17: ++ case UNW_LOONGARCH64_R18: ++ case UNW_LOONGARCH64_R19: ++ case UNW_LOONGARCH64_R20: ++ case UNW_LOONGARCH64_R21: ++ case UNW_LOONGARCH64_R22: ++ case UNW_LOONGARCH64_R23: ++ case UNW_LOONGARCH64_R24: ++ case UNW_LOONGARCH64_R25: ++ case UNW_LOONGARCH64_R26: ++ case UNW_LOONGARCH64_R27: ++ case UNW_LOONGARCH64_R28: ++ case UNW_LOONGARCH64_R29: ++ case UNW_LOONGARCH64_R30: ++ case UNW_LOONGARCH64_R31: ++ loc = c->dwarf.loc[reg - UNW_LOONGARCH64_R0]; ++ break; ++ ++ case UNW_LOONGARCH64_PC: ++ if (write) ++ { ++ Debug (16, "pc is now 0x%lx\n", *valp); ++ c->dwarf.ip = *valp; ++ } ++ loc = c->dwarf.loc[reg]; ++ break; ++ case UNW_TDEP_SP: /* UNW_LOONGARCH64_R3 */ ++ case UNW_LOONGARCH64_CFA: ++ if (write) ++ return -UNW_EREADONLYREG; ++ *valp = c->dwarf.cfa; ++ return 0; ++ ++ /* FIXME: IP? Copro & shadow registers? */ ++ ++ default: ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++ } ++ ++ if (write) ++ return dwarf_put (&c->dwarf, loc, *valp); ++ else ++ return dwarf_get (&c->dwarf, loc, valp); ++ ++} ++ ++/* FIXME for LoongArch64. */ ++ ++HIDDEN int ++tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, ++ int write) ++{ ++ return -UNW_EBADREG; ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gresume.c b/src/loongarch64/Gresume.c +new file mode 100644 +index 0000000..d20f3e5 +--- /dev/null ++++ b/src/loongarch64/Gresume.c +@@ -0,0 +1,126 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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. */ ++ ++/* FIXME for LoongArch64. */ ++ ++#include ++ ++#include "unwind_i.h" ++ ++#ifndef UNW_REMOTE_ONLY ++ ++HIDDEN inline int ++loongarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_tdep_context_t *uc = c->uc; ++ ++ if (c->sigcontext_format == LOONGARCH64_SCF_NONE) ++ { ++ /* Since there are no signals involved here we restore EH and non scratch ++ registers only. */ ++ register void *gregs asm("$t0") = uc->uc_mcontext.__gregs; ++ asm volatile ( ++ "ld.d $ra, %0, 8\n" ++ "ld.d $sp, %0, 3*8\n" ++ "ld.d $fp, %0, 22*8\n" ++ "ld.d $s0, %0, 23*8\n" ++ "ld.d $s1, %0, 24*8\n" ++ "ld.d $s2, %0, 25*8\n" ++ "ld.d $s3, %0, 26*8\n" ++ "ld.d $s4, %0, 27*8\n" ++ "ld.d $s5, %0, 28*8\n" ++ "ld.d $s6, %0, 29*8\n" ++ "ld.d $s7, %0, 30*8\n" ++ "ld.d $s8, %0, 31*8\n" ++ "jr $ra\n" ++ : ++ : "r" (gregs) ++ ); ++ unreachable(); ++ } ++ else /* c->sigcontext_format == LOONGARCH64_SCF_LINUX_RT_SIGFRAME */ ++ { ++ int i; ++ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; ++ ++ sc->sc_pc = c->dwarf.ip; ++ for (i = UNW_LOONGARCH64_R0; i <= UNW_LOONGARCH64_R31; i++) ++ sc->sc_regs[i] = uc->uc_mcontext.__gregs[i]; ++ ++ Debug (8, "resuming at ip=0x%lx via sigreturn() (trampoline @ 0x%lx, sp @ 0x%lx)\n", ++ c->dwarf.ip, c->sigcontext_pc, c->sigcontext_sp); ++ ++ asm volatile ( ++ "move $sp, %0\n" ++ "jr %1\n" ++ : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) ++ ); ++ } ++ unreachable(); ++ ++ return -UNW_EINVAL; ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ ++ ++static inline void ++establish_machine_state (struct cursor *c) ++{ ++ unw_addr_space_t as = c->dwarf.as; ++ void *arg = c->dwarf.as_arg; ++ unw_word_t val; ++ int reg; ++ ++ Debug (8, "copying out cursor state\n"); ++ ++ for (reg = UNW_LOONGARCH64_R0; reg <= UNW_LOONGARCH64_R31; reg++) ++ { ++ Debug (16, "copying %s %d\n", unw_regname (reg), reg); ++ if (tdep_access_reg (c, reg, &val, 0) >= 0) ++ as->acc.access_reg (as, reg, &val, 1, arg); ++ } ++} ++ ++int ++unw_resume (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ if (!c->dwarf.ip) ++ { ++ /* This can happen easily when the frame-chain gets truncated ++ due to bad or missing unwind-info. */ ++ Debug (1, "refusing to resume execution at address 0\n"); ++ return -UNW_EINVAL; ++ } ++ ++ establish_machine_state (c); ++ ++ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, ++ c->dwarf.as_arg); ++} +\ No newline at end of file +diff --git a/src/loongarch64/Gstep.c b/src/loongarch64/Gstep.c +new file mode 100644 +index 0000000..4bfe213 +--- /dev/null ++++ b/src/loongarch64/Gstep.c +@@ -0,0 +1,144 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2015 Imagination Technologies Limited ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++#include "offsets.h" ++ ++static int ++loongarch64_handle_signal_frame (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t sc_addr, sp_addr = c->dwarf.cfa; ++ unw_word_t ra, fp; ++ int ret; ++ ++ if (unw_is_signal_frame (cursor)) { ++ sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; ++ } else { ++ c->sigcontext_format = LOONGARCH64_SCF_NONE; ++ return -UNW_EUNSPEC; ++ } ++ ++ c->sigcontext_addr = sc_addr; ++ ++ /* Save the SP and PC to be able to return execution at this point ++ later in time (unw_resume). */ ++ c->sigcontext_sp = c->dwarf.cfa; ++ c->sigcontext_pc = c->dwarf.ip; ++ c->sigcontext_format = LOONGARCH64_SCF_LINUX_RT_SIGFRAME; ++ ++ /* Update the dwarf cursor. ++ Set the location of the registers to the corresponding addresses of the ++ uc_mcontext / sigcontext structure contents. */ ++ ++ c->dwarf.loc[UNW_LOONGARCH64_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); ++ c->dwarf.loc[UNW_LOONGARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); ++ ++ /* Set SP/CFA and PC/IP. */ ++ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH64_R3], &c->dwarf.cfa); ++ ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), ++ &c->dwarf.ip)) < 0) ++ return ret; ++ ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R1_OFF, 0), ++ &ra)) < 0) ++ return ret; ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R22_OFF, 0), ++ &fp)) < 0) ++ return ret; ++ ++ Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", ++ (unsigned long long)c->dwarf.ip, (unsigned long long)ra, ++ (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); ++ ++ c->dwarf.pi_valid = 0; ++ c->dwarf.use_prev_instr = 0; ++ ++ return 1; ++ ++} ++ ++int ++unw_step (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ int validate = c->validate; ++ int ret; ++ ++ Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", ++ c, c->dwarf.ip, c->dwarf.cfa); ++ ++ ret = unw_is_signal_frame (cursor); ++ if (ret > 0) ++ return loongarch64_handle_signal_frame (cursor); ++ ++ /* Not a signal frame, try DWARF-based unwinding. */ ++ ret = dwarf_step (&c->dwarf); ++ ++ /* Restore default memory validation state */ ++ c->validate = validate; ++ ++ if (unlikely (ret == -UNW_ESTOPUNWIND)) ++ return ret; ++ ++ /* Dwarf unwinding didn't work, stop. */ ++ if (unlikely (ret < 0)) ++ return 0; ++ ++ return (c->dwarf.ip == 0) ? 0 : 1; ++} +\ No newline at end of file +diff --git a/src/loongarch64/Lapply_reg_state.c b/src/loongarch64/Lapply_reg_state.c +new file mode 100644 +index 0000000..105b1ee +--- /dev/null ++++ b/src/loongarch64/Lapply_reg_state.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gapply_reg_state.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lcreate_addr_space.c b/src/loongarch64/Lcreate_addr_space.c +new file mode 100644 +index 0000000..8b365a9 +--- /dev/null ++++ b/src/loongarch64/Lcreate_addr_space.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gcreate_addr_space.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lget_proc_info.c b/src/loongarch64/Lget_proc_info.c +new file mode 100644 +index 0000000..36feae1 +--- /dev/null ++++ b/src/loongarch64/Lget_proc_info.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gget_proc_info.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lget_save_loc.c b/src/loongarch64/Lget_save_loc.c +new file mode 100644 +index 0000000..79f5aab +--- /dev/null ++++ b/src/loongarch64/Lget_save_loc.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gget_save_loc.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lglobal.c b/src/loongarch64/Lglobal.c +new file mode 100644 +index 0000000..68b0d35 +--- /dev/null ++++ b/src/loongarch64/Lglobal.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gglobal.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Linit.c b/src/loongarch64/Linit.c +new file mode 100644 +index 0000000..f334a4b +--- /dev/null ++++ b/src/loongarch64/Linit.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Linit_local.c b/src/loongarch64/Linit_local.c +new file mode 100644 +index 0000000..b5d5eda +--- /dev/null ++++ b/src/loongarch64/Linit_local.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit_local.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Linit_remote.c b/src/loongarch64/Linit_remote.c +new file mode 100644 +index 0000000..36bad1f +--- /dev/null ++++ b/src/loongarch64/Linit_remote.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit_remote.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lis_signal_frame.c b/src/loongarch64/Lis_signal_frame.c +new file mode 100644 +index 0000000..e6ba4b2 +--- /dev/null ++++ b/src/loongarch64/Lis_signal_frame.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gis_signal_frame.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lreg_states_iterate.c b/src/loongarch64/Lreg_states_iterate.c +new file mode 100644 +index 0000000..d93fc99 +--- /dev/null ++++ b/src/loongarch64/Lreg_states_iterate.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Greg_states_iterate.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lregs.c b/src/loongarch64/Lregs.c +new file mode 100644 +index 0000000..572499d +--- /dev/null ++++ b/src/loongarch64/Lregs.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gregs.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lresume.c b/src/loongarch64/Lresume.c +new file mode 100644 +index 0000000..e27bdbb +--- /dev/null ++++ b/src/loongarch64/Lresume.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gresume.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/Lstep.c b/src/loongarch64/Lstep.c +new file mode 100644 +index 0000000..542c5ee +--- /dev/null ++++ b/src/loongarch64/Lstep.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gstep.c" ++#endif +\ No newline at end of file +diff --git a/src/loongarch64/getcontext.S b/src/loongarch64/getcontext.S +new file mode 100644 +index 0000000..222200e +--- /dev/null ++++ b/src/loongarch64/getcontext.S +@@ -0,0 +1,61 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2012 Tommi Rantala ++ Copyright (C) 2021 Loongson Technology Corporation 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 "offsets.h" ++#include ++ .text ++ ++#define SREG(X) st.d $r##X, $r4, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ++#define SPC st.d $r1, $r4, (LINUX_UC_MCONTEXT_PC) ++ ++ .global _Uloongarch64_getcontext ++ .type _Uloongarch64_getcontext, %function ++ ++_Uloongarch64_getcontext: ++ .cfi_startproc ++ SREG(0) ++ SREG(1) ++ SREG(3) ++ SREG(21) ++ SREG(22) ++ SREG(23) ++ SREG(24) ++ SREG(25) ++ SREG(26) ++ SREG(27) ++ SREG(28) ++ SREG(29) ++ SREG(30) ++ SREG(31) ++ ++ SPC ++ ++ ori $r4, $r0, 0 ++ jirl $r0, $r1, 0 ++ ++ .cfi_endproc ++ ++ .size _Uloongarch64_getcontext, .-_Uloongarch64_getcontext +\ No newline at end of file +diff --git a/src/loongarch64/init.h b/src/loongarch64/init.h +new file mode 100644 +index 0000000..692372f +--- /dev/null ++++ b/src/loongarch64/init.h +@@ -0,0 +1,64 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++ ++static inline int ++common_init (struct cursor *c, unsigned use_prev_instr) ++{ ++ int ret, i; ++ ++ for (i = UNW_LOONGARCH64_R0; i <= UNW_LOONGARCH64_R31; i++) ++ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); ++ ++ for (i = UNW_LOONGARCH64_R31 + 1; i < DWARF_NUM_PRESERVED_REGS; i++) ++ c->dwarf.loc[i] = DWARF_NULL_LOC; ++ ++ c->dwarf.loc[UNW_LOONGARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH64_PC); ++ ++ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH64_PC], &c->dwarf.ip); ++ if (ret < 0) ++ return ret; ++ ++ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH64_R3), ++ &c->dwarf.cfa); ++ if (ret < 0) ++ return ret; ++ ++ c->sigcontext_format = LOONGARCH64_SCF_NONE; ++ c->sigcontext_addr = 0; ++ c->sigcontext_sp = 0; ++ c->sigcontext_pc = 0; ++ ++ c->dwarf.args_size = 0; ++ c->dwarf.stash_frames = 0; ++ c->dwarf.use_prev_instr = use_prev_instr; ++ c->dwarf.pi_valid = 0; ++ c->dwarf.pi_is_dynamic = 0; ++ c->dwarf.hint = 0; ++ c->dwarf.prev_rs = 0; ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/loongarch64/is_fpreg.c b/src/loongarch64/is_fpreg.c +new file mode 100644 +index 0000000..688c526 +--- /dev/null ++++ b/src/loongarch64/is_fpreg.c +@@ -0,0 +1,35 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "libunwind_i.h" ++ ++/* FIXME: I'm not sure if libunwind's FP register distinction is very useful ++ on LoongArch64. */ ++ ++int ++unw_is_fpreg (int regnum) ++{ ++ /* FIXME: Support FP. */ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/loongarch64/offsets.h b/src/loongarch64/offsets.h +new file mode 100644 +index 0000000..d6b06f4 +--- /dev/null ++++ b/src/loongarch64/offsets.h +@@ -0,0 +1,50 @@ ++/* Linux-specific definitions: */ ++ ++/* Define various structure offsets to simplify cross-compilation. */ ++ ++/* Offsets for LoongArch64 Linux "ucontext_t": */ ++ ++# define LINUX_UC_FLAGS_OFF 0x0 /* offsetof(struct ucontext_t, __uc_flags) */ ++# define LINUX_UC_LINK_OFF 0x8 /* offsetof(struct ucontext_t, uc_link) */ ++# define LINUX_UC_STACK_OFF 0x10 /* offsetof(struct ucontext_t, uc_stack) */ ++# define LINUX_UC_SIGMASK_OFF 0x28 /* offsetof(struct ucontext_t, uc_sigmask) */ ++# define LINUX_UC_MCONTEXT_OFF 0xb0 /* offsetof(struct ucontext_t, uc_mcontext) */ ++ ++# define LINUX_UC_MCONTEXT_PC 0xb0 /* offsetof(struct ucontext_t, uc_mcontext.__pc) */ ++# define LINUX_UC_MCONTEXT_GREGS 0xb8 /* offsetof(struct ucontext_t, uc_mcontext.__gregs) */ ++/* Offsets for LoongArch64 Linux "struct sigcontext": */ ++#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) ++#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) ++#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) ++#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) ++#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) ++#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) ++#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) ++#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) ++#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) ++#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) ++#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) ++#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) ++#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) ++#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) ++#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) ++#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) ++#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) ++#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) ++#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) ++#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) ++#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) ++#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) ++#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) ++#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) ++#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) ++#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) ++#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) ++#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) ++#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) ++#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) ++#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) ++#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) ++ ++#define LINUX_SC_SP_OFF LINUX_SC_R3_OFF ++#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) +\ No newline at end of file +diff --git a/src/loongarch64/regname.c b/src/loongarch64/regname.c +new file mode 100644 +index 0000000..c2e0283 +--- /dev/null ++++ b/src/loongarch64/regname.c +@@ -0,0 +1,50 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2021 Loongson Technology Corporation 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 "unwind_i.h" ++ ++static const char *regname[] = ++ { ++ /* 0. */ ++ "zero", "ra", "tp", "sp", "a0(v0)", "a1(v1)", "a2", "a3", ++ /* 8. */ ++ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", ++ /* 16. */ ++ "t4", "t5", "t6", "t7", "t8", "reserve", "fp", "s0", ++ /* 24. */ ++ "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", ++ ++ /* pc */ ++ "pc" ++ }; ++ ++const char * ++unw_regname (unw_regnum_t reg) ++{ ++ if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) ++ return regname[reg]; ++ else ++ return "???"; ++} +\ No newline at end of file +diff --git a/src/loongarch64/siglongjmp.S b/src/loongarch64/siglongjmp.S +new file mode 100644 +index 0000000..ad72b3a +--- /dev/null ++++ b/src/loongarch64/siglongjmp.S +@@ -0,0 +1,8 @@ ++ /* Dummy implementation for now. */ ++ ++ .globl _UI_siglongjmp_cont ++ .globl _UI_longjmp_cont ++ ++_UI_siglongjmp_cont: ++_UI_longjmp_cont: ++ jirl $r0, $r1, 0 +\ No newline at end of file +diff --git a/src/loongarch64/unwind_i.h b/src/loongarch64/unwind_i.h +new file mode 100644 +index 0000000..09a44d9 +--- /dev/null ++++ b/src/loongarch64/unwind_i.h +@@ -0,0 +1,43 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 unwind_i_h ++#define unwind_i_h ++ ++#include ++ ++#include ++ ++#include "libunwind_i.h" ++ ++#define loongarch64_lock UNW_OBJ(lock) ++#define loongarch64_local_resume UNW_OBJ(local_resume) ++#define loongarch64_local_addr_space_init UNW_OBJ(local_addr_space_init) ++ ++extern int loongarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, ++ void *arg); ++ ++extern void loongarch64_local_addr_space_init (void); ++ ++#endif /* unwind_i_h */ +\ No newline at end of file +-- +2.41.0 + diff --git a/add-sw_64-support-not-upstream-modified.patch b/add-sw_64-support-not-upstream-modified.patch new file mode 100644 index 0000000000000000000000000000000000000000..49a556196a3819fb850270e13888e4e8bc6055b5 --- /dev/null +++ b/add-sw_64-support-not-upstream-modified.patch @@ -0,0 +1,1060 @@ +From 2de9d29328a90980f6b33bd8f312b2c274bc9eea Mon Sep 17 00:00:00 2001 +From: herengui +Date: Mon, 28 Aug 2023 16:15:57 +0800 +Subject: [PATCH 1/2] libunwind add sw_64 support + +Signed-off-by: herengui +--- + Makefile.am | 5 + + Makefile.in | 6 +- + config/config.guess | 41 ++++ + config/config.sub | 2 + + configure | 23 ++- + configure.ac | 5 +- + include/libunwind.h | 2 + + include/libunwind.h.in | 2 + + include/tdep/dwarf-config.h | 2 + + include/tdep/jmpbuf.h | 2 + + include/tdep/libunwind_i.h | 2 + + include/tdep/libunwind_i.h.in | 2 + + src/Makefile.am | 35 ++++ + src/Makefile.in | 267 +++++++++++++++++++++++++++ + src/coredump/_UCD_access_reg_linux.c | 37 ++++ + src/ptrace/_UPT_reg_offset.c | 66 +++++++ + tests/Makefile.am | 4 + + tests/Makefile.in | 2 +- + tests/check-namespace.sh.in | 14 ++ + 19 files changed, 515 insertions(+), 4 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 3b7566f..91d487d 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -23,6 +23,9 @@ endif + if ARCH_MIPS + include_HEADERS += include/libunwind-mips.h + endif ++if ARCH_SW_64 ++include_HEADERS += include/libunwind-sw_64.h ++endif + if ARCH_TILEGX + include_HEADERS += include/libunwind-tilegx.h + endif +@@ -87,6 +90,8 @@ noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ + include/tdep-loongarch64/libunwind_i.h \ + include/tdep-mips/libunwind_i.h \ + include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \ ++ include/tdep-sw_64/libunwind_i.h \ ++ include/tdep-sw_64/jmpbuf.h include/tdep-sw_64/dwarf-config.h \ + include/tdep-tilegx/libunwind_i.h \ + include/tdep-tilegx/jmpbuf.h include/tdep-tilegx/dwarf-config.h \ + include/tdep-x86/libunwind_i.h \ +diff --git a/Makefile.in b/Makefile.in +index 723a11e..58c248f 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -108,6 +108,7 @@ target_triplet = @target@ + @BUILD_UNWIND_HEADER_TRUE@@REMOTE_ONLY_FALSE@am__append_17 = include/unwind.h + @CONFIG_TESTS_TRUE@am__append_18 = tests + @CONFIG_DOCS_TRUE@am__append_19 = doc ++@ARCH_SW_64_TRUE@am__append_20 = include/libunwind-sw_64.h + subdir = . + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ +@@ -161,6 +162,7 @@ am__include_HEADERS_DIST = include/libunwind-dynamic.h \ + include/libunwind-x86.h include/libunwind-x86_64.h \ + include/libunwind-ppc32.h include/libunwind-ppc64.h \ + include/libunwind-sh.h include/libunwind-s390x.h \ ++ include/libunwind-sw_64.h \ + include/libunwind-riscv.h include/libunwind.h include/unwind.h + am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; + am__vpath_adj = case $$p in \ +@@ -433,7 +435,7 @@ include_HEADERS = include/libunwind-dynamic.h $(am__append_1) \ + $(am__append_8) $(am__append_9) $(am__append_10) \ + $(am__append_11) $(am__append_12) $(am__append_13) \ + $(am__append_14) $(am__append_15) $(am__append_16) \ +- $(am__append_17) ++ $(am__append_17) $(am__append_20) + nodist_include_HEADERS = include/libunwind-common.h + SUBDIRS = src $(am__append_18) $(am__append_19) + noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ +@@ -462,6 +464,8 @@ noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ + include/tdep-ppc64/jmpbuf.h include/tdep-ppc64/libunwind_i.h \ + include/tdep-sh/dwarf-config.h \ + include/tdep-sh/jmpbuf.h include/tdep-sh/libunwind_i.h \ ++ include/tdep-sw_64/dwarf-config.h \ ++ include/tdep-sw_64/jmpbuf.h include/tdep-sw_64/libunwind_i.h \ + include/tdep-s390x/dwarf-config.h \ + include/tdep-s390x/jmpbuf.h include/tdep-s390x/libunwind_i.h \ + include/tdep-riscv/dwarf-config.h \ +diff --git a/config/config.guess b/config/config.guess +index 49cd5b2..d8ac646 100755 +--- a/config/config.guess ++++ b/config/config.guess +@@ -275,6 +275,36 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; ++ sw_64:OSF1:*:*) ++ case $UNAME_RELEASE in ++ *4.0) ++ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ++ ;; ++ *5.*) ++ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ++ ;; ++ esac ++ # According to Compaq, /usr/sbin/psrinfo has been available on ++ # OSF/1 and Tru64 systems produced since 1995. I hope that ++ # covers most systems running today. This code pipes the CPU ++ # types through head -n 1, so we only detect the type of CPU 0. ++ SW_64_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The sw_64 \(.*\) processor.*$/\1/p' | head -n 1` ++ case "$SW_64_CPU_TYPE" in ++ "SW6A (1621)") ++ UNAME_MACHINE=sw_64sw6a ;; ++ "SW6B (3231)") ++ UNAME_MACHINE=sw_64sw6b ;; ++ esac ++ # A Pn.n version is a patched version. ++ # A Vn.n version is a released version. ++ # A Tn.n version is a released field test version. ++ # A Xn.n version is an unreleased experimental baselevel. ++ # 1.2 uses "1.2" for uname -r. ++ echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" ++ # Reset EXIT trap before exiting to avoid spurious non-zero exit code. ++ exitcode=$? ++ trap '' 0 ++ exit $exitcode ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) +@@ -904,6 +934,16 @@ EOF + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; ++ sw_64:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in ++ SW6A) UNAME_MACHINE=sw_64sw6a ;; ++ SW6B) UNAME_MACHINE=sw_64sw6b ;; ++ sw) UNAME_MACHINE=sw_64 ;; ++ esac ++ objdump --private-headers /bin/sh | grep -q ld.so.1 ++ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; +@@ -1400,6 +1440,7 @@ EOF + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; ++ S*) echo sw_64-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; +diff --git a/config/config.sub b/config/config.sub +index 92eca01..ec0ae70 100755 +--- a/config/config.sub ++++ b/config/config.sub +@@ -309,6 +309,7 @@ case $basic_machine in + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ ++ | sw_64 | sw_64sw6a | sw_64sw6b \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ +@@ -436,6 +437,7 @@ case $basic_machine in + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ ++ | sw_64-* | sw_64sw6a-* | sw_64sw6b-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ +diff --git a/configure b/configure +index 016e495..d01e365 100755 +--- a/configure ++++ b/configure +@@ -699,6 +699,8 @@ ARCH_X86_64_FALSE + ARCH_X86_64_TRUE + ARCH_X86_FALSE + ARCH_X86_TRUE ++ARCH_SW_64_FALSE ++ARCH_SW_64_TRUE + ARCH_MIPS_FALSE + ARCH_MIPS_TRUE + ARCH_HPPA_FALSE +@@ -17447,6 +17449,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + build_arch=hppa ;; #( + mips*) : + build_arch=mips ;; #( ++ sw_64*) : ++ build_arch=sw_64 ;; #( + powerpc*) : + build_arch=ppc$ppc_bits ;; #( + sh*) : +@@ -17473,6 +17477,8 @@ esac + host_arch=hppa ;; #( + mips*) : + host_arch=mips ;; #( ++ sw_64*) : ++ host_arch=sw_64 ;; #( + powerpc*) : + host_arch=ppc$ppc_bits ;; #( + sh*) : +@@ -17499,6 +17505,8 @@ esac + target_arch=hppa ;; #( + mips*) : + target_arch=mips ;; #( ++ sw_64*) : ++ target_arch=sw_64 ;; #( + powerpc*) : + target_arch=ppc$ppc_bits ;; #( + sh*) : +@@ -17730,6 +17738,14 @@ else + ARCH_MIPS_FALSE= + fi + ++ if test x$target_arch = xsw_64; then ++ ARCH_SW_64_TRUE= ++ ARCH_SW_64_FALSE='#' ++else ++ ARCH_SW_64_TRUE='#' ++ ARCH_SW_64_FALSE= ++fi ++ + if test x$target_arch = xx86; then + ARCH_X86_TRUE= + ARCH_X86_FALSE='#' +@@ -17840,7 +17856,7 @@ $as_echo_n "checking for ELF helper width... " >&6; } + case "${target_arch}" in + (arm|hppa|ppc32|x86|sh) use_elf32=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: 32" >&5 + $as_echo "32" >&6; };; +-(aarch64|ia64|ppc64|x86_64|s390x|tilegx) use_elf64=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: 64" >&5 ++(aarch64|ia64|ppc64|x86_64|s390x|tilegx|sw_64) use_elf64=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: 64" >&5 + $as_echo "64" >&6; };; + (mips|riscv) use_elfxx=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: xx" >&5 + $as_echo "xx" >&6; };; +@@ -17927,6 +17943,7 @@ case $target_arch in + x86*) enable_cxx_exceptions=no;; + aarch64*) enable_cxx_exceptions=no;; + arm*) enable_cxx_exceptions=no;; ++ sw_64*) enable_cxx_exceptions=no;; + mips*) enable_cxx_exceptions=no;; + tile*) enable_cxx_exceptions=no;; + s390x*) enable_cxx_exceptions=no;; +@@ -18711,6 +18728,10 @@ if test -z "${ARCH_MIPS_TRUE}" && test -z "${ARCH_MIPS_FALSE}"; then + as_fn_error $? "conditional \"ARCH_MIPS\" was never defined. + Usually this means the macro was only invoked conditionally." "$LINENO" 5 + fi ++if test -z "${ARCH_SW_64_TRUE}" && test -z "${ARCH_SW_64_FALSE}"; then ++ as_fn_error $? "conditional \"ARCH_SW_64\" was never defined. ++Usually this means the macro was only invoked conditionally." "$LINENO" 5 ++fi + if test -z "${ARCH_X86_TRUE}" && test -z "${ARCH_X86_FALSE}"; then + as_fn_error $? "conditional \"ARCH_X86\" was never defined. + Usually this means the macro was only invoked conditionally." "$LINENO" 5 +diff --git a/configure.ac b/configure.ac +index 5e450b2..c3af7d7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -93,6 +93,7 @@ AC_DEFUN([SET_ARCH],[ + [i?86],[$2=x86], + [hppa*],[$2=hppa], + [mips*],[$2=mips], ++ [sw_64],[$2=sw_64], + [powerpc*],[$2=ppc$ppc_bits], + [sh*],[$2=sh], + [amd64],[$2=x86_64], +@@ -183,6 +184,7 @@ AM_CONDITIONAL(ARCH_IA64, test x$target_arch = xia64) + AM_CONDITIONAL(ARCH_HPPA, test x$target_arch = xhppa) + AM_CONDITIONAL(ARCH_LOONGARCH64, test x$target_arch = xloongarch64) + AM_CONDITIONAL(ARCH_MIPS, test x$target_arch = xmips) ++AM_CONDITIONAL(ARCH_SW_64, test x$target_arch = xsw_64) + AM_CONDITIONAL(ARCH_X86, test x$target_arch = xx86) + AM_CONDITIONAL(ARCH_X86_64, test x$target_arch = xx86_64) + AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32) +@@ -200,7 +202,7 @@ AM_CONDITIONAL(OS_SOLARIS, expr x$target_os : xsolaris >/dev/null) + AC_MSG_CHECKING([for ELF helper width]) + case "${target_arch}" in + (arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);; +-(aarch64|ia64|ppc64|x86_64|s390x|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);; ++(aarch64|ia64|ppc64|x86_64|s390x|tilegx|sw_64) use_elf64=yes; AC_MSG_RESULT([64]);; + (mips|riscv|loongarch64) use_elfxx=yes; AC_MSG_RESULT([xx]);; + *) AC_MSG_ERROR([Unknown ELF target: ${target_arch}]) + esac +@@ -245,6 +247,7 @@ case $target_arch in + x86*) enable_cxx_exceptions=no;; + aarch64*) enable_cxx_exceptions=no;; + arm*) enable_cxx_exceptions=no;; ++ sw_64*) enable_cxx_exceptions=no;; + mips*) enable_cxx_exceptions=no;; + tile*) enable_cxx_exceptions=no;; + loongarch*) enable_cxx_exceptions=no;; +diff --git a/include/libunwind.h b/include/libunwind.h +index 421d601..888697f 100644 +--- a/include/libunwind.h ++++ b/include/libunwind.h +@@ -13,6 +13,8 @@ + # include "libunwind-ia64.h" + #elif defined __mips__ + # include "libunwind-mips.h" ++#elif defined __sw_64__ ++# include "libunwind-sw_64.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "libunwind-ppc32.h" + #elif defined __powerpc64__ +diff --git a/include/libunwind.h.in b/include/libunwind.h.in +index 1ba5401..ba5e1c2 100644 +--- a/include/libunwind.h.in ++++ b/include/libunwind.h.in +@@ -13,6 +13,8 @@ + # include "libunwind-ia64.h" + #elif defined __mips__ + # include "libunwind-mips.h" ++#elif defined __sw_64__ ++# include "libunwind-sw_64.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "libunwind-ppc32.h" + #elif defined __powerpc64__ +diff --git a/include/tdep/dwarf-config.h b/include/tdep/dwarf-config.h +index d367756..743b076 100644 +--- a/include/tdep/dwarf-config.h ++++ b/include/tdep/dwarf-config.h +@@ -11,6 +11,8 @@ + # include "tdep-ia64/dwarf-config.h" + #elif defined __mips__ + # include "tdep-mips/dwarf-config.h" ++#elif defined __sw_64__ ++# include "tdep-sw_64/dwarf-config.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "tdep-ppc32/dwarf-config.h" + #elif defined __powerpc64__ +diff --git a/include/tdep/jmpbuf.h b/include/tdep/jmpbuf.h +index 22d9f26..04560ab 100644 +--- a/include/tdep/jmpbuf.h ++++ b/include/tdep/jmpbuf.h +@@ -13,6 +13,8 @@ + # include "tdep-ia64/jmpbuf.h" + #elif defined __mips__ + # include "tdep-mips/jmpbuf.h" ++#elif defined __sw_64__ ++# include "tdep-sw_64/jmpbuf.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "tdep-ppc32/jmpbuf.h" + #elif defined __powerpc64__ +diff --git a/include/tdep/libunwind_i.h b/include/tdep/libunwind_i.h +index bfb89bf..c567343 100644 +--- a/include/tdep/libunwind_i.h ++++ b/include/tdep/libunwind_i.h +@@ -13,6 +13,8 @@ + # include "tdep-ia64/libunwind_i.h" + #elif defined __mips__ + # include "tdep-mips/libunwind_i.h" ++#elif defined __sw_64__ ++# include "tdep-sw_64/libunwind_i.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "tdep-ppc32/libunwind_i.h" + #elif defined __powerpc64__ +diff --git a/include/tdep/libunwind_i.h.in b/include/tdep/libunwind_i.h.in +index 1e0a247..2a99a14 100644 +--- a/include/tdep/libunwind_i.h.in ++++ b/include/tdep/libunwind_i.h.in +@@ -13,6 +13,8 @@ + # include "tdep-ia64/libunwind_i.h" + #elif defined __mips__ + # include "tdep-mips/libunwind_i.h" ++#elif defined __sw_64__ ++# include "tdep-sw_64/libunwind_i.h" + #elif defined __powerpc__ && !defined __powerpc64__ + # include "tdep-ppc32/libunwind_i.h" + #elif defined __powerpc64__ +diff --git a/src/Makefile.am b/src/Makefile.am +index 9afd58f..ef3f10b 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -385,6 +385,27 @@ libunwind_loongarch64_la_SOURCES_loongarch64 = $(libunwind_la_SOURCES_loongarch6 + loongarch64/Gis_signal_frame.c loongarch64/Gregs.c \ + loongarch64/Gresume.c loongarch64/Gstep.c + ++# The list of files that go info libunwind and libunwind-sw_64: ++noinst_HEADERS += sw_64/init.h sw_64/offsets.h sw_64/unwind_i.h ++libunwind_la_SOURCES_sw_64_common = $(libunwind_la_SOURCES_common) \ ++ sw_64/is_fpreg.c sw_64/regname.c ++ ++# The list of files that go into libunwind: ++libunwind_la_SOURCES_sw_64 = $(libunwind_la_SOURCES_sw_64_common) \ ++ $(libunwind_la_SOURCES_local) \ ++ sw_64/getcontext.S \ ++ sw_64/Lapply_reg_state.c sw_64/Lreg_states_iterate.c \ ++ sw_64/Lcreate_addr_space.c sw_64/Lget_proc_info.c sw_64/Lget_save_loc.c \ ++ sw_64/Lglobal.c sw_64/Linit.c sw_64/Linit_local.c sw_64/Linit_remote.c \ ++ sw_64/Lis_signal_frame.c sw_64/Lregs.c sw_64/Lresume.c sw_64/Lstep.c ++ ++libunwind_sw_64_la_SOURCES_sw_64 = $(libunwind_la_SOURCES_sw_64_common) \ ++ $(libunwind_la_SOURCES_generic) \ ++ sw_64/Gapply_reg_state.c sw_64/Greg_states_iterate.c \ ++ sw_64/Gcreate_addr_space.c sw_64/Gget_proc_info.c sw_64/Gget_save_loc.c \ ++ sw_64/Gglobal.c sw_64/Ginit.c sw_64/Ginit_local.c sw_64/Ginit_remote.c \ ++ sw_64/Gis_signal_frame.c sw_64/Gregs.c sw_64/Gresume.c sw_64/Gstep.c ++ + # The list of files that go both into libunwind and libunwind-x86: + noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h + libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ +@@ -651,6 +672,18 @@ endif + libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \ + ia64/longjmp.S ia64/siglongjmp.S + else ++if ARCH_SW_64 ++ lib_LTLIBRARIES += libunwind-sw_64.la ++ libunwind_la_SOURCES = $(libunwind_la_SOURCES_sw_64) ++ libunwind_sw_64_la_SOURCES = $(libunwind_sw_64_la_SOURCES_sw_64) ++ libunwind_sw_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) ++ libunwind_sw_64_la_LIBADD = libunwind-dwarf-generic.la ++ libunwind_sw_64_la_LIBADD += libunwind-elfxx.la ++if !REMOTE_ONLY ++ libunwind_sw_64_la_LIBADD += libunwind.la -lc ++endif ++ libunwind_setjmp_la_SOURCES += sw_64/siglongjmp.S ++else + if ARCH_HPPA + lib_LTLIBRARIES += libunwind-hppa.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa) +@@ -793,6 +826,7 @@ endif # ARCH_LOONGARCH64 + endif # ARCH_TILEGX + endif # ARCH_MIPS + endif # ARCH_HPPA ++endif # ARCH_SW_64 + endif # ARCH_IA64 + endif # ARCH_ARM + endif # ARCH_AARCH64 +@@ -838,6 +872,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ + $(libunwind_ia64_la_SOURCES_ia64) \ + $(libunwind_mips_la_SOURCES_mips) \ + $(libunwind_sh_la_SOURCES_sh) \ ++ $(libunwind_sw_64_la_SOURCES_sw_64) \ + $(libunwind_x86_la_SOURCES_x86) \ + $(libunwind_x86_64_la_SOURCES_x86_64) + +diff --git a/src/Makefile.in b/src/Makefile.in +index be215b5..fc7a964 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -152,6 +152,14 @@ target_triplet = @target@ + # libunwind-setjmp depends on libunwind-$(arch). Therefore must be added + # at the end. + @BUILD_SETJMP_TRUE@am__append_51 = libunwind-setjmp.la ++ ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@am__append_52 = libunwind-sw_64.la ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@@REMOTE_ONLY_FALSE@am__append_53 = libunwind.la -lc ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@am__append_54 = sw_64/siglongjmp.S ++ ++# libunwind-setjmp depends on libunwind-$(arch). Therefore must be added ++# at the end. ++@BUILD_SETJMP_TRUE@am__append_55 = libunwind-setjmp.la + subdir = src + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ +@@ -629,6 +637,7 @@ am__libunwind_setjmp_la_SOURCES_DIST = setjmp/longjmp.c \ + ia64/siglongjmp.S hppa/siglongjmp.S mips/siglongjmp.S \ + tilegx/siglongjmp.S riscv/siglongjmp.S x86/longjmp.S \ + x86/siglongjmp.S x86_64/longjmp.S x86_64/siglongjmp.S \ ++ sw_64/siglongjmp.S \ + ppc/longjmp.S ppc/siglongjmp.S sh/siglongjmp.S + @ARCH_AARCH64_TRUE@am__objects_31 = aarch64/siglongjmp.lo + @ARCH_AARCH64_FALSE@@ARCH_ARM_TRUE@am__objects_32 = arm/siglongjmp.lo +@@ -832,6 +841,11 @@ am__libunwind_la_SOURCES_DIST = os-freebsd.c os-hpux.c os-linux.c \ + sh/Lcreate_addr_space.c sh/Lget_proc_info.c sh/Lget_save_loc.c \ + sh/Lglobal.c sh/Linit.c sh/Linit_local.c sh/Linit_remote.c \ + sh/Lis_signal_frame.c sh/Lregs.c sh/Lresume.c sh/Lstep.c \ ++ sw_64/is_fpreg.c sw_64/regname.c \ ++ sw_64/getcontext.S sw_64/Lapply_reg_state.c sw_64/Lreg_states_iterate.c \ ++ sw_64/Lcreate_addr_space.c sw_64/Lget_proc_info.c sw_64/Lget_save_loc.c \ ++ sw_64/Lglobal.c sw_64/Linit.c sw_64/Linit_local.c sw_64/Linit_remote.c \ ++ sw_64/Lis_signal_frame.c sw_64/Lregs.c sw_64/Lresume.c sw_64/Lstep.c \ + ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c \ + ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \ + ppc/Linit_remote.c ppc/Lis_signal_frame.c \ +@@ -1044,6 +1058,57 @@ am__objects_75 = $(am__objects_8) $(am__objects_57) \ + @ARCH_AARCH64_FALSE@@ARCH_ARM_TRUE@am_libunwind_la_OBJECTS = \ + @ARCH_AARCH64_FALSE@@ARCH_ARM_TRUE@ $(am__objects_74) + @ARCH_AARCH64_TRUE@am_libunwind_la_OBJECTS = $(am__objects_75) ++ ++@ARCH_SW_64_TRUE@am__objects_76 = sw_64/siglongjmp.lo ++am_libunwind_setjmp_la_OBJECTS = setjmp/longjmp.lo \ ++ setjmp/siglongjmp.lo $(am__objects_76) ++libunwind_setjmp_la_OBJECTS = $(am_libunwind_setjmp_la_OBJECTS) ++libunwind_setjmp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(AM_CFLAGS) $(CFLAGS) $(libunwind_setjmp_la_LDFLAGS) \ ++ $(LDFLAGS) -o $@ ++@BUILD_SETJMP_TRUE@am_libunwind_setjmp_la_rpath = -rpath $(libdir) ++@ARCH_SW_64_TRUE@@REMOTE_ONLY_FALSE@am__DEPENDENCIES_15 = libunwind.la ++@ARCH_SW_64_TRUE@libunwind_sw_64_la_DEPENDENCIES = libunwind-dwarf-generic.la \ ++@ARCH_SW_64_TRUE@ libunwind-elfxx.la \ ++@ARCH_SW_64_TRUE@ $(am__DEPENDENCIES_15) ++am__libunwind_sw_64_la_SOURCES_DIST = os-freebsd.c os-hpux.c os-linux.c \ ++ os-qnx.c os-solaris.c mi/init.c mi/flush_cache.c mi/mempool.c \ ++ mi/strerror.c sw_64/is_fpreg.c sw_64/regname.c mi/Gdyn-extract.c \ ++ mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \ ++ mi/Gget_accessors.c mi/Gget_proc_info_by_ip.c \ ++ mi/Gget_proc_name.c mi/Gput_dynamic_unwind_info.c \ ++ mi/Gdestroy_addr_space.c mi/Gget_reg.c mi/Gset_reg.c \ ++ mi/Gget_fpreg.c mi/Gset_fpreg.c mi/Gset_caching_policy.c \ ++ mi/Gset_cache_size.c sw_64/Gapply_reg_state.c \ ++ sw_64/Greg_states_iterate.c sw_64/Gcreate_addr_space.c \ ++ sw_64/Gget_proc_info.c sw_64/Gget_save_loc.c sw_64/Gglobal.c sw_64/Ginit.c \ ++ sw_64/Ginit_local.c sw_64/Ginit_remote.c sw_64/Gis_signal_frame.c \ ++ sw_64/Gregs.c sw_64/Gresume.c sw_64/Gstep.c ++am__objects_76 = $(am__objects_7) sw_64/is_fpreg.lo sw_64/regname.lo ++am__objects_77 = $(am__objects_76) $(am__objects_9) \ ++ sw_64/Gapply_reg_state.lo sw_64/Greg_states_iterate.lo \ ++ sw_64/Gcreate_addr_space.lo sw_64/Gget_proc_info.lo \ ++ sw_64/Gget_save_loc.lo sw_64/Gglobal.lo sw_64/Ginit.lo \ ++ sw_64/Ginit_local.lo sw_64/Ginit_remote.lo sw_64/Gis_signal_frame.lo \ ++ sw_64/Gregs.lo sw_64/Gresume.lo sw_64/Gstep.lo ++@ARCH_SW_64_TRUE@am_libunwind_sw_64_la_OBJECTS = $(am__objects_77) ++libunwind_sw_64_la_OBJECTS = $(am_libunwind_sw_64_la_OBJECTS) ++libunwind_sw_64_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ ++ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ ++ $(AM_CFLAGS) $(CFLAGS) $(libunwind_sw_64_la_LDFLAGS) $(LDFLAGS) \ ++ -o $@ ++@ARCH_SW_64_TRUE@am_libunwind_sw_64_la_rpath = -rpath \ ++@ARCH_SW_64_TRUE@ $(libdir) ++am__objects_78 = $(am__objects_76) $(am__objects_57) \ ++ sw_64/getcontext.lo sw_64/Lapply_reg_state.lo \ ++ sw_64/Lreg_states_iterate.lo sw_64/Lcreate_addr_space.lo \ ++ sw_64/Lget_proc_info.lo sw_64/Lget_save_loc.lo sw_64/Lglobal.lo \ ++ sw_64/Linit.lo sw_64/Linit_local.lo sw_64/Linit_remote.lo \ ++ sw_64/Lis_signal_frame.lo sw_64/Lregs.lo sw_64/Lresume.lo \ ++ sw_64/Lstep.lo ++@ARCH_SW_64_TRUE@am_libunwind_la_OBJECTS = $(am__objects_78) ++ + libunwind_la_OBJECTS = $(am_libunwind_la_OBJECTS) + libunwind_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ +@@ -1344,6 +1409,25 @@ am__depfiles_remade = ./$(DEPDIR)/dl-iterate-phdr.Plo \ + sh/$(DEPDIR)/Lresume.Plo sh/$(DEPDIR)/Lstep.Plo \ + sh/$(DEPDIR)/is_fpreg.Plo sh/$(DEPDIR)/regname.Plo \ + sh/$(DEPDIR)/siglongjmp.Plo \ ++ sw_64/$(DEPDIR)/Gapply_reg_state.Plo \ ++ sw_64/$(DEPDIR)/Gcreate_addr_space.Plo \ ++ sw_64/$(DEPDIR)/Gget_proc_info.Plo sw_64/$(DEPDIR)/Gget_save_loc.Plo \ ++ sw_64/$(DEPDIR)/Gglobal.Plo sw_64/$(DEPDIR)/Ginit.Plo \ ++ sw_64/$(DEPDIR)/Ginit_local.Plo sw_64/$(DEPDIR)/Ginit_remote.Plo \ ++ sw_64/$(DEPDIR)/Gis_signal_frame.Plo \ ++ sw_64/$(DEPDIR)/Greg_states_iterate.Plo sw_64/$(DEPDIR)/Gregs.Plo \ ++ sw_64/$(DEPDIR)/Gresume.Plo sw_64/$(DEPDIR)/Gstep.Plo \ ++ sw_64/$(DEPDIR)/Lapply_reg_state.Plo \ ++ sw_64/$(DEPDIR)/Lcreate_addr_space.Plo \ ++ sw_64/$(DEPDIR)/Lget_proc_info.Plo sw_64/$(DEPDIR)/Lget_save_loc.Plo \ ++ sw_64/$(DEPDIR)/Lglobal.Plo sw_64/$(DEPDIR)/Linit.Plo \ ++ sw_64/$(DEPDIR)/Linit_local.Plo sw_64/$(DEPDIR)/Linit_remote.Plo \ ++ sw_64/$(DEPDIR)/Lis_signal_frame.Plo \ ++ sw_64/$(DEPDIR)/Lreg_states_iterate.Plo sw_64/$(DEPDIR)/Lregs.Plo \ ++ sw_64/$(DEPDIR)/Lresume.Plo sw_64/$(DEPDIR)/Lstep.Plo \ ++ sw_64/$(DEPDIR)/getcontext.Plo \ ++ sw_64/$(DEPDIR)/is_fpreg.Plo sw_64/$(DEPDIR)/regname.Plo \ ++ sw_64/$(DEPDIR)/siglongjmp.Plo \ + tilegx/$(DEPDIR)/Gapply_reg_state.Plo \ + tilegx/$(DEPDIR)/Gcreate_addr_space.Plo \ + tilegx/$(DEPDIR)/Gget_proc_info.Plo \ +@@ -1474,6 +1558,7 @@ SOURCES = $(libunwind_aarch64_la_SOURCES) $(libunwind_arm_la_SOURCES) \ + $(libunwind_ppc32_la_SOURCES) $(libunwind_ppc64_la_SOURCES) \ + $(libunwind_ptrace_la_SOURCES) $(libunwind_riscv_la_SOURCES) \ + $(libunwind_s390x_la_SOURCES) $(libunwind_setjmp_la_SOURCES) \ ++ $(libunwind_sw_64_la_SOURCES) \ + $(libunwind_sh_la_SOURCES) $(libunwind_tilegx_la_SOURCES) \ + $(libunwind_x86_la_SOURCES) $(libunwind_x86_64_la_SOURCES) \ + $(libunwind_la_SOURCES) +@@ -1495,6 +1580,7 @@ DIST_SOURCES = $(am__libunwind_aarch64_la_SOURCES_DIST) \ + $(am__libunwind_s390x_la_SOURCES_DIST) \ + $(am__libunwind_setjmp_la_SOURCES_DIST) \ + $(am__libunwind_sh_la_SOURCES_DIST) \ ++ $(am__libunwind_sw_64_la_SOURCES_DIST) \ + $(am__libunwind_tilegx_la_SOURCES_DIST) \ + $(am__libunwind_x86_la_SOURCES_DIST) \ + $(am__libunwind_x86_64_la_SOURCES_DIST) \ +@@ -1689,6 +1775,8 @@ lib_LTLIBRARIES = $(am__append_1) $(am__append_2) $(am__append_3) \ + $(am__append_31) $(am__append_34) $(am__append_37) \ + $(am__append_40) $(am__append_43) $(am__append_46) \ + $(am__append_49) $(am__append_51) ++lib_LTLIBRARIES = $(am__append_1) $(am__append_2) $(am__append_3) \ ++ $(am__append_52) $(am__append_55) + + # The list of files that go into libunwind and libunwind-aarch64: + +@@ -1714,6 +1802,8 @@ lib_LTLIBRARIES = $(am__append_1) $(am__append_2) $(am__append_3) \ + + # The list of files that go into libunwind and libunwind-sh: + ++# The list of files that go into libunwind and libunwind-sw_64: ++ + # The list of files that go both into libunwind and libunwind-s390x: + noinst_HEADERS = ptrace/_UPT_internal.h coredump/_UCD_internal.h \ + coredump/_UCD_lib.h setjmp/setjmp_i.h os-linux.h elf32.h \ +@@ -1729,6 +1819,7 @@ noinst_HEADERS = ptrace/_UPT_internal.h coredump/_UCD_internal.h \ + x86_64/unwind_i.h x86_64/ucontext_i.h ppc32/init.h \ + ppc32/unwind_i.h ppc32/ucontext_i.h ppc64/init.h \ + ppc64/unwind_i.h ppc64/ucontext_i.h sh/init.h sh/offsets.h \ ++ sw_64/init.h sw_64/offsets.h sw_64/unwind_i.h \ + sh/unwind_i.h s390x/init.h s390x/unwind_i.h \ + unwind/unwind-internal.h + noinst_LTLIBRARIES = $(am__append_8) $(am__append_9) $(LIBUNWIND_ELF) +@@ -1778,6 +1869,8 @@ libunwind_setjmp_la_SOURCES = setjmp/longjmp.c setjmp/siglongjmp.c \ + $(am__append_24) $(am__append_27) $(am__append_30) \ + $(am__append_33) $(am__append_36) $(am__append_39) \ + $(am__append_42) $(am__append_45) $(am__append_48) ++libunwind_setjmp_la_SOURCES = setjmp/longjmp.c setjmp/siglongjmp.c \ ++ $(am__append_54) + + ### libunwind: + libunwind_la_LIBADD = $(am__append_10) $(LIBUNWIND_ELF) -lc $(LIBCRTS) \ +@@ -2150,6 +2243,26 @@ libunwind_sh_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \ + sh/Gglobal.c sh/Ginit.c sh/Ginit_local.c sh/Ginit_remote.c \ + sh/Gis_signal_frame.c sh/Gregs.c sh/Gresume.c sh/Gstep.c + ++libunwind_la_SOURCES_sw_64_common = $(libunwind_la_SOURCES_common) \ ++sw_64/is_fpreg.c sw_64/regname.c ++ ++ ++# The list of files that go into libunwind: ++libunwind_la_SOURCES_sw_64 = $(libunwind_la_SOURCES_sw_64_common) \ ++ $(libunwind_la_SOURCES_local) \ ++ sw_64/getcontext.S \ ++ sw_64/Lapply_reg_state.c sw_64/Lreg_states_iterate.c \ ++ sw_64/Lcreate_addr_space.c sw_64/Lget_proc_info.c sw_64/Lget_save_loc.c \ ++ sw_64/Lglobal.c sw_64/Linit.c sw_64/Linit_local.c sw_64/Linit_remote.c \ ++ sw_64/Lis_signal_frame.c sw_64/Lregs.c sw_64/Lresume.c sw_64/Lstep.c ++ ++libunwind_sw_64_la_SOURCES_sw_64 = $(libunwind_la_SOURCES_sw_64_common) \ ++ $(libunwind_la_SOURCES_generic) \ ++ sw_64/Gapply_reg_state.c sw_64/Greg_states_iterate.c \ ++ sw_64/Gcreate_addr_space.c sw_64/Gget_proc_info.c sw_64/Gget_save_loc.c \ ++ sw_64/Gglobal.c sw_64/Ginit.c sw_64/Ginit_local.c sw_64/Ginit_remote.c \ ++ sw_64/Gis_signal_frame.c sw_64/Gregs.c sw_64/Gresume.c sw_64/Gstep.c ++ + libunwind_la_SOURCES_s390x_common = $(libunwind_la_SOURCES_common) \ + s390x/is_fpreg.c s390x/regname.c + +@@ -2280,6 +2393,12 @@ libunwind_s390x_la_SOURCES_s390x = $(libunwind_la_SOURCES_s390x_common) \ + @ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_S390X_TRUE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@libunwind_s390x_la_LIBADD = libunwind-dwarf-generic.la \ + @ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_S390X_TRUE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@ libunwind-elf64.la \ + @ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_S390X_TRUE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@ $(am__append_50) ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@libunwind_sw_64_la_SOURCES = $(libunwind_sw_64_la_SOURCES_sw_64) ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@libunwind_sw_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@libunwind_sw_64_la_LIBADD = libunwind-dwarf-generic.la \ ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@ libunwind-elfxx.la \ ++@ARCH_AARCH64_FALSE@@ARCH_ARM_FALSE@@ARCH_HPPA_FALSE@@ARCH_IA64_FALSE@@ARCH_MIPS_FALSE@@ARCH_PPC32_FALSE@@ARCH_PPC64_FALSE@@ARCH_RISCV_FALSE@@ARCH_SW_64_TRUE@@ARCH_S390X_FALSE@@ARCH_SH_FALSE@@ARCH_TILEGX_FALSE@@ARCH_X86_64_FALSE@@ARCH_X86_FALSE@ $(am__append_53) ++ + + # + # Don't link with standard libraries, because those may mention +@@ -2297,6 +2416,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ + $(libunwind_la_EXTRAS_ia64) \ + $(libunwind_la_SOURCES_mips) \ + $(libunwind_la_SOURCES_sh) \ ++ $(libunwind_la_SOURCES_sw_64) \ + $(libunwind_la_SOURCES_x86) \ + $(libunwind_la_SOURCES_os_freebsd) \ + $(libunwind_la_SOURCES_os_linux) \ +@@ -2312,6 +2432,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ + $(libunwind_ia64_la_SOURCES_ia64) \ + $(libunwind_mips_la_SOURCES_mips) \ + $(libunwind_sh_la_SOURCES_sh) \ ++ $(libunwind_sw_64_la_SOURCES_sw_64) \ + $(libunwind_x86_la_SOURCES_x86) \ + $(libunwind_x86_64_la_SOURCES_x86_64) + +@@ -2986,6 +3107,38 @@ sh/Gstep.lo: sh/$(am__dirstamp) sh/$(DEPDIR)/$(am__dirstamp) + + libunwind-sh.la: $(libunwind_sh_la_OBJECTS) $(libunwind_sh_la_DEPENDENCIES) $(EXTRA_libunwind_sh_la_DEPENDENCIES) + $(AM_V_CCLD)$(libunwind_sh_la_LINK) $(am_libunwind_sh_la_rpath) $(libunwind_sh_la_OBJECTS) $(libunwind_sh_la_LIBADD) $(LIBS) ++sw_64/$(am__dirstamp): ++ @$(MKDIR_P) sw_64 ++ @: > sw_64/$(am__dirstamp) ++sw_64/$(DEPDIR)/$(am__dirstamp): ++ @$(MKDIR_P) sw_64/$(DEPDIR) ++ @: > sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/siglongjmp.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++ ++libunwind-setjmp.la: $(libunwind_setjmp_la_OBJECTS) $(libunwind_setjmp_la_DEPENDENCIES) $(EXTRA_libunwind_setjmp_la_DEPENDENCIES) ++ $(AM_V_CCLD)$(libunwind_setjmp_la_LINK) $(am_libunwind_setjmp_la_rpath) $(libunwind_setjmp_la_OBJECTS) $(libunwind_setjmp_la_LIBADD) $(LIBS) ++sw_64/is_fpreg.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/regname.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gapply_reg_state.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Greg_states_iterate.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gcreate_addr_space.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gget_proc_info.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gget_save_loc.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gglobal.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Ginit.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Ginit_local.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Ginit_remote.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gis_signal_frame.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gregs.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gresume.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Gstep.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++ ++libunwind-sw_64.la: $(libunwind_sw_64_la_OBJECTS) $(libunwind_sw_64_la_DEPENDENCIES) $(EXTRA_libunwind_sw_64_la_DEPENDENCIES) ++ $(AM_V_CCLD)$(libunwind_sw_64_la_LINK) $(am_libunwind_sw_64_la_rpath) $(libunwind_sw_64_la_OBJECTS) $(libunwind_sw_64_la_LIBADD) $(LIBS) + tilegx/is_fpreg.lo: tilegx/$(am__dirstamp) \ + tilegx/$(DEPDIR)/$(am__dirstamp) + tilegx/regname.lo: tilegx/$(am__dirstamp) \ +@@ -3194,6 +3347,25 @@ sh/Lis_signal_frame.lo: sh/$(am__dirstamp) \ + sh/Lregs.lo: sh/$(am__dirstamp) sh/$(DEPDIR)/$(am__dirstamp) + sh/Lresume.lo: sh/$(am__dirstamp) sh/$(DEPDIR)/$(am__dirstamp) + sh/Lstep.lo: sh/$(am__dirstamp) sh/$(DEPDIR)/$(am__dirstamp) ++sw_64/getcontext.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lapply_reg_state.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lreg_states_iterate.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lcreate_addr_space.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lget_proc_info.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lget_save_loc.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lglobal.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Linit.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Linit_local.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Linit_remote.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lis_signal_frame.lo: sw_64/$(am__dirstamp) \ ++ sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lregs.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lresume.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) ++sw_64/Lstep.lo: sw_64/$(am__dirstamp) sw_64/$(DEPDIR)/$(am__dirstamp) + ppc/Lget_proc_info.lo: ppc/$(am__dirstamp) \ + ppc/$(DEPDIR)/$(am__dirstamp) + ppc/Lget_save_loc.lo: ppc/$(am__dirstamp) \ +@@ -3519,6 +3691,8 @@ mostlyclean-compile: + -rm -f setjmp/*.lo + -rm -f sh/*.$(OBJEXT) + -rm -f sh/*.lo ++ -rm -f sw_64/*.$(OBJEXT) ++ -rm -f sw_64/*.lo + -rm -f tilegx/*.$(OBJEXT) + -rm -f tilegx/*.lo + -rm -f unwind/*.$(OBJEXT) +@@ -3942,6 +4116,36 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@sh/$(DEPDIR)/is_fpreg.Plo@am__quote@ # am--include-marker + @AMDEP_TRUE@@am__include@ @am__quote@sh/$(DEPDIR)/regname.Plo@am__quote@ # am--include-marker + @AMDEP_TRUE@@am__include@ @am__quote@sh/$(DEPDIR)/siglongjmp.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gapply_reg_state.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gcreate_addr_space.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gget_proc_info.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gget_save_loc.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gglobal.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Ginit.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Ginit_local.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Ginit_remote.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gis_signal_frame.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Greg_states_iterate.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gregs.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gresume.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Gstep.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lapply_reg_state.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lcreate_addr_space.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lget_proc_info.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lget_save_loc.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lglobal.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Linit.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Linit_local.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Linit_remote.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lis_signal_frame.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lreg_states_iterate.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lregs.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lresume.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/Lstep.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/getcontext.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/is_fpreg.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/regname.Plo@am__quote@ # am--include-marker ++@AMDEP_TRUE@@am__include@ @am__quote@sw_64/$(DEPDIR)/siglongjmp.Plo@am__quote@ # am--include-marker + @AMDEP_TRUE@@am__include@ @am__quote@tilegx/$(DEPDIR)/Gapply_reg_state.Plo@am__quote@ # am--include-marker + @AMDEP_TRUE@@am__include@ @am__quote@tilegx/$(DEPDIR)/Gcreate_addr_space.Plo@am__quote@ # am--include-marker + @AMDEP_TRUE@@am__include@ @am__quote@tilegx/$(DEPDIR)/Gget_proc_info.Plo@am__quote@ # am--include-marker +@@ -4140,6 +4344,7 @@ clean-libtool: + -rm -rf s390x/.libs s390x/_libs + -rm -rf setjmp/.libs setjmp/_libs + -rm -rf sh/.libs sh/_libs ++ -rm -rf sw_64/.libs sw_64/_libs + -rm -rf tilegx/.libs tilegx/_libs + -rm -rf unwind/.libs unwind/_libs + -rm -rf x86/.libs x86/_libs +@@ -4318,6 +4523,8 @@ distclean-generic: + -rm -f setjmp/$(am__dirstamp) + -rm -f sh/$(DEPDIR)/$(am__dirstamp) + -rm -f sh/$(am__dirstamp) ++ -rm -f sw_64/$(DEPDIR)/$(am__dirstamp) ++ -rm -f sw_64/$(am__dirstamp) + -rm -f tilegx/$(DEPDIR)/$(am__dirstamp) + -rm -f tilegx/$(am__dirstamp) + -rm -f unwind/$(DEPDIR)/$(am__dirstamp) +@@ -4749,6 +4956,36 @@ distclean: distclean-am + -rm -f sh/$(DEPDIR)/is_fpreg.Plo + -rm -f sh/$(DEPDIR)/regname.Plo + -rm -f sh/$(DEPDIR)/siglongjmp.Plo ++ -rm -f sw_64/$(DEPDIR)/Gapply_reg_state.Plo ++ -rm -f sw_64/$(DEPDIR)/Gcreate_addr_space.Plo ++ -rm -f sw_64/$(DEPDIR)/Gget_proc_info.Plo ++ -rm -f sw_64/$(DEPDIR)/Gget_save_loc.Plo ++ -rm -f sw_64/$(DEPDIR)/Gglobal.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit_local.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit_remote.Plo ++ -rm -f sw_64/$(DEPDIR)/Gis_signal_frame.Plo ++ -rm -f sw_64/$(DEPDIR)/Greg_states_iterate.Plo ++ -rm -f sw_64/$(DEPDIR)/Gregs.Plo ++ -rm -f sw_64/$(DEPDIR)/Gresume.Plo ++ -rm -f sw_64/$(DEPDIR)/Gstep.Plo ++ -rm -f sw_64/$(DEPDIR)/Lapply_reg_state.Plo ++ -rm -f sw_64/$(DEPDIR)/Lcreate_addr_space.Plo ++ -rm -f sw_64/$(DEPDIR)/Lget_proc_info.Plo ++ -rm -f sw_64/$(DEPDIR)/Lget_save_loc.Plo ++ -rm -f sw_64/$(DEPDIR)/Lglobal.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit_local.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit_remote.Plo ++ -rm -f sw_64/$(DEPDIR)/Lis_signal_frame.Plo ++ -rm -f sw_64/$(DEPDIR)/Lreg_states_iterate.Plo ++ -rm -f sw_64/$(DEPDIR)/Lregs.Plo ++ -rm -f sw_64/$(DEPDIR)/Lresume.Plo ++ -rm -f sw_64/$(DEPDIR)/Lstep.Plo ++ -rm -f sw_64/$(DEPDIR)/getcontext.Plo ++ -rm -f sw_64/$(DEPDIR)/is_fpreg.Plo ++ -rm -f sw_64/$(DEPDIR)/regname.Plo ++ -rm -f sw_64/$(DEPDIR)/siglongjmp.Plo + -rm -f tilegx/$(DEPDIR)/Gapply_reg_state.Plo + -rm -f tilegx/$(DEPDIR)/Gcreate_addr_space.Plo + -rm -f tilegx/$(DEPDIR)/Gget_proc_info.Plo +@@ -5328,6 +5565,36 @@ maintainer-clean: maintainer-clean-am + -rm -f sh/$(DEPDIR)/is_fpreg.Plo + -rm -f sh/$(DEPDIR)/regname.Plo + -rm -f sh/$(DEPDIR)/siglongjmp.Plo ++ -rm -f sw_64/$(DEPDIR)/Gapply_reg_state.Plo ++ -rm -f sw_64/$(DEPDIR)/Gcreate_addr_space.Plo ++ -rm -f sw_64/$(DEPDIR)/Gget_proc_info.Plo ++ -rm -f sw_64/$(DEPDIR)/Gget_save_loc.Plo ++ -rm -f sw_64/$(DEPDIR)/Gglobal.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit_local.Plo ++ -rm -f sw_64/$(DEPDIR)/Ginit_remote.Plo ++ -rm -f sw_64/$(DEPDIR)/Gis_signal_frame.Plo ++ -rm -f sw_64/$(DEPDIR)/Greg_states_iterate.Plo ++ -rm -f sw_64/$(DEPDIR)/Gregs.Plo ++ -rm -f sw_64/$(DEPDIR)/Gresume.Plo ++ -rm -f sw_64/$(DEPDIR)/Gstep.Plo ++ -rm -f sw_64/$(DEPDIR)/Lapply_reg_state.Plo ++ -rm -f sw_64/$(DEPDIR)/Lcreate_addr_space.Plo ++ -rm -f sw_64/$(DEPDIR)/Lget_proc_info.Plo ++ -rm -f sw_64/$(DEPDIR)/Lget_save_loc.Plo ++ -rm -f sw_64/$(DEPDIR)/Lglobal.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit_local.Plo ++ -rm -f sw_64/$(DEPDIR)/Linit_remote.Plo ++ -rm -f sw_64/$(DEPDIR)/Lis_signal_frame.Plo ++ -rm -f sw_64/$(DEPDIR)/Lreg_states_iterate.Plo ++ -rm -f sw_64/$(DEPDIR)/Lregs.Plo ++ -rm -f sw_64/$(DEPDIR)/Lresume.Plo ++ -rm -f sw_64/$(DEPDIR)/Lstep.Plo ++ -rm -f sw_64/$(DEPDIR)/getcontext.Plo ++ -rm -f sw_64/$(DEPDIR)/is_fpreg.Plo ++ -rm -f sw_64/$(DEPDIR)/regname.Plo ++ -rm -f sw_64/$(DEPDIR)/siglongjmp.Plo + -rm -f tilegx/$(DEPDIR)/Gapply_reg_state.Plo + -rm -f tilegx/$(DEPDIR)/Gcreate_addr_space.Plo + -rm -f tilegx/$(DEPDIR)/Gget_proc_info.Plo +diff --git a/src/coredump/_UCD_access_reg_linux.c b/src/coredump/_UCD_access_reg_linux.c +index f22d164..1ed6946 100644 +--- a/src/coredump/_UCD_access_reg_linux.c ++++ b/src/coredump/_UCD_access_reg_linux.c +@@ -167,6 +167,43 @@ _UCD_access_reg (unw_addr_space_t as, + [UNW_X86_64_RSP] = offsetof(struct user_regs_struct, rsp) / sizeof(long), + [UNW_X86_64_RIP] = offsetof(struct user_regs_struct, rip) / sizeof(long), + }; ++#elif defined(UNW_TARGET_SW_64) ++ static const uint8_t remap_regs[] = ++ { ++ [UNW_SW_64_R0] = 0, ++ [UNW_SW_64_R1] = 1, ++ [UNW_SW_64_R2] = 2, ++ [UNW_SW_64_R3] = 3, ++ [UNW_SW_64_R4] = 4, ++ [UNW_SW_64_R5] = 5, ++ [UNW_SW_64_R6] = 6, ++ [UNW_SW_64_R7] = 7, ++ [UNW_SW_64_R8] = 8, ++ [UNW_SW_64_R9] = 9, ++ [UNW_SW_64_R10] = 10, ++ [UNW_SW_64_R11] = 11, ++ [UNW_SW_64_R12] = 12, ++ [UNW_SW_64_R13] = 13, ++ [UNW_SW_64_R14] = 14, ++ [UNW_SW_64_R15] = 15, ++ [UNW_SW_64_R16] = 16, ++ [UNW_SW_64_R17] = 17, ++ [UNW_SW_64_R18] = 18, ++ [UNW_SW_64_R19] = 19, ++ [UNW_SW_64_R20] = 20, ++ [UNW_SW_64_R21] = 21, ++ [UNW_SW_64_R22] = 22, ++ [UNW_SW_64_R23] = 23, ++ [UNW_SW_64_R24] = 24, ++ [UNW_SW_64_R25] = 25, ++ [UNW_SW_64_R26] = 26, ++ [UNW_SW_64_R27] = 27, ++ [UNW_SW_64_R28] = 28, ++ [UNW_SW_64_R29] = 29, ++ [UNW_SW_64_R30] = 30, ++ [UNW_SW_64_PC] = 31, ++ [UNW_SW_64_R31] = 32, ++ }; + #else + #error Port me + #endif +diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c +index 80a072e..8e47bbd 100644 +--- a/src/ptrace/_UPT_reg_offset.c ++++ b/src/ptrace/_UPT_reg_offset.c +@@ -679,6 +679,72 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] = + [UNW_TILEGX_R54] = 0x1b0, + [UNW_TILEGX_R55] = 0x1b8, + [UNW_TILEGX_PC] = 0x1a0 ++#elif defined(UNW_TARGET_SW_64) ++ [UNW_SW_64_R0] = 0x00, ++ [UNW_SW_64_R1] = 0x1, ++ [UNW_SW_64_R2] = 0x2, ++ [UNW_SW_64_R3] = 0x3, ++ [UNW_SW_64_R4] = 0x4, ++ [UNW_SW_64_R5] = 0x5, ++ [UNW_SW_64_R6] = 0x6, ++ [UNW_SW_64_R7] = 0x7, ++ [UNW_SW_64_R8] = 0x8, ++ [UNW_SW_64_R9] = 0x9, ++ [UNW_SW_64_R10] = 10, ++ [UNW_SW_64_R11] = 11, ++ [UNW_SW_64_R12] = 12, ++ [UNW_SW_64_R13] = 13, ++ [UNW_SW_64_R14] = 14, ++ [UNW_SW_64_R15] = 0xf, ++ [UNW_SW_64_R16] = 0x10, ++ [UNW_SW_64_R17] = 0x11, ++ [UNW_SW_64_R18] = 0x12, ++ [UNW_SW_64_R19] = 0x13, ++ [UNW_SW_64_R20] = 0x14, ++ [UNW_SW_64_R21] = 0x15, ++ [UNW_SW_64_R22] = 0x16, ++ [UNW_SW_64_R23] = 0x17, ++ [UNW_SW_64_R24] = 0x18, ++ [UNW_SW_64_R25] = 0x19, ++ [UNW_SW_64_R26] = 0x1a, ++ [UNW_SW_64_R27] = 0x1b, ++ [UNW_SW_64_R28] = 0x1c, ++ [UNW_SW_64_R29] = 0x1d, ++ [UNW_SW_64_R30] = 0x1e, ++ [UNW_SW_64_R31] = 0x1f, ++ [UNW_SW_64_F0] = 0x20, ++ [UNW_SW_64_F1] = 0x21, ++ [UNW_SW_64_F2] = 0x22, ++ [UNW_SW_64_F3] = 0x23, ++ [UNW_SW_64_F4] = 0x24, ++ [UNW_SW_64_F5] = 0x25, ++ [UNW_SW_64_F6] = 0x26, ++ [UNW_SW_64_F7] = 0x27, ++ [UNW_SW_64_F8] = 0x28, ++ [UNW_SW_64_F9] = 0x29, ++ [UNW_SW_64_F10] = 0x2a, ++ [UNW_SW_64_F11] = 0x2b, ++ [UNW_SW_64_F12] = 0x2c, ++ [UNW_SW_64_F13] = 0x2d, ++ [UNW_SW_64_F14] = 0x2e, ++ [UNW_SW_64_F15] = 0x2f, ++ [UNW_SW_64_F16] = 0x30, ++ [UNW_SW_64_F17] = 0x31, ++ [UNW_SW_64_F18] = 0x32, ++ [UNW_SW_64_F19] = 0x33, ++ [UNW_SW_64_F20] = 0x34, ++ [UNW_SW_64_F21] = 0x35, ++ [UNW_SW_64_F22] = 0x36, ++ [UNW_SW_64_F23] = 0x37, ++ [UNW_SW_64_F24] = 0x38, ++ [UNW_SW_64_F25] = 0x39, ++ [UNW_SW_64_F26] = 0x3a, ++ [UNW_SW_64_F27] = 0x3b, ++ [UNW_SW_64_F28] = 0x3c, ++ [UNW_SW_64_F29] = 0x3d, ++ [UNW_SW_64_F30] = 0x3e, ++ [UNW_SW_64_FPCR] = 0x3f, ++ [UNW_SW_64_PC] = 0x40, + #elif defined(UNW_TARGET_S390X) + [UNW_S390X_R0] = 0x10, + [UNW_S390X_R1] = 0x18, +diff --git a/tests/Makefile.am b/tests/Makefile.am +index b513c72..d54511d 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -124,6 +124,10 @@ if ARCH_LOONGARCH64 + XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) + endif + ++if ARCH_SW_64 ++XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) ++endif ++ + if ARCH_ARM + # ARM Linux kernel >=2.6.39 removed PTRACE_SINGLESTEP emulation + XFAIL_TESTS += $(XFAIL_TESTS_PTRACE_SINGLESTEP) +diff --git a/tests/Makefile.in b/tests/Makefile.in +index 359f815..966152e 100644 +--- a/tests/Makefile.in ++++ b/tests/Makefile.in +@@ -139,7 +139,7 @@ XFAIL_TESTS = $(am__append_17) $(am__append_18) $(am__append_19) \ + + XFAIL_TESTS = $(am__append_20) + @ARCH_LOONGARCH64_TRUE@am__append_20 = $(XFAIL_TESTS_PTRACE_SINGLESTEP) +- ++@ARCH_SW_64_TRUE@am__append_20 = $(XFAIL_TESTS_PTRACE_SINGLESTEP) + noinst_PROGRAMS = $(am__EXEEXT_11) $(am__EXEEXT_15) $(am__EXEEXT_18) + subdir = tests + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in +index 3291c8a..ce4beae 100644 +--- a/tests/check-namespace.sh.in ++++ b/tests/check-namespace.sh.in +@@ -167,6 +167,13 @@ check_local_unw_abi () { + match _UL${plat}_dwarf_find_unwind_table + match _U${plat}_setcontext + ;; ++ sw_64) ++ match _U${plat}_get_elf_image ++ match _U${plat}_get_exe_image_path ++ match _U${plat}_is_fpreg ++ match _UL${plat}_dwarf_search_unwind_table ++ match _UL${plat}_dwarf_find_unwind_table ++ ;; + ppc*) + match _U${plat}_getcontext + match _U${plat}_get_func_addr +@@ -284,6 +291,13 @@ check_generic_unw_abi () { + match _U${plat}_dwarf_search_unwind_table + match _U${plat}_dwarf_find_unwind_table + ;; ++ sw_64) ++ match _U${plat}_get_elf_image ++ match _U${plat}_get_exe_image_path ++ match _U${plat}_is_fpreg ++ match _U${plat}_dwarf_search_unwind_table ++ match _U${plat}_dwarf_find_unwind_table ++ ;; + ppc*) + match _U${plat}_get_elf_image + match _U${plat}_get_exe_image_path +-- +2.41.0 + diff --git a/add-sw_64-support-not-upstream-new.patch b/add-sw_64-support-not-upstream-new.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7e160f70ab3faccaefd7320155e4b40592eddd9 --- /dev/null +++ b/add-sw_64-support-not-upstream-new.patch @@ -0,0 +1,2751 @@ +From 825a84e50f83adcb34f17d6fd8003f7e3eff4549 Mon Sep 17 00:00:00 2001 +From: herengui +Date: Mon, 28 Aug 2023 16:16:13 +0800 +Subject: [PATCH 2/2] libunwind sw_64 architecture resources + +Signed-off-by: herengui +--- + include/libunwind-sw_64.h | 178 +++++++++++++++ + include/tdep-sw_64/dwarf-config.h | 51 +++++ + include/tdep-sw_64/jmpbuf.h | 32 +++ + include/tdep-sw_64/libunwind_i.h | 349 ++++++++++++++++++++++++++++++ + src/sw_64/Gapply_reg_state.c | 37 ++++ + src/sw_64/Gcreate_addr_space.c | 65 ++++++ + src/sw_64/Gget_proc_info.c | 44 ++++ + src/sw_64/Gget_save_loc.c | 132 +++++++++++ + src/sw_64/Gglobal.c | 56 +++++ + src/sw_64/Ginit.c | 202 +++++++++++++++++ + src/sw_64/Ginit_local.c | 76 +++++++ + src/sw_64/Ginit_remote.c | 45 ++++ + src/sw_64/Gis_signal_frame.c | 116 ++++++++++ + src/sw_64/Greg_states_iterate.c | 37 ++++ + src/sw_64/Gregs.c | 131 +++++++++++ + src/sw_64/Gresume.c | 112 ++++++++++ + src/sw_64/Gstep.c | 349 ++++++++++++++++++++++++++++++ + src/sw_64/Lapply_reg_state.c | 5 + + src/sw_64/Lcreate_addr_space.c | 5 + + src/sw_64/Lget_proc_info.c | 5 + + src/sw_64/Lget_save_loc.c | 5 + + src/sw_64/Lglobal.c | 5 + + src/sw_64/Linit.c | 5 + + src/sw_64/Linit_local.c | 5 + + src/sw_64/Linit_remote.c | 5 + + src/sw_64/Lis_signal_frame.c | 5 + + src/sw_64/Lreg_states_iterate.c | 5 + + src/sw_64/Lregs.c | 5 + + src/sw_64/Lresume.c | 5 + + src/sw_64/Lstep.c | 5 + + src/sw_64/getcontext.S | 77 +++++++ + src/sw_64/init.h | 59 +++++ + src/sw_64/is_fpreg.c | 37 ++++ + src/sw_64/offsets.h | 86 ++++++++ + src/sw_64/regname.c | 55 +++++ + src/sw_64/siglongjmp.S | 9 + + src/sw_64/unwind_i.h | 43 ++++ + 37 files changed, 2443 insertions(+) + create mode 100644 include/libunwind-sw_64.h + create mode 100644 include/tdep-sw_64/dwarf-config.h + create mode 100644 include/tdep-sw_64/jmpbuf.h + create mode 100644 include/tdep-sw_64/libunwind_i.h + create mode 100644 src/sw_64/Gapply_reg_state.c + create mode 100644 src/sw_64/Gcreate_addr_space.c + create mode 100644 src/sw_64/Gget_proc_info.c + create mode 100644 src/sw_64/Gget_save_loc.c + create mode 100644 src/sw_64/Gglobal.c + create mode 100644 src/sw_64/Ginit.c + create mode 100644 src/sw_64/Ginit_local.c + create mode 100644 src/sw_64/Ginit_remote.c + create mode 100644 src/sw_64/Gis_signal_frame.c + create mode 100644 src/sw_64/Greg_states_iterate.c + create mode 100644 src/sw_64/Gregs.c + create mode 100644 src/sw_64/Gresume.c + create mode 100644 src/sw_64/Gstep.c + create mode 100644 src/sw_64/Lapply_reg_state.c + create mode 100644 src/sw_64/Lcreate_addr_space.c + create mode 100644 src/sw_64/Lget_proc_info.c + create mode 100644 src/sw_64/Lget_save_loc.c + create mode 100644 src/sw_64/Lglobal.c + create mode 100644 src/sw_64/Linit.c + create mode 100644 src/sw_64/Linit_local.c + create mode 100644 src/sw_64/Linit_remote.c + create mode 100644 src/sw_64/Lis_signal_frame.c + create mode 100644 src/sw_64/Lreg_states_iterate.c + create mode 100644 src/sw_64/Lregs.c + create mode 100644 src/sw_64/Lresume.c + create mode 100644 src/sw_64/Lstep.c + create mode 100644 src/sw_64/getcontext.S + create mode 100644 src/sw_64/init.h + create mode 100644 src/sw_64/is_fpreg.c + create mode 100644 src/sw_64/offsets.h + create mode 100644 src/sw_64/regname.c + create mode 100644 src/sw_64/siglongjmp.S + create mode 100644 src/sw_64/unwind_i.h + +diff --git a/include/libunwind-sw_64.h b/include/libunwind-sw_64.h +new file mode 100644 +index 0000000..cf92772 +--- /dev/null ++++ b/include/libunwind-sw_64.h +@@ -0,0 +1,178 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 LIBUNWIND_H ++#define LIBUNWIND_H ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++extern "C" { ++#endif ++ ++#include ++#include ++ ++#ifdef sw_64 ++# undef sw_64 ++#endif ++ ++#define UNW_TARGET sw_64 ++#define UNW_TARGET_SW_64 1 ++ ++#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ ++ ++/* This needs to be big enough to accommodate "struct cursor", while ++ leaving some slack for future expansion. Changing this value will ++ require recompiling all users of this library. Stack allocation is ++ relatively cheap and unwind-state copying is relatively rare, so we ++ want to err on making it rather too big than too small. */ ++ ++/* FIXME for SW_64. Too big? What do other things use for similar tasks? */ ++#define UNW_TDEP_CURSOR_LEN 4096 ++ ++/* The size of a "word" varies on SW_64. This type is used for memory ++ addresses and register values, which are 32-bit wide for O32 and N32 ++ ABIs, and 64-bit wide for N64 ABI. */ ++typedef uint64_t unw_word_t; ++typedef int32_t unw_sword_t; ++ ++/* FIXME: SW_64 ABIs. */ ++typedef long double unw_tdep_fpreg_t; ++ ++typedef enum ++ { ++ UNW_SW_64_R0, ++ UNW_SW_64_R1, ++ UNW_SW_64_R2, ++ UNW_SW_64_R3, ++ UNW_SW_64_R4, ++ UNW_SW_64_R5, ++ UNW_SW_64_R6, ++ UNW_SW_64_R7, ++ UNW_SW_64_R8, ++ UNW_SW_64_R9, ++ UNW_SW_64_R10, ++ UNW_SW_64_R11, ++ UNW_SW_64_R12, ++ UNW_SW_64_R13, ++ UNW_SW_64_R14, ++ UNW_SW_64_R15, ++ UNW_SW_64_R16, ++ UNW_SW_64_R17, ++ UNW_SW_64_R18, ++ UNW_SW_64_R19, ++ UNW_SW_64_R20, ++ UNW_SW_64_R21, ++ UNW_SW_64_R22, ++ UNW_SW_64_R23, ++ UNW_SW_64_R24, ++ UNW_SW_64_R25, ++ UNW_SW_64_R26, ++ UNW_SW_64_R27, ++ UNW_SW_64_R28, ++ UNW_SW_64_R29, ++ UNW_SW_64_R30, ++ UNW_SW_64_R31, ++ UNW_SW_64_F0, ++ UNW_SW_64_F1, ++ UNW_SW_64_F2, ++ UNW_SW_64_F3, ++ UNW_SW_64_F4, ++ UNW_SW_64_F5, ++ UNW_SW_64_F6, ++ UNW_SW_64_F7, ++ UNW_SW_64_F8, ++ UNW_SW_64_F9, ++ UNW_SW_64_F10, ++ UNW_SW_64_F11, ++ UNW_SW_64_F12, ++ UNW_SW_64_F13, ++ UNW_SW_64_F14, ++ UNW_SW_64_F15, ++ UNW_SW_64_F16, ++ UNW_SW_64_F17, ++ UNW_SW_64_F18, ++ UNW_SW_64_F19, ++ UNW_SW_64_F20, ++ UNW_SW_64_F21, ++ UNW_SW_64_F22, ++ UNW_SW_64_F23, ++ UNW_SW_64_F24, ++ UNW_SW_64_F25, ++ UNW_SW_64_F26, ++ UNW_SW_64_F27, ++ UNW_SW_64_F28, ++ UNW_SW_64_F29, ++ UNW_SW_64_F30, ++ UNW_SW_64_FPCR, ++ UNW_SW_64_PC = 64, ++ ++ UNW_TDEP_LAST_REG = UNW_SW_64_PC, ++ UNW_TDEP_IP = UNW_SW_64_PC, ++ UNW_TDEP_SP = UNW_SW_64_R30, ++ UNW_TDEP_EH = UNW_SW_64_R0 ++ } ++sw_64_regnum_t; ++ ++typedef enum ++ { ++ UNW_SW_64_ABI_N64 ++ } ++sw_64_abi_t; ++ ++#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for SW_64. */ ++ ++typedef struct unw_tdep_save_loc ++ { ++ /* Additional target-dependent info on a save location. */ ++ } ++unw_tdep_save_loc_t; ++ ++/* On x86, we can directly use ucontext_t as the unwind context. FIXME for ++ SW_64. */ ++typedef ucontext_t unw_tdep_context_t; ++ ++#include "libunwind-dynamic.h" ++ ++typedef struct ++ { ++ /* no sw_64-specific auxiliary proc-info */ ++ } ++unw_tdep_proc_info_t; ++ ++#include "libunwind-common.h" ++ ++/* There is no getcontext() on SW_64. Use a stub version which only saves GP ++ registers. FIXME: Not ideal, may not be sufficient for all libunwind ++ use cases. */ ++#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) ++extern int unw_tdep_getcontext (ucontext_t *uc); ++ ++#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) ++extern int unw_tdep_is_fpreg (int); ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++} ++#endif ++ ++#endif /* LIBUNWIND_H */ +diff --git a/include/tdep-sw_64/dwarf-config.h b/include/tdep-sw_64/dwarf-config.h +new file mode 100644 +index 0000000..2e270b8 +--- /dev/null ++++ b/include/tdep-sw_64/dwarf-config.h +@@ -0,0 +1,51 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2012 Tommi Rantala ++ ++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 dwarf_config_h ++#define dwarf_config_h ++ ++/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not ++ explicitly defined. */ ++#define DWARF_NUM_PRESERVED_REGS 65 ++ ++#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) ++ ++/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ ++#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) ++ ++/* Convert a pointer to a dwarf_cursor structure to a pointer to ++ unw_cursor_t. */ ++#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) ++ ++typedef struct dwarf_loc ++ { ++ unw_word_t val; ++#ifndef UNW_LOCAL_ONLY ++ unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ ++#endif ++ } ++dwarf_loc_t; ++ ++#endif /* dwarf_config_h */ +diff --git a/include/tdep-sw_64/jmpbuf.h b/include/tdep-sw_64/jmpbuf.h +new file mode 100644 +index 0000000..c099f92 +--- /dev/null ++++ b/include/tdep-sw_64/jmpbuf.h +@@ -0,0 +1,32 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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. */ ++ ++/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ ++ ++/* FIXME for MIPS! */ ++ ++#define JB_SP 4 ++#define JB_RP 5 ++#define JB_MASK_SAVED 6 ++#define JB_MASK 7 +diff --git a/include/tdep-sw_64/libunwind_i.h b/include/tdep-sw_64/libunwind_i.h +new file mode 100644 +index 0000000..4a04c43 +--- /dev/null ++++ b/include/tdep-sw_64/libunwind_i.h +@@ -0,0 +1,349 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 SW_64_LIBUNWIND_I_H ++#define SW_64_LIBUNWIND_I_H ++ ++/* Target-dependent definitions that are internal to libunwind but need ++ to be shared with target-independent code. */ ++ ++#include ++#include ++# include "elf64.h" ++#include "mempool.h" ++#include "dwarf.h" ++ ++typedef struct ++ { ++ /* no sw_64-specific fast trace */ ++ uint64_t virtual_address; ++ int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */ ++ int64_t last_frame : 1; /* non-zero if last frame in chain */ ++ int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */ ++ int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */ ++ int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */ ++ int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */ ++ } ++unw_tdep_frame_t; ++ ++struct unw_addr_space ++ { ++ struct unw_accessors acc; ++ ++ int big_endian; ++ sw_64_abi_t abi; ++ unsigned int addr_size; ++ ++ unw_caching_policy_t caching_policy; ++#ifdef HAVE_ATOMIC_OPS_H ++ AO_t cache_generation; ++#else ++ uint32_t cache_generation; ++#endif ++ unw_word_t dyn_generation; /* see dyn-common.h */ ++ unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ ++ struct dwarf_rs_cache global_cache; ++ struct unw_debug_frame_list *debug_frames; ++}; ++ ++#define tdep_big_endian(as) ((as)->big_endian) ++ ++struct cursor ++ { ++ struct dwarf_cursor dwarf; /* must be first */ ++ unw_tdep_frame_t frame_info; /* quick tracing assist info */ ++ enum ++ { ++ SW_SCF_NONE, /* no signal frame */ ++ SW_SCF_LINUX_SIGFRAME, /* non-RT signal frame */ ++ SW_SCF_LINUX_RT_SIGFRAME, /* RT signal frame */ ++ } ++ sigcontext_format; ++ ++ unw_word_t sigcontext_addr; ++ unw_word_t sigcontext_sp; ++ unw_word_t sigcontext_pc; ++ unw_word_t ucontext_addr; ++ }; ++ ++#define DWARF_GET_LOC(l) ((l).val) ++ ++#ifndef UNW_REMOTE_ONLY ++# if _SW_64_SIM == _ABIN32 ++typedef long long sw_64_reg_t; ++# else ++typedef long sw_64_reg_t; ++# endif ++#endif ++ ++#ifdef UNW_LOCAL_ONLY ++# define DWARF_NULL_LOC DWARF_LOC (0, 0) ++# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) ++# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) ++# define DWARF_IS_REG_LOC(l) 0 ++# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ ++ tdep_uc_addr((c)->as_arg, (r)), 0)) ++# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) ++# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ ++ tdep_uc_addr((c)->as_arg, (r)), 0)) ++ ++/* FIXME: Implement these for the SW_64 FPU. */ ++static inline int ++dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc); ++ return 0; ++} ++ ++static inline int ++dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; ++ return 0; ++} ++ ++static inline int ++dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *val = *(sw_64_reg_t *) (intptr_t) DWARF_GET_LOC (loc); ++ return 0; ++} ++ ++static inline int ++dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) ++{ ++ if (!DWARF_GET_LOC (loc)) ++ return -1; ++ *(sw_64_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; ++ return 0; ++} ++ ++#else /* !UNW_LOCAL_ONLY */ ++# define DWARF_LOC_TYPE_FP (1 << 0) ++# define DWARF_LOC_TYPE_REG (1 << 1) ++# define DWARF_NULL_LOC DWARF_LOC (0, 0) ++# define DWARF_IS_NULL_LOC(l) \ ++ ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) ++# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) ++# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) ++# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) ++# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) ++# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) ++# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ ++ | DWARF_LOC_TYPE_FP)) ++ ++static inline int ++read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val) ++{ ++ int offset = addr & 4; ++ int ret; ++ unw_word_t memval; ++ ++ ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); ++ if (ret < 0) ++ return ret; ++ ++ if ((offset != 0) == tdep_big_endian (c->as)) ++ *val = (int32_t) memval; ++ else ++ *val = (int32_t) (memval >> 32); ++ ++ return 0; ++} ++ ++static inline int ++write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val) ++{ ++ int offset = addr & 4; ++ int ret; ++ unw_word_t memval; ++ ++ ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); ++ if (ret < 0) ++ return ret; ++ ++ if ((offset != 0) == tdep_big_endian (c->as)) ++ memval = (memval & ~0xffffffffLL) | (uint32_t) *val; ++ else ++ memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32); ++ ++ return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg); ++} ++ ++/* FIXME: Implement these for the SW_64 FPU. */ ++static inline int ++dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) ++{ ++ char *valp = (char *) &val; ++ unw_word_t addr; ++// int ret; ++ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), ++ val, 0, c->as_arg); ++ ++ addr = DWARF_GET_LOC (loc); ++#if 0 ++ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, ++ 0, c->as_arg)) < 0) ++ return ret; ++ ++ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, ++ c->as_arg); ++#else ++ return (*c->as->acc.access_mem) (c->as, addr,(unw_word_t *) valp,0,c->as_arg); ++#endif ++} ++ ++static inline int ++dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) ++{ ++ char *valp = (char *) &val; ++ unw_word_t addr; ++// int ret; ++ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), ++ &val, 1, c->as_arg); ++ ++ addr = DWARF_GET_LOC (loc); ++#if 0 ++ if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, ++ 1, c->as_arg)) < 0) ++ return ret; ++ ++ return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, ++ 1, c->as_arg); ++#else ++ return (*c->as->acc.access_mem) (c->as, addr, (unw_word_t *) valp,1, c->as_arg); ++#endif ++} ++ ++static inline int ++dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) ++{ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ /* If a code-generator were to save a value of type unw_word_t in a ++ floating-point register, we would have to support this case. I ++ suppose it could happen with MMX registers, but does it really ++ happen? */ ++ assert (!DWARF_IS_FP_LOC (loc)); ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, ++ 0, c->as_arg); ++ else ++ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, ++ 0, c->as_arg); ++} ++ ++static inline int ++dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) ++{ ++ if (DWARF_IS_NULL_LOC (loc)) ++ return -UNW_EBADREG; ++ ++ /* If a code-generator were to save a value of type unw_word_t in a ++ floating-point register, we would have to support this case. I ++ suppose it could happen with MMX registers, but does it really ++ happen? */ ++ assert (!DWARF_IS_FP_LOC (loc)); ++ ++ if (DWARF_IS_REG_LOC (loc)) ++ return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, ++ 1, c->as_arg); ++ else ++ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, ++ 1, c->as_arg); ++} ++ ++#endif /* !UNW_LOCAL_ONLY */ ++ ++#define tdep_getcontext_trace unw_getcontext ++#define tdep_init_done UNW_OBJ(init_done) ++#define tdep_init UNW_OBJ(init) ++/* Platforms that support UNW_INFO_FORMAT_TABLE need to define ++ tdep_search_unwind_table. */ ++#define tdep_search_unwind_table dwarf_search_unwind_table ++#define tdep_find_unwind_table dwarf_find_unwind_table ++#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) ++#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) ++#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) ++#define tdep_access_reg UNW_OBJ(access_reg) ++#define tdep_access_fpreg UNW_OBJ(access_fpreg) ++#define tdep_fetch_frame(c,ip,n) do {} while(0) ++#define tdep_cache_frame(c) 0 ++#define tdep_reuse_frame(c,frame) do {} while(0) ++#define tdep_stash_frame(c,rs) do {} while(0) ++#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) ++ ++#ifdef UNW_LOCAL_ONLY ++# define tdep_find_proc_info(c,ip,n) \ ++ dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ ++ (c)->as_arg) ++# define tdep_put_unwind_info(as,pi,arg) \ ++ dwarf_put_unwind_info((as), (pi), (arg)) ++#else ++# define tdep_find_proc_info(c,ip,n) \ ++ (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ ++ (c)->as_arg) ++# define tdep_put_unwind_info(as,pi,arg) \ ++ (*(as)->acc.put_unwind_info)((as), (pi), (arg)) ++#endif ++ ++#define tdep_get_as(c) ((c)->dwarf.as) ++#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) ++#define tdep_get_ip(c) ((c)->dwarf.ip) ++ ++extern int tdep_init_done; ++ ++extern void tdep_init (void); ++extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, ++ unw_dyn_info_t *di, unw_proc_info_t *pi, ++ int need_unwind_info, void *arg); ++extern void *tdep_uc_addr (ucontext_t *uc, int reg); ++extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, ++ unsigned long *segbase, unsigned long *mapoff, ++ char *path, size_t pathlen); ++extern void tdep_get_exe_image_path (char *path); ++extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, ++ unw_word_t *valp, int write); ++extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, ++ unw_fpreg_t *valp, int write); ++ ++#endif /* SW_64_LIBUNWIND_I_H */ +diff --git a/src/sw_64/Gapply_reg_state.c b/src/sw_64/Gapply_reg_state.c +new file mode 100644 +index 0000000..82f056d +--- /dev/null ++++ b/src/sw_64/Gapply_reg_state.c +@@ -0,0 +1,37 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. ++ Contributed by David Mosberger-Tang ++ ++ Modified for x86_64 by Max Asbock ++ ++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 "unwind_i.h" ++ ++int ++unw_apply_reg_state (unw_cursor_t *cursor, ++ void *reg_states_data) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); ++} +diff --git a/src/sw_64/Gcreate_addr_space.c b/src/sw_64/Gcreate_addr_space.c +new file mode 100644 +index 0000000..7e33f5f +--- /dev/null ++++ b/src/sw_64/Gcreate_addr_space.c +@@ -0,0 +1,65 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++unw_addr_space_t ++unw_create_addr_space (unw_accessors_t *a, int byte_order) ++{ ++#ifdef UNW_LOCAL_ONLY ++ return NULL; ++#else ++ unw_addr_space_t as; ++ ++ /* ++ * SW_64 supports only big or little-endian, not weird stuff like ++ * PDP_ENDIAN. ++ */ ++ if (byte_order != 0 ++ && byte_order != __LITTLE_ENDIAN ++ && byte_order != __BIG_ENDIAN) ++ return NULL; ++ ++ as = malloc (sizeof (*as)); ++ if (!as) ++ return NULL; ++ ++ memset (as, 0, sizeof (*as)); ++ ++ as->acc = *a; ++ ++ if (byte_order == 0) ++ /* use host default: */ ++ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); ++ else ++ as->big_endian = (byte_order == __BIG_ENDIAN); ++ ++ /* FIXME! There is no way to specify the ABI. */ ++ as->abi = UNW_SW_64_ABI_N64; ++ ++ return as; ++#endif ++} +diff --git a/src/sw_64/Gget_proc_info.c b/src/sw_64/Gget_proc_info.c +new file mode 100644 +index 0000000..04c4326 +--- /dev/null ++++ b/src/sw_64/Gget_proc_info.c +@@ -0,0 +1,44 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++int ++unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ int ret; ++ ++ ret = dwarf_make_proc_info (&c->dwarf); ++ if (ret < 0) { ++ /* Construct a dummy proc info if Dwarf failed */ ++ memset (pi, 0, sizeof (*pi)); ++ pi->start_ip = c->dwarf.ip; ++ pi->end_ip = c->dwarf.ip + 4; ++ return 0; ++ } ++ ++ *pi = c->dwarf.pi; ++ return 0; ++} +diff --git a/src/sw_64/Gget_save_loc.c b/src/sw_64/Gget_save_loc.c +new file mode 100644 +index 0000000..ecc64a5 +--- /dev/null ++++ b/src/sw_64/Gget_save_loc.c +@@ -0,0 +1,132 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++/* FIXME for SW_64. */ ++ ++int ++unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ dwarf_loc_t loc; ++ ++ loc = DWARF_NULL_LOC; /* default to "not saved" */ ++ ++ switch (reg) ++ { ++ case UNW_SW_64_R0: ++ case UNW_SW_64_R1: ++ case UNW_SW_64_R2: ++ case UNW_SW_64_R3: ++ case UNW_SW_64_R4: ++ case UNW_SW_64_R5: ++ case UNW_SW_64_R6: ++ case UNW_SW_64_R7: ++ case UNW_SW_64_R8: ++ case UNW_SW_64_R9: ++ case UNW_SW_64_R10: ++ case UNW_SW_64_R11: ++ case UNW_SW_64_R12: ++ case UNW_SW_64_R13: ++ case UNW_SW_64_R14: ++ case UNW_SW_64_R15: ++ case UNW_SW_64_R16: ++ case UNW_SW_64_R17: ++ case UNW_SW_64_R18: ++ case UNW_SW_64_R19: ++ case UNW_SW_64_R20: ++ case UNW_SW_64_R21: ++ case UNW_SW_64_R22: ++ case UNW_SW_64_R23: ++ case UNW_SW_64_R24: ++ case UNW_SW_64_R25: ++ case UNW_SW_64_R26: ++ case UNW_SW_64_R27: ++ case UNW_SW_64_R28: ++ case UNW_SW_64_R29: ++ case UNW_SW_64_R30: ++ case UNW_SW_64_R31: ++ case UNW_SW_64_F0: ++ case UNW_SW_64_F1: ++ case UNW_SW_64_F2: ++ case UNW_SW_64_F3: ++ case UNW_SW_64_F4: ++ case UNW_SW_64_F5: ++ case UNW_SW_64_F6: ++ case UNW_SW_64_F7: ++ case UNW_SW_64_F8: ++ case UNW_SW_64_F9: ++ case UNW_SW_64_F10: ++ case UNW_SW_64_F11: ++ case UNW_SW_64_F12: ++ case UNW_SW_64_F13: ++ case UNW_SW_64_F14: ++ case UNW_SW_64_F15: ++ case UNW_SW_64_F16: ++ case UNW_SW_64_F17: ++ case UNW_SW_64_F18: ++ case UNW_SW_64_F19: ++ case UNW_SW_64_F20: ++ case UNW_SW_64_F21: ++ case UNW_SW_64_F22: ++ case UNW_SW_64_F23: ++ case UNW_SW_64_F24: ++ case UNW_SW_64_F25: ++ case UNW_SW_64_F26: ++ case UNW_SW_64_F27: ++ case UNW_SW_64_F28: ++ case UNW_SW_64_F29: ++ case UNW_SW_64_F30: ++ case UNW_SW_64_FPCR: ++ case UNW_SW_64_PC: ++ loc = c->dwarf.loc[reg - UNW_SW_64_R0]; ++ break; ++ ++ default: ++ break; ++ } ++ ++ memset (sloc, 0, sizeof (*sloc)); ++ ++ if (DWARF_IS_NULL_LOC (loc)) ++ { ++ sloc->type = UNW_SLT_NONE; ++ return 0; ++ } ++ ++#if !defined(UNW_LOCAL_ONLY) ++ if (DWARF_IS_REG_LOC (loc)) ++ { ++ sloc->type = UNW_SLT_REG; ++ sloc->u.regnum = DWARF_GET_LOC (loc); ++ } ++ else ++#endif ++ { ++ sloc->type = UNW_SLT_MEMORY; ++ sloc->u.addr = DWARF_GET_LOC (loc); ++ } ++ return 0; ++} +diff --git a/src/sw_64/Gglobal.c b/src/sw_64/Gglobal.c +new file mode 100644 +index 0000000..80d77ae +--- /dev/null ++++ b/src/sw_64/Gglobal.c +@@ -0,0 +1,56 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++#include "dwarf_i.h" ++ ++HIDDEN define_lock (sw_64_lock); ++HIDDEN int tdep_init_done; ++ ++HIDDEN void ++tdep_init (void) ++{ ++ intrmask_t saved_mask; ++ ++ sigfillset (&unwi_full_mask); ++ sigdelset(&unwi_full_mask, 5); /* LIJM */ ++ ++ lock_acquire (&sw_64_lock, saved_mask); ++ { ++ if (tdep_init_done) ++ /* another thread else beat us to it... */ ++ goto out; ++ ++ mi_init (); ++ ++ dwarf_init (); ++ ++#ifndef UNW_REMOTE_ONLY ++ sw_64_local_addr_space_init (); ++#endif ++ tdep_init_done = 1; /* signal that we're initialized... */ ++ } ++ out: ++ lock_release (&sw_64_lock, saved_mask); ++} +diff --git a/src/sw_64/Ginit.c b/src/sw_64/Ginit.c +new file mode 100644 +index 0000000..2ad39c0 +--- /dev/null ++++ b/src/sw_64/Ginit.c +@@ -0,0 +1,202 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++#ifdef UNW_REMOTE_ONLY ++ ++/* unw_local_addr_space is a NULL pointer in this case. */ ++unw_addr_space_t unw_local_addr_space; ++ ++#else /* !UNW_REMOTE_ONLY */ ++ ++static struct unw_addr_space local_addr_space; ++ ++unw_addr_space_t unw_local_addr_space = &local_addr_space; ++ ++/* Return the address of the 64-bit slot in UC for REG (even for o32, ++ where registers are 32-bit, the slots are still 64-bit). */ ++ ++static inline void * ++uc_addr (ucontext_t *uc, int reg) ++{ ++ if (reg >= UNW_SW_64_R0 && reg < UNW_SW_64_R0 + 32) ++ return &uc->uc_mcontext.sc_regs[reg - UNW_SW_64_R0]; ++ else if (reg >= UNW_SW_64_F0 && reg < UNW_SW_64_F0 + 32) ++ return &uc->uc_mcontext.sc_fpregs[reg - UNW_SW_64_F0]; ++ else if (reg == UNW_SW_64_PC) ++ return &uc->uc_mcontext.sc_pc; ++ else ++ return NULL; ++} ++ ++# ifdef UNW_LOCAL_ONLY ++ ++HIDDEN void * ++tdep_uc_addr (ucontext_t *uc, int reg) ++{ ++ char *addr = uc_addr (uc, reg); ++#if 0 ++ if (((reg >= UNW_SW_64_R0 && reg <= UNW_SW_64_R31) || reg == UNW_SW_64_PC) ++ && tdep_big_endian (unw_local_addr_space)) ++ addr += 4; ++#endif ++ return addr; ++} ++ ++# endif /* UNW_LOCAL_ONLY */ ++ ++static void ++put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) ++{ ++ /* it's a no-op */ ++} ++ ++static int ++get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, ++ void *arg) ++{ ++#ifndef UNW_LOCAL_ONLY ++# pragma weak _U_dyn_info_list_addr ++ if (!_U_dyn_info_list_addr) ++ return -UNW_ENOINFO; ++#endif ++ // Access the `_U_dyn_info_list` from `LOCAL_ONLY` library, i.e. libunwind.so. ++ *dyn_info_list_addr = _U_dyn_info_list_addr (); ++ return 0; ++} ++ ++static int ++access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, ++ void *arg) ++{ ++ if (write) ++ { ++ Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); ++ *(unw_word_t *) (intptr_t) addr = *val; ++ } ++ else ++ { ++ *val = *(unw_word_t *) (intptr_t) addr; ++ Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); ++ } ++ return 0; ++} ++ ++static int ++access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, ++ void *arg) ++{ ++ unw_word_t *addr; ++ ucontext_t *uc = arg; ++ ++ if (unw_is_fpreg (reg)) ++ goto badreg; ++ ++ Debug (16, "reg = %s\n", unw_regname (reg)); ++ if (!(addr = uc_addr (uc, reg))) ++ goto badreg; ++ ++ if (write) ++ { ++ *(unw_word_t *) (intptr_t) addr = (sw_64_reg_t) *val; ++ Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); ++ } ++ else ++ { ++ *val = (sw_64_reg_t) *(unw_word_t *) (intptr_t) addr; ++ Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); ++ } ++ return 0; ++ ++ badreg: ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++} ++ ++static int ++access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, ++ int write, void *arg) ++{ ++ ucontext_t *uc = arg; ++ unw_fpreg_t *addr; ++ ++ if (!unw_is_fpreg (reg)) ++ goto badreg; ++ ++ if (!(addr = uc_addr (uc, reg))) ++ goto badreg; ++ ++ if (write) ++ { ++ Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), ++ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); ++ *(unw_fpreg_t *) (intptr_t) addr = *val; ++ } ++ else ++ { ++ *val = *(unw_fpreg_t *) (intptr_t) addr; ++ Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), ++ ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); ++ } ++ return 0; ++ ++ badreg: ++ Debug (1, "bad register number %u\n", reg); ++ /* attempt to access a non-preserved register */ ++ return -UNW_EBADREG; ++} ++ ++static int ++get_static_proc_name (unw_addr_space_t as, unw_word_t ip, ++ char *buf, size_t buf_len, unw_word_t *offp, ++ void *arg) ++{ ++ ++ return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); ++} ++ ++HIDDEN void ++sw_64_local_addr_space_init (void) ++{ ++ memset (&local_addr_space, 0, sizeof (local_addr_space)); ++ local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); ++ local_addr_space.abi = UNW_SW_64_ABI_N64; ++ local_addr_space.addr_size = sizeof (void *); ++ local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; ++ local_addr_space.acc.find_proc_info = dwarf_find_proc_info; ++ local_addr_space.acc.put_unwind_info = put_unwind_info; ++ local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; ++ local_addr_space.acc.access_mem = access_mem; ++ local_addr_space.acc.access_reg = access_reg; ++ local_addr_space.acc.access_fpreg = access_fpreg; ++ local_addr_space.acc.resume = sw_64_local_resume; /* sw_64_local_resume? FIXME! */ ++ local_addr_space.acc.get_proc_name = get_static_proc_name; ++ unw_flush_cache (&local_addr_space, 0, 0); ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ +diff --git a/src/sw_64/Ginit_local.c b/src/sw_64/Ginit_local.c +new file mode 100644 +index 0000000..f3153b5 +--- /dev/null ++++ b/src/sw_64/Ginit_local.c +@@ -0,0 +1,76 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++#include "init.h" ++ ++#ifdef UNW_REMOTE_ONLY ++ ++int ++unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) ++{ ++ return -UNW_EINVAL; ++} ++ ++#else /* !UNW_REMOTE_ONLY */ ++ ++static int ++unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ if (!tdep_init_done) ++ tdep_init (); ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ c->dwarf.as = unw_local_addr_space; ++ c->dwarf.as_arg = uc; ++ return common_init (c, use_prev_instr); ++} ++ ++int ++unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) ++{ ++ return unw_init_local_common(cursor, uc, 1); ++} ++ ++int ++unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) ++{ ++ if (!flag) ++ { ++ return unw_init_local_common(cursor, uc, 1); ++ } ++ else if (flag == UNW_INIT_SIGNAL_FRAME) ++ { ++ return unw_init_local_common(cursor, uc, 0); ++ } ++ else ++ { ++ return -UNW_EINVAL; ++ } ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ +diff --git a/src/sw_64/Ginit_remote.c b/src/sw_64/Ginit_remote.c +new file mode 100644 +index 0000000..9b8ba5b +--- /dev/null ++++ b/src/sw_64/Ginit_remote.c +@@ -0,0 +1,45 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "init.h" ++#include "unwind_i.h" ++ ++int ++unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) ++{ ++#ifdef UNW_LOCAL_ONLY ++ return -UNW_EINVAL; ++#else /* !UNW_LOCAL_ONLY */ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ if (!tdep_init_done) ++ tdep_init (); ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ c->dwarf.as = as; ++ c->dwarf.as_arg = as_arg; ++ return common_init (c, 0); ++#endif /* !UNW_LOCAL_ONLY */ ++} +diff --git a/src/sw_64/Gis_signal_frame.c b/src/sw_64/Gis_signal_frame.c +new file mode 100644 +index 0000000..f0f476e +--- /dev/null ++++ b/src/sw_64/Gis_signal_frame.c +@@ -0,0 +1,116 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++#include "offsets.h" ++#include ++ ++ ++int ++unw_is_signal_frame (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t w1, ip; ++ unw_addr_space_t as; ++ unw_accessors_t *a; ++ void *arg; ++ int ret; ++ ++ as = c->dwarf.as; ++ a = unw_get_accessors_int (as); ++ arg = c->dwarf.as_arg; ++ ++ ip = c->dwarf.ip; ++ ++ /* syscall */ ++ if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) ++ return 0; ++ ++ if ( w1 == 0x2000083f81f0067UL) ++ c->sigcontext_format = SW_SCF_LINUX_SIGFRAME; ++ else{ ++ if ( w1 == 0x2000083f81f015fUL) ++ c->sigcontext_format = SW_SCF_LINUX_RT_SIGFRAME; ++ else ++ c->sigcontext_format = SW_SCF_NONE; ++ } ++ return c->sigcontext_format > SW_SCF_NONE; ++ ++ //return -UNW_ENOINFO; ++} ++#if 0 ++int ++unw_handle_signal_frame (unw_cursor_t *cursor) ++{ ++ int i; ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; ++ struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); ++ int ret; ++ ++ if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) ++ return -UNW_EUNSPEC; ++ ++ ++ /* Save the SP and PC to be able to return execution at this point ++ later in time (unw_resume). */ ++ c->sigcontext_sp = c->dwarf.cfa; ++ c->sigcontext_pc = c->dwarf.ip; ++ if ( c->sigcontext_format == SW_SCF_LINUX_RT_SIGFRAME) ++ { ++ c->ucontext_addr = sp_addr + sizeof (siginfo_t); ++ c->sigcontext_addr = sp_addr + sizeof (siginfo_t) + 48; ++ } ++ else ++ { ++ c->ucontext_addr = 0; ++ c->sigcontext_addr = sp_addr; ++ } ++ sc_addr = c->sigcontext_addr + 16; ++ c->dwarf.loc[UNW_SW_64_PC] = DWARF_LOC (sc_addr, 0); ++ ++ /* Update the dwarf cursor. ++ Set the location of the registers to the corresponding addresses */ ++ ++ sc_addr = c->sigcontext_addr + 32; ++ ++#define SC_REG_OFFSET(X) (8 * X) ++ ++ for (i = UNW_SW_64_R0; i <= UNW_SW_64_R31; i++) ++ { ++ c->dwarf.loc[i] = DWARF_LOC (sc_addr + SC_REG_OFFSET(i), 0); ++ } ++ sc_addr += sizeof(long); //sc_fpregs ++ ++ for (i = UNW_SW_64_F0; i < UNW_SW_64_PC; i++) ++ { ++ c->dwarf.loc[i] = DWARF_LOC (sc_addr + SC_REG_OFFSET(i), 0); ++ } ++ ++ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SW_64_R30], &c->dwarf.cfa); ++ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SW_64_PC], &c->dwarf.ip); ++ ++ return 1; ++} ++#endif +diff --git a/src/sw_64/Greg_states_iterate.c b/src/sw_64/Greg_states_iterate.c +new file mode 100644 +index 0000000..a17dc1b +--- /dev/null ++++ b/src/sw_64/Greg_states_iterate.c +@@ -0,0 +1,37 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. ++ Contributed by David Mosberger-Tang ++ ++ Modified for x86_64 by Max Asbock ++ ++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 "unwind_i.h" ++ ++int ++unw_reg_states_iterate (unw_cursor_t *cursor, ++ unw_reg_states_callback cb, void *token) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ++ return dwarf_reg_states_iterate (&c->dwarf, cb, token); ++} +diff --git a/src/sw_64/Gregs.c b/src/sw_64/Gregs.c +new file mode 100644 +index 0000000..fb6c325 +--- /dev/null ++++ b/src/sw_64/Gregs.c +@@ -0,0 +1,131 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++/* FIXME: The following is probably unfinished and/or at least partly bogus. */ ++ ++HIDDEN int ++tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, ++ int write) ++{ ++ dwarf_loc_t loc = DWARF_NULL_LOC; ++ ++ switch (reg) ++ { ++ case UNW_SW_64_R0: ++ case UNW_SW_64_R1: ++ case UNW_SW_64_R2: ++ case UNW_SW_64_R3: ++ case UNW_SW_64_R4: ++ case UNW_SW_64_R5: ++ case UNW_SW_64_R6: ++ case UNW_SW_64_R7: ++ case UNW_SW_64_R8: ++ case UNW_SW_64_R9: ++ case UNW_SW_64_R10: ++ case UNW_SW_64_R11: ++ case UNW_SW_64_R12: ++ case UNW_SW_64_R13: ++ case UNW_SW_64_R14: ++ case UNW_SW_64_R15: ++ case UNW_SW_64_R16: ++ case UNW_SW_64_R17: ++ case UNW_SW_64_R18: ++ case UNW_SW_64_R19: ++ case UNW_SW_64_R20: ++ case UNW_SW_64_R21: ++ case UNW_SW_64_R22: ++ case UNW_SW_64_R23: ++ case UNW_SW_64_R24: ++ case UNW_SW_64_R25: ++ case UNW_SW_64_R26: ++ case UNW_SW_64_R27: ++ case UNW_SW_64_R28: ++ case UNW_SW_64_R29: ++ case UNW_SW_64_R30: ++ case UNW_SW_64_R31: ++ loc = c->dwarf.loc[reg - UNW_SW_64_R0]; ++ break; ++#ifndef LIJM ++ case UNW_SW_64_PC: ++ if (!write) ++ { ++ *valp = c->dwarf.ip; ++ return 0; ++ } ++ loc = c->dwarf.loc[reg - UNW_SW_64_R0]; ++ break; ++ ++ default: ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++ } ++ ++ if (write) ++ return dwarf_put (&c->dwarf, loc, *valp); ++ else ++ return dwarf_get (&c->dwarf, loc, valp); ++} ++ ++HIDDEN int ++tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, ++ int write) ++{ ++ dwarf_loc_t loc = DWARF_NULL_LOC; ++ if (reg >= UNW_SW_64_F0 && reg <= UNW_SW_64_FPCR ) ++ loc = c->dwarf.loc[reg - UNW_SW_64_R0]; ++ if (write) ++ return dwarf_putfp (&c->dwarf, loc, *valp); ++ else ++ return dwarf_getfp (&c->dwarf, loc, valp); ++} ++#else ++ case UNW_SW_64_PC: ++ if (write) ++ c->dwarf.ip = *valp; /* update the IP cache */ ++ loc = c->dwarf.loc[reg]; ++ break; ++ ++ default: ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++ } ++ ++ if (write) ++ return dwarf_put (&c->dwarf, loc, *valp); ++ else ++ return dwarf_get (&c->dwarf, loc, valp); ++} ++ ++/* FIXME for SW_64. */ ++ ++HIDDEN int ++tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, ++ int write) ++{ ++ Debug (1, "bad register number %u\n", reg); ++ return -UNW_EBADREG; ++} ++#endif +diff --git a/src/sw_64/Gresume.c b/src/sw_64/Gresume.c +new file mode 100644 +index 0000000..f21e825 +--- /dev/null ++++ b/src/sw_64/Gresume.c +@@ -0,0 +1,112 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++#ifndef UNW_REMOTE_ONLY ++ ++HIDDEN inline int ++sw_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ ucontext_t *uc = (ucontext_t *)c->dwarf.as_arg; ++ ++ /* Ensure c->pi is up-to-date. On sw_64, it's relatively common to be ++ missing DWARF unwind info. We don't want to fail in that case, ++ because the frame-chain still would let us do a backtrace at ++ least. */ ++ dwarf_make_proc_info (&c->dwarf); ++ ++ if (unlikely (c->sigcontext_format != SW_SCF_NONE)) ++ { ++ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; ++ ++ Debug (8, "resuming at ip=%#lx cfa=%#lx via sigreturn(%p)\n", ++ c->dwarf.ip, c->dwarf.cfa, sc); ++ sigreturn (sc); ++ } ++ else ++ { ++ Debug (8, "resuming at ip=%#lx cfa=%#lx sp= %#lx via setcontext()\n", ++ c->dwarf.ip, c->dwarf.cfa, uc->uc_mcontext.sc_regs[30]); ++ setcontext (uc); ++ } ++ return -UNW_EINVAL; ++} ++ ++#endif /* !UNW_REMOTE_ONLY */ ++ ++static inline int ++establish_machine_state (struct cursor *c) ++{ ++ int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, ++ int write, void *); ++ int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, ++ int write, void *); ++ unw_addr_space_t as = c->dwarf.as; ++ void *arg = c->dwarf.as_arg; ++ unw_fpreg_t fpval; ++ unw_word_t val; ++ int reg; ++ ++ access_reg = as->acc.access_reg; ++ access_fpreg = as->acc.access_fpreg; ++ ++ Debug (8, "copying out cursor state\n"); ++ ++ for (reg = 0; reg <= UNW_SW_64_PC; ++reg) ++ { ++ Debug (16, "copying %s %d\n", unw_regname (reg), reg); ++ if (unw_is_fpreg (reg)) ++ { ++ if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) ++ (*access_fpreg) (as, reg, &fpval, 1, arg); ++ } ++ else ++ { ++ if (tdep_access_reg (c, reg, &val, 0) >= 0) ++ (*access_reg) (as, reg, &val, 1, arg); ++ } ++ } ++ (*access_reg) (as, UNW_SW_64_R30, &c->dwarf.cfa, 1, arg); ++ return 0; ++} ++ ++int ++unw_resume (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ int ret; ++ ++ Debug (1, "(cursor=%p)\n", c); ++ ++ if ((ret = establish_machine_state (c)) < 0) ++ return ret; ++ ++ return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, ++ c->dwarf.as_arg); ++} +diff --git a/src/sw_64/Gstep.c b/src/sw_64/Gstep.c +new file mode 100644 +index 0000000..fa2a4ce +--- /dev/null ++++ b/src/sw_64/Gstep.c +@@ -0,0 +1,349 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2015 Imagination Technologies Limited ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++#include "offsets.h" ++ ++static int ++sw_64_handle_signal_frame (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t sc_addr, sp_addr = c->dwarf.cfa; ++ unw_word_t ra, fp; ++ int ret; ++ ++ switch (unw_is_signal_frame (cursor)) { ++ case 1: ++ sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + ++ LINUX_UC_MCONTEXT_OFF; ++ break; ++ case 2: ++ sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; ++ break; ++ default: ++ return -UNW_EUNSPEC; ++ } ++ ++ if (tdep_big_endian(c->dwarf.as)) ++ sc_addr += 4; ++ ++ c->sigcontext_addr = sc_addr; ++ ++ /* Update the dwarf cursor. */ ++ c->dwarf.loc[UNW_SW_64_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); ++ c->dwarf.loc[UNW_SW_64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); ++ ++ /* Set SP/CFA and PC/IP. */ ++ dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SW_64_R30], &c->dwarf.cfa); ++ ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), ++ &c->dwarf.ip)) < 0) ++ return ret; ++ ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R26_OFF, 0), ++ &ra)) < 0) ++ return ret; ++ if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R15_OFF, 0), ++ &fp)) < 0) ++ return ret; ++ ++ Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", ++ (unsigned long long)c->dwarf.ip, (unsigned long long)ra, ++ (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); ++ ++ c->dwarf.pi_valid = 0; ++ c->dwarf.use_prev_instr = 0; ++ ++ return 1; ++} ++ ++ ++static inline ++int is_valid_fp_val(unw_word_t cfa_val, unw_word_t fp_val) ++{ ++ return fp_val > 0 && cfa_val > 0 && fp_val >cfa_val && (fp_val - cfa_val < 0x4000); ++} ++ ++static int _step_n64(struct cursor *c) ++{ ++ #define FP_REG UNW_SW_64_R15 ++ #define SP_REG UNW_SW_64_R30 ++ #define RA_REG UNW_SW_64_R26 ++ ++ //TODO:handle plt entry ++ int ret; ++ unw_word_t current_fp_val = 0; ++ unw_word_t current_ra_val = 0; ++ unw_word_t current_sp_val = 0; ++ struct dwarf_loc up_fp_loc = DWARF_NULL_LOC; ++ struct dwarf_loc up_ra_loc = DWARF_NULL_LOC; ++ ++ ret = dwarf_get (&c->dwarf, c->dwarf.loc[SP_REG], ¤t_sp_val); ++ if (ret < 0) ++ { ++ Debug (2, "returning %d [SP=0x%lx]\n", ret, ++ DWARF_GET_LOC (c->dwarf.loc[FP_REG])); ++ return ret; ++ } ++ ret = dwarf_get (&c->dwarf, c->dwarf.loc[FP_REG], ¤t_fp_val); ++ if (ret < 0) ++ { ++ Debug (2, "returning %d [FP=0x%lx]\n", ret, ++ DWARF_GET_LOC (c->dwarf.loc[FP_REG])); ++ return ret; ++ } ++ ret = dwarf_get (&c->dwarf, c->dwarf.loc[RA_REG], ¤t_ra_val); ++ if (ret < 0) ++ { ++ Debug (2, "returning %d [RA=0x%lx]\n", ret, ++ DWARF_GET_LOC (c->dwarf.loc[RA_REG])); ++ return ret; ++ } ++ ++ Debug(2, "BEGIN GUESSING WITH SP:%p FP:%p CFA:%p at %p, RA:%p\n", ++ current_sp_val, current_fp_val, c->dwarf.cfa, ++ c->dwarf.ip, current_ra_val ++ ); ++ ++ if (current_fp_val == current_sp_val) { ++ // Don't adjust FP ++ up_fp_loc = c->dwarf.loc[FP_REG]; ++ up_ra_loc = c->dwarf.loc[RA_REG]; ++ } else if (is_valid_fp_val(c->dwarf.cfa, current_fp_val)) { ++ /* Heuristic to determine incorrect guess. For FP to be a ++ valid frame it needs to be above current CFA, but don't ++ let it go more than a little. Note that we can't deduce ++ anything about new FP (fp1) since it may not be a frame ++ pointer in the frame above. Just check we get the value. */ ++ up_fp_loc = DWARF_MEM_LOC (c, current_fp_val+16); ++ up_ra_loc = DWARF_MEM_LOC (c, current_fp_val+24); ++ unw_word_t up_fp_val = 0; ++ ret = dwarf_get (&c->dwarf, up_fp_loc, &up_fp_val); ++ if (ret > 0 && is_valid_fp_val(current_fp_val, up_fp_val)) { ++ c->dwarf.loc[FP_REG] = up_fp_loc; ++ } ++ } ++ ++ if (DWARF_IS_NULL_LOC (up_fp_loc)) ++ { ++ ret = 0; ++ Debug (2, "NULL %%fp loc, returning %d\n", ret); ++ return ret; ++ } ++ ++ c->dwarf.loc[UNW_SW_64_PC] = c->dwarf.loc[RA_REG]; ++ c->dwarf.loc[RA_REG] = up_ra_loc; ++ c->dwarf.loc[SP_REG] = up_fp_loc; ++ c->dwarf.loc[FP_REG] = up_fp_loc; ++ c->dwarf.use_prev_instr = 1; ++ ++ if (c->dwarf.ip == current_ra_val && current_fp_val == current_sp_val) { ++ // Backtrace stopped: frame did not save the PC ++ c->dwarf.ip = 0; ++ } else { ++ c->dwarf.ip = current_ra_val; ++ } ++ return (c->dwarf.ip == 0) ? 0 : 1; ++} ++ ++ ++#ifdef XWB20210316 ++static int ++my_step(unw_cursor_t *cursor, int ret) ++{ ++ int i, w1; ++ unw_proc_info_t pi; ++ struct dwarf_loc loc; ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t pc, ip, w0, min; ++ unw_addr_space_t as = tdep_get_as (c); ++ unw_accessors_t *a; ++ unsigned int frame_size,stack_offp[2]; ++ void *arg; ++#define EIP UNW_SW_64_PC ++ /* DWARF failed, let's see if we can follow the frame-chain ++ * */ ++ ++ ip = tdep_get_ip (c);//c->dwarf.ip; ++ a = unw_get_accessors (as); ++ arg = tdep_get_as_arg (c);//c->dwarf.as_arg; ++ ++ if ((ret = unw_get_proc_info(cursor,&pi))<0) ++ { ++ Debug (13, "get_proc_info returning %d, ip=%#lx, start %#lx\n", ret, ip, pi.start_ip); ++ c->dwarf.ip = 0; ++ return ret; ++ } ++ Debug (2, "pc: %#lx, start_ip %#lx, end_ip%#lx\n", ip, ++ pi.start_ip, pi.end_ip); ++ ++ stack_offp[0] = 0; ++ stack_offp[1] = 0; ++ frame_size = 0; ++ w0 = pi.start_ip+ (20<<4); ++ min = (w0access_mem) (as, pc, &w0, 0, arg)) < 0) ++ return ret; ++ ++ w1 = w0 & 0xffff8000U; ++ if (w1 == 0xfbde8000U) ++ { ++ if (frame_size == 0) ++ { ++ w1 = w0 &0xffffU; ++ frame_size = (-w1) & 0xffff; ++ } ++ } ++ else ++ if (w1== 0xaf5e0000U) ++ { ++ if (stack_offp[0] == 0) ++ stack_offp[0] = (w0 & 0xffff) ; ++ } ++ else ++ if (w1== 0xadfe0000U) ++ { ++ if (stack_offp[1] == 0) ++ stack_offp[1] = (w0 & 0xffff) ; ++ } ++ } ++ ++ Debug (13, "frame_size %d, stack_offp %d, %d\n", frame_size, ++ stack_offp[0],stack_offp[1]); ++ ++ if (stack_offp[1]) ++ c->dwarf.loc[UNW_SW_64_R15] = DWARF_LOC (c->dwarf.cfa+stack_offp[1],0); ++ loc = DWARF_LOC (c->dwarf.cfa+stack_offp[0],0); ++ ++ if (!DWARF_IS_NULL_LOC(loc)) ++ { ++ ret = dwarf_get (&c->dwarf,loc,&c->dwarf.ip); ++ if (ret < 0) ++ { ++ Debug(13,"dwarf_get([EIP=0x%lx]) failed\n", DWARF_GET_LOC (loc)); ++ Debug (2, "returning %d\n", ret); ++ return ret; ++ } ++ else ++ { ++ Debug (13, "[EIP=0x%lx] = 0x%lx\n", DWARF_GET_LOC (loc), c->dwarf.ip); ++ c->dwarf.cfa += frame_size; ++ } ++ } ++ else ++ c->dwarf.ip = 0; ++ ++ ret = (c->dwarf.ip == 0) ? 0 : 1; ++ Debug (1, "returning %d\n", ret); ++ return ret; ++} ++unw_step (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ unw_word_t w0; ++ struct dwarf_loc loc; ++ int i, ret; ++ ++ Debug (0, "(cursor=%p),ip=0x%016lx, cfa=0x%016lx)\n", ++ c, c->dwarf.ip, c->dwarf.cfa); ++ ++ if (unw_is_signal_frame(cursor)) ++ { ++ ret = unw_handle_signal_frame(cursor); ++ if (ret == -UNW_ENOINFO) ++ Debug (1, "unw_is_signal_frame error\n"); ++ return ret; ++ } ++ ++ ret = dwarf_step (&c->dwarf); ++ if (unlikely (ret == -UNW_ESTOPUNWIND)) ++ { ++ Debug (1, "dwarf_step STOPUNWIND\n"); ++ return ret; ++ } ++ /* Dwarf unwinding didn't work, stop. */ ++ if (unlikely (ret < 0)) ++ my_step(c,ret); ++ ret = (c->dwarf.ip == 0) ? 0 : 1; ++ Debug (1, "returning %d\n", ret); ++ return ret; ++} ++#else ++int ++unw_step (unw_cursor_t *cursor) ++{ ++ struct cursor *c = (struct cursor *) cursor; ++ int ret; ++ ++ ret = sw_64_handle_signal_frame (cursor); ++ if (ret < 0) ++ /* Not a signal frame, try DWARF-based unwinding. */ ++ ret = dwarf_step (&c->dwarf); ++ ++ if (unlikely (ret == -UNW_ESTOPUNWIND)) ++ return ret; ++ ++#if _SW_64_SIM == _ABI64 ++ if (unlikely (ret < 0)) ++ { ++ return _step_n64(c); ++ } ++#endif ++ return (c->dwarf.ip == 0) ? 0 : 1; ++} ++#endif +diff --git a/src/sw_64/Lapply_reg_state.c b/src/sw_64/Lapply_reg_state.c +new file mode 100644 +index 0000000..7ebada4 +--- /dev/null ++++ b/src/sw_64/Lapply_reg_state.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gapply_reg_state.c" ++#endif +diff --git a/src/sw_64/Lcreate_addr_space.c b/src/sw_64/Lcreate_addr_space.c +new file mode 100644 +index 0000000..0f2dc6b +--- /dev/null ++++ b/src/sw_64/Lcreate_addr_space.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gcreate_addr_space.c" ++#endif +diff --git a/src/sw_64/Lget_proc_info.c b/src/sw_64/Lget_proc_info.c +new file mode 100644 +index 0000000..69028b0 +--- /dev/null ++++ b/src/sw_64/Lget_proc_info.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gget_proc_info.c" ++#endif +diff --git a/src/sw_64/Lget_save_loc.c b/src/sw_64/Lget_save_loc.c +new file mode 100644 +index 0000000..9ea048a +--- /dev/null ++++ b/src/sw_64/Lget_save_loc.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gget_save_loc.c" ++#endif +diff --git a/src/sw_64/Lglobal.c b/src/sw_64/Lglobal.c +new file mode 100644 +index 0000000..6d7b489 +--- /dev/null ++++ b/src/sw_64/Lglobal.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gglobal.c" ++#endif +diff --git a/src/sw_64/Linit.c b/src/sw_64/Linit.c +new file mode 100644 +index 0000000..e9abfdd +--- /dev/null ++++ b/src/sw_64/Linit.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit.c" ++#endif +diff --git a/src/sw_64/Linit_local.c b/src/sw_64/Linit_local.c +new file mode 100644 +index 0000000..68a1687 +--- /dev/null ++++ b/src/sw_64/Linit_local.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit_local.c" ++#endif +diff --git a/src/sw_64/Linit_remote.c b/src/sw_64/Linit_remote.c +new file mode 100644 +index 0000000..58cb04a +--- /dev/null ++++ b/src/sw_64/Linit_remote.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Ginit_remote.c" ++#endif +diff --git a/src/sw_64/Lis_signal_frame.c b/src/sw_64/Lis_signal_frame.c +new file mode 100644 +index 0000000..b9a7c4f +--- /dev/null ++++ b/src/sw_64/Lis_signal_frame.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gis_signal_frame.c" ++#endif +diff --git a/src/sw_64/Lreg_states_iterate.c b/src/sw_64/Lreg_states_iterate.c +new file mode 100644 +index 0000000..f1eb1e7 +--- /dev/null ++++ b/src/sw_64/Lreg_states_iterate.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Greg_states_iterate.c" ++#endif +diff --git a/src/sw_64/Lregs.c b/src/sw_64/Lregs.c +new file mode 100644 +index 0000000..2c9c75c +--- /dev/null ++++ b/src/sw_64/Lregs.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gregs.c" ++#endif +diff --git a/src/sw_64/Lresume.c b/src/sw_64/Lresume.c +new file mode 100644 +index 0000000..41a8cf0 +--- /dev/null ++++ b/src/sw_64/Lresume.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gresume.c" ++#endif +diff --git a/src/sw_64/Lstep.c b/src/sw_64/Lstep.c +new file mode 100644 +index 0000000..c1ac3c7 +--- /dev/null ++++ b/src/sw_64/Lstep.c +@@ -0,0 +1,5 @@ ++#define UNW_LOCAL_ONLY ++#include ++#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) ++#include "Gstep.c" ++#endif +diff --git a/src/sw_64/getcontext.S b/src/sw_64/getcontext.S +new file mode 100644 +index 0000000..0258f57 +--- /dev/null ++++ b/src/sw_64/getcontext.S +@@ -0,0 +1,77 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ Copyright (C) 2012 Tommi Rantala ++ ++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 "offsets.h" ++#include ++ ++ .text ++#define OFFSET 80 ++ .global _Usw_64_getcontext ++ .type _Usw_64_getcontext, %function ++ .ent _Usw_64_getcontext ++ # This is a stub version of getcontext() for SW_64 which only stores core ++ # registers. ++_Usw_64_getcontext: ++ .set noat ++ stl $0, (0 + OFFSET)($16) ++ stl $1, (8 + OFFSET)($16) ++ stl $2, (16 + OFFSET)($16) ++ stl $3, (24 + OFFSET)($16) ++ stl $4, (32 + OFFSET)($16) ++ stl $5, (40 + OFFSET)($16) ++ stl $6, (48 + OFFSET)($16) ++ stl $7, (56 + OFFSET)($16) ++ stl $8, (64 + OFFSET)($16) ++ stl $9, (72 + OFFSET)($16) ++ stl $10, (80 + OFFSET)($16) ++ stl $11, (88 + OFFSET)($16) ++ stl $12, (96 + OFFSET)($16) ++ stl $13, (104 + OFFSET)($16) ++ stl $14, (112 + OFFSET)($16) ++ stl $15, (120 + OFFSET)($16) ++ stl $16, (128 + OFFSET)($16) ++ stl $17, (136 + OFFSET)($16) ++ stl $18, (144 + OFFSET)($16) ++ stl $19, (152 + OFFSET)($16) ++ stl $20, (160 + OFFSET)($16) ++ stl $21, (168 + OFFSET)($16) ++ stl $22, (176 + OFFSET)($16) ++ stl $23, (184 + OFFSET)($16) ++ stl $24, (192 + OFFSET)($16) ++ stl $25, (200 + OFFSET)($16) ++ stl $26, (208 + OFFSET)($16) ++ stl $27, (216 + OFFSET)($16) ++ stl $28, (224 + OFFSET)($16) ++ stl $29, (232 + OFFSET)($16) ++ stl $30, (240 + OFFSET)($16) ++ stl $31, (248 + OFFSET)($16) ++# br $0,2f ++2: ++# stl $0, (OFFSET-16)($16) ++ stl $26, (OFFSET-16)($16) ++ ldl $0, (0 + OFFSET)($16) ++ ret ++ .end _Usw_64_getcontext ++ .size _Usw_64_getcontext, .-_Usw_64_getcontext +diff --git a/src/sw_64/init.h b/src/sw_64/init.h +new file mode 100644 +index 0000000..e40865a +--- /dev/null ++++ b/src/sw_64/init.h +@@ -0,0 +1,59 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++static inline int ++common_init (struct cursor *c, unsigned use_prev_instr) ++{ ++ int ret, i; ++ ++ for (i = 0; i < 32; i++) ++ c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_SW_64_R0 + i); ++ for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i) ++ c->dwarf.loc[i] = DWARF_NULL_LOC; ++ ++ c->dwarf.loc[UNW_SW_64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_SW_64_PC); ++ ++ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SW_64_PC], &c->dwarf.ip); ++ if (ret < 0) ++ return ret; ++ ++ ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_SW_64_R30), ++ &c->dwarf.cfa); ++ if (ret < 0) ++ return ret; ++ ++ /* FIXME: Initialisation for other registers. */ ++ ++ c->dwarf.args_size = 0; ++ c->dwarf.stash_frames = 0; ++ c->dwarf.use_prev_instr = use_prev_instr; ++ c->dwarf.pi_valid = 0; ++ c->dwarf.pi_is_dynamic = 0; ++ c->dwarf.hint = 0; ++ c->dwarf.prev_rs = 0; ++ ++ return 0; ++} +diff --git a/src/sw_64/is_fpreg.c b/src/sw_64/is_fpreg.c +new file mode 100644 +index 0000000..f7eab9c +--- /dev/null ++++ b/src/sw_64/is_fpreg.c +@@ -0,0 +1,37 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "libunwind_i.h" ++ ++/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful ++ on SW_64. */ ++ ++int ++unw_is_fpreg (int regnum) ++{ ++ /* FIXME: Support FP. */ ++ if (regnum >= UNW_SW_64_F0 && regnum < UNW_SW_64_PC) ++ return 1; ++ return 0; ++} +diff --git a/src/sw_64/offsets.h b/src/sw_64/offsets.h +new file mode 100644 +index 0000000..8656283 +--- /dev/null ++++ b/src/sw_64/offsets.h +@@ -0,0 +1,86 @@ ++/* Linux-specific definitions: */ ++ ++/* Define various structure offsets to simplify cross-compilation. */ ++ ++/* FIXME: Currently these are only used in getcontext.S, which is only used ++ for a local unwinder, so we can use the compile-time ABI. At a later date ++ we will want all three here, to use for signal handlers. Also, because ++ of the three ABIs, gen-offsets.c can not quite generate this file. */ ++ ++/* Offsets for SW_64 Linux "ucontext_t": */ ++ ++/* First 24 bytes in sigframe are argument save space and padding for ++what used to be signal trampolines. Ref: arch/sw_64/kernel/signal.c */ ++#define LINUX_SF_TRAMP_SIZE 0x18 ++ ++#if _SW_64_SIM == _ABIO32 ++ ++# define LINUX_UC_FLAGS_OFF 0x0 ++# define LINUX_UC_LINK_OFF 0x4 ++# define LINUX_UC_STACK_OFF 0x8 ++# define LINUX_UC_MCONTEXT_OFF 0x18 ++# define LINUX_UC_SIGMASK_OFF 0x268 ++# define LINUX_UC_MCONTEXT_PC 0x20 ++# define LINUX_UC_MCONTEXT_GREGS 0x28 ++ ++#elif _SW_64_SIM == _ABIN32 ++ ++# define LINUX_UC_FLAGS_OFF 0x0 ++# define LINUX_UC_LINK_OFF 0x4 ++# define LINUX_UC_STACK_OFF 0x8 ++# define LINUX_UC_MCONTEXT_OFF 0x18 ++# define LINUX_UC_SIGMASK_OFF 0x270 ++# define LINUX_UC_MCONTEXT_PC 0x258 ++# define LINUX_UC_MCONTEXT_GREGS 0x18 ++ ++#elif _SW_64_SIM == _ABI64 ++ ++# define LINUX_UC_FLAGS_OFF 0x0 ++# define LINUX_UC_LINK_OFF 0x8 ++# define LINUX_UC_STACK_OFF 0x10 ++# define LINUX_UC_MCONTEXT_OFF 0x28 ++# define LINUX_UC_SIGMASK_OFF 0x280 ++# define LINUX_UC_MCONTEXT_PC 0x268 ++# define LINUX_UC_MCONTEXT_GREGS 0x28 ++ ++#else ++ ++#error Unsupported ABI ++ ++#endif ++ ++#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) ++#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) ++#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) ++#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) ++#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) ++#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) ++#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) ++#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) ++#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) ++#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) ++#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) ++#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) ++#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) ++#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) ++#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) ++#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) ++#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) ++#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) ++#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) ++#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) ++#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) ++#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) ++#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) ++#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) ++#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) ++#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) ++#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) ++#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) ++#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) ++#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) ++#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) ++#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) ++ ++#define LINUX_SC_SP_OFF LINUX_SC_R30_OFF ++#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) +diff --git a/src/sw_64/regname.c b/src/sw_64/regname.c +new file mode 100644 +index 0000000..532f4d4 +--- /dev/null ++++ b/src/sw_64/regname.c +@@ -0,0 +1,55 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 "unwind_i.h" ++ ++static const char *regname[] = ++ { ++ /* 0. */ ++ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", ++ /* 8. */ ++ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", ++ /* 16. */ ++ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", ++ /* 24. */ ++ "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", ++ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", ++ /* 8. */ ++ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", ++ /* 16. */ ++ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", ++ /* 24. */ ++ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", ++ }; ++ ++const char * ++unw_regname (unw_regnum_t reg) ++{ ++ if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) ++ return regname[reg]; ++ else if (reg == UNW_SW_64_PC) ++ return "pc"; ++ else ++ return "???"; ++} +diff --git a/src/sw_64/siglongjmp.S b/src/sw_64/siglongjmp.S +new file mode 100644 +index 0000000..332033b +--- /dev/null ++++ b/src/sw_64/siglongjmp.S +@@ -0,0 +1,9 @@ ++ /* Dummy implementation for now. */ ++ ++ .globl _UI_siglongjmp_cont ++ .globl _UI_longjmp_cont ++ ++_UI_siglongjmp_cont: ++_UI_longjmp_cont: ++# j $31 ++ ret +diff --git a/src/sw_64/unwind_i.h b/src/sw_64/unwind_i.h +new file mode 100644 +index 0000000..c2e109d +--- /dev/null ++++ b/src/sw_64/unwind_i.h +@@ -0,0 +1,43 @@ ++/* libunwind - a platform-independent unwind library ++ Copyright (C) 2008 CodeSourcery ++ ++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 unwind_i_h ++#define unwind_i_h ++ ++#include ++ ++#include ++ ++#include "libunwind_i.h" ++ ++#define sw_64_lock UNW_OBJ(lock) ++#define sw_64_local_resume UNW_OBJ(local_resume) ++#define sw_64_local_addr_space_init UNW_OBJ(local_addr_space_init) ++ ++extern int sw_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, ++ void *arg); ++ ++extern void sw_64_local_addr_space_init (void); ++ ++#endif /* unwind_i_h */ +-- +2.41.0 + diff --git a/libunwind.spec b/libunwind.spec index 288974cc05e05b81d1098582abd95022185d9eba..72d9ffcfba0860730f4231e6b36c8fe8b76d6f52 100644 --- a/libunwind.spec +++ b/libunwind.spec @@ -1,7 +1,7 @@ Name: libunwind Epoch: 2 Version: 1.6.2 -Release: 7 +Release: 8 Summary: Libunwind provides a C ABI to determine the call-chain of a program License: BSD URL: http://savannah.nongnu.org/projects/libunwind @@ -14,7 +14,12 @@ Patch4: backport-aarch64-unw_step-validates-address-before-calling-dwarf_get.pat Patch5: backport-avoid-calling-printf-because-OE-glibc-2.34-used-mno-.patch Patch6: backport-fix-run-ptrace-mapper-test-case-failed.patch -ExclusiveArch: aarch64 %{ix86} x86_64 +Patch1000: add-loongarch-support-not-upstream-modified.patch +Patch1001: add-loongarch-support-not-upstream-new.patch +Patch1002: add-sw_64-support-not-upstream-modified.patch +Patch1003: add-sw_64-support-not-upstream-new.patch + +ExclusiveArch: aarch64 %{ix86} x86_64 loongarch64 sw_64 BuildRequires: automake libtool autoconf texlive-latex2man gcc-c++ @@ -90,11 +95,17 @@ make check || true %{_mandir}/*/* %changelog +* Mon Aug 28 2023 herengui - 2:1.6.2-8 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add support for loongarch64 and sw_64 + * Tue Jul 11 2023 chenziyang - 2:1.6.2-7 - Type:bugfix - ID:NA - SUG:NA -- DESC:backport upstream patch to fix failed run-ptrace-mapper testcase +- DESC:backport upstream patch to fix failed run-ptrace-mapper testcase * Mon Jul 03 2023 chenziyang - 2:1.6.2-6 - Type:bugfix