jasonmolenda created this revision. jasonmolenda added reviewers: JDevlieghere, bulbazord. jasonmolenda added a project: LLDB. Herald added a subscriber: kristof.beyls. Herald added a project: All. jasonmolenda requested review of this revision. Herald added a subscriber: lldb-commits.
To recap, on AArch64 where we need to strip pointer authentication bits off of addresses, it can have a different number of bits in use for high and low memory (you can have a different page table setup for high and low memory, so different number of addressing bits for virtual addresses). I added this to Process and defined a new setting so these can be done manually in https://reviews.llvm.org/D151292 a few months ago. This patch defines keys for qHostInfo and a new "addrable bits" LC_NOTE format for mach-o corefiles to define both of them. qHostInfo gains `low_mem_addressing_bits` and `high_mem_addressing_bits` keys. The previous `addressing_bits` is still accepted for a value that is used for both regions of memory (this is by far the most common case). For Mach-O corefile, I've needed to update the "addrable bits" LC_NOTE. The previous definition was struct addressing_bit_count_v3 // ** DEPRECATED ** { uint32_t version; // currently 3 uint32_t addressing_bits; // # of bits used for addressing uint64_t unused; }; The new definition is struct addressing_bit_count { // currently 4 uint32_t version; // Number of bits used for addressing in low // memory (addresses starting with 0) uint32_t low_memory_addressing_bits; // Number of bits used for addressing in high // memory (addresses starting with f) uint32_t high_memory_addressing_bits; // set to zero uint32_t reserved; }; The changes in this patchset are to GDBRemoteCommunicationClient (read the new qHostInfo keys), ProcessGDBRemote (set both in the Process when they are specified). And ObjectFileMachO (read and write the new LC_NOTE in mach-o corefiles), ProcessMachCore (set both in Process when they are specified). I still accept the previous formats of a single value, and only initialize the base CodeAddressMask and DataAddressMask. Only when both high and low memory addressing bits are specified and are different, do we set the Process' HighmemCodeAddressMask, HighmemDataAddressMask. This is the final part of adding support for the different address masks that can be used on AArch64 targets. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D157667 Files: 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
Index: lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp =================================================================== --- lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -509,10 +509,14 @@ CleanupMemoryRegionPermissions(); - addr_t address_mask = core_objfile->GetAddressMask(); - if (address_mask != 0) { - SetCodeAddressMask(address_mask); - SetDataAddressMask(address_mask); + addr_t lo_addr_mask, hi_addr_mask; + if (core_objfile->GetAddressMask(lo_addr_mask, hi_addr_mask)) { + SetCodeAddressMask(lo_addr_mask); + SetDataAddressMask(lo_addr_mask); + if (lo_addr_mask != hi_addr_mask) { + SetHighmemCodeAddressMask(hi_addr_mask); + SetHighmemDataAddressMask(hi_addr_mask); + } } return error; } Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -899,10 +899,21 @@ process_arch.GetTriple().getTriple()); } - if (int addressable_bits = m_gdb_comm.GetAddressingBits()) { - lldb::addr_t address_mask = ~((1ULL << addressable_bits) - 1); + uint32_t low_mem_addressable_bits, high_mem_addressable_bits; + m_gdb_comm.GetAddressingBits(low_mem_addressable_bits, + high_mem_addressable_bits); + // In case we were only given a high memory addressing bits + if (low_mem_addressable_bits == 0) + low_mem_addressable_bits = high_mem_addressable_bits; + if (low_mem_addressable_bits != 0) { + lldb::addr_t address_mask = ~((1ULL << low_mem_addressable_bits) - 1); SetCodeAddressMask(address_mask); SetDataAddressMask(address_mask); + if (low_mem_addressable_bits != high_mem_addressable_bits) { + lldb::addr_t hi_address_mask = ~((1ULL << high_mem_addressable_bits) - 1); + SetCodeAddressMask(hi_address_mask); + SetDataAddressMask(hi_address_mask); + } } if (process_arch.IsValid()) { Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -237,7 +237,8 @@ ArchSpec GetSystemArchitecture(); - uint32_t GetAddressingBits(); + void GetAddressingBits(uint32_t &lo_mem_addr_bits, + uint32_t &hi_mem_addr_bits); bool GetHostname(std::string &s); @@ -580,7 +581,8 @@ 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; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1265,7 +1265,15 @@ 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,16 @@ return m_host_arch; } -uint32_t GDBRemoteCommunicationClient::GetAddressingBits() { +void GDBRemoteCommunicationClient::GetAddressingBits( + uint32_t &lo_mem_addr_bits, uint32_t &hi_mem_addr_bits) { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); - return m_addressing_bits; + // These are initialized to zero, so we'll return zeroes + // if there were no address bits hints in qHostInfo. + lo_mem_addr_bits = m_low_mem_addressing_bits; + hi_mem_addr_bits = m_high_mem_addressing_bits; } + seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h =================================================================== --- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -122,7 +122,8 @@ std::string GetIdentifierString() override; - lldb::addr_t GetAddressMask() override; + bool GetAddressMask(lldb::addr_t &lowmem_mask, + lldb::addr_t &highmem_mask) override; bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset, lldb_private::UUID &uuid, Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5486,8 +5486,10 @@ return result; } -addr_t ObjectFileMachO::GetAddressMask() { - addr_t mask = 0; +bool ObjectFileMachO::GetAddressMask(addr_t &lowmem_mask, + addr_t &highmem_mask) { + lowmem_mask = highmem_mask = 0; + Log *log(GetLog(LLDBLog::Process)); ModuleSP module_sp(GetModule()); if (module_sp) { @@ -5514,13 +5516,37 @@ if (version == 3) { uint32_t num_addr_bits = m_data.GetU32_unchecked(&offset); if (num_addr_bits != 0) { - mask = ~((1ULL << num_addr_bits) - 1); + lowmem_mask = highmem_mask = ~((1ULL << num_addr_bits) - 1); } LLDB_LOGF(log, - "LC_NOTE 'addrable bits' found, value %d bits, " + "LC_NOTE 'addrable bits' v3 found, value %d bits, " "mask 0x%" PRIx64, - num_addr_bits, mask); - break; + num_addr_bits, lowmem_mask); + 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); + + if (lo_addr_bits == hi_addr_bits) { + LLDB_LOGF(log, + "LC_NOTE 'addrable bits' v4 found, value %d bits", + lo_addr_bits); + } else { + LLDB_LOGF( + log, "LC_NOTE 'addrable bits' v4 found, value %d & %d bits", + lo_addr_bits, hi_addr_bits); + } + + if (lo_addr_bits == 0) + lo_addr_bits = hi_addr_bits; + + if (lo_addr_bits != 0) + lowmem_mask = ~((1ULL << lo_addr_bits) - 1); + if (hi_addr_bits != 0) + highmem_mask = ~((1ULL << hi_addr_bits) - 1); + + return true; } } } @@ -5528,7 +5554,7 @@ offset = cmd_offset + lc.cmdsize; } } - return mask; + return false; } bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, @@ -6669,10 +6695,12 @@ 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(); Index: lldb/include/lldb/Symbol/ObjectFile.h =================================================================== --- lldb/include/lldb/Symbol/ObjectFile.h +++ lldb/include/lldb/Symbol/ObjectFile.h @@ -496,11 +496,20 @@ /// 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. + /// + /// /param[out] lowmem_mask + /// Address mask to be used for low memory addresses. + /// + /// /param[out] highmem_mask + /// Address mask to be used for high memory addresses. + /// /// \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 address masks were found. + virtual bool GetAddressMask(lldb::addr_t &lowmem_mask, + lldb::addr_t &highmem_mask) { + lowmem_mask = highmem_mask = 0; + 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 Index: lldb/docs/lldb-gdb-remote.txt =================================================================== --- lldb/docs/lldb-gdb-remote.txt +++ lldb/docs/lldb-gdb-remote.txt @@ -978,6 +978,14 @@ 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 different page table setups for low and high + memory, and therefore a different 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 different page table setups for low and high + memory, and therefore a different number of bits used for addressing. //---------------------------------------------------------------------- // "qGDBServerVersion"
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits