Skip to content

Commit 1ab9e53

Browse files
authored
[lldb][Mach-O corefiles] Don't init Target arch to corefile (llvm#136065)
This patch is making three changes, when loading a Mach-O corefile: 1. At the start of `DoLoadCore`, if a binary was provided in addition to the corefile, initialize the Target's ArchSpec. 2. Before ProcessMachCore does its "exhaustive search" fallback, looking through the corefile contents for a userland dyld or mach kernel, we must make sure the Target has an ArchSpec, or methods that check the address word size, or initialize a DataExtractor based on the Target arch will not succeed. 3. Add logging when setting the Target's arch listing exactly what that setting was based on -- the corefile itself, or the main binary. Jonas landed a change last August (started with a patch from me) which removed the Target ArchSpec initialization at the start of DoLoadCore, in a scenario where the corefile had arch armv7 and the main binary had arch armv7em (Cortex-M), and there was python code in the main binary's dSYM which sets the operating system threads provider based on the Target arch. It did different things for armv7 or armv7em, and so it would fail. Jonas' patch removed any ArchSpec setting at the start of DoLoadCore, so we wouldn't have an incorrect arch value, but that broke the exhaustive search for kernel binaries, because we didn't have an address word size or endianness. This patch should navigate the needs of both use cases. I spent a good bit of time trying to construct a test to capture all of these requirements -- but it turns out to be a good bit difficult, encompassing both a genuine kernel corefiles and a microcontroller firmware corefiles. rdar://146821929
1 parent 3e5a9d9 commit 1ab9e53

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,22 @@ void ProcessMachCore::LoadBinariesViaExhaustiveSearch() {
426426
std::vector<addr_t> dylds_found;
427427
std::vector<addr_t> kernels_found;
428428

429+
// To do an exhaustive search, we'll need to create data extractors
430+
// to get correctly sized/endianness fields. If we had a main binary
431+
// already, we would have set the Target to that - so here we'll use
432+
// the corefile's cputype/cpusubtype as the best guess.
433+
if (!GetTarget().GetArchitecture().IsValid()) {
434+
// The corefile's architecture is our best starting point.
435+
ArchSpec arch(m_core_module_sp->GetArchitecture());
436+
if (arch.IsValid()) {
437+
LLDB_LOGF(log,
438+
"ProcessMachCore::%s: Setting target ArchSpec based on "
439+
"corefile mach-o cputype/cpusubtype",
440+
__FUNCTION__);
441+
GetTarget().SetArchitecture(arch);
442+
}
443+
}
444+
429445
const size_t num_core_aranges = m_core_aranges.GetSize();
430446
for (size_t i = 0; i < num_core_aranges; ++i) {
431447
const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
@@ -569,6 +585,7 @@ Status ProcessMachCore::DoLoadCore() {
569585
error = Status::FromErrorString("invalid core module");
570586
return error;
571587
}
588+
Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Target));
572589

573590
ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
574591
if (core_objfile == nullptr) {
@@ -578,20 +595,47 @@ Status ProcessMachCore::DoLoadCore() {
578595

579596
SetCanJIT(false);
580597

598+
// If we have an executable binary in the Target already,
599+
// use that to set the Target's ArchSpec.
600+
//
601+
// Don't initialize the ArchSpec based on the corefile's cputype/cpusubtype
602+
// here, the corefile creator may not know the correct subtype of the code
603+
// that is executing, initialize the Target to that, and if the
604+
// main binary has Python code which initializes based on the Target arch,
605+
// get the wrong subtype value.
606+
ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
607+
if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {
608+
LLDB_LOGF(log,
609+
"ProcessMachCore::%s: Was given binary + corefile, setting "
610+
"target ArchSpec to binary to start",
611+
__FUNCTION__);
612+
GetTarget().SetArchitecture(exe_module_sp->GetArchitecture());
613+
}
614+
581615
CreateMemoryRegions();
582616

583617
LoadBinariesAndSetDYLD();
584618

585619
CleanupMemoryRegionPermissions();
586620

587-
ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
621+
exe_module_sp = GetTarget().GetExecutableModule();
588622
if (exe_module_sp && exe_module_sp->GetArchitecture().IsValid()) {
623+
LLDB_LOGF(log,
624+
"ProcessMachCore::%s: have executable binary in the Target "
625+
"after metadata/scan. Setting Target's ArchSpec based on "
626+
"that.",
627+
__FUNCTION__);
589628
GetTarget().SetArchitecture(exe_module_sp->GetArchitecture());
590629
} else {
591630
// The corefile's architecture is our best starting point.
592631
ArchSpec arch(m_core_module_sp->GetArchitecture());
593-
if (arch.IsValid())
632+
if (arch.IsValid()) {
633+
LLDB_LOGF(log,
634+
"ProcessMachCore::%s: Setting target ArchSpec based on "
635+
"corefile mach-o cputype/cpusubtype",
636+
__FUNCTION__);
594637
GetTarget().SetArchitecture(arch);
638+
}
595639
}
596640

597641
AddressableBits addressable_bits = core_objfile->GetAddressableBits();

0 commit comments

Comments
 (0)