[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

GitOrigin-RevId: 8770b4ecca557b02d37188ae2fa5479e6136b2fb
diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h
index 131b2ea..8fbb6aa 100644
--- a/include/lldb/Target/ABI.h
+++ b/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<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;
diff --git a/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/source/Plugins/ABI/AArch64/ABIAArch64.cpp
index 7cae4cc..42d73ce 100644
--- a/source/Plugins/ABI/AArch64/ABIAArch64.cpp
+++ b/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<uint32_t, uint32_t>
 ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
   if (name == "pc")
diff --git a/source/Plugins/ABI/AArch64/ABIAArch64.h b/source/Plugins/ABI/AArch64/ABIAArch64.h
index bdff648..41bbf5c 100644
--- a/source/Plugins/ABI/AArch64/ABIAArch64.h
+++ b/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<uint32_t, uint32_t>
   GetEHAndDWARFNums(llvm::StringRef name) override;
 
diff --git a/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index 861310e..c7ae128 100644
--- a/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/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/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
index fc8ccee..dc3ab35 100644
--- a/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ b/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/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
index 0f74c1f..312b562 100644
--- a/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
+++ b/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/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/source/Plugins/ABI/AArch64/ABISysV_arm64.h
index aeb74ac..4c88ee2 100644
--- a/source/Plugins/ABI/AArch64/ABISysV_arm64.h
+++ b/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/source/Target/RegisterContextUnwind.cpp b/source/Target/RegisterContextUnwind.cpp
index e77905f..b8d9926 100644
--- a/source/Target/RegisterContextUnwind.cpp
+++ b/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,