[Lldb-commits] [lldb] 21dfaf6 - Setting to control addressable bits in high memory

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Wed May 31 18:38:48 PDT 2023


Author: Jason Molenda
Date: 2023-05-31T18:38:34-07:00
New Revision: 21dfaf60a763795e3834d67def48fc2ba5214e59

URL: https://github.com/llvm/llvm-project/commit/21dfaf60a763795e3834d67def48fc2ba5214e59
DIFF: https://github.com/llvm/llvm-project/commit/21dfaf60a763795e3834d67def48fc2ba5214e59.diff

LOG: Setting to control addressable bits in high memory

On AArch64, it is possible to have a program that accesses both low
(0x000...) and high (0xfff...) memory, and with pointer authentication,
you can have different numbers of bits used for pointer authentication
depending on whether the address is in high or low memory.

This adds a new target.process.highmem-virtual-addressable-bits
setting which the AArch64 Mac ABI plugin will use, when set, to
always set those unaddressable high bits for high memory addresses,
and will use the existing target.process.virtual-addressable-bits
setting for low memory addresses.

This patch does not change the existing behavior when only
target.process.virtual-addressable-bits is set.  In that case, the
value will apply to all addresses.

Not yet done is recognizing metadata in a live process connection
(gdb-remote qHostInfo) or a Mach-O corefile LC_NOTE to set the
correct number of addressing bits for both memory ranges.  That
will be a future change.

Differential Revision: https://reviews.llvm.org/D151292
rdar://109746900

Added: 
    

Modified: 
    lldb/include/lldb/Target/Process.h
    lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
    lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
    lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
    lldb/source/Target/Process.cpp
    lldb/source/Target/TargetProperties.td

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 207b4939d0232..d565931af7087 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -81,6 +81,8 @@ class ProcessProperties : public Properties {
   FileSpec GetPythonOSPluginPath() const;
   uint32_t GetVirtualAddressableBits() const;
   void SetVirtualAddressableBits(uint32_t bits);
+  uint32_t GetHighmemVirtualAddressableBits() const;
+  void SetHighmemVirtualAddressableBits(uint32_t bits);
   void SetPythonOSPluginPath(const FileSpec &file);
   bool GetIgnoreBreakpointsInExpressions() const;
   void SetIgnoreBreakpointsInExpressions(bool ignore);
@@ -1371,6 +1373,9 @@ class Process : public std::enable_shared_from_this<Process>,
   lldb::addr_t GetCodeAddressMask();
   lldb::addr_t GetDataAddressMask();
 
+  lldb::addr_t GetHighmemCodeAddressMask();
+  lldb::addr_t GetHighmemDataAddressMask();
+
   void SetCodeAddressMask(lldb::addr_t code_address_mask) {
     m_code_address_mask = code_address_mask;
   }
@@ -1379,6 +1384,14 @@ class Process : public std::enable_shared_from_this<Process>,
     m_data_address_mask = data_address_mask;
   }
 
+  void SetHighmemCodeAddressMask(lldb::addr_t code_address_mask) {
+    m_highmem_code_address_mask = code_address_mask;
+  }
+
+  void SetHighmemDataAddressMask(lldb::addr_t data_address_mask) {
+    m_highmem_data_address_mask = data_address_mask;
+  }
+
   /// Get the Modification ID of the process.
   ///
   /// \return
@@ -3000,9 +3013,13 @@ void PruneThreadPlans();
   /// Mask for code an data addresses. The default value (0) means no mask is
   /// set.  The bits set to 1 indicate bits that are NOT significant for
   /// addressing.
+  /// The highmem versions are for targets where we may have 
diff erent masks
+  /// for low memory versus high memory addresses.
   /// @{
   lldb::addr_t m_code_address_mask = 0;
   lldb::addr_t m_data_address_mask = 0;
+  lldb::addr_t m_highmem_code_address_mask = 0;
+  lldb::addr_t m_highmem_data_address_mask = 0;
   /// @}
 
   bool m_clear_thread_plans_on_stop;

diff  --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index 4d2505ece50de..b54f6846db3b6 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -814,15 +814,41 @@ 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;
-  // When no mask is specified, clear/set the top byte; preserve
-  // the low 55 bits (00..54) for addressing and bit 55 to indicate
-  // sign.
-  if (mask == 0) {
-    // ~((1ULL<<55)-1)
-    mask = 0xff80000000000000;
+addr_t ABIMacOSX_arm64::FixCodeAddress(addr_t pc) {
+  addr_t pac_sign_extension = 0x0080000000000000ULL;
+  addr_t tbi_mask = 0xff80000000000000ULL;
+  addr_t mask = 0;
+
+  if (ProcessSP process_sp = GetProcessSP()) {
+    mask = process_sp->GetCodeAddressMask();
+    if (pc & pac_sign_extension) {
+      addr_t highmem_mask = process_sp->GetHighmemCodeAddressMask();
+      if (highmem_mask)
+        mask = highmem_mask;
+    }
+  }
+  if (mask == 0)
+    mask = tbi_mask;
+
+  return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
+}
+
+addr_t ABIMacOSX_arm64::FixDataAddress(addr_t pc) {
+  addr_t pac_sign_extension = 0x0080000000000000ULL;
+  addr_t tbi_mask = 0xff80000000000000ULL;
+  addr_t mask = 0;
+
+  if (ProcessSP process_sp = GetProcessSP()) {
+    mask = process_sp->GetDataAddressMask();
+    if (pc & pac_sign_extension) {
+      addr_t highmem_mask = process_sp->GetHighmemDataAddressMask();
+      if (highmem_mask)
+        mask = highmem_mask;
+    }
   }
+  if (mask == 0)
+    mask = tbi_mask;
+
   return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
 }
 

diff  --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
index 1a5bc7f67573d..283306ed0f815 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
@@ -62,7 +62,8 @@ class ABIMacOSX_arm64 : public ABIAArch64 {
     return true;
   }
 
-  lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
+  lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
+  lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
 
   // Static Functions
 

diff  --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index 846fdbbaa4aba..82f21fef22156 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -1080,15 +1080,18 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
       }
       // If the kernel global with the T1Sz setting is available,
       // update the target.process.virtual-addressable-bits to be correct.
+      // NB the xnu kernel always has T0Sz and T1Sz the same value.  If
+      // it wasn't the same, we would need to set
+      // target.process.virtual-addressable-bits = T0Sz
+      // target.process.highmem-virtual-addressable-bits = T1Sz
       symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType(
           arm64_T1Sz_value, eSymbolTypeData);
       if (symbol) {
-        const uint32_t orig_bits_value = m_process->GetVirtualAddressableBits();
-        // Mark all bits as addressable so we don't strip any from our
-        // memory read below, with an incorrect default value.
-        // b55 is the sign extension bit with PAC, b56:63 are TBI,
-        // don't mark those as addressable.
-        m_process->SetVirtualAddressableBits(55);
+        const addr_t orig_code_mask = m_process->GetCodeAddressMask();
+        const addr_t orig_data_mask = m_process->GetDataAddressMask();
+
+        m_process->SetCodeAddressMask(0);
+        m_process->SetDataAddressMask(0);
         Status error;
         // gT1Sz is 8 bytes.  We may run on a stripped kernel binary
         // where we can't get the size accurately.  Hardcode it.
@@ -1103,9 +1106,12 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
           // T1Sz is 25, then 64-25 == 39, bits 0..38 are used for
           // addressing, bits 39..63 are used for PAC/TBI or whatever.
           uint32_t virt_addr_bits = 64 - sym_value;
-          m_process->SetVirtualAddressableBits(virt_addr_bits);
+          addr_t mask = ~((1ULL << virt_addr_bits) - 1);
+          m_process->SetCodeAddressMask(mask);
+          m_process->SetDataAddressMask(mask);
         } else {
-          m_process->SetVirtualAddressableBits(orig_bits_value);
+          m_process->SetCodeAddressMask(orig_code_mask);
+          m_process->SetDataAddressMask(orig_data_mask);
         }
       }
     } else {

diff  --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 0aefeebbc07b4..8545ca4c12c02 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -227,6 +227,18 @@ void ProcessProperties::SetVirtualAddressableBits(uint32_t bits) {
   const uint32_t idx = ePropertyVirtualAddressableBits;
   SetPropertyAtIndex(idx, static_cast<uint64_t>(bits));
 }
+
+uint32_t ProcessProperties::GetHighmemVirtualAddressableBits() const {
+  const uint32_t idx = ePropertyHighmemVirtualAddressableBits;
+  return GetPropertyAtIndexAs<uint64_t>(
+      idx, g_process_properties[idx].default_uint_value);
+}
+
+void ProcessProperties::SetHighmemVirtualAddressableBits(uint32_t bits) {
+  const uint32_t idx = ePropertyHighmemVirtualAddressableBits;
+  SetPropertyAtIndex(idx, static_cast<uint64_t>(bits));
+}
+
 void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) {
   const uint32_t idx = ePropertyPythonOSPluginPath;
   SetPropertyAtIndex(idx, file);
@@ -5651,25 +5663,31 @@ void Process::Flush() {
 }
 
 lldb::addr_t Process::GetCodeAddressMask() {
-  if (m_code_address_mask == 0) {
-    if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
-      lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
-      SetCodeAddressMask(address_mask);
-    }
-  }
+  if (uint32_t num_bits_setting = GetVirtualAddressableBits())
+    return ~((1ULL << num_bits_setting) - 1);
+
   return m_code_address_mask;
 }
 
 lldb::addr_t Process::GetDataAddressMask() {
-  if (m_data_address_mask == 0) {
-    if (uint32_t number_of_addressable_bits = GetVirtualAddressableBits()) {
-      lldb::addr_t address_mask = ~((1ULL << number_of_addressable_bits) - 1);
-      SetDataAddressMask(address_mask);
-    }
-  }
+  if (uint32_t num_bits_setting = GetVirtualAddressableBits())
+    return ~((1ULL << num_bits_setting) - 1);
+
   return m_data_address_mask;
 }
 
+lldb::addr_t Process::GetHighmemCodeAddressMask() {
+  if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
+    return ~((1ULL << num_bits_setting) - 1);
+  return GetCodeAddressMask();
+}
+
+lldb::addr_t Process::GetHighmemDataAddressMask() {
+  if (uint32_t num_bits_setting = GetHighmemVirtualAddressableBits())
+    return ~((1ULL << num_bits_setting) - 1);
+  return GetDataAddressMask();
+}
+
 void Process::DidExec() {
   Log *log = GetLog(LLDBLog::Process);
   LLDB_LOGF(log, "Process::%s()", __FUNCTION__);

diff  --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index e8350cb9e2799..19ea505af6563 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -255,6 +255,9 @@ let Definition = "process" in {
   def VirtualAddressableBits: Property<"virtual-addressable-bits", "UInt64">,
     DefaultUnsignedValue<0>,
     Desc<"The number of bits used for addressing. If the value is 39, then bits 0..38 are used for addressing. The default value of 0 means unspecified.">;
+  def HighmemVirtualAddressableBits: Property<"highmem-virtual-addressable-bits", "UInt64">,
+    DefaultUnsignedValue<0>,
+    Desc<"The number of bits used for addressing high memory, when it 
diff ers from low memory in the same Process. When this is non-zero, target.process.virtual-addressable-bits will be the value for low memory (0x000... addresses) and this setting will be the value for high memory (0xfff... addresses). When this is zero, target.process.virtual-addressable-bits applies to all addresses. It is very uncommon to use this setting.">;
   def FollowForkMode: Property<"follow-fork-mode", "Enum">,
     DefaultEnumValue<"eFollowParent">,
     EnumValues<"OptionEnumValues(g_follow_fork_mode_values)">,


        


More information about the lldb-commits mailing list