[lldb] Implement ABI::Fix{Code,Data}Address for AArch64

Implement FixCodeAddress and FixDataAddress for ABIMacOSX_arm64 and
ABISysV_arm64 and add missing calls to RegisterContextUnwind. We need
this to unwind on Apple Silicon where libraries like libSystem are
arm64e even when the program being debugged is arm64.

Differential revision: https://reviews.llvm.org/D100521
This commit is contained in:
Jonas Devlieghere
2021-04-16 12:39:39 -07:00
parent 550ed575cb
commit 8770b4ecca
8 changed files with 72 additions and 7 deletions

View File

@@ -117,12 +117,13 @@ public:
// "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 @@ protected:
lldb::ProcessWP m_process_wp;
std::unique_ptr<llvm::MCRegisterInfo> 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;

View File

@@ -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 @@ void ABIAArch64::Terminate() {
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<uint32_t, uint32_t>
ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
if (name == "pc")

View File

@@ -16,7 +16,14 @@ public:
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<uint32_t, uint32_t>
GetEHAndDWARFNums(llvm::StringRef name) override;

View File

@@ -815,6 +815,11 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
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);

View File

@@ -62,6 +62,8 @@ public:
return true;
}
lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
// Static Functions
static void Initialize();

View File

@@ -782,6 +782,11 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
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);

View File

@@ -67,6 +67,8 @@ public:
bool GetPointerReturnRegister(const char *&name) override;
lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
// Static Functions
static void Initialize();

View File

@@ -1730,6 +1730,10 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
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 @@ bool RegisterContextUnwind::TryFallbackUnwindPlan() {
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 @@ bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
}
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 @@ bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
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,