https://github.com/medismailben updated 
https://github.com/llvm/llvm-project/pull/94575

>From f00c33948310576668bc886415cf98dbd1ab97be Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ism...@bennani.ma>
Date: Mon, 10 Jun 2024 14:54:36 -0700
Subject: [PATCH] [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 <ism...@bennani.ma>
---
 lldb/examples/python/crashlog.py              | 126 +++++++++++-------
 .../Python/Crashlog/altered_threadState.test  |   2 +-
 .../Python/Crashlog/json.test                 |   6 +-
 .../Python/Crashlog/no_threadState.test       |   2 +-
 .../skipped_status_interactive_crashlog.test  |   2 +-
 .../Python/Crashlog/text.test                 |   2 +-
 6 files changed, 85 insertions(+), 55 deletions(-)

diff --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index 1c0d717ce455c..18f1bbb818bf2 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -31,6 +31,7 @@
 import concurrent.futures
 import contextlib
 import datetime
+import enum
 import json
 import os
 import platform
@@ -45,7 +46,6 @@
 import time
 import uuid
 
-
 print_lock = threading.RLock()
 
 try:
@@ -1582,9 +1582,12 @@ def synchronous(debugger):
                 debugger.RunCommandInterpreter(True, False, run_options, 0, 
False, True)
 
 
-def CreateSymbolicateCrashLogOptions(
-    command_name, description, add_interactive_options
-):
+class CrashLogLoadingMode(str, enum.Enum):
+    batch = "batch"
+    interactive = "interactive"
+
+
+def CreateSymbolicateCrashLogOptions(command_name, description):
     usage = "crashlog [options] <FILE> [FILE ...]"
     arg_parser = argparse.ArgumentParser(
         description=description,
@@ -1600,6 +1603,13 @@ def CreateSymbolicateCrashLogOptions(
         help="crash report(s) to symbolicate",
     )
 
+    arg_parser.add_argument(
+        "-m",
+        "--mode",
+        choices=[mode.value for mode in CrashLogLoadingMode],
+        help="change how the symbolicated process and threads are displayed to 
the user",
+        default=CrashLogLoadingMode.interactive,
+    )
     arg_parser.add_argument(
         "--version",
         "-V",
@@ -1736,36 +1746,35 @@ def CreateSymbolicateCrashLogOptions(
         help=argparse.SUPPRESS,
         default=False,
     )
-    if add_interactive_options:
-        arg_parser.add_argument(
-            "-i",
-            "--interactive",
-            action="store_true",
-            help="parse a crash log and load it in a ScriptedProcess",
-            default=False,
-        )
-        arg_parser.add_argument(
-            "-b",
-            "--batch",
-            action="store_true",
-            help="dump symbolicated stackframes without creating a debug 
session",
-            default=True,
-        )
-        arg_parser.add_argument(
-            "--target",
-            "-t",
-            dest="target_path",
-            help="the target binary path that should be used for interactive 
crashlog (optional)",
-            default=None,
-        )
-        arg_parser.add_argument(
-            "--skip-status",
-            "-s",
-            dest="skip_status",
-            action="store_true",
-            help="prevent the interactive crashlog to dump the process status 
and thread backtrace at launch",
-            default=False,
-        )
+    arg_parser.add_argument(
+        "--target",
+        "-t",
+        dest="target_path",
+        help="the target binary path that should be used for interactive 
crashlog (optional)",
+        default=None,
+    )
+    arg_parser.add_argument(
+        "--skip-status",
+        "-s",
+        dest="skip_status",
+        action="store_true",
+        help="prevent the interactive crashlog to dump the process status and 
thread backtrace at launch",
+        default=False,
+    )
+    legacy_group = arg_parser.add_mutually_exclusive_group()
+    legacy_group.add_argument(
+        "-i",
+        "--interactive",
+        action="store_true",
+        help=argparse.SUPPRESS,
+    )
+    legacy_group.add_argument(
+        "-b",
+        "--batch",
+        action="store_true",
+        help=argparse.SUPPRESS,
+    )
+
     return arg_parser
 
 
@@ -1778,7 +1787,7 @@ def CrashLogOptionParser():
 created that has all of the shared libraries loaded at the load addresses 
found in the crash log file. This allows
 you to explore the program as if it were stopped at the locations described in 
the crash log and functions can
 be disassembled and lookups can be performed using the addresses found in the 
crash log."""
-    return CreateSymbolicateCrashLogOptions("crashlog", description, True)
+    return CreateSymbolicateCrashLogOptions("crashlog", description)
 
 
 def SymbolicateCrashLogs(debugger, command_args, result, is_command):
@@ -1794,8 +1803,36 @@ def SymbolicateCrashLogs(debugger, command_args, result, 
is_command):
         result.SetError(str(e))
         return
 
+    # To avoid breaking existing users, we should keep supporting legacy flags
+    # even if we don't use them / advertise them anymore.
+    if options.interactive:
+        options.mode = CrashLogLoadingMode.interactive
+    elif options.batch:
+        options.mode = CrashLogLoadingMode.batch
+
+    if (
+        options.mode
+        and options.mode != CrashLogLoadingMode.interactive
+        and (options.target_path or options.skip_status)
+    ):
+        print(
+            "Target path (-t) and skipping process status (-s) options can 
only used in interactive mode (-m=interactive)."
+        )
+        print("Aborting symbolication.")
+        arg_parser.print_help()
+        return
+
+    if options.version:
+        print(debugger.GetVersionString())
+        return
+
+    if options.debug:
+        print("command_args = %s" % command_args)
+        print("options", options)
+        print("args", options.reports)
+
     # Interactive mode requires running the crashlog command from inside lldb.
-    if options.interactive and not is_command:
+    if options.mode == CrashLogLoadingMode.interactive and not is_command:
         lldb_exec = (
             subprocess.check_output(["/usr/bin/xcrun", "-f", "lldb"])
             .decode("utf-8")
@@ -1821,31 +1858,24 @@ def SymbolicateCrashLogs(debugger, command_args, 
result, is_command):
         print(debugger.GetVersionString())
         return
 
-    if options.debug:
-        print("command_args = %s" % command_args)
-        print("options", options)
-        print("args", options.reports)
-
     if options.debug_delay > 0:
         print("Waiting %u seconds for debugger to attach..." % 
options.debug_delay)
         time.sleep(options.debug_delay)
     error = lldb.SBError()
 
     def should_run_in_interactive_mode(options, ci):
-        if options.interactive:
+        if options.mode:
+            return options.mode == CrashLogLoadingMode.interactive
+        elif ci and ci.IsInteractive():
             return True
-        elif options.batch:
-            return False
-        # elif ci and ci.IsInteractive():
-        #     return True
         else:
-            return False
+            return sys.stdout.isatty()
 
     ci = debugger.GetCommandInterpreter()
 
     if options.reports:
         for crashlog_file in options.reports:
-            crashlog_path = os.path.expanduser(crashlog_file)
+            crashlog_path = os.path.normpath(os.path.expanduser(crashlog_file))
             if not os.path.exists(crashlog_path):
                 raise FileNotFoundError(
                     "crashlog file %s does not exist" % crashlog_path
diff --git 
a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test
index 5a946a38b1952..d925324822de7 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/altered_threadState.test
@@ -1,7 +1,7 @@
 # RUN: %clang_host -g %S/Inputs/test.c -o %t.out
 # RUN: cp %S/Inputs/altered_threadState.crash %t.crash
 # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash 
--offsets '{"main":20, "bar":9, "foo":16}'
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog %t.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog -b %t.crash' 2>&1 | FileCheck %s
 
 # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" 
options on these commands
 
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test
index c2e23e82be7f5..d5c6d915316e8 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/json.test
@@ -2,12 +2,12 @@
 
 # RUN: cp %S/Inputs/a.out.ips %t.crash
 # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash 
--offsets '{"main":20, "bar":9, "foo":16}' --json
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog %t.crash' 2>&1 | FileCheck %s
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog -c %t.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog --mode batch -c %t.crash' 2>&1 | FileCheck %s
 
 # RUN: cp %S/Inputs/a.out.ips %t.nometadata.crash
 # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog 
%t.nometadata.crash --offsets '{"main":20, "bar":9, "foo":16}' --json 
--no-metadata
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog %t.nometadata.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog --mode batch %t.nometadata.crash' 2>&1 | FileCheck %s
 
 # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" 
options on these commands
 
diff --git 
a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test
index 5b5cef40716ca..2e4b46c8c2409 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/no_threadState.test
@@ -2,7 +2,7 @@
 
 # RUN: cp %S/Inputs/no_threadState.ips %t.crash
 # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash 
--offsets '{"main":20, "bar":9, "foo":16}' --json
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog %t.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog --mode batch %t.crash' 2>&1 | FileCheck %s
 
 # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" 
options on these commands
 
diff --git 
a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
index 64cd0904371aa..52a185b8cf760 100644
--- 
a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
+++ 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
@@ -3,7 +3,7 @@
 # RUN: mkdir -p %t.dir
 # RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > 
%t.dir/multithread-test
 # RUN: %lldb -b -o 'command script import lldb.macosx.crashlog' \
-# RUN: -o 'crashlog -a -i -s -t %t.dir/multithread-test 
%S/Inputs/interactive_crashlog/multithread-test.ips' \
+# RUN: -o 'crashlog -a -s -t %t.dir/multithread-test 
%S/Inputs/interactive_crashlog/multithread-test.ips' \
 # RUN: -o 'command source -s 0 %s' 2>&1 | FileCheck %s
 
 # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" 
options on these commands
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test 
b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test
index e9d1c5e98fb32..eec30a1da64c6 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/text.test
@@ -1,7 +1,7 @@
 # RUN: %clang_host -g %S/Inputs/test.c -o %t.out
 # RUN: cp %S/Inputs/a.out.crash %t.crash
 # RUN: %python %S/patch-crashlog.py --binary %t.out --crashlog %t.crash 
--offsets '{"main":20, "bar":9, "foo":16}'
-# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog %t.crash' 2>&1 | FileCheck %s
+# RUN: %lldb %t.out -o 'command script import lldb.macosx.crashlog' -o 
'crashlog -b %t.crash' 2>&1 | FileCheck %s
 
 # CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" 
options on these commands
 

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to