diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt --- a/lldb/docs/lldb-gdb-remote.txt +++ b/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" diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/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 diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/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, diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/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,41 @@ 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); + } + + // In case we were only given a low or high memory addressing + // bits, copy the value to the other. + if (lo_addr_bits == 0) + lo_addr_bits = hi_addr_bits; + if (hi_addr_bits == 0) + hi_addr_bits = lo_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 +5558,7 @@ offset = cmd_offset + lc.cmdsize; } } - return mask; + return false; } bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, @@ -6669,10 +6699,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(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/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; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/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(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -899,10 +899,24 @@ 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 low or high memory addressing bits, + // copy the value to the other. + if (low_mem_addressable_bits == 0) + low_mem_addressable_bits = high_mem_addressable_bits; + if (high_mem_addressable_bits == 0) + high_mem_addressable_bits = low_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); + SetHighmemCodeAddressMask(hi_address_mask); + SetHighmemDataAddressMask(hi_address_mask); + } } if (process_arch.IsValid()) { diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/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; }