Author: Jason Molenda Date: 2023-08-15T13:21:33-07:00 New Revision: 3ad618f4aea1ef7442f7ff75d92632aec177a4fd
URL: https://github.com/llvm/llvm-project/commit/3ad618f4aea1ef7442f7ff75d92632aec177a4fd DIFF: https://github.com/llvm/llvm-project/commit/3ad618f4aea1ef7442f7ff75d92632aec177a4fd.diff LOG: Update qHostInfo/LC_NOTE so multiple address bits can be specified On AArch64 systems, we may have different page table setups for low memory and high memory, and therefore a different number of bits used for addressing depending on which half of memory the address is in. This patch extends the qHostInfo and LC_NOTE "addrable bits" so that it can specify the number of addressing bits in high memory and in low memory separately. It builds on the patch I added in https://reviews.llvm.org/D151292 where Process tracks the separate address masks, and there is a user setting to set them manually. Differential Revision: https://reviews.llvm.org/D157667 rdar://113225907 Added: lldb/include/lldb/Utility/AddressableBits.h lldb/source/Utility/AddressableBits.cpp Modified: lldb/docs/lldb-gdb-remote.txt lldb/include/lldb/Symbol/ObjectFile.h lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp lldb/source/Utility/CMakeLists.txt Removed: ################################################################################ diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 27adaa33d14045..bfc10133051a3a 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -978,6 +978,14 @@ addressing_bits: optional, specifies how many bits in addresses are v8.3 ABIs that use pointer authentication, so lldb knows which bits to clear/set to get the actual addresses. +low_mem_addressing_bits: optional, specifies how many bits in + addresses in low memory are significant for addressing, base 10. + AArch64 can have diff erent page table setups for low and high + memory, and therefore a diff erent number of bits used for addressing. +high_mem_addressing_bits: optional, specifies how many bits in + addresses in high memory are significant for addressing, base 10. + AArch64 can have diff erent page table setups for low and high + memory, and therefore a diff erent number of bits used for addressing. //---------------------------------------------------------------------- // "qGDBServerVersion" diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index 2fc1cc582d2ceb..02d1248e23c342 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -13,6 +13,7 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/UnwindTable.h" +#include "lldb/Utility/AddressableBits.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/FileSpec.h" @@ -494,13 +495,18 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>, /// Some object files may have the number of bits used for addressing /// embedded in them, e.g. a Mach-O core file using an LC_NOTE. These - /// object files can return the address mask that should be used in - /// the Process. + /// object files can return an AddressableBits object that can can be + /// used to set the address masks in the Process. + /// + /// \param[out] address_bits + /// Can be used to set the Process address masks. + /// /// \return - /// The mask will have bits set which aren't used for addressing -- - /// typically, the high bits. - /// Zero is returned when no address bits mask is available. - virtual lldb::addr_t GetAddressMask() { return 0; } + /// Returns true if addressable bits metadata was found. + virtual bool GetAddressableBits(lldb_private::AddressableBits &address_bits) { + address_bits.Clear(); + return false; + } /// When the ObjectFile is a core file, lldb needs to locate the "binary" in /// the core file. lldb can iterate over the pages looking for a valid diff --git a/lldb/include/lldb/Utility/AddressableBits.h b/lldb/include/lldb/Utility/AddressableBits.h new file mode 100644 index 00000000000000..d7e2e341569655 --- /dev/null +++ b/lldb/include/lldb/Utility/AddressableBits.h @@ -0,0 +1,43 @@ +//===-- AddressableBits.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_ADDRESSABLEBITS_H +#define LLDB_UTILITY_ADDRESSABLEBITS_H + +#include "lldb/lldb-forward.h" + +namespace lldb_private { + +/// \class AddressableBits AddressableBits.h "lldb/Core/AddressableBits.h" +/// A class which holds the metadata from a remote stub/corefile note +/// about how many bits are used for addressing on this target. +/// +class AddressableBits { +public: + AddressableBits() : m_low_memory_addr_bits(0), m_high_memory_addr_bits(0) {} + + /// When a single value is available for the number of bits. + void SetAddressableBits(uint32_t addressing_bits); + + /// When we have separate values for low memory addresses and high memory + /// addresses. + void SetAddressableBits(uint32_t lowmem_addressing_bits, + uint32_t highmem_addressing_bits); + + void SetProcessMasks(lldb_private::Process &process); + + void Clear(); + +private: + uint32_t m_low_memory_addr_bits; + uint32_t m_high_memory_addr_bits; +}; + +} // namespace lldb_private + +#endif // LLDB_UTILITY_ADDRESSABLEBITS_H diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index f407abb800aaa3..b737733c1b5148 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5486,8 +5486,9 @@ std::string ObjectFileMachO::GetIdentifierString() { return result; } -addr_t ObjectFileMachO::GetAddressMask() { - addr_t mask = 0; +bool ObjectFileMachO::GetAddressableBits(AddressableBits &address_bits) { + address_bits.Clear(); + Log *log(GetLog(LLDBLog::Process)); ModuleSP module_sp(GetModule()); if (module_sp) { @@ -5514,13 +5515,24 @@ addr_t ObjectFileMachO::GetAddressMask() { if (version == 3) { uint32_t num_addr_bits = m_data.GetU32_unchecked(&offset); if (num_addr_bits != 0) { - mask = ~((1ULL << num_addr_bits) - 1); + address_bits.SetAddressableBits(num_addr_bits); } LLDB_LOGF(log, - "LC_NOTE 'addrable bits' found, value %d bits, " - "mask 0x%" PRIx64, - num_addr_bits, mask); - break; + "LC_NOTE 'addrable bits' v3 found, value %d " + "bits", + num_addr_bits); + return true; + } + if (version == 4) { + uint32_t lo_addr_bits = m_data.GetU32_unchecked(&offset); + uint32_t hi_addr_bits = m_data.GetU32_unchecked(&offset); + + address_bits.SetAddressableBits(lo_addr_bits, hi_addr_bits); + LLDB_LOGF(log, + "LC_NOTE 'addrable bits' v4 found, value %d & %d bits", + lo_addr_bits, hi_addr_bits); + + return true; } } } @@ -5528,7 +5540,7 @@ addr_t ObjectFileMachO::GetAddressMask() { offset = cmd_offset + lc.cmdsize; } } - return mask; + return false; } bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, @@ -6669,10 +6681,12 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp, addrable_bits_lcnote_up->name = "addrable bits"; addrable_bits_lcnote_up->payload_file_offset = file_offset; int bits = std::bitset<64>(~address_mask).count(); - addrable_bits_lcnote_up->payload.PutHex32(3); // version + addrable_bits_lcnote_up->payload.PutHex32(4); // version + addrable_bits_lcnote_up->payload.PutHex32( + bits); // # of bits used for low addresses addrable_bits_lcnote_up->payload.PutHex32( - bits); // # of bits used for addressing - addrable_bits_lcnote_up->payload.PutHex64(0); // unused + bits); // # of bits used for high addresses + addrable_bits_lcnote_up->payload.PutHex32(0); // reserved file_offset += addrable_bits_lcnote_up->payload.GetSize(); diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 7099a4fbadf405..3f6acbf4832b7e 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -122,7 +122,7 @@ class ObjectFileMachO : public lldb_private::ObjectFile { std::string GetIdentifierString() override; - lldb::addr_t GetAddressMask() override; + bool GetAddressableBits(lldb_private::AddressableBits &address_bits) override; bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset, lldb_private::UUID &uuid, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c6503129685ab4..f836f08c4c847a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1265,7 +1265,15 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { if (!value.getAsInteger(0, pointer_byte_size)) ++num_keys_decoded; } else if (name.equals("addressing_bits")) { - if (!value.getAsInteger(0, m_addressing_bits)) + if (!value.getAsInteger(0, m_low_mem_addressing_bits)) { + m_high_mem_addressing_bits = m_low_mem_addressing_bits; + ++num_keys_decoded; + } + } else if (name.equals("high_mem_addressing_bits")) { + if (!value.getAsInteger(0, m_high_mem_addressing_bits)) + ++num_keys_decoded; + } else if (name.equals("low_mem_addressing_bits")) { + if (!value.getAsInteger(0, m_low_mem_addressing_bits)) ++num_keys_decoded; } else if (name.equals("os_version") || name.equals("version")) // Older debugserver binaries used @@ -1407,11 +1415,19 @@ GDBRemoteCommunicationClient::GetHostArchitecture() { return m_host_arch; } -uint32_t GDBRemoteCommunicationClient::GetAddressingBits() { +bool GDBRemoteCommunicationClient::GetAddressableBits( + lldb_private::AddressableBits &addressable_bits) { + addressable_bits.Clear(); if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); - return m_addressing_bits; + if (m_low_mem_addressing_bits != 0 || m_high_mem_addressing_bits != 0) { + addressable_bits.SetAddressableBits(m_low_mem_addressing_bits, + m_high_mem_addressing_bits); + return true; + } + return false; } + seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 6cf5de68911be2..fcdf7541ae25f2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -19,6 +19,7 @@ #include <vector> #include "lldb/Host/File.h" +#include "lldb/Utility/AddressableBits.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/ProcessInfo.h" @@ -237,7 +238,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { ArchSpec GetSystemArchitecture(); - uint32_t GetAddressingBits(); + bool GetAddressableBits(lldb_private::AddressableBits &addressable_bits); bool GetHostname(std::string &s); @@ -580,7 +581,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID; uint32_t m_num_supported_hardware_watchpoints = 0; - uint32_t m_addressing_bits = 0; + uint32_t m_low_mem_addressing_bits = 0; + uint32_t m_high_mem_addressing_bits = 0; ArchSpec m_host_arch; std::string m_host_distribution_id; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 336f0607e6d57d..2c35957d2e55ae 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -899,10 +899,9 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetTriple().getTriple()); } - if (int addressable_bits = m_gdb_comm.GetAddressingBits()) { - lldb::addr_t address_mask = ~((1ULL << addressable_bits) - 1); - SetCodeAddressMask(address_mask); - SetDataAddressMask(address_mask); + AddressableBits addressable_bits; + if (m_gdb_comm.GetAddressableBits(addressable_bits)) { + addressable_bits.SetProcessMasks(*this); } if (process_arch.IsValid()) { diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index c93a2a2479aa6b..9ad6d70e25299d 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -509,10 +509,9 @@ Status ProcessMachCore::DoLoadCore() { CleanupMemoryRegionPermissions(); - addr_t address_mask = core_objfile->GetAddressMask(); - if (address_mask != 0) { - SetCodeAddressMask(address_mask); - SetDataAddressMask(address_mask); + AddressableBits addressable_bits; + if (core_objfile->GetAddressableBits(addressable_bits)) { + addressable_bits.SetProcessMasks(*this); } return error; } diff --git a/lldb/source/Utility/AddressableBits.cpp b/lldb/source/Utility/AddressableBits.cpp new file mode 100644 index 00000000000000..29033ea67ec37e --- /dev/null +++ b/lldb/source/Utility/AddressableBits.cpp @@ -0,0 +1,50 @@ +//===-- AddressableBits.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/AddressableBits.h" +#include "lldb/Target/Process.h" +#include "lldb/lldb-types.h" + +using namespace lldb; +using namespace lldb_private; + +void AddressableBits::SetAddressableBits(uint32_t addressing_bits) { + m_low_memory_addr_bits = m_high_memory_addr_bits = addressing_bits; +} + +void AddressableBits::SetAddressableBits(uint32_t lowmem_addressing_bits, + uint32_t highmem_addressing_bits) { + m_low_memory_addr_bits = lowmem_addressing_bits; + m_high_memory_addr_bits = highmem_addressing_bits; +} + +void AddressableBits::Clear() { + m_low_memory_addr_bits = m_high_memory_addr_bits = 0; +} + +void AddressableBits::SetProcessMasks(Process &process) { + // In case either value is set to 0, indicating it was not set, use the + // other value. + if (m_low_memory_addr_bits == 0) + m_low_memory_addr_bits = m_high_memory_addr_bits; + if (m_high_memory_addr_bits == 0) + m_high_memory_addr_bits = m_low_memory_addr_bits; + + if (m_low_memory_addr_bits == 0) + return; + + addr_t address_mask = ~((1ULL << m_low_memory_addr_bits) - 1); + process.SetCodeAddressMask(address_mask); + process.SetDataAddressMask(address_mask); + + if (m_low_memory_addr_bits != m_high_memory_addr_bits) { + lldb::addr_t hi_address_mask = ~((1ULL << m_high_memory_addr_bits) - 1); + process.SetHighmemCodeAddressMask(hi_address_mask); + process.SetHighmemDataAddressMask(hi_address_mask); + } +} diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt index b376ace0ebe3d0..16afab1113a970 100644 --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -24,6 +24,7 @@ if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB ) endif() add_lldb_library(lldbUtility NO_INTERNAL_DEPENDENCIES + AddressableBits.cpp ArchSpec.cpp Args.cpp Baton.cpp _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits