[Lldb-commits] [lldb] dfdd898 - [lldb/crashlog] Load inlined symbol into interactive crashlog

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri May 19 20:08:33 PDT 2023


Author: Med Ismail Bennani
Date: 2023-05-19T20:08:18-07:00
New Revision: dfdd8988621bcdce0364e0c3ab2d6ba52e875f32

URL: https://github.com/llvm/llvm-project/commit/dfdd8988621bcdce0364e0c3ab2d6ba52e875f32
DIFF: https://github.com/llvm/llvm-project/commit/dfdd8988621bcdce0364e0c3ab2d6ba52e875f32.diff

LOG: [lldb/crashlog] Load inlined symbol into interactive crashlog

Sometimes, crash reports come with inlined symbols. These provide the
exact stacktrace from the user binary.

However, when investigating a crash, it's very likely that the images related
to the crashed thread are not available on the debugging user system or
that the versions don't match. This causes interactive crashlog to show
a degraded backtrace in lldb.

This patch aims to address that issue, by parsing the inlined symbols
from the crash report and load them into lldb's target.

This patch is a follow-up to 27f27d1, focusing on inlined symbols
loading from legacy (non-json) crash reports.

To do so, it updates the stack frame regular expression to make the
capture groups more granular, to be able to extract the symbol name, the
offset and the source location if available, while making it more
maintainable.

So now, when parsing the crash report, we build a data structure
containing all the symbol information for each stackframe. Then, after
launching the scripted process for interactive mode, we write a JSON
symbol file for each module, only containing the symbols that it contains.

Finally, we load the json symbol file into lldb, before showing the user
the process status and backtrace.

rdar://97345586

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

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>

Added: 
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/Inputs/interactive_crashlog/multithread-test.crash
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test

Modified: 
    lldb/examples/python/crashlog.py

Removed: 
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test


################################################################################
diff  --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index dadab3cd8b7f4..d207af10f36f2 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -432,6 +432,8 @@ def __init__(self, debugger, path, verbose):
         self.path = os.path.expanduser(path)
         self.verbose = verbose
         self.crashlog = CrashLog(debugger, self.path, self.verbose)
+        # List of DarwinImages sorted by their index.
+        self.images = list()
 
     @abc.abstractmethod
     def parse(self):
@@ -459,8 +461,6 @@ def parse_json(buffer):
 
     def __init__(self, debugger, path, verbose):
         super().__init__(debugger, path, verbose)
-        # List of DarwinImages sorted by their index.
-        self.images = list()
 
     def parse(self):
         try:
@@ -603,14 +603,45 @@ def parse_asi_backtrace(self, thread, bt):
                 print("error: can't parse application specific backtrace.")
                 return False
 
-            (frame_id, frame_img_name, frame_addr,
-                frame_ofs) = frame_match.groups()
+            frame_id = frame_img_name = frame_addr = frame_symbol = frame_offset = frame_file = frame_line = frame_column = None
+
+            if len(frame_match.groups()) == 3:
+                # Get the image UUID from the frame image name.
+                (frame_id, frame_img_name, frame_addr) = frame_match.groups()
+            elif len(frame_match.groups()) == 5:
+                (frame_id, frame_img_name, frame_addr,
+                        frame_symbol, frame_offset) = frame_match.groups()
+            elif len(frame_match.groups()) == 7:
+                (frame_id, frame_img_name, frame_addr,
+                        frame_symbol, frame_offset,
+                        frame_file, frame_line) = frame_match.groups()
+            elif len(frame_match.groups()) == 8:
+                (frame_id, frame_img_name, frame_addr,
+                        frame_symbol, frame_offset,
+                        frame_file, frame_line, frame_column) = frame_match.groups()
 
             thread.add_ident(frame_img_name)
             if frame_img_name not in self.crashlog.idents:
                 self.crashlog.idents.append(frame_img_name)
-            thread.frames.append(self.crashlog.Frame(int(frame_id), int(
-                frame_addr, 0), frame_ofs))
+
+            description = ""
+            if frame_img_name and frame_addr and frame_symbol:
+                description = frame_symbol
+                frame_offset_value = 0
+                if frame_offset:
+                    description += " + " + frame_offset
+                    frame_offset_value = int(frame_offset, 0)
+                for image in self.images:
+                    if image.identifier == frame_img_name:
+                        image.symbols[frame_symbol] = {
+                            "name": frame_symbol,
+                            "type": "code",
+                            "address": int(frame_addr, 0) - frame_offset_value,
+                        }
+
+            thread.frames.append(
+                self.crashlog.Frame(int(frame_id), int(frame_addr, 0), description)
+            )
 
         return True
 
