[Lldb-commits] [lldb] 032d91c - [lldb/crashlog] Create interactive crashlog with no binary

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 1 17:11:14 PDT 2023


Author: Med Ismail Bennani
Date: 2023-06-01T17:10:57-07:00
New Revision: 032d91cb2fb539a541f24558a8c61a40b1577dfd

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

LOG: [lldb/crashlog] Create interactive crashlog with no binary

This patch changes the way we load a crash report into a scripted
process by creating a empty target.

To do so, it parses the architecture information from the report (for
both the legacy and json format) and uses that to create a target that
doesn't have any executable, like what we do when attaching to a process.

For the legacy format, we mostly rely on the `Code Type` line, since the
architure is an optional field on the `Binary Images` sections.

However for the json format, we first try to get the architecture while
parsing the image dictionary if we couldn't find it, we try to infer it
using the "flavor" key when parsing the frame's registers.

If the architecture is still not set after parsing the report, we raise
an exception.

rdar://107850263

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

Differential

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

Added: 
    

Modified: 
    lldb/examples/python/crashlog.py
    lldb/source/Target/Process.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index 387f84cca33d4..9978c70d0bfdf 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -395,6 +395,10 @@ def __init__(self, debugger, path, verbose):
         self.version = -1
         self.target = None
         self.verbose = verbose
+        self.process_id = None
+        self.process_identifier = None
+        self.process_path = None
+        self.process_arch = None
 
     def dump(self):
         print("Crash Log File: %s" % (self.path))
@@ -484,9 +488,9 @@ def create(debugger, path, verbose):
     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()
+        self.crashlog = CrashLog(debugger, self.path, self.verbose)
 
     @abc.abstractmethod
     def parse(self):
@@ -547,6 +551,8 @@ def get_used_image(self, idx):
     def parse_process_info(self, json_data):
         self.crashlog.process_id = json_data["pid"]
         self.crashlog.process_identifier = json_data["procName"]
+        if "procPath" in json_data:
+            self.crashlog.process_path = json_data["procPath"]
 
     def parse_crash_reason(self, json_exception):
         self.crashlog.exception = json_exception
@@ -574,6 +580,10 @@ def parse_images(self, json_images):
             darwin_image = self.crashlog.DarwinImage(
                 low, high, name, version, img_uuid, path, self.verbose
             )
+            if "arch" in json_image:
+                darwin_image.arch = json_image["arch"]
+                if path == self.crashlog.process_path:
+                    self.crashlog.process_arch = darwin_image.arch
             self.images.append(darwin_image)
             self.crashlog.images.append(darwin_image)
 
@@ -740,6 +750,13 @@ def parse_thread_registers(self, json_thread_state, prefix=None):
                 gpr_dict = {str(idx): reg for idx, reg in enumerate(state)}
                 registers.update(self.parse_thread_registers(gpr_dict, key))
                 continue
+            if key == "flavor":
+                if not self.crashlog.process_arch:
+                    if state == "ARM_THREAD_STATE64":
+                        self.crashlog.process_arch = "arm64"
+                    elif state == "X86_THREAD_STATE":
+                        self.crashlog.process_arch = "x86_64"
+                continue
             try:
                 value = int(state["value"])
                 registers["{}{}".format(prefix or "", key)] = value
@@ -912,6 +929,8 @@ def parse_normal(self, line):
                 line[8:].strip().split(" [")
             )
             self.crashlog.process_id = pid_with_brackets.strip("[]")
+        elif line.startswith("Path:"):
+            self.crashlog.process_path = line[5:].strip()
         elif line.startswith("Identifier:"):
             self.crashlog.process_identifier = line[11:].strip()
         elif line.startswith("Version:"):
@@ -923,6 +942,11 @@ def parse_normal(self, line):
             else:
                 self.crashlog.process = version_string
                 self.crashlog.process_compatability_version = version_string
+        elif line.startswith("Code Type:"):
+            if "ARM-64" in line:
+                self.crashlog.process_arch = "arm64"
+            elif "X86-64" in line:
+                self.crashlog.process_arch = "x86_64"
         elif self.parent_process_regex.search(line):
             parent_process_match = self.parent_process_regex.search(line)
             self.crashlog.parent_process_name = parent_process_match.group(1)
@@ -1343,9 +1367,12 @@ def load_crashlog_in_scripted_process(debugger, crash_log_file, options, result)
     # 2. If the user didn't provide a target, try to create a target using the symbolicator
     if not target or not target.IsValid():
         target = crashlog.create_target()
-    # 3. If that didn't work, and a target is already loaded, use it
-    if (target is None or not target.IsValid()) and debugger.GetNumTargets() > 0:
-        target = debugger.GetTargetAtIndex(0)
+    # 3. If that didn't work, create a dummy target
+    if target is None or not target.IsValid():
+        arch = crashlog.process_arch
+        if not arch:
+            raise InteractiveCrashLogException("couldn't create find the architecture to create the target")
+        target = debugger.CreateTargetWithFileAndArch(None, arch)
     # 4. Fail
     if target is None or not target.IsValid():
         raise InteractiveCrashLogException("couldn't create target")

diff  --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 8545ca4c12c02..c5ec8a36fc7c1 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2527,7 +2527,7 @@ Status Process::LaunchPrivate(ProcessLaunchInfo &launch_info, StateType &state,
 
   FileSpec exe_spec_to_use;
   if (!exe_module) {
-    if (!launch_info.GetExecutableFile()) {
+    if (!launch_info.GetExecutableFile() && !launch_info.IsScriptedProcess()) {
       error.SetErrorString("executable module does not exist");
       return error;
     }


        


More information about the lldb-commits mailing list