3131import  concurrent .futures 
3232import  contextlib 
3333import  datetime 
34+ import  enum 
3435import  json 
3536import  os 
3637import  platform 
4546import  time 
4647import  uuid 
4748
48- 
4949print_lock  =  threading .RLock ()
5050
5151try :
@@ -1585,9 +1585,12 @@ def synchronous(debugger):
15851585                debugger .RunCommandInterpreter (True , False , run_options , 0 , False , True )
15861586
15871587
1588- def  CreateSymbolicateCrashLogOptions (
1589-     command_name , description , add_interactive_options 
1590- ):
1588+ class  CrashLogLoadingMode (str , enum .Enum ):
1589+     batch  =  "batch" 
1590+     interactive  =  "interactive" 
1591+ 
1592+ 
1593+ def  CreateSymbolicateCrashLogOptions (command_name , description ):
15911594    usage  =  "crashlog [options] <FILE> [FILE ...]" 
15921595    arg_parser  =  argparse .ArgumentParser (
15931596        description = description ,
@@ -1603,6 +1606,12 @@ def CreateSymbolicateCrashLogOptions(
16031606        help = "crash report(s) to symbolicate" ,
16041607    )
16051608
1609+     arg_parser .add_argument (
1610+         "-m" ,
1611+         "--mode" ,
1612+         choices = [mode .value  for  mode  in  CrashLogLoadingMode ],
1613+         help = "change how the symbolicated process and threads are displayed to the user (default: interactive)" ,
1614+     )
16061615    arg_parser .add_argument (
16071616        "--version" ,
16081617        "-V" ,
@@ -1739,36 +1748,35 @@ def CreateSymbolicateCrashLogOptions(
17391748        help = argparse .SUPPRESS ,
17401749        default = False ,
17411750    )
1742-     if  add_interactive_options :
1743-         arg_parser .add_argument (
1744-             "-i" ,
1745-             "--interactive" ,
1746-             action = "store_true" ,
1747-             help = "parse a crash log and load it in a ScriptedProcess" ,
1748-             default = False ,
1749-         )
1750-         arg_parser .add_argument (
1751-             "-b" ,
1752-             "--batch" ,
1753-             action = "store_true" ,
1754-             help = "dump symbolicated stackframes without creating a debug session" ,
1755-             default = True ,
1756-         )
1757-         arg_parser .add_argument (
1758-             "--target" ,
1759-             "-t" ,
1760-             dest = "target_path" ,
1761-             help = "the target binary path that should be used for interactive crashlog (optional)" ,
1762-             default = None ,
1763-         )
1764-         arg_parser .add_argument (
1765-             "--skip-status" ,
1766-             "-s" ,
1767-             dest = "skip_status" ,
1768-             action = "store_true" ,
1769-             help = "prevent the interactive crashlog to dump the process status and thread backtrace at launch" ,
1770-             default = False ,
1771-         )
1751+     arg_parser .add_argument (
1752+         "--target" ,
1753+         "-t" ,
1754+         dest = "target_path" ,
1755+         help = "the target binary path that should be used for interactive crashlog (optional)" ,
1756+         default = None ,
1757+     )
1758+     arg_parser .add_argument (
1759+         "--skip-status" ,
1760+         "-s" ,
1761+         dest = "skip_status" ,
1762+         action = "store_true" ,
1763+         help = "prevent the interactive crashlog to dump the process status and thread backtrace at launch" ,
1764+         default = False ,
1765+     )
1766+     legacy_group  =  arg_parser .add_mutually_exclusive_group ()
1767+     legacy_group .add_argument (
1768+         "-i" ,
1769+         "--interactive" ,
1770+         action = "store_true" ,
1771+         help = argparse .SUPPRESS ,
1772+     )
1773+     legacy_group .add_argument (
1774+         "-b" ,
1775+         "--batch" ,
1776+         action = "store_true" ,
1777+         help = argparse .SUPPRESS ,
1778+     )
1779+ 
17721780    return  arg_parser 
17731781
17741782
@@ -1781,7 +1789,7 @@ def CrashLogOptionParser():
17811789created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows 
17821790you to explore the program as if it were stopped at the locations described in the crash log and functions can 
17831791be disassembled and lookups can be performed using the addresses found in the crash log.""" 
1784-     return  CreateSymbolicateCrashLogOptions ("crashlog" , description ,  True )
1792+     return  CreateSymbolicateCrashLogOptions ("crashlog" , description )
17851793
17861794
17871795def  SymbolicateCrashLogs (debugger , command_args , result , is_command ):
@@ -1797,8 +1805,35 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
17971805        result .SetError (str (e ))
17981806        return 
17991807
1808+     # To avoid breaking existing users, we should keep supporting legacy flags 
1809+     # even if we don't use them / advertise them anymore. 
1810+     if  not  options .mode :
1811+         if  options .batch :
1812+             options .mode  =  CrashLogLoadingMode .batch 
1813+         else :
1814+             options .mode  =  CrashLogLoadingMode .interactive 
1815+ 
1816+     if  options .mode  !=  CrashLogLoadingMode .interactive  and  (
1817+         options .target_path  or  options .skip_status 
1818+     ):
1819+         print (
1820+             "Target path (-t) and skipping process status (-s) options can only used in interactive mode (-m=interactive)." 
1821+         )
1822+         print ("Aborting symbolication." )
1823+         arg_parser .print_help ()
1824+         return 
1825+ 
1826+     if  options .version :
1827+         print (debugger .GetVersionString ())
1828+         return 
1829+ 
1830+     if  options .debug :
1831+         print ("command_args = %s"  %  command_args )
1832+         print ("options" , options )
1833+         print ("args" , options .reports )
1834+ 
18001835    # Interactive mode requires running the crashlog command from inside lldb. 
1801-     if  options .interactive  and  not  is_command :
1836+     if  options .mode   ==   CrashLogLoadingMode . interactive  and  not  is_command :
18021837        lldb_exec  =  (
18031838            subprocess .check_output (["/usr/bin/xcrun" , "-f" , "lldb" ])
18041839            .decode ("utf-8" )
@@ -1824,31 +1859,26 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
18241859        print (debugger .GetVersionString ())
18251860        return 
18261861
1827-     if  options .debug :
1828-         print ("command_args = %s"  %  command_args )
1829-         print ("options" , options )
1830-         print ("args" , options .reports )
1831- 
18321862    if  options .debug_delay  >  0 :
18331863        print ("Waiting %u seconds for debugger to attach..."  %  options .debug_delay )
18341864        time .sleep (options .debug_delay )
18351865    error  =  lldb .SBError ()
18361866
18371867    def  should_run_in_interactive_mode (options , ci ):
1838-         if  options .interactive :
1839-             return  True 
1840-         elif  options .batch :
1868+         if  options .mode  ==  CrashLogLoadingMode .batch :
18411869            return  False 
1842-         # elif ci and ci.IsInteractive(): 
1843-         #     return True 
1870+         elif  options .mode  ==  CrashLogLoadingMode .interactive  or  (
1871+             ci  and  ci .IsInteractive ()
1872+         ):
1873+             return  True 
18441874        else :
1845-             return  False 
1875+             return  sys . stdout . isatty () 
18461876
18471877    ci  =  debugger .GetCommandInterpreter ()
18481878
18491879    if  options .reports :
18501880        for  crashlog_file  in  options .reports :
1851-             crashlog_path  =  os .path .expanduser (crashlog_file )
1881+             crashlog_path  =  os .path .normpath ( os . path . expanduser (crashlog_file ) )
18521882            if  not  os .path .exists (crashlog_path ):
18531883                raise  FileNotFoundError (
18541884                    "crashlog file %s does not exist"  %  crashlog_path 
0 commit comments