@@ -657,19 +688,48 @@ class TextCrashLogParser(CrashLogParser):
     thread_instrs_regex = re.compile(r'^Thread \d+ instruction stream')
     thread_regex = re.compile(r'^Thread (\d+).*:')
     app_backtrace_regex = re.compile(r'^Application Specific Backtrace (\d+).*:')
-    version = r'\(.+\)|(?:arm|x86_)[0-9a-z]+'
-    frame_regex = re.compile(r'^(\d+)\s+'              # id
-                             r'(.+?)\s+'               # img_name
-                             r'(?:' +version+ r'\s+)?' # img_version
-                             r'(0x[0-9a-fA-F]{4,})'    # addr (4 chars or more)
-                             r'(?: +(.*))?'            # offs
+
+    class VersionRegex:
+        version = r'\(.+\)|(?:arm|x86_)[0-9a-z]+'
+
+    class FrameRegex(VersionRegex):
+        @classmethod
+        def get(cls):
+            index    = r'^(\d+)\s+'
+            img_name = r'(.+?)\s+'
+            version  = r'(?:' + super().version + r'\s+)?'
+            address  = r'(0x[0-9a-fA-F]{4,})' # 4 digits or more
+
+            symbol   = """
+                        (?:
+                            [ ]+
+                            (?P<symbol>.+)
+                            (?:
+                                [ ]\+[ ]
+                                (?P<symbol_offset>\d+)
                             )
+                            (?:
+                                [ ]\(
+                                (?P<file_name>[^:]+):(?P<line_number>\d+)
+                                (?:
+                                    :(?P<column_num>\d+)
+                                )?
+                            )?
+                        )?
+                       """
+
+            return re.compile(index + img_name + version + address + symbol,
+                              flags=re.VERBOSE)
+
+    frame_regex = FrameRegex.get()
     null_frame_regex = re.compile(r'^\d+\s+\?\?\?\s+0{4,} +')
     image_regex_uuid = re.compile(r'(0x[0-9a-fA-F]+)'          # img_lo
                                   r'\s+-\s+'                   #   -
                                   r'(0x[0-9a-fA-F]+)\s+'       # img_hi
                                   r'[+]?(.+?)\s+'              # img_name
-                                  r'(?:(' +version+ r')\s+)?'  # img_version
+                                  r'(?:(' +
+                                  VersionRegex.version +         # img_version
+                                  r')\s+)?'
                                   r'(?:<([-0-9a-fA-F]+)>\s+)?' # img_uuid
                                   r'(\?+|/.*)'                 # img_path
                                  )
@@ -690,6 +750,7 @@ def __init__(self, debugger, path, verbose):
             CrashLogParseMode.SYSTEM : self.parse_system,
             CrashLogParseMode.INSTRS : self.parse_instructions,
         }
+        self.symbols = {}
 
     def parse(self):
         with open(self.path,'r', encoding='utf-8') as f:
@@ -844,29 +905,76 @@ def parse_thread(self, line):
             print('warning: thread parser ignored null-frame: "%s"' % line)
             return
         frame_match = self.frame_regex.search(line)
-        if frame_match:
-            (frame_id, frame_img_name, frame_addr,
-                frame_ofs) = frame_match.groups()
-            ident = frame_img_name
-            self.thread.add_ident(ident)
-            if ident not in self.crashlog.idents:
-                self.crashlog.idents.append(ident)
-            self.thread.frames.append(self.crashlog.Frame(int(frame_id), int(
-                frame_addr, 0), frame_ofs))
-        else:
+        if not frame_match:
             print('error: frame regex failed for line: "%s"' % line)
