Skip to content

Commit 5e87a05

Browse files
committed
Make changes according to feedback
- If we are saving core style with eSaveCoreDirtyOnly and process doesn't support dirty ranges, save all regions with write permssions as a backup. - Modify the TestProcessSaveCoreMinidump.py test case to handle minidump now able to handle eSaveCoreDirtyOnly and eSaveCoreFull
1 parent f1bd931 commit 5e87a05

File tree

2 files changed

+103
-48
lines changed

2 files changed

+103
-48
lines changed

lldb/source/Target/Process.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6311,16 +6311,16 @@ static void GetCoreFileSaveRangesFull(Process &process,
63116311
Process::CoreFileMemoryRanges &ranges) {
63126312

63136313
// Don't add only dirty pages, add full regions.
6314-
const bool try_dirty_pages = false;
6314+
const bool try_dirty_pages = false;
63156315
for (const auto &region : regions)
63166316
AddRegion(region, try_dirty_pages, ranges);
63176317
}
63186318

63196319
// Save only the dirty pages to the core file. Make sure the process has at
63206320
// least some dirty pages, as some OS versions don't support reporting what
63216321
// pages are dirty within an memory region. If no memory regions have dirty
6322-
// page information, return an error.
6323-
static Status
6322+
// page information fall back to saving out all ranges with write permissions.
6323+
static void
63246324
GetCoreFileSaveRangesDirtyOnly(Process &process,
63256325
const MemoryRegionInfos &regions,
63266326
Process::CoreFileMemoryRanges &ranges) {
@@ -6331,10 +6331,14 @@ GetCoreFileSaveRangesDirtyOnly(Process &process,
63316331
have_dirty_page_info = true;
63326332
}
63336333

6334-
if (!have_dirty_page_info)
6335-
return Status("no process memory regions have dirty page information");
6336-
6337-
return Status();
6334+
if (!have_dirty_page_info) {
6335+
// We didn't find support for reporting dirty pages from the process
6336+
// plug-in so fall back to any region with write access permissions.
6337+
const bool try_dirty_pages = false;
6338+
for (const auto &region : regions)
6339+
if (region.GetWritable() == MemoryRegionInfo::eYes)
6340+
AddRegion(region, try_dirty_pages, ranges);
6341+
}
63386342
}
63396343

