Skip to content

Commit

Permalink
[lldb/crashlog] Create artificial frames for non-crashed scripted thr…
Browse files Browse the repository at this point in the history
…eads

This patch pipes down the `-a|--load-all` crashlog command option to the
Scripted Process initializer to load all the images used by crashed
process instead of only loading the images related to the crashed
thread.

This allows us to recreate artificial frames also for the non-crashed
scripted threads.

rdar://90396265

Differential Revision: https://reviews.llvm.org/D121826

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
  • Loading branch information
medismailben committed Mar 16, 2022
1 parent 0c4e9fb commit 0a65112
Show file tree
Hide file tree
Showing 5 changed files with 519 additions and 100 deletions.
12 changes: 8 additions & 4 deletions lldb/examples/python/crashlog.py
Expand Up @@ -977,7 +977,7 @@ def SymbolicateCrashLog(crash_log, options):
for error in crash_log.errors:
print(error)

def load_crashlog_in_scripted_process(debugger, crash_log_file):
def load_crashlog_in_scripted_process(debugger, crash_log_file, options):
result = lldb.SBCommandReturnObject()

crashlog_path = os.path.expanduser(crash_log_file)
Expand Down Expand Up @@ -1010,7 +1010,8 @@ def load_crashlog_in_scripted_process(debugger, crash_log_file):
return

structured_data = lldb.SBStructuredData()
structured_data.SetFromJSON(json.dumps({ "crashlog_path" : crashlog_path }))
structured_data.SetFromJSON(json.dumps({ "crashlog_path" : crashlog_path,
"load_all_images": options.load_all_images }))
launch_info = lldb.SBLaunchInfo(None)
launch_info.SetProcessPluginName("ScriptedProcess")
launch_info.SetScriptedProcessClassName("crashlog_scripted_process.CrashLogScriptedProcess")
Expand Down Expand Up @@ -1069,7 +1070,9 @@ def CreateSymbolicateCrashLogOptions(
'-a',
action='store_true',
dest='load_all_images',
help='load all executable images, not just the images found in the crashed stack frames',
help='load all executable images, not just the images found in the '
'crashed stack frames, loads stackframes for all the threads in '
'interactive mode.',
default=False)
option_parser.add_option(
'--images',
Expand Down Expand Up @@ -1199,7 +1202,8 @@ def should_run_in_interactive_mode(options, ci):
if args:
for crash_log_file in args:
if should_run_in_interactive_mode(options, ci):
load_crashlog_in_scripted_process(debugger, crash_log_file)
load_crashlog_in_scripted_process(debugger, crash_log_file,
options)
else:
crash_log = CrashLogParser().parse(debugger, crash_log_file, options.verbose)
SymbolicateCrashLog(crash_log, options)
Expand Down
36 changes: 25 additions & 11 deletions lldb/examples/python/scripted_process/crashlog_scripted_process.py
Expand Up @@ -19,18 +19,24 @@ def parse_crashlog(self):
self.crashed_thread_idx = crash_log.crashed_thread_idx
self.loaded_images = []

def load_images(self, images):
#TODO: Add to self.loaded_images and load images in lldb
if images:
for image in images:
if image not in self.loaded_images:
err = image.add_module(self.target)
if err:
print(err)
else:
self.loaded_images.append(image)

for thread in crash_log.threads:
if thread.did_crash():
if self.load_all_images:
load_images(self, crash_log.images)
elif thread.did_crash():
for ident in thread.idents:
images = crash_log.find_images_with_identifier(ident)
if images:
for image in images:
#TODO: Add to self.loaded_images and load images in lldb
err = image.add_module(self.target)
if err:
print(err)
else:
self.loaded_images.append(image)
load_images(self, crash_log.find_images_with_identifier(ident))

self.threads[thread.index] = CrashLogScriptedThread(self, None, thread)

def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
Expand All @@ -49,6 +55,14 @@ def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
if not self.crashlog_path:
return

load_all_images = args.GetValueForKey("load_all_images")
if load_all_images and load_all_images.IsValid():
if load_all_images.GetType() == lldb.eStructuredDataTypeBoolean:
self.load_all_images = load_all_images.GetBooleanValue()

if not self.load_all_images:
self.load_all_images = False

self.pid = super().get_process_id()
self.crashed_thread_idx = 0
self.parse_crashlog()
Expand Down Expand Up @@ -101,7 +115,7 @@ def create_register_ctx(self):
return self.register_ctx

def create_stackframes(self):
if not self.has_crashed:
if not (self.scripted_process.load_all_images or self.has_crashed):
return None

if not self.backing_thread or not len(self.backing_thread.frames):
Expand Down
@@ -0,0 +1,35 @@
#include <iostream>
#include <mutex>
#include <thread>

int bar(int i) {
int *j = 0;
*j = 1;
return i; // break here
}

int foo(int i) { return bar(i); }

void call_and_wait(int &n) {
std::cout << "waiting for computation!" << std::endl;
while (n != 42 * 42)
;
std::cout << "finished computation!" << std::endl;
}

void compute_pow(int &n) { n = foo(n); }

int main() {
int n = 42;
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);

std::thread thread_1(call_and_wait, std::ref(n));
std::thread thread_2(compute_pow, std::ref(n));
lock.unlock();

thread_1.join();
thread_2.join();

return 0;
}

0 comments on commit 0a65112

Please sign in to comment.