diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -81,6 +81,8 @@ 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 @@ 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 @@ 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 @@ /// 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 different 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.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,7 +62,8 @@ 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/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 @@ -814,15 +814,41 @@ 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/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -1080,15 +1080,18 @@ } // 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 @@ // 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 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -227,6 +227,18 @@ const uint32_t idx = ePropertyVirtualAddressableBits; SetPropertyAtIndex(idx, static_cast(bits)); } + +uint32_t ProcessProperties::GetHighmemVirtualAddressableBits() const { + const uint32_t idx = ePropertyHighmemVirtualAddressableBits; + return GetPropertyAtIndexAs( + idx, g_process_properties[idx].default_uint_value); +} + +void ProcessProperties::SetHighmemVirtualAddressableBits(uint32_t bits) { + const uint32_t idx = ePropertyHighmemVirtualAddressableBits; + SetPropertyAtIndex(idx, static_cast(bits)); +} + void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) { const uint32_t idx = ePropertyPythonOSPluginPath; SetPropertyAtIndex(idx, file); @@ -5651,25 +5663,31 @@ } 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 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -255,6 +255,9 @@ 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 differs 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)">,