63406344
// Save all thread stacks to the core file. Some OS versions support reporting
@@ -6405,7 +6409,7 @@ Status Process::CalculateCoreFileSaveRanges(lldb::SaveCoreStyle core_style,
64056409
break;
64066410

64076411
case eSaveCoreDirtyOnly:
6408-
err = GetCoreFileSaveRangesDirtyOnly(*this, regions, ranges);
6412+
GetCoreFileSaveRangesDirtyOnly(*this, regions, ranges);
64096413
break;
64106414

64116415
case eSaveCoreStackOnly:

lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py

Lines changed: 91 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,50 @@
1111

1212

1313
class ProcessSaveCoreMinidumpTestCase(TestBase):
14+
15+
def verify_core_file(self, core_path, expected_pid, expected_modules,
16+
expected_threads):
17+
# To verify, we'll launch with the mini dump
18+
target = self.dbg.CreateTarget(None)
19+
process = target.LoadCore(core_path)
20+
21+
# check if the core is in desired state
22+
self.assertTrue(process, PROCESS_IS_VALID)
23+
self.assertTrue(process.GetProcessInfo().IsValid())
24+
self.assertEqual(process.GetProcessInfo().GetProcessID(), expected_pid)
25+
self.assertTrue(target.GetTriple().find("linux") != -1)
26+
self.assertTrue(target.GetNumModules(), len(expected_modules))
27+
self.assertEqual(process.GetNumThreads(), len(expected_threads))
28+
29+
for module, expected in zip(target.modules, expected_modules):
30+
self.assertTrue(module.IsValid())
31+
module_file_name = module.GetFileSpec().GetFilename()
32+
expected_file_name = expected.GetFileSpec().GetFilename()
33+
# skip kernel virtual dynamic shared objects
34+
if "vdso" in expected_file_name:
35+
continue
36+
self.assertEqual(module_file_name, expected_file_name)
37+
self.assertEqual(module.GetUUIDString(), expected.GetUUIDString())
38+
39+
for thread_idx in range(process.GetNumThreads()):
40+
thread = process.GetThreadAtIndex(thread_idx)
41+
self.assertTrue(thread.IsValid())
42+
thread_id = thread.GetThreadID()
43+
self.assertTrue(thread_id in expected_threads)
44+
self.dbg.DeleteTarget(target)
45+
1446
@skipUnlessArch("x86_64")
1547
@skipUnlessPlatform(["linux"])
1648
def test_save_linux_mini_dump(self):
1749
"""Test that we can save a Linux mini dump."""
1850
self.build()
1951
exe = self.getBuildArtifact("a.out")
20-
core = self.getBuildArtifact("core.dmp")
21-
core_sb = self.getBuildArtifact("core_sb.dmp")
52+
core_stack = self.getBuildArtifact("core.stack.dmp")
53+
core_dirty = self.getBuildArtifact("core.dirty.dmp")
54+
core_full = self.getBuildArtifact("core.full.dmp")
55+
core_sb_stack = self.getBuildArtifact("core_sb.stack.dmp")
56+
core_sb_dirty = self.getBuildArtifact("core_sb.dirty.dmp")
57+
core_sb_full = self.getBuildArtifact("core_sb.full.dmp")
2258
try:
2359
target = self.dbg.CreateTarget(exe)
2460
process = target.LaunchSimple(
@@ -41,53 +77,68 @@ def test_save_linux_mini_dump(self):
4177

4278
# save core and, kill process and verify corefile existence
4379
self.runCmd(
44-
"process save-core --plugin-name=minidump --style=stack " + core
80+
"process save-core --plugin-name=minidump --style=stack '%s'" % (core_stack)
81+
)
82+
self.assertTrue(os.path.isfile(core_stack))
83+
self.verify_core_file(core_stack, expected_pid, expected_modules,
84+
expected_threads)
85+
86+
self.runCmd(
87+
"process save-core --plugin-name=minidump --style=modified-memory '%s'" (core_dirty)
88+
)
89+
self.assertTrue(os.path.isfile(core_dirty))
90+
self.verify_core_file(core_dirty, expected_pid, expected_modules,
91+
expected_threads)
92+
93+
94+
self.runCmd(
95+
"process save-core --plugin-name=minidump --style=full '%s'" (core_full)
4596
)
46-
self.assertTrue(os.path.isfile(core))
97+
self.assertTrue(os.path.isfile(core_full))
98+
self.verify_core_file(core_full, expected_pid, expected_modules,
99+
expected_threads)
100+
47101

48-
# validate savinig via SBProcess
49-
error = process.SaveCore(core_sb, "minidump", lldb.eSaveCoreStackOnly)
102+
# validate saving via SBProcess
103+
error = process.SaveCore(core_sb_stack, "minidump",
104+
lldb.eSaveCoreStackOnly)
50105
self.assertTrue(error.Success())
51-
self.assertTrue(os.path.isfile(core_sb))
106+
self.assertTrue(os.path.isfile(core_sb_stack))
107+
self.verify_core_file(core_sb_stack, expected_pid, expected_modules,
108+
expected_threads)
52109

53-
error = process.SaveCore(core_sb, "minidump", lldb.eSaveCoreFull)
54-
self.assertTrue(error.Fail())
55-
error = process.SaveCore(core_sb, "minidump", lldb.eSaveCoreDirtyOnly)
56-
self.assertTrue(error.Fail())
57110

58-
self.assertSuccess(process.Kill())
111+
error = process.SaveCore(core_sb_dirty, "minidump",
112+
lldb.eSaveCoreDirtyOnly)
113+
self.assertTrue(error.Success())
114+
self.assertTrue(os.path.isfile(core_sb_dirty))
115+
self.verify_core_file(core_sb_dirty, expected_pid, expected_modules,
116+
expected_threads)
59117

60-
# To verify, we'll launch with the mini dump
61-
target = self.dbg.CreateTarget(None)
62-
process = target.LoadCore(core)
63-
64-
# check if the core is in desired state
65-
self.assertTrue(process, PROCESS_IS_VALID)
66-
self.assertTrue(process.GetProcessInfo().IsValid())
67-
self.assertEqual(process.GetProcessInfo().GetProcessID(), expected_pid)
68-
self.assertTrue(target.GetTriple().find("linux") != -1)
69-
self.assertTrue(target.GetNumModules(), expected_number_of_modules)
70-
self.assertEqual(process.GetNumThreads(), expected_number_of_threads)
71-
72-
for module, expected in zip(target.modules, expected_modules):
73-
self.assertTrue(module.IsValid())
74-
module_file_name = module.GetFileSpec().GetFilename()
75-
expected_file_name = expected.GetFileSpec().GetFilename()
76-
# skip kernel virtual dynamic shared objects
77-
if "vdso" in expected_file_name:
78-
continue
79-
self.assertEqual(module_file_name, expected_file_name)
80-
self.assertEqual(module.GetUUIDString(), expected.GetUUIDString())
118+
# Minidump can now save full core files, but they will be huge and
119+
# they might cause this test to timeout.
120+
error = process.SaveCore(core_sb_full, "minidump",
121+
lldb.eSaveCoreFull)
122+
self.assertTrue(error.Success())
123+
self.assertTrue(os.path.isfile(core_sb_full))
124+
self.verify_core_file(core_sb_full, expected_pid, expected_modules,
125+
expected_threads)
81126

82-
for thread_idx in range(process.GetNumThreads()):
83-
thread = process.GetThreadAtIndex(thread_idx)
84-
self.assertTrue(thread.IsValid())
85-
thread_id = thread.GetThreadID()
86-
self.assertTrue(thread_id in expected_threads)
127+
self.assertSuccess(process.Kill())
87128
finally:
88129
# Clean up the mini dump file.
89130
self.assertTrue(self.dbg.DeleteTarget(target))
90131
if os.path.isfile(core):
91132
os.unlink(core)
92-
if os.path.isfile(core_sb):
93-
os.unlink(core_sb)
133+
if os.path.isfile(core_stack):
134+
os.unlink(core_stack)
135+
if os.path.isfile(core_dirty):
136+
os.unlink(core_dirty)
137+
if os.path.isfile(core_full):
138+
os.unlink(core_full)
139+
if os.path.isfile(core_sb_stack):
140+
os.unlink(core_sb_stack)
141+
if os.path.isfile(core_sb_dirty):
142+
os.unlink(core_sb_dirty)
143+
if os.path.isfile(core_sb_full):
144+
os.unlink(core_sb_full)

0 commit comments

Comments
 (0)