diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h --- a/lldb/include/lldb/Target/ABI.h +++ b/lldb/include/lldb/Target/ABI.h @@ -117,12 +117,13 @@ // "pc". virtual bool CodeAddressIsValid(lldb::addr_t pc) = 0; - virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) { - // Some targets might use bits in a code address to indicate a mode switch. - // ARM uses bit zero to signify a code address is thumb, so any ARM ABI - // plug-ins would strip those bits. - return pc; - } + /// Some targets might use bits in a code address to indicate a mode switch. + /// ARM uses bit zero to signify a code address is thumb, so any ARM ABI + /// plug-ins would strip those bits. + /// @{ + virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) { return pc; } + virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) { return pc; } + /// @} llvm::MCRegisterInfo &GetMCRegisterInfo() { return *m_mc_register_info_up; } @@ -147,6 +148,10 @@ lldb::ProcessWP m_process_wp; std::unique_ptr m_mc_register_info_up; + virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc, lldb::addr_t mask) { + return pc; + } + private: ABI(const ABI &) = delete; const ABI &operator=(const ABI &) = delete; diff --git a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h --- a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h +++ b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h @@ -16,7 +16,14 @@ static void Initialize(); static void Terminate(); + virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) override; + virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) override; + protected: + virtual lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) { + return pc; + } + std::pair GetEHAndDWARFNums(llvm::StringRef name) override; diff --git a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp --- a/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp @@ -11,6 +11,7 @@ #include "ABISysV_arm64.h" #include "Utility/ARM64_DWARF_Registers.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Target/Process.h" LLDB_PLUGIN_DEFINE(ABIAArch64) @@ -24,6 +25,18 @@ ABIMacOSX_arm64::Terminate(); } +lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) + return FixAddress(pc, process_sp->GetCodeAddressMask()); + return pc; +} + +lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) + return FixAddress(pc, process_sp->GetDataAddressMask()); + return pc; +} + std::pair ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) { if (name == "pc") diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h --- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h +++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h @@ -62,6 +62,8 @@ return true; } + lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override; + // Static Functions static void Initialize(); diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp --- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -815,6 +815,11 @@ return return_valobj_sp; } +lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) { + lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; + return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); +} + void ABIMacOSX_arm64::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc, CreateInstance); diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h @@ -67,6 +67,8 @@ bool GetPointerReturnRegister(const char *&name) override; + lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override; + // Static Functions static void Initialize(); diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -782,6 +782,11 @@ return return_valobj_sp; } +lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) { + lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; + return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); +} + void ABISysV_arm64::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), "SysV ABI for AArch64 targets", CreateInstance); diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -1730,6 +1730,10 @@ RegisterValue reg_value; if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { old_caller_pc_value = reg_value.GetAsUInt64(); + if (ProcessSP process_sp = m_thread.GetProcess()) { + if (ABISP abi = process_sp->GetABI()) + old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value); + } } } } @@ -1785,6 +1789,10 @@ if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { new_caller_pc_value = reg_value.GetAsUInt64(); + if (ProcessSP process_sp = m_thread.GetProcess()) { + if (ABISP abi = process_sp->GetABI()) + new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value); + } } } } @@ -2121,6 +2129,12 @@ } if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { value = reg_value.GetAsUInt64(); + if (pc_register) { + if (ProcessSP process_sp = m_thread.GetProcess()) { + if (ABISP abi = process_sp->GetABI()) + value = abi->FixCodeAddress(value); + } + } return true; } return false; @@ -2162,7 +2176,19 @@ lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) return false; - return ReadRegisterValueFromRegisterLocation(regloc, reg_info, value); + bool result = ReadRegisterValueFromRegisterLocation(regloc, reg_info, value); + if (result) { + if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) { + addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS); + if (reg_value != LLDB_INVALID_ADDRESS) { + if(ProcessSP process_sp = m_thread.GetProcess()) { + if (ABISP abi = process_sp->GetABI()) + value = abi->FixCodeAddress(reg_value); + } + } + } + } + return result; } bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,