summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2018-02-27 21:24:02 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2018-02-27 21:24:02 +0000
commitd550d634cd38e02f4693e844f2ce2be2a65d14c5 (patch)
treeb5e27a3870aee68d88ea6ef5ddfe7c770b4b28b3
parent2b0efb9ccf3f3e5cc7486bbb70edc6521e7e9e4f (diff)
[libunwind][MIPS]: Add support for unwinding in N32 processes.
Summary: N32 uses the same register context as N64. However, N32 requires one change to properly fetch addresses from registers stored in memory. Since N32 is an ILP32 platform, getP() only fetches the first 32-bits of a stored register. For a big-endian platform this fetches the upper 32-bits which will be zero. To fix this, add a new getRegister() method to AddressSpace which is responsible for extracting the address stored in a register in memory. This matches getP() for all current ABIs except for N32 where it reads the 64-bit register and returns the low 32-bits as an address. The DwarfInstructions::getSavedRegister() method uses AddressSpace::getRegister() instead of AddressSpace::getP(). Reviewers: sdardis, compnerd Reviewed By: sdardis Differential Revision: https://reviews.llvm.org/D39074 git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@326250 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/__libunwind_config.h8
-rw-r--r--src/AddressSpace.hpp17
-rw-r--r--src/DwarfInstructions.hpp4
-rw-r--r--src/UnwindRegistersRestore.S5
-rw-r--r--src/UnwindRegistersSave.S5
-rw-r--r--src/libunwind.cpp5
6 files changed, 33 insertions, 11 deletions
diff --git a/include/__libunwind_config.h b/include/__libunwind_config.h
index 6ae0166..1b75fa9 100644
--- a/include/__libunwind_config.h
+++ b/include/__libunwind_config.h
@@ -71,11 +71,15 @@
# define _LIBUNWIND_CURSOR_SIZE 24
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
# elif defined(__mips__)
-# if defined(_ABIO32) && defined(__mips_soft_float)
+# if defined(_ABIO32) && _MIPS_SIM == _ABIO32 && defined(__mips_soft_float)
# define _LIBUNWIND_TARGET_MIPS_O32 1
# define _LIBUNWIND_CONTEXT_SIZE 18
# define _LIBUNWIND_CURSOR_SIZE 24
-# elif defined(_ABI64) && defined(__mips_soft_float)
+# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 && defined(__mips_soft_float)
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# define _LIBUNWIND_CONTEXT_SIZE 35
+# define _LIBUNWIND_CURSOR_SIZE 42
+# elif defined(_ABI64) && _MIPS_SIM == _ABI64 && defined(__mips_soft_float)
# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# define _LIBUNWIND_CONTEXT_SIZE 35
# define _LIBUNWIND_CURSOR_SIZE 47
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index 384fc9a..32ff1f3 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -207,6 +207,7 @@ public:
return val;
}
uintptr_t getP(pint_t addr);
+ uint64_t getRegister(pint_t addr);
static uint64_t getULEB128(pint_t &addr, pint_t end);
static int64_t getSLEB128(pint_t &addr, pint_t end);
@@ -228,6 +229,14 @@ inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
#endif
}
+inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
+#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
+ return get64(addr);
+#else
+ return get32(addr);
+#endif
+}
+
/// Read a ULEB128 into a 64-bit word.
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
@@ -600,6 +609,7 @@ public:
uint32_t get32(pint_t addr);
uint64_t get64(pint_t addr);
pint_t getP(pint_t addr);
+ uint64_t getRegister(pint_t addr);
uint64_t getULEB128(pint_t &addr, pint_t end);
int64_t getSLEB128(pint_t &addr, pint_t end);
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
@@ -636,7 +646,12 @@ typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
}
template <typename P>
-uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
+typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
+ return P::getRegister(*(uint64_t *)localCopy(addr));
+}
+
+template <typename P>
+uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
uintptr_t size = (end - addr);
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
LocalAddressSpace::pint_t sladdr = laddr;
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index bd1448b..88e6719 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -82,10 +82,10 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getP(cfa + (pint_t)savedReg.value);
+ return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getP(
+ return addressSpace.getRegister(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
diff --git a/src/UnwindRegistersRestore.S b/src/UnwindRegistersRestore.S
index d774414..a3ba4d1 100644
--- a/src/UnwindRegistersRestore.S
+++ b/src/UnwindRegistersRestore.S
@@ -799,7 +799,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
l.jr r9
l.nop
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \
+ defined(__mips_soft_float)
//
// void libunwind::Registers_mips_o32::jumpto()
@@ -855,7 +856,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
lw $4, (4 * 4)($4)
.set pop
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64) && defined(__mips_soft_float)
//
// void libunwind::Registers_mips_newabi::jumpto()
diff --git a/src/UnwindRegistersSave.S b/src/UnwindRegistersSave.S
index 8c5816b..1b6cff8 100644
--- a/src/UnwindRegistersSave.S
+++ b/src/UnwindRegistersSave.S
@@ -116,7 +116,8 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
xorl %eax, %eax # return UNW_ESUCCESS
ret
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \
+ defined(__mips_soft_float)
#
# extern int unw_getcontext(unw_context_t* thread_state)
@@ -172,7 +173,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
or $2, $0, $0
.set pop
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64) && defined(__mips_soft_float)
#
# extern int unw_getcontext(unw_context_t* thread_state)
diff --git a/src/libunwind.cpp b/src/libunwind.cpp
index 4079de3..c7318fb 100644
--- a/src/libunwind.cpp
+++ b/src/libunwind.cpp
@@ -61,9 +61,10 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_arm
#elif defined(__or1k__)
# define REGISTER_KIND Registers_or1k
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \
+ defined(__mips_soft_float)
# define REGISTER_KIND Registers_mips_o32
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64) && defined(__mips_soft_float)
# define REGISTER_KIND Registers_mips_newabi
#elif defined(__mips__)
# warning The MIPS architecture is not supported with this ABI and environment!