+            return
+
+        frame_id = frame_img_name = frame_addr = frame_symbol = frame_offset = frame_file = frame_line = frame_column = None
+
+        if len(frame_match.groups()) == 3:
+            # Get the image UUID from the frame image name.
+            (frame_id, frame_img_name, frame_addr) = frame_match.groups()
+        elif len(frame_match.groups()) == 5:
+            (frame_id, frame_img_name, frame_addr,
+                    frame_symbol, frame_offset) = frame_match.groups()
+        elif len(frame_match.groups()) == 7:
+            (frame_id, frame_img_name, frame_addr,
+                    frame_symbol, frame_offset,
+                    frame_file, frame_line) = frame_match.groups()
+        elif len(frame_match.groups()) == 8:
+            (frame_id, frame_img_name, frame_addr,
+                    frame_symbol, frame_offset,
+                    frame_file, frame_line, frame_column) = frame_match.groups()
+
+        self.thread.add_ident(frame_img_name)
+        if frame_img_name not in self.crashlog.idents:
+            self.crashlog.idents.append(frame_img_name)
+
+        description = ""
+        # Since images are parsed after threads, we need to build a
+        # map for every image with a list of all the symbols and addresses
+        if frame_img_name and frame_addr and frame_symbol:
+            description = frame_symbol
+            frame_offset_value = 0
+            if frame_offset:
+                description += " + " + frame_offset
+                frame_offset_value = int(frame_offset, 0)
+            if frame_img_name not in self.symbols:
+                self.symbols[frame_img_name] = list()
+            self.symbols[frame_img_name].append(
+                {
+                    "name": frame_symbol,
+                    "address": int(frame_addr, 0) - frame_offset_value,
+                }
+            )
+
+        self.thread.frames.append(
+            self.crashlog.Frame(int(frame_id), int(frame_addr, 0), description)
+        )
 
     def parse_images(self, line):
         image_match = self.image_regex_uuid.search(line)
         if image_match:
             (img_lo, img_hi, img_name, img_version,
                 img_uuid, img_path) = image_match.groups()
+
             image = self.crashlog.DarwinImage(int(img_lo, 0), int(img_hi, 0),
                                             img_name.strip(),
                                             img_version.strip()
                                             if img_version else "",
                                             uuid.UUID(img_uuid), img_path,
                                             self.verbose)
