diff options
author | John Baldwin <jhb@FreeBSD.org> | 2018-02-27 21:24:02 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2018-02-27 21:24:02 +0000 |
commit | 0594aee52fad70d2a0b44b321579b857b8cf9244 (patch) | |
tree | 6f14b96634dacd317fc854d49c16e19c8ce7a905 /libunwind/src/AddressSpace.hpp | |
parent | 5337efc69cdd59950faf0579043eb7aa8b9a3f2e (diff) | |
download | bcm5719-llvm-0594aee52fad70d2a0b44b321579b857b8cf9244.tar.gz bcm5719-llvm-0594aee52fad70d2a0b44b321579b857b8cf9244.zip |
[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
llvm-svn: 326250
Diffstat (limited to 'libunwind/src/AddressSpace.hpp')
-rw-r--r-- | libunwind/src/AddressSpace.hpp | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 384fc9a32da..32ff1f3d104 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/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; |