Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions lldb/bindings/interface/SBSaveCoreOptionsExtensions.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

%extend lldb::SBSaveCoreOptions {
#ifdef SWIGPYTHON
%pythoncode%{
'''Add a thread to the SaveCoreOptions thread list, and follow its children N pointers deep, adding each memory region to the SaveCoreOptions Memory region list.'''
def save_thread_with_heaps(self, thread, num_pointers_deep = 3):
import lldb
self.AddThread(thread)
frame = thread.GetFrameAtIndex(0)
process = thread.GetProcess()
queue = []
for var in frame.locals:
type = var.GetType()
if type.IsPointerType() or type.IsReferenceType():
queue.append(var.Dereference())

while (num_pointers_deep > 0 and len(queue) > 0):
queue_size = len(queue)
for i in range(0, queue_size):
var = queue.pop(0)
var_type = var.GetType()
addr = var.GetAddress().GetOffset()
if addr == 0 or addr == None:
continue
memory_region = lldb.SBMemoryRegionInfo()
err = process.GetMemoryRegionInfo(addr, memory_region)
if err.Fail():
continue
self.AddMemoryRegionToSave(memory_region)
# We only check for direct pointer children T*, should probably xscan
# internal to the children themselves.
for x in var.children:
if x.TypeIsPointerType():
queue.append(x.Dereference())

num_pointers_deep -= 1
%}
#endif
}
1 change: 1 addition & 0 deletions lldb/bindings/interfaces.swig
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
%include "./interface/SBProcessExtensions.i"
%include "./interface/SBProcessInfoListExtensions.i"
%include "./interface/SBQueueItemExtensions.i"
%include "./interface/SBSaveCoreOptionsExtensions.i"
%include "./interface/SBScriptObjectExtensions.i"
%include "./interface/SBSectionExtensions.i"
%include "./interface/SBStreamExtensions.i"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ CXX_SOURCES := main.cpp
CFLAGS_EXTRAS := -lpthread

include Makefile.rules

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import os

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/python_api/sbsavecoreoptions/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *


class SBSaveCoreOptionsAPICase(TestBase):
basic_minidump = "basic_minidump.yaml"
basic_minidump_different_pid = "basic_minidump_different_pid.yaml"

def get_process_from_yaml(self, yaml_file):
minidump_path = self.getBuildArtifact(os.path.basename(yaml_file) + ".dmp")
print ("minidump_path: " + minidump_path)
print("minidump_path: " + minidump_path)
self.yaml2obj(yaml_file, minidump_path)
self.assertTrue(os.path.exists(minidump_path), "yaml2obj did not emit a minidump file")
self.assertTrue(
os.path.exists(minidump_path), "yaml2obj did not emit a minidump file"
)
target = self.dbg.CreateTarget(None)
process = target.LoadCore(minidump_path)
self.assertTrue(process.IsValid(), "Process is not valid")
Expand Down Expand Up @@ -59,7 +62,6 @@ def test_adding_and_removing_thread(self):
removed_success = options.RemoveThread(thread)
self.assertFalse(removed_success)


def test_adding_thread_different_process(self):
"""Test adding and removing a thread from save core options."""
options = lldb.SBSaveCoreOptions()
Expand All @@ -79,3 +81,43 @@ def test_adding_thread_different_process(self):
self.assertTrue(error.Fail())
error = options.AddThread(thread)
self.assertTrue(error.Success())

def verify_linked_list(self, node, depth, max_depth):
if depth > max_depth:
return

x_val = node.GetChildMemberWithName("x").GetValueAsUnsigned(0)
self.assertEqual(x_val, depth)
next_node = node.GetChildMemberWithName("next").Dereference()
self.verify_linked_list(next_node, depth + 1, max_depth)

@skipIfWindows
def test_thread_and_heaps_extension(self):
"""Test the thread and heap extension for save core options."""
options = lldb.SBSaveCoreOptions()
self.build()
(target, process, t, bp) = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("a.out")
)
main_thread = None
for thread_idx in range(process.GetNumThreads()):
thread = process.GetThreadAtIndex(thread_idx)
frame = thread.GetFrameAtIndex(0)
if "main" in frame.name:
main_thread = thread
break
self.assertTrue(main_thread != None)
options.save_thread_with_heaps(main_thread, 3)
core_file = self.getBuildArtifact("core.one_thread_and_heap.dmp")
spec = lldb.SBFileSpec(core_file)
options.SetOutputFile(spec)
options.SetPluginName("minidump")
options.SetStyle(lldb.eSaveCoreCustomOnly)
error = process.SaveCore(options)
self.assertTrue(error.Success())
core_proc = target.LoadCore(core_file)
self.assertTrue(core_proc.IsValid())
self.assertEqual(core_proc.GetNumThreads(), 1)
frame = core_proc.GetThreadAtIndex(0).GetFrameAtIndex(0)
head = frame.FindVariable("head")
self.verify_linked_list(head.Dereference(), 0, 3)
20 changes: 20 additions & 0 deletions lldb/test/API/python_api/sbsavecoreoptions/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <cstddef>

struct Node {
Node *next;
int x;
};

int main() {
Node *head = new Node();
Node *current = head;
head->x = 0;
for (size_t i = 0; i < 10; i++) {
Node *next = new Node();
next->x = current->x + 1;
current->next = next;
current = next;
}

return 0; // break here
}
Loading