Skip to content

Commit 47a248f

Browse files
committed
[lldb/Target] Delay image loading after corefile process creation
This patch is a follow-up to db223b7. Similarly to it, it changes the timing of binary image loading for the ProcessMachCore plugin. This issue came up after getting reports of scripting resources that would fail to execute because they relied on data provided by the corefile process (i.e. for reading memory). However, rior to this change, the scripting resource loading would happen as part of the binary image loading, which in turns happened before the process finished being created. This patch address that issue by delaying the binary image loading phase until we receive the corefile process stop event event, ensuring that the process is fully formed. Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 2204364 commit 47a248f

File tree

8 files changed

+110
-15
lines changed

8 files changed

+110
-15
lines changed

lldb/include/lldb/Target/Process.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ class Process : public std::enable_shared_from_this<Process>,
614614
return error;
615615
}
616616

617+
virtual void DidLoadCore() {}
618+
617619
/// The "ShadowListener" for a process is just an ordinary Listener that
618620
/// listens for all the Process event bits. It's convenient because you can
619621
/// specify it in the LaunchInfo or AttachInfo, so it will get events from

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -570,8 +570,6 @@ Status ProcessMachCore::DoLoadCore() {
570570

571571
CreateMemoryRegions();
572572

573-
LoadBinariesAndSetDYLD();
574-
575573
CleanupMemoryRegionPermissions();
576574

577575
AddressableBits addressable_bits = core_objfile->GetAddressableBits();
@@ -580,6 +578,8 @@ Status ProcessMachCore::DoLoadCore() {
580578
return error;
581579
}
582580

581+
void ProcessMachCore::DidLoadCore() { LoadBinariesAndSetDYLD(); }
582+
583583
lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() {
584584
if (m_dyld_up.get() == nullptr)
585585
m_dyld_up.reset(DynamicLoader::FindPlugin(this, m_dyld_plugin_name));

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class ProcessMachCore : public lldb_private::PostMortemProcess {
4646
// Creating a new process, or attaching to an existing one
4747
lldb_private::Status DoLoadCore() override;
4848

49+
void DidLoadCore() override;
50+
4951
lldb_private::DynamicLoader *GetDynamicLoader() override;
5052

5153
// PluginInterface protocol

lldb/source/Target/Process.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2639,19 +2639,6 @@ Status Process::LoadCore() {
26392639
else
26402640
StartPrivateStateThread();
26412641

2642-
DynamicLoader *dyld = GetDynamicLoader();
2643-
if (dyld)
2644-
dyld->DidAttach();
2645-
2646-
GetJITLoaders().DidAttach();
2647-
2648-
SystemRuntime *system_runtime = GetSystemRuntime();
2649-
if (system_runtime)
2650-
system_runtime->DidAttach();
2651-
2652-
if (!m_os_up)
2653-
LoadOperatingSystemPlugin(false);
2654-
26552642
// We successfully loaded a core file, now pretend we stopped so we can
26562643
// show all of the threads in the core file and explore the crashed state.
26572644
SetPrivateState(eStateStopped);
@@ -2668,7 +2655,23 @@ Status Process::LoadCore() {
26682655
StateAsCString(state));
26692656
error.SetErrorString(
26702657
"Did not get stopped event after loading the core file.");
2658+
} else {
2659+
DidLoadCore();
2660+
2661+
DynamicLoader *dyld = GetDynamicLoader();
2662+
if (dyld)
2663+
dyld->DidAttach();
2664+
2665+
GetJITLoaders().DidAttach();
2666+
2667+
SystemRuntime *system_runtime = GetSystemRuntime();
2668+
if (system_runtime)
2669+
system_runtime->DidAttach();
2670+
2671+
if (!m_os_up)
2672+
LoadOperatingSystemPlugin(false);
26712673
}
2674+
26722675
RestoreProcessEvents();
26732676
}
26742677
return error;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CXX_SOURCES := main.cpp
2+
3+
override ARCH := $(shell uname -m)
4+
5+
include Makefile.rules
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Test loading python scripting resource from corefile
3+
"""
4+
5+
import os, tempfile
6+
7+
import lldb
8+
from lldbsuite.test.decorators import *
9+
from lldbsuite.test.lldbtest import *
10+
from lldbsuite.test import lldbutil
11+
from lldbsuite.test import lldbtest
12+
13+
14+
class ScriptResourceLoadingTestCase(TestBase):
15+
NO_DEBUG_INFO_TESTCASE = True
16+
17+
def create_stack_skinny_corefile(self, file):
18+
self.build()
19+
target, process, thread, _ = lldbutil.run_to_source_breakpoint(
20+
self, "// break", lldb.SBFileSpec("main.cpp")
21+
)
22+
self.assertTrue(process.IsValid(), "Process is invalid.")
23+
# FIXME: Use SBAPI to save the process corefile.
24+
self.runCmd("process save-core -s stack " + file)
25+
self.assertTrue(os.path.exists(file), "No stack-only corefile found.")
26+
self.assertTrue(self.dbg.DeleteTarget(target), "Couldn't delete target")
27+
28+
def move_blueprint_to_dsym(self, blueprint_name):
29+
blueprint_origin_path = os.path.join(self.getSourceDir(), blueprint_name)
30+
dsym_bundle = self.getBuildArtifact("a.out.dSYM")
31+
blueprint_destination_path = os.path.join(
32+
dsym_bundle, "Contents", "Resources", "Python"
33+
)
34+
if not os.path.exists(blueprint_destination_path):
35+
os.mkdir(blueprint_destination_path)
36+
37+
blueprint_destination_path = os.path.join(
38+
blueprint_destination_path, "a_out.py"
39+
)
40+
shutil.copy(blueprint_origin_path, blueprint_destination_path)
41+
42+
@skipUnlessDarwin
43+
def test_script_resource_loading(self):
44+
"""
45+
Test that we're able to load the python scripting resource from
46+
corefile dSYM bundle.
47+
48+
"""
49+
self.build()
50+
51+
self.runCmd("settings set target.load-script-from-symbol-file true")
52+
self.move_blueprint_to_dsym("my_scripting_resource.py")
53+
54+
corefile_process = None
55+
with tempfile.NamedTemporaryFile() as file:
56+
self.create_stack_skinny_corefile(file.name)
57+
corefile_target = self.dbg.CreateTarget(None)
58+
corefile_process = corefile_target.LoadCore(
59+
self.getBuildArtifact(file.name)
60+
)
61+
self.assertTrue(corefile_process, PROCESS_IS_VALID)
62+
self.expect("command script list", substrs=["test_script_resource_loading"])
63+
self.runCmd("test_script_resource_loading")
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int foo() {
2+
return 42; // break
3+
}
4+
5+
int main() { return foo(); }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import sys, lldb
2+
3+
4+
def test_script_resource_loading(debugger, command, exe_ctx, result, dict):
5+
if not exe_ctx.target.process.IsValid():
6+
result.SetError("invalid process")
7+
process = exe_ctx.target.process
8+
if not len(process):
9+
result.SetError("invalid thread count")
10+
11+
12+
def __lldb_init_module(debugger, dict):
13+
debugger.HandleCommand(
14+
"command script add -o -f a_out.test_script_resource_loading test_script_resource_loading"
15+
)

0 commit comments

Comments
 (0)