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 @@ -1068,6 +1068,7 @@ if (m_kernel.IsLoaded() && m_kernel.GetModule()) { static ConstString kext_summary_symbol("gLoadedKextSummaries"); + static ConstString arm64_T1Sz_value("gT1Sz"); const Symbol *symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType( kext_summary_symbol, eSymbolTypeData); @@ -1076,6 +1077,45 @@ // Update all image infos ReadAllKextSummaries(); } + // If the kernel global with the T1Sz setting is available, + // update the target.process.virtual-addressable-bits to be correct. + symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType( + arm64_T1Sz_value, eSymbolTypeData); + uint32_t wordsize = + m_process->GetTarget().GetArchitecture().GetAddressByteSize(); + if (symbol && wordsize == 8) { + if (symbol->GetByteSizeIsValid()) { + // Mark all bits as addressable so we don't strip any from our + // memory read below, with an incorrect default value. + uint32_t old_bits_value = m_process->GetVirtualAddressableBits(); + // b55 is the sign extension bit with PAC, b56:63 are TBI, + // don't mark those as addressable. + m_process->SetVirtualAddressableBits((wordsize * 8) - 9); + addr_t sym_addr = symbol->GetLoadAddress(&m_process->GetTarget()); + Status error; + // The definition of gT1Sz is in the xnu sources -- it is 8 bytes. + // We may be running on a stripped kernel binary and the size of + // the Symbol may be incorrect because neighboring symbols have + // been stripped out. Hardcode it to 8 bytes here to sidestep + // this problem. + const size_t bytesize = 8; // size of gT1Sz value + uint64_t sym_value = + m_process->GetTarget().ReadUnsignedIntegerFromMemory( + sym_addr, bytesize, 0, error, /*force_live_memory=*/true); + if (error.Success()) { + // 64 - T1Sz is the highest bit used for auth. + // The value we pass in to SetVirtualAddressableBits is + // the number of bits used for addressing, so if + // T1Sz is 25, then 64-25 == 39, bits 0..38 are used for + // addressing, bits 39..63 are used for PAC/TBI or whatever. + int virt_addr_bits = 64 - sym_value; + m_process->SetVirtualAddressableBits(virt_addr_bits); + } else { + if (old_bits_value != 0) + m_process->SetVirtualAddressableBits(old_bits_value); + } + } + } } else { m_kernel.Clear(); }