Skip to content

Commit 7d0dd1b

Browse files
committed
[lldb/crashlog] Create artificial frames for non-crashed scripted threads
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 <[email protected]>
1 parent 7432dcd commit 7d0dd1b

File tree

5 files changed

+519
-100
lines changed

5 files changed

+519
-100
lines changed

lldb/examples/python/crashlog.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ def SymbolicateCrashLog(crash_log, options):
966966
for error in crash_log.errors:
967967
print(error)
968968

969-
def load_crashlog_in_scripted_process(debugger, crash_log_file):
969+
def load_crashlog_in_scripted_process(debugger, crash_log_file, options):
970970
result = lldb.SBCommandReturnObject()
971971

972972
crashlog_path = os.path.expanduser(crash_log_file)
@@ -999,7 +999,8 @@ def load_crashlog_in_scripted_process(debugger, crash_log_file):
999999
return
10001000

10011001
structured_data = lldb.SBStructuredData()
1002-
structured_data.SetFromJSON(json.dumps({ "crashlog_path" : crashlog_path }))
1002+
structured_data.SetFromJSON(json.dumps({ "crashlog_path" : crashlog_path,
1003+
"load_all_images": options.load_all_images }))
10031004
launch_info = lldb.SBLaunchInfo(None)
10041005
launch_info.SetProcessPluginName("ScriptedProcess")
10051006
launch_info.SetScriptedProcessClassName("crashlog_scripted_process.CrashLogScriptedProcess")
@@ -1058,7 +1059,9 @@ def CreateSymbolicateCrashLogOptions(
10581059
'-a',
10591060
action='store_true',
10601061
dest='load_all_images',
1061-
help='load all executable images, not just the images found in the crashed stack frames',
1062+
help='load all executable images, not just the images found in the '
1063+
'crashed stack frames, loads stackframes for all the threads in '
1064+
'interactive mode.',
10621065
default=False)
10631066
option_parser.add_option(
10641067
'--images',
@@ -1186,7 +1189,8 @@ def should_run_in_interactive_mode(options, ci):
11861189
if args:
11871190
for crash_log_file in args:
11881191
if should_run_in_interactive_mode(options, ci):
1189-
load_crashlog_in_scripted_process(debugger, crash_log_file)
1192+
load_crashlog_in_scripted_process(debugger, crash_log_file,
1193+
options)
11901194
else:
11911195
crash_log = CrashLogParser().parse(debugger, crash_log_file, options.verbose)
11921196
SymbolicateCrashLog(crash_log, options)

lldb/examples/python/scripted_process/crashlog_scripted_process.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,24 @@ def parse_crashlog(self):
1919
self.crashed_thread_idx = crash_log.crashed_thread_idx
2020
self.loaded_images = []
2121

22+
def load_images(self, images):
23+
#TODO: Add to self.loaded_images and load images in lldb
24+
if images:
25+
for image in images:
26+
if image not in self.loaded_images:
27+
err = image.add_module(self.target)
28+
if err:
29+
print(err)
30+
else:
31+
self.loaded_images.append(image)
32+
2233
for thread in crash_log.threads:
23-
if thread.did_crash():
34+
if self.load_all_images:
35+
load_images(self, crash_log.images)
36+
elif thread.did_crash():
2437
for ident in thread.idents:
25-
images = crash_log.find_images_with_identifier(ident)
26-
if images:
27-
for image in images:
28-
#TODO: Add to self.loaded_images and load images in lldb
29-
err = image.add_module(self.target)
30-
if err:
31-
print(err)
32-
else:
33-
self.loaded_images.append(image)
38+
load_images(self, crash_log.find_images_with_identifier(ident))
39+
3440
self.threads[thread.index] = CrashLogScriptedThread(self, None, thread)
3541

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

58+
load_all_images = args.GetValueForKey("load_all_images")
59+
if load_all_images and load_all_images.IsValid():
60+
if load_all_images.GetType() == lldb.eStructuredDataTypeBoolean:
61+
self.load_all_images = load_all_images.GetBooleanValue()
62+
63+
if not self.load_all_images:
64+
self.load_all_images = False
65+
5266
self.pid = super().get_process_id()
5367
self.crashed_thread_idx = 0
5468
self.parse_crashlog()
@@ -101,7 +115,7 @@ def create_register_ctx(self):
101115
return self.register_ctx
102116

103117
def create_stackframes(self):
104-
if not self.has_crashed:
118+
if not (self.scripted_process.load_all_images or self.has_crashed):
105119
return None
106120

107121
if not self.backing_thread or not len(self.backing_thread.frames):
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <iostream>
2+
#include <mutex>
3+
#include <thread>
4+
5+
int bar(int i) {
6+
int *j = 0;
7+
*j = 1;
8+
return i; // break here
9+
}
10+
11+
int foo(int i) { return bar(i); }
12+
13+
void call_and_wait(int &n) {
14+
std::cout << "waiting for computation!" << std::endl;
15+
while (n != 42 * 42)
16+
;
17+
std::cout << "finished computation!" << std::endl;
18+
}
19+
20+
void compute_pow(int &n) { n = foo(n); }
21+
22+
int main() {
23+
int n = 42;
24+
std::mutex mutex;
25+
std::unique_lock<std::mutex> lock(mutex);
26+
27+
std::thread thread_1(call_and_wait, std::ref(n));
28+
std::thread thread_2(compute_pow, std::ref(n));
29+
lock.unlock();
30+
31+
thread_1.join();
32+
thread_2.join();
33+
34+
return 0;
35+
}

0 commit comments

Comments
 (0)