Skip to content

Commit f00c339

Browse files
committed
[lldb/crashlog] Make interactive mode the new default
This patch makes interactive mode as the default when using the crashlog command. It replaces the existing `-i|--interactive` flag with a new `-m|--mode` option, that can either be `interactive` or `batch`. By default, when the option is not explicitely set by the user, the interactive mode is selected, however, lldb will fallback to batch mode if the command interpreter is not interactive or if stdout is not a tty. This also adds some railguards to prevent users from using interactive only options with the batch mode and updates the tests accordingly. rdar://97801509 Differential Revision: https://reviews.llvm.org/D141658 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 3c8e0b8 commit f00c339

File tree

6 files changed

+85
-55
lines changed

6 files changed

+85
-55
lines changed

lldb/examples/python/crashlog.py

Lines changed: 78 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import concurrent.futures
3232
import contextlib
3333
import datetime
34+
import enum
3435
import json
3536
import os
3637
import platform
@@ -45,7 +46,6 @@
4546
import time
4647
import uuid
4748

48-
4949
print_lock = threading.RLock()
5050

5151
try:
@@ -1582,9 +1582,12 @@ def synchronous(debugger):
15821582
debugger.RunCommandInterpreter(True, False, run_options, 0, False, True)
15831583

15841584

1585-
def CreateSymbolicateCrashLogOptions(
1586-
command_name, description, add_interactive_options
1587-
):
1585+
class CrashLogLoadingMode(str, enum.Enum):
1586+
batch = "batch"
1587+
interactive = "interactive"
1588+
1589+
1590+
def CreateSymbolicateCrashLogOptions(command_name, description):
15881591
usage = "crashlog [options] <FILE> [FILE ...]"
15891592
arg_parser = argparse.ArgumentParser(
15901593
description=description,
@@ -1600,6 +1603,13 @@ def CreateSymbolicateCrashLogOptions(
16001603
help="crash report(s) to symbolicate",
16011604
)
16021605

1606+
arg_parser.add_argument(
1607+
"-m",
1608+
"--mode",
1609+
choices=[mode.value for mode in CrashLogLoadingMode],
1610+
help="change how the symbolicated process and threads are displayed to the user",
1611+
default=CrashLogLoadingMode.interactive,
1612+
)
16031613
arg_parser.add_argument(
16041614
"--version",
16051615
"-V",
@@ -1736,36 +1746,35 @@ def CreateSymbolicateCrashLogOptions(
17361746
help=argparse.SUPPRESS,
17371747
default=False,
17381748
)
1739-
if add_interactive_options:
1740-
arg_parser.add_argument(
1741-
"-i",
1742-
"--interactive",
1743-
action="store_true",
1744-
help="parse a crash log and load it in a ScriptedProcess",
1745-
default=False,
1746-
)
1747-
arg_parser.add_argument(
1748-
"-b",
1749-
"--batch",
1750-
action="store_true",
1751-
help="dump symbolicated stackframes without creating a debug session",
1752-
default=True,
1753-
)
1754-
arg_parser.add_argument(
1755-
"--target",
1756-
"-t",
1757-
dest="target_path",
1758-
help="the target binary path that should be used for interactive crashlog (optional)",
1759-
default=None,
1760-
)
1761-
arg_parser.add_argument(
1762-
"--skip-status",
1763-
"-s",
1764-
dest="skip_status",
1765-
action="store_true",
1766-
help="prevent the interactive crashlog to dump the process status and thread backtrace at launch",
1767-
default=False,
1768-
)
1749+
arg_parser.add_argument(
1750+
"--target",
1751+
"-t",
1752+
dest="target_path",
1753+
help="the target binary path that should be used for interactive crashlog (optional)",
1754+
default=None,
1755+
)
1756+
arg_parser.add_argument(
1757+
"--skip-status",
1758+
"-s",
1759+
dest="skip_status",
1760+
action="store_true",
1761+
help="prevent the interactive crashlog to dump the process status and thread backtrace at launch",
1762+
default=False,
1763+
)
1764+
legacy_group = arg_parser.add_mutually_exclusive_group()
1765+
legacy_group.add_argument(
1766+
"-i",
1767+
"--interactive",
1768+
action="store_true",
1769+
help=argparse.SUPPRESS,
1770+
)
1771+
legacy_group.add_argument(
1772+
"-b",
1773+
"--batch",
1774+
action="store_true",
1775+
help=argparse.SUPPRESS,
1776+
)
1777+
17691778
return arg_parser
17701779

17711780

@@ -1778,7 +1787,7 @@ def CrashLogOptionParser():
17781787
created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows
17791788
you to explore the program as if it were stopped at the locations described in the crash log and functions can
17801789
be disassembled and lookups can be performed using the addresses found in the crash log."""
1781-
return CreateSymbolicateCrashLogOptions("crashlog", description, True)
1790+
return CreateSymbolicateCrashLogOptions("crashlog", description)
17821791

17831792

17841793
def SymbolicateCrashLogs(debugger, command_args, result, is_command):
@@ -1794,8 +1803,36 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
17941803
result.SetError(str(e))
17951804
return
17961805

1806+
# To avoid breaking existing users, we should keep supporting legacy flags
1807+
# even if we don't use them / advertise them anymore.
1808+
if options.interactive:
1809+
options.mode = CrashLogLoadingMode.interactive
1810+
elif options.batch:
1811+
options.mode = CrashLogLoadingMode.batch
1812+
1813+
if (
1814+
options.mode
1815+
and options.mode != CrashLogLoadingMode.interactive
1816+
and (options.target_path or options.skip_status)
1817+
):
1818+
print(
1819+
"Target path (-t) and skipping process status (-s) options can only used in interactive mode (-m=interactive)."
1820+
)
1821+
print("Aborting symbolication.")
1822+
arg_parser.print_help()
1823+
return
1824+
1825+
if options.version:
1826+
print(debugger.GetVersionString())
1827+
return
1828+
1829+
if options.debug:
1830+
print("command_args = %s" % command_args)
1831+
print("options", options)
1832+
print("args", options.reports)
1833+
17971834
# Interactive mode requires running the crashlog command from inside lldb.
1798-
if options.interactive and not is_command:
1835+
if options.mode == CrashLogLoadingMode.interactive and not is_command:
17991836
lldb_exec = (
18001837
subprocess.check_output(["/usr/bin/xcrun", "-f", "lldb"])
18011838
.decode("utf-8")
@@ -1821,31 +1858,24 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
18211858
print(debugger.GetVersionString())
18221859
return
18231860

1824-
if options.debug:
1825-
print("command_args = %s" % command_args)
1826-
print("options", options)
1827-
print("args", options.reports)
1828-
18291861
if options.debug_delay > 0:
18301862
print("Waiting %u seconds for debugger to attach..." % options.debug_delay)
18311863
time.sleep(options.debug_delay)
18321864
error = lldb.SBError()
18331865

18341866
def should_run_in_interactive_mode(options, ci):
1835-
if options.interactive:
1867+
if options.mode:
1868+
return options.mode == CrashLogLoadingMode.interactive
1869+
elif ci and ci.IsInteractive():
18361870
return True
1837-
elif options.batch:
1838-
return False
1839-
# elif ci and ci.IsInteractive():
1840-
# return True
18411871
else:
1842-
return False
1872+
return sys.stdout.isatty()
18431873

18441874
ci = debugger.GetCommandInterpreter()
18451875

18461876
if options.reports:
18471877
for crashlog_file in options.reports:
1848-
crashlog_path = os.path.expanduser(crashlog_file)
1878+
crashlog_path = os.path.normpath(os.path.expanduser(crashlog_file))
18491879
if not os.path.exists(crashlog_path):
18501880
raise FileNotFoundError(
18511881
"crashlog file %s does not exist" % crashlog_path

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RUN: %clang_host -g %S/Inputs/test.c -o %t.out
22
# RUN: cp %S/Inputs/altered_threadState.crash %t.crash
33
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}'
4-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s
4+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -b %t.crash' 2>&1 | FileCheck %s
55

66
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
77

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
# RUN: cp %S/Inputs/a.out.ips %t.crash
44
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' --json
5-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s
6-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -c %t.crash' 2>&1 | FileCheck %s
5+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s
6+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch -c %t.crash' 2>&1 | FileCheck %s
77

88
# RUN: cp %S/Inputs/a.out.ips %t.nometadata.crash
99
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.nometadata.crash --offsets '{"main":20, "bar":9, "foo":16}' --json --no-metadata
10-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.nometadata.crash' 2>&1 | FileCheck %s
10+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.nometadata.crash' 2>&1 | FileCheck %s
1111

1212
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
1313

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# RUN: cp %S/Inputs/no_threadState.ips %t.crash
44
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}' --json
5-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s
5+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s
66

77
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
88

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# RUN: mkdir -p %t.dir
44
# RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > %t.dir/multithread-test
55
# RUN: %lldb -b -o 'command script import lldb.macosx.crashlog' \
6-
# RUN: -o 'crashlog -a -i -s -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \
6+
# RUN: -o 'crashlog -a -s -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \
77
# RUN: -o 'command source -s 0 %s' 2>&1 | FileCheck %s
88

99
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands

lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RUN: %clang_host -g %S/Inputs/test.c -o %t.out
22
# RUN: cp %S/Inputs/a.out.crash %t.crash
33
# RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash --offsets '{"main":20, "bar":9, "foo":16}'
4-
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog %t.crash' 2>&1 | FileCheck %s
4+
# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 'crashlog -b %t.crash' 2>&1 | FileCheck %s
55

66
# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
77

0 commit comments

Comments
 (0)