diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -794,14 +794,20 @@ // Reads code or data address mask for the current Linux process. static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp, llvm::StringRef reg_name) { - // Linux configures user-space virtual addresses with top byte ignored. - // We set default value of mask such that top byte is masked out. - uint64_t address_mask = ~((1ULL << 56) - 1); - // If Pointer Authentication feature is enabled then Linux exposes - // PAC data and code mask register. Try reading relevant register - // below and merge it with default address mask calculated above. + // 0 means there isn't a mask or it has not been read yet. + // We do not return the top byte mask unless thread_sp is valid. + // This prevents calls to this function before the thread is setup locking + // in the value to just the top byte mask, in cases where pointer + // authentication might also be active. + uint64_t address_mask = 0; lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); if (thread_sp) { + // Linux configures user-space virtual addresses with top byte ignored. + // We set default value of mask such that top byte is masked out. + address_mask = ~((1ULL << 56) - 1); + // If Pointer Authentication feature is enabled then Linux exposes + // PAC data and code mask register. Try reading relevant register + // below and merge it with default address mask calculated above. lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); if (reg_ctx_sp) { const RegisterInfo *reg_info = diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" @@ -281,6 +282,9 @@ // Process Memory size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) { + if (lldb::ABISP abi_sp = GetABI()) + addr = abi_sp->FixAnyAddress(addr); + // Don't allow the caching that lldb_private::Process::ReadMemory does since // in core files we have it all cached our our core file anyway. return DoReadMemory(addr, buf, size, error); diff --git a/lldb/test/API/linux/aarch64/non_address_bit_memory_access/TestAArch64LinuxNonAddressBitMemoryAccess.py b/lldb/test/API/linux/aarch64/non_address_bit_memory_access/TestAArch64LinuxNonAddressBitMemoryAccess.py --- a/lldb/test/API/linux/aarch64/non_address_bit_memory_access/TestAArch64LinuxNonAddressBitMemoryAccess.py +++ b/lldb/test/API/linux/aarch64/non_address_bit_memory_access/TestAArch64LinuxNonAddressBitMemoryAccess.py @@ -163,6 +163,10 @@ # Open log ignoring utf-8 decode errors with open(log_file, 'r', errors='ignore') as f: read_packet = "send packet: $x{:x}" + + # Since we allocated a 4k page that page will be aligned to 4k, which + # also fits the 512 byte line size of the memory cache. So we can expect + # to find a packet with its exact address. read_buf_packet = read_packet.format(buf) read_buf_with_non_address_packet = read_packet.format(buf_with_non_address) @@ -180,3 +184,51 @@ if not found_read_buf: self.fail("Did not find any reads of buf.") + + @skipIfLLVMTargetMissing("AArch64") + def test_non_address_bit_memory_corefile(self): + self.runCmd("target create --core corefile") + + self.expect("thread list", substrs=['stopped', + 'stop reason = signal SIGSEGV']) + + # No caching (the program/corefile are the cache) and no writing + # to memory. So just check that tagged/untagged addresses read + # the same location. + + # These are known addresses in the corefile, since we won't have symbols. + buf = 0x0000ffffa75a5000 + buf_with_non_address = 0xff0bffffa75a5000 + + expected = ["4c 4c 44 42", "LLDB"] + self.expect("memory read 0x{:x}".format(buf), substrs=expected) + self.expect("memory read 0x{:x}".format(buf_with_non_address), substrs=expected) + + # This takes a more direct route to ReadMemory. As opposed to "memory read" + # above that might fix the addresses up front for display reasons. + self.expect("expression (char*)0x{:x}".format(buf), substrs=["LLDB"]) + self.expect("expression (char*)0x{:x}".format(buf_with_non_address), substrs=["LLDB"]) + + def check_reads(addrs, method, num_bytes, expected): + error = lldb.SBError() + for addr in addrs: + if num_bytes is None: + got = method(addr, error) + else: + got = method(addr, num_bytes, error) + + self.assertTrue(error.Success()) + self.assertEqual(expected, got) + + addr_buf = lldb.SBAddress() + addr_buf.SetLoadAddress(buf, self.target()) + addr_buf_with_non_address = lldb.SBAddress() + addr_buf_with_non_address.SetLoadAddress(buf_with_non_address, self.target()) + check_reads([addr_buf, addr_buf_with_non_address], self.target().ReadMemory, + 4, b'LLDB') + + addrs = [buf, buf_with_non_address] + check_reads(addrs, self.process().ReadMemory, 4, b'LLDB') + check_reads(addrs, self.process().ReadCStringFromMemory, 5, "LLDB") + check_reads(addrs, self.process().ReadUnsignedFromMemory, 4, 0x42444c4c) + check_reads(addrs, self.process().ReadPointerFromMemory, None, 0x0000000042444c4c) diff --git a/lldb/test/API/linux/aarch64/non_address_bit_memory_access/corefile b/lldb/test/API/linux/aarch64/non_address_bit_memory_access/corefile new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ + // Uncomment this line to crash and generate a corefile. + // Prints so we know what fixed address to look for in testing. + // printf("buf: %p\n", buf); + // printf("buf_with_non_address: %p\n", buf_with_non_address); + // *(char*)0 = 0; + return 0; // Set break point at this line. }