[PATCH] D144839: Add support to symbolize backtraces on crashes on Macho platforms

Mehdi AMINI via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 26 20:25:24 PST 2023


mehdi_amini created this revision.
mehdi_amini added a reviewer: aprantl.
Herald added a subscriber: hiraditya.
Herald added a reviewer: JDevlieghere.
Herald added a project: All.
mehdi_amini requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

llvm-symbolizer still requires to run dsymutil to find debug info though,
I'm not sure if we can teach llvm-symbolizer to find these without?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144839

Files:
  llvm/lib/Support/Unix/Signals.inc


Index: llvm/lib/Support/Unix/Signals.inc
===================================================================
--- llvm/lib/Support/Unix/Signals.inc
+++ llvm/lib/Support/Unix/Signals.inc
@@ -61,6 +61,7 @@
 #endif
 #if HAVE_MACH_MACH_H
 #include <mach/mach.h>
+#include <mach-o/dyld.h>
 #endif
 #if HAVE_LINK_H
 #include <link.h>
@@ -507,6 +508,70 @@
   dl_iterate_phdr(dl_iterate_phdr_cb, &data);
   return true;
 }
+#elif HAVE_MACH_MACH_H
+
+// Use the _dyld_* functions to find the loaded modules and populate
+// the modules and offset arrays for each stack frame.
+static bool findModulesAndOffsets(void **StackTrace, int Depth,
+                                  const char **Modules, intptr_t *Offsets,
+                                  const char *MainExecutableName,
+                                  StringSaver &Unused) {
+  int ImageCount = _dyld_image_count();
+  // Find the image name and the offset for a given PC.
+  auto ProcessPC = [&](intptr_t pc, const char **Name, intptr_t *Offset) {
+    *Name = nullptr;
+    *Offset = 0;
+    // Scan the images in the binary and find the one that contains the PC.
+    for (int ImageID = 0; ImageID < ImageCount; ++ImageID) {
+      // Get the image header, and find the pointer to the first command (right
+      // after the header).
+      const struct mach_header *Header =
+          (const struct mach_header *)_dyld_get_image_header(ImageID);
+      intptr_t ImageOffset = _dyld_get_image_vmaddr_slide(ImageID);
+      intptr_t HeaderSize = sizeof(mach_header);
+      if (Header->magic == MH_MAGIC_64)
+        HeaderSize = sizeof(mach_header_64);
+      const struct load_command *cmd =
+          reinterpret_cast<const struct load_command *>(
+              reinterpret_cast<const char *>(Header) + HeaderSize);
+
+      // Iterate all the load commands, looking for a segment containing the PC.
+      for (unsigned CmdID = 0; CmdID < Header->ncmds;
+           ++CmdID, cmd = (const struct load_command
+                               *)(reinterpret_cast<const char *>(cmd) +
+                                  cmd->cmdsize)) {
+        // Compute the interval of addresses covered by this segment.
+        intptr_t SegStart = 0;
+        intptr_t SegEnd = 0;
+        if (cmd->cmd == LC_SEGMENT) {
+          const struct segment_command *seg =
+              (const struct segment_command *)cmd;
+          SegStart = seg->vmaddr + ImageOffset;
+          SegEnd = SegStart + seg->vmsize;
+        } else if (cmd->cmd == LC_SEGMENT_64) {
+          const struct segment_command_64 *seg =
+              (const struct segment_command_64 *)cmd;
+          SegStart = seg->vmaddr + ImageOffset;
+          SegEnd = SegStart + seg->vmsize;
+        } else {
+          continue;
+        }
+        if ((pc >= SegStart) && (pc < SegEnd)) {
+          *Name = _dyld_get_image_name(ImageID);
+          *Offset = pc - ImageOffset;
+          return;
+        }
+      }
+    }
+  };
+  // Iterate over the stack trace and find the module and offset for each PC.
+  for (int i = 0; i < Depth; i++) {
+    intptr_t pc = reinterpret_cast<intptr_t>(StackTrace[i]);
+    ProcessPC(pc, &Modules[i], &Offsets[i]);
+  }
+  return true;
+}
+
 #else
 /// This platform does not have dl_iterate_phdr, so we do not yet know how to
 /// find all loaded DSOs.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D144839.500654.patch
Type: text/x-patch
Size: 3315 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230227/3e3abfc4/attachment.bin>


More information about the llvm-commits mailing list