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 @@ -79,8 +79,8 @@ Args GetExtraStartupCommands() const; void SetExtraStartupCommands(const Args &args); FileSpec GetPythonOSPluginPath() const; - uint32_t GetVirtualAddressableBits() const; - void SetVirtualAddressableBits(uint32_t bits); + Args GetVirtualAddressableBits() const; + void SetVirtualAddressableBits(const Args &args); void SetPythonOSPluginPath(const FileSpec &file); bool GetIgnoreBreakpointsInExpressions() const; void SetIgnoreBreakpointsInExpressions(bool ignore); @@ -1371,6 +1371,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 +1382,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 +3011,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 @@ -1083,12 +1083,11 @@ 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 +1102,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 @@ -217,15 +217,16 @@ return GetPropertyAtIndexAs(idx, {}); } -uint32_t ProcessProperties::GetVirtualAddressableBits() const { +Args ProcessProperties::GetVirtualAddressableBits() const { + Args args; const uint32_t idx = ePropertyVirtualAddressableBits; - return GetPropertyAtIndexAs( - idx, g_process_properties[idx].default_uint_value); + m_collection_sp->GetPropertyAtIndexAsArgs(idx, args); + return args; } -void ProcessProperties::SetVirtualAddressableBits(uint32_t bits) { +void ProcessProperties::SetVirtualAddressableBits(const Args &args) { const uint32_t idx = ePropertyVirtualAddressableBits; - SetPropertyAtIndex(idx, static_cast(bits)); + m_collection_sp->SetPropertyAtIndexFromArgs(idx, args); } void ProcessProperties::SetPythonOSPluginPath(const FileSpec &file) { const uint32_t idx = ePropertyPythonOSPluginPath; @@ -5651,25 +5652,50 @@ } 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); - } - } + Args args = GetVirtualAddressableBits(); + uint32_t bits; + if (args.GetArgumentCount() >= 1) + if (llvm::to_integer(args.GetArgumentAtIndex(0), bits, 10)) + return ~((1ULL << bits) - 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); - } - } + Args args = GetVirtualAddressableBits(); + uint32_t bits; + if (args.GetArgumentCount() >= 1) + if (llvm::to_integer(args.GetArgumentAtIndex(0), bits, 10)) + return ~((1ULL << bits) - 1); + return m_data_address_mask; } +lldb::addr_t Process::GetHighmemCodeAddressMask() { + Args args = GetVirtualAddressableBits(); + size_t count = args.GetArgumentCount(); + uint32_t bits; + + if (count == 2 && llvm::to_integer(args.GetArgumentAtIndex(1), bits, 10)) + return ~((1ULL << bits) - 1); + if (count == 1 && llvm::to_integer(args.GetArgumentAtIndex(0), bits, 10)) + return ~((1ULL << bits) - 1); + + return m_highmem_code_address_mask; +} + +lldb::addr_t Process::GetHighmemDataAddressMask() { + Args args = GetVirtualAddressableBits(); + size_t count = args.GetArgumentCount(); + uint32_t bits; + if (count == 2 && llvm::to_integer(args.GetArgumentAtIndex(1), bits, 10)) + return ~((1ULL << bits) - 1); + if (count == 1 && llvm::to_integer(args.GetArgumentAtIndex(0), bits, 10)) + return ~((1ULL << bits) - 1); + + return m_highmem_data_address_mask; +} + 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 @@ -252,9 +252,9 @@ def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">, DefaultFalse, Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">; - 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 VirtualAddressableBits: Property<"virtual-addressable-bits", "Array">, + ElementType<"String">, + Desc<"The number of bits used for addressing. If the value is 39, then bits 0..38 are used for addressing. If two values are provided, the first value is for low memory addresses, the second value for high memory addresses. This is uncommon.">; def FollowForkMode: Property<"follow-fork-mode", "Enum">, DefaultEnumValue<"eFollowParent">, EnumValues<"OptionEnumValues(g_follow_fork_mode_values)">,