[Lldb-commits] [lldb] 794d208 - Don't load non-kexts in darwin kernel debug; handle unslid segs
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Wed Mar 8 16:51:38 PST 2023
Author: Jason Molenda
Date: 2023-03-08T16:51:27-08:00
New Revision: 794d2089cd741135b60e94ac2495174a03b38143
URL: https://github.com/llvm/llvm-project/commit/794d2089cd741135b60e94ac2495174a03b38143
DIFF: https://github.com/llvm/llvm-project/commit/794d2089cd741135b60e94ac2495174a03b38143.diff
LOG: Don't load non-kexts in darwin kernel debug; handle unslid segs
We have some non-kexts in the binary list in the Darwin kernel
in some situations. The binary has likely already been loaded;
check if it has been, and don't re-load it. Also, if we do need
to load it at this point, if in-memory segment vmaddrs have not
been updated to the actual load addresses, calculate a fixed slide
for the in-memory image and apply that slide to the ondisk binary.
Differential Revision: https://reviews.llvm.org/D145547
rdar://106343477
Added:
Modified:
lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt
lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt
index fb838f42489db..a22a83363ffea 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt
@@ -17,6 +17,7 @@ add_lldb_library(lldbPluginDynamicLoaderDarwinKernel PLUGIN
lldbSymbol
lldbTarget
lldbUtility
+ lldbPluginObjectFileMachO
)
add_dependencies(lldbPluginDynamicLoaderDarwinKernel
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index fcbaf7e1ed7d2..b3b199e1bf71d 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
@@ -713,6 +714,7 @@ void DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel(bool is_kernel) {
bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
Process *process) {
+ Log *log = GetLog(LLDBLog::DynamicLoader);
if (IsLoaded())
return true;
@@ -810,6 +812,28 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
}
}
+ if (m_module_sp && m_uuid.IsValid() && m_module_sp->GetUUID() == m_uuid) {
+ ObjectFileMachO *ondisk_objfile_macho =
+ llvm::dyn_cast_or_null<ObjectFileMachO>(
+ m_module_sp ? m_module_sp->GetObjectFile() : nullptr);
+ if (ondisk_objfile_macho) {
+ if (!IsKernel() && !ondisk_objfile_macho->IsKext()) {
+ // We have a non-kext, non-kernel binary. If we already have this
+ // loaded in the Target with load addresses, don't re-load it again.
+ ModuleSP existing_module_sp = target.GetImages().FindModule(m_uuid);
+ if (existing_module_sp &&
+ existing_module_sp->IsLoadedInTarget(&target)) {
+ LLDB_LOGF(log,
+ "'%s' with UUID %s is not a kext or kernel, and is "
+ "already registered in target, not loading.",
+ m_name.c_str(), m_uuid.GetAsString().c_str());
+ // It's already loaded, return true.
+ return true;
+ }
+ }
+ }
+ }
+
// If we managed to find a module, append it to the target's list of
// images. If we also have a memory module, require that they have matching
// UUIDs
@@ -837,6 +861,34 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
// it.
const bool ignore_linkedit = !IsKernel();
+ // Normally a kext will have its segment load commands
+ // (LC_SEGMENT vmaddrs) corrected in memory to have their
+ // actual segment addresses.
+ // Userland proceses have their libraries updated the same way
+ // by dyld. The Mach-O load commands in memory are the canonical
+ // addresses.
+ //
+ // If the kernel gives us a binary where the in-memory segment
+ // vmaddr is incorrect, then this binary was put in memory without
+ // updating its Mach-O load commands. We should assume a static
+ // slide value will be applied to every segment; we don't have the
+ // correct addresses for each individual segment.
+ addr_t fixed_slide = LLDB_INVALID_ADDRESS;
+ if (ObjectFileMachO *memory_objfile_macho =
+ llvm::dyn_cast<ObjectFileMachO>(memory_object_file)) {
+ if (Section *header_sect =
+ memory_objfile_macho->GetMachHeaderSection()) {
+ if (header_sect->GetFileAddress() != m_load_address) {
+ fixed_slide = m_load_address - header_sect->GetFileAddress();
+ LLDB_LOGF(
+ log,
+ "kext %s in-memory LC_SEGMENT vmaddr is not correct, using a "
+ "fixed slide of 0x%" PRIx64,
+ m_name.c_str(), fixed_slide);
+ }
+ }
+ }
+
SectionList *ondisk_section_list = ondisk_object_file->GetSectionList();
SectionList *memory_section_list = memory_object_file->GetSectionList();
if (memory_section_list && ondisk_section_list) {
@@ -865,14 +917,20 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
ondisk_section_sp->GetName() == g_section_name_LINKEDIT)
continue;
- const Section *memory_section =
- memory_section_list
- ->FindSectionByName(ondisk_section_sp->GetName())
- .get();
- if (memory_section) {
- target.SetSectionLoadAddress(ondisk_section_sp,
- memory_section->GetFileAddress());
- ++num_sections_loaded;
+ if (fixed_slide != LLDB_INVALID_ADDRESS) {
+ target.SetSectionLoadAddress(
+ ondisk_section_sp,
+ ondisk_section_sp->GetFileAddress() + fixed_slide);
+ } else {
+ const Section *memory_section =
+ memory_section_list
+ ->FindSectionByName(ondisk_section_sp->GetName())
+ .get();
+ if (memory_section) {
+ target.SetSectionLoadAddress(
+ ondisk_section_sp, memory_section->GetFileAddress());
+ ++num_sections_loaded;
+ }
}
}
}
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index eaa47359ac882..d41279ce864cb 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1141,6 +1141,10 @@ bool ObjectFileMachO::IsSharedCacheBinary() const {
return m_header.flags & MH_DYLIB_IN_CACHE;
}
+bool ObjectFileMachO::IsKext() const {
+ return m_header.filetype == MH_KEXT_BUNDLE;
+}
+
uint32_t ObjectFileMachO::GetAddressByteSize() const {
return m_data.GetAddressByteSize();
}
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 3b458d8da8342..d4f42a8d61e3b 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -90,6 +90,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
bool IsSharedCacheBinary() const;
+ bool IsKext() const;
+
uint32_t GetAddressByteSize() const override;
lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
@@ -151,6 +153,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
bool AllowAssemblyEmulationUnwindPlans() override;
+ lldb_private::Section *GetMachHeaderSection();
+
// PluginInterface protocol
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
@@ -193,8 +197,6 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
/// should not be used.
void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid);
- lldb_private::Section *GetMachHeaderSection();
-
lldb::addr_t CalculateSectionLoadAddressForMemoryImage(
lldb::addr_t mach_header_load_address,
const lldb_private::Section *mach_header_section,
More information about the lldb-commits
mailing list