Index: lldb/include/lldb/Target/ABI.h =================================================================== --- lldb/include/lldb/Target/ABI.h +++ 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; Index: lldb/source/Plugins/ABI/AArch64/ABIAArch64.h =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIAArch64.h +++ 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; Index: lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ 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") Index: lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h +++ 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(); Index: lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -815,6 +815,13 @@ return return_valobj_sp; } +lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) { + if (mask == (lldb::addr_t)-1) + return pc; + 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); Index: lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h +++ 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(); Index: lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -782,6 +782,13 @@ return return_valobj_sp; } +lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) { + if (mask == (lldb::addr_t)-1) + return pc; + 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); Index: lldb/source/Target/RegisterContextUnwind.cpp =================================================================== --- lldb/source/Target/RegisterContextUnwind.cpp +++ lldb/source/Target/RegisterContextUnwind.cpp @@ -383,7 +383,7 @@ // symbol/function information - just stick in some reasonable defaults and // hope we can unwind past this frame. If we're above a trap handler, // we may be at a bogus address because we jumped through a bogus function - // pointer and trapped, so don't force the arch default unwind plan in that + // pointer and trapped, so don't force the arch default unwind plan in that // case. ModuleSP pc_module_sp(m_current_pc.GetModule()); if ((!m_current_pc.IsValid() || !pc_module_sp) && @@ -1277,7 +1277,7 @@ // arch default unwind plan is used as the Fast Unwind Plan, we // need to recognize this & switch over to the Full Unwind Plan // to see what unwind rule that (more knoweldgeable, probably) - // UnwindPlan has. If the full UnwindPlan says the register + // UnwindPlan has. If the full UnwindPlan says the register // location is Undefined, then it really is. if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), unwindplan_regloc) && @@ -1325,14 +1325,14 @@ m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) { // If this is a trap handler frame, we should have access to - // the complete register context when the interrupt/async + // the complete register context when the interrupt/async // signal was received, we should fetch the actual saved $pc // value instead of the Return Address register. // If $pc is not available, fall back to the RA reg. UnwindPlan::Row::RegisterLocation scratch; if (m_frame_type == eTrapHandlerFrame && - active_row->GetRegisterInfo - (pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) { + active_row->GetRegisterInfo( + pc_regnum.GetAsKind(unwindplan_registerkind), scratch)) { UnwindLogMsg("Providing pc register instead of rewriting to " "RA reg because this is a trap handler and there is " "a location for the saved pc register value."); @@ -1730,6 +1730,12 @@ RegisterValue reg_value; if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { old_caller_pc_value = reg_value.GetAsUInt64(); + ProcessSP process_sp(m_thread.GetProcess()); + if (process_sp) { + ABI *abi = process_sp->GetABI().get(); + if (abi) + old_caller_pc_value = abi->FixCodeAddress(old_caller_pc_value); + } } } } @@ -1785,6 +1791,12 @@ if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { new_caller_pc_value = reg_value.GetAsUInt64(); + ProcessSP process_sp(m_thread.GetProcess()); + if (process_sp) { + ABI *abi = process_sp->GetABI().get(); + if (abi) + new_caller_pc_value = abi->FixCodeAddress(new_caller_pc_value); + } } } } @@ -2121,6 +2133,14 @@ } if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) { value = reg_value.GetAsUInt64(); + if (pc_register) { + ProcessSP process_sp(m_thread.GetProcess()); + if (process_sp) { + ABI *abi = process_sp->GetABI().get(); + if (abi) + value = abi->FixCodeAddress(value); + } + } return true; } return false; @@ -2162,7 +2182,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) { + ProcessSP process_sp(m_thread.GetProcess()); + addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS); + if (process_sp && reg_value != LLDB_INVALID_ADDRESS) { + ABI *abi = process_sp->GetABI().get(); + if (abi) + value = abi->FixCodeAddress(reg_value); + } + } + } + return result; } bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,