+            unqualified_img_name = os.path.basename(img_path)
+            if unqualified_img_name in self.symbols:
+                for symbol in self.symbols[unqualified_img_name]:
+                    image.symbols[symbol["name"]] = {
+                        "name": symbol["name"],
+                        "type": "code",
+                        # NOTE: "address" is actually the symbol image offset
+                        "address": symbol["address"] - int(img_lo, 0),
+                    }
+
+            self.images.append(image)
             self.crashlog.images.append(image)
         else:
             print("error: image regex failed for: %s" % line)

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/Inputs/interactive_crashlog/multithread-test.crash b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/Inputs/interactive_crashlog/multithread-test.crash
new file mode 100644
index 0000000000000..6bd5c109fc4ba
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/Inputs/interactive_crashlog/multithread-test.crash
@@ -0,0 +1,140 @@
+Process:               multithread-test [22511]
+Path:                  /Users/USER/*/multithread-test
+Identifier:            multithread-test
+Version:               ???
+Code Type:             ARM-64 (Native)
+Parent Process:        zsh [59146]
+Responsible:           Terminal [1640]
+User ID:               501
+
+Date/Time:             2022-07-28 11:10:19.4194 -0700
+OS Version:            macOS 13.0 ()
+Report Version:        12
+Anonymous UUID:        CDC11418-EDBF-2A49-0D83-8B441A5004B0
+
+Sleep/Wake UUID:       7B2A0D73-8966-4B8D-98E9-CC6EC1B44967
+
+Time Awake Since Boot: 110000 seconds
+Time Since Wake:       214 seconds
+
+System Integrity Protection: disabled
+
+Crashed Thread:        2
+
+Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
+Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
+Exception Codes:       0x0000000000000001, 0x0000000000000000
+
+Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
+Terminating Process:   exc handler [22511]
+
+VM Region Info: 0 is not in any region.  Bytes before following region: 4310450176
+      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
+      UNUSED SPACE AT START
+--->  
+      __TEXT                      100ec4000-100ec8000    [   16K] r-x/r-x SM=COW  ...tithread-test
+
+Thread 0::  Dispatch queue: com.apple.main-thread
+0   libsystem_kernel.dylib        	       0x19cc40b84 __ulock_wait + 8
+1   libsystem_pthread.dylib       	       0x19cc80394 _pthread_join + 444
+2   libc++.1.dylib                	       0x19cbd8274 std::__1::thread::join() + 36
+3   multithread-test              	       0x100ec5b3c main + 160 (multithread-test.cpp:31)
+4   dyld                          	       0x2230f8da8 start + 2376
+
+Thread 1:
+0   libsystem_kernel.dylib        	       0x19cc42c9c __write_nocancel + 8
+1   libsystem_c.dylib             	       0x19cb719a8 __swrite + 24
+2   libsystem_c.dylib             	       0x19cb50ac8 _swrite + 108
+3   libsystem_c.dylib             	       0x19cb4ec2c __sflush + 232
+4   libsystem_c.dylib             	       0x19cb42f20 __sfvwrite + 792
+5   libsystem_c.dylib             	       0x19cb61f64 fwrite + 152
+6   libc++.1.dylib                	       0x19cbed084 std::__1::__stdoutbuf<char>::overflow(int) + 96
+7   libc++.1.dylib                	       0x19cbe06b4 std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >::operator=(char) + 96
+8   libc++.1.dylib                	       0x19cbe0798 std::__1::basic_ostream<char, std::__1::char_traits<char> >::put(char) + 200
+9   multithread-test              	       0x100ec5a54 std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) + 64 (ostream:994)
+10  multithread-test              	       0x100ec5a08 std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >& (*)(std::__1::basic_ostream<char, std::__1::char_traits<char> >&)) + 32 (ostream:189)
+11  multithread-test              	       0x100ec5958 call_and_wait(int&) + 48 (multithread-test.cpp:14)
+12  multithread-test              	       0x100ec7684 decltype(static_cast<void (*>(fp)(static_cast<std::__1::reference_wrapper<int>>(fp0))) std::__1::__invoke<void (*)(int&), std::__1::reference_wrapper<int> >(void (*&&)(int&), std::__1::reference_wrapper<int>&&) + 48 (type_traits:3918)
+13  multithread-test              	       0x100ec7608 void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int>, 2ul>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int> >&, std::__1::__tuple_indices<2ul>) + 56 (thread:287)
+14  multithread-test              	       0x100ec6d58 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int> > >(void*) + 84 (thread:298)
+15  libsystem_pthread.dylib       	       0x19cc7e06c _pthread_start + 148
+16  libsystem_pthread.dylib       	       0x19cc78e2c thread_start + 8
+
+Thread 2 Crashed:
+0   multithread-test              	       0x100ec58f4 bar(int) + 20 (multithread-test.cpp:7)
+1   multithread-test              	       0x100ec591c foo(int) + 24 (multithread-test.cpp:11)
+2   multithread-test              	       0x100ec5a88 compute_pow(int&) + 28 (multithread-test.cpp:20)
+3   multithread-test              	       0x100ec7684 decltype(static_cast<void (*>(fp)(static_cast<std::__1::reference_wrapper<int>>(fp0))) std::__1::__invoke<void (*)(int&), std::__1::reference_wrapper<int> >(void (*&&)(int&), std::__1::reference_wrapper<int>&&) + 48 (type_traits:3918)
+4   multithread-test              	       0x100ec7608 void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int>, 2ul>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int> >&, std::__1::__tuple_indices<2ul>) + 56 (thread:287)
+5   multithread-test              	       0x100ec6d58 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(int&), std::__1::reference_wrapper<int> > >(void*) + 84 (thread:298)
+6   libsystem_pthread.dylib       	       0x19cc7e06c _pthread_start + 148
+7   libsystem_pthread.dylib       	       0x19cc78e2c thread_start + 8
+
+
+Thread 2 crashed with ARM Thread State (64-bit):
+    x0: 0x000000000000002a   x1: 0x0000600001d291b0   x2: 0x000000019cbbf000   x3: 0x0000000000000000
+    x4: 0x00000000000030a0   x5: 0x00000000190008ff   x6: 0x0000000000000000   x7: 0x0000000000000000
+    x8: 0x0000000000000001   x9: 0x0000000000000000  x10: 0xfffffffe634277cf  x11: 0x0000010000000102
+   x12: 0x0000010000000102  x13: 0x0000010000000100  x14: 0x0000010000000000  x15: 0x0000000000000001
+   x16: 0x000000019cc78ea8  x17: 0x00000001fd0a7698  x18: 0x0000000000000000  x19: 0x000000016f04f000
+   x20: 0x0000000000000000  x21: 0x0000000000000000  x22: 0x0000000000000000  x23: 0x0000000000000000
+   x24: 0x0000000000000000  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x0000000000000000
+   x28: 0x0000000000000000   fp: 0x000000016f04ef00   lr: 0x0000000100ec591c
+    sp: 0x000000016f04eee0   pc: 0x0000000100ec58f4 cpsr: 0x80001000
+   far: 0x0000000000000000  esr: 0x92000046 (Data Abort) byte write Translation fault
+
+Binary Images:
+       0x19cc3e000 -        0x19cc76feb libsystem_kernel.dylib (*) <b8898079-5424-3e89-92b0-33022c3be1bb> /usr/lib/system/libsystem_kernel.dylib
+       0x19cc77000 -        0x19cc83ffb libsystem_pthread.dylib (*) <ffd36328-45f2-31c5-9240-9f76f26a1a2b> /usr/lib/system/libsystem_pthread.dylib
+       0x19cbbf000 -        0x19cc25ff3 libc++.1.dylib (*) <da619b87-2723-3731-919a-bb3467eab9e1> /usr/lib/libc++.1.dylib
+       0x100ec4000 -        0x100ec7fff multithread-test (*) <ab9b94f9-6cdf-3b8e-b140-fae3cb13d327> /Users/USER/*/multithread-test
+       0x2230f3000 -        0x22317be4b dyld (*) <e81312a0-f3e5-3c60-8c25-4599b62b8b4a> /usr/lib/dyld
+       0x19cb3e000 -        0x19cbbefff libsystem_c.dylib (*) <b8f1c3ed-9048-34a6-8070-6c18d4ade541> /usr/lib/system/libsystem_c.dylib
+               0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???
+            0x3039 -             0x3420 bogus.dylib (*) <11111111-2222-3333-4444-555555555555> /usr/lib/system/bogus.dylib
+
+External Modification Summary:
+  Calls made by other processes targeting this process:
+    task_for_pid: 0
+    thread_create: 0
+    thread_set_state: 0
+  Calls made by this process:
+    task_for_pid: 0
+    thread_create: 0
+    thread_set_state: 0
+  Calls made by all processes on this machine:
+    task_for_pid: 23
+    thread_create: 0
+    thread_set_state: 812
+
+VM Region Summary:
+ReadOnly portion of Libraries: Total=762.9M resident=0K(0%) swapped_out_or_unallocated=762.9M(100%)
+Writable regions: Total=538.2M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=538.2M(100%)
+
+                                VIRTUAL   REGION 
+REGION TYPE                        SIZE    COUNT (non-coalesced) 
+===========                     =======  ======= 
+Kernel Alloc Once                   32K        1 
+MALLOC                           145.2M       12 
+MALLOC guard page                   96K        5 
+MALLOC_NANO (reserved)           384.0M        1         reserved VM address space (unallocated)
+STACK GUARD                       56.0M        3 
+Stack                             9264K        3 
+__AUTH                              46K       11 
+__AUTH_CONST                        70K       38 
+__DATA                             169K       36 
+__DATA_CONST                       187K       40 
+__DATA_DIRTY                        78K       22 
+__LINKEDIT                       758.0M        2 
+__OBJC_CONST                        11K        5 
+__OBJC_RO                         64.7M        1 
+__OBJC_RW                         1971K        1 
+__TEXT                            5076K       42 
+dyld private memory                256K        1 
+shared memory                       64K        3 
+===========                     =======  ======= 
+TOTAL                              1.4G      227 
+TOTAL, minus reserved VM space     1.0G      227 
+
+
+

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test
similarity index 100%
rename from lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test
rename to lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_json.test

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test
new file mode 100644
index 0000000000000..6e2826e88aedf
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_legacy.test
@@ -0,0 +1,43 @@
+# REQUIRES: python, native && target-aarch64 && system-darwin
+
+# RUN: mkdir -p %t.dir
+# RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > %t.dir/multithread-test
+# RUN: %lldb -o 'command script import lldb.macosx.crashlog' \
+# RUN: -o 'crashlog -a -i -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.crash' \
+# RUN: -o "thread list" -o "bt all" 2>&1 | FileCheck %s
+
+# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
+
+# CHECK: (lldb) process status
+# CHECK-NEXT: Process 22511 stopped
+# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
+# CHECK-NEXT:     frame #0: 0x0000000100ec58f4 multithread-test`bar
+
+# CHECK: (lldb) thread backtrace
+# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
+# CHECK-NEXT:   * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
+# CHECK-NEXT:     frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
+# CHECK-NEXT:     frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]
+
+# CHECK: (lldb) thread list
+# CHECK-NEXT: Process 22511 stopped
+# CHECK-NEXT:   thread #1: tid = 0x0000, 0x000000019cc40b84{{.*}}
+# CHECK-NEXT:   thread #2: tid = 0x0001, 0x000000019cc42c9c{{.*}}
+# CHECK-NEXT: * thread #3: tid = 0x0002, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
+
+# CHECK: (lldb) bt all
+# CHECK:  thread #1
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial]
+# CHECK-NEXT:  thread #2
+# CHECK-NEXT:    frame #0: 0x000000019cc42c9c{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial]
+# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
+# CHECK-NEXT:  * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
+# CHECK-NEXT:    frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
+# CHECK-NEXT:    frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial]


        


More information about the lldb-commits mailing list