Skip to content

fix(minidump): add module header pages to MemoryList and fix exception code#1576

Merged
mujacica merged 4 commits into
masterfrom
fix/minidump-module-header-pages
Mar 17, 2026
Merged

fix(minidump): add module header pages to MemoryList and fix exception code#1576
mujacica merged 4 commits into
masterfrom
fix/minidump-module-header-pages

Conversation

@mujacica

Copy link
Copy Markdown
Contributor

Three fixes for the native minidump writer:

  1. Use raw signal number as exception_code (e.g. 11 for SIGSEGV) instead of Windows-style 0x40000000|signum. This matches breakpad/crashpad convention and fixes lldb hanging when loading our minidumps.

  2. Include first page (4096 bytes) of each loaded module in the MemoryList stream for SMART mode on both Linux and macOS. Debuggers need these ELF/Mach-O headers for offline symbolication when symbol files aren't available locally, matching breakpad/crashpad behavior.

  3. On macOS, capture module header pages in the signal handler and save them to disk. System dylibs in the dyld shared cache don't exist as individual files, so the daemon reads headers from a capture file written by the crashed process instead of requiring task_for_pid.

mujacica added a commit that referenced this pull request Mar 12, 2026
Co-Authored-By: Claude Opus 4.6 <[email protected]>
@mujacica
mujacica marked this pull request as ready for review March 13, 2026 02:54
Comment thread src/backends/native/minidump/sentry_minidump_linux.c
Comment thread src/backends/native/minidump/sentry_minidump_linux.c
Comment thread src/backends/native/sentry_crash_handler.c
mujacica added a commit that referenced this pull request Mar 16, 2026
Co-Authored-By: Claude Opus 4.6 <[email protected]>
@mujacica
mujacica force-pushed the fix/minidump-module-header-pages branch from 1125a14 to ea35e47 Compare March 16, 2026 10:32

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread src/backends/native/minidump/sentry_minidump_macos.c
Comment thread src/backends/native/minidump/sentry_minidump_macos.c
Comment thread src/backends/native/minidump/sentry_minidump_macos.c
Comment thread src/backends/native/minidump/sentry_minidump_linux.c Outdated
mujacica and others added 4 commits March 16, 2026 13:29
…n code

Three fixes for the native minidump writer:

1. Use raw signal number as exception_code (e.g. 11 for SIGSEGV) instead
   of Windows-style 0x40000000|signum. This matches breakpad/crashpad
   convention and fixes lldb hanging when loading our minidumps.

2. Include first page (4096 bytes) of each loaded module in the MemoryList
   stream for SMART mode on both Linux and macOS. Debuggers need these
   ELF/Mach-O headers for offline symbolication when symbol files aren't
   available locally, matching breakpad/crashpad behavior.

3. On macOS, capture module header pages in the signal handler and save
   them to disk. System dylibs in the dyld shared cache don't exist as
   individual files, so the daemon reads headers from a capture file
   written by the crashed process instead of requiring task_for_pid.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
@mujacica
mujacica force-pushed the fix/minidump-module-header-pages branch from 8dbcd90 to 414cb35 Compare March 16, 2026 12:47
@mujacica
mujacica merged commit 9cad572 into master Mar 17, 2026
51 checks passed
@mujacica
mujacica deleted the fix/minidump-module-header-pages branch March 17, 2026 08:57
BernhardMarconato pushed a commit to elgatosf/sentry-native that referenced this pull request Apr 21, 2026
…n code (getsentry#1576)

* fix(minidump): add module header pages to MemoryList and fix exception code

Three fixes for the native minidump writer:

1. Use raw signal number as exception_code (e.g. 11 for SIGSEGV) instead
   of Windows-style 0x40000000|signum. This matches breakpad/crashpad
   convention and fixes lldb hanging when loading our minidumps.

2. Include first page (4096 bytes) of each loaded module in the MemoryList
   stream for SMART mode on both Linux and macOS. Debuggers need these
   ELF/Mach-O headers for offline symbolication when symbol files aren't
   available locally, matching breakpad/crashpad behavior.

3. On macOS, capture module header pages in the signal handler and save
   them to disk. System dylibs in the dyld shared cache don't exist as
   individual files, so the daemon reads headers from a capture file
   written by the crashed process instead of requiring task_for_pid.

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
mujacica added a commit that referenced this pull request May 15, 2026
``MINIDUMP_EXCEPTION.exception_code`` on macOS must carry the **Mach
exception type** (EXC_BAD_ACCESS = 1, EXC_BREAKPOINT = 6, ...) per the
Breakpad / Crashpad convention every minidump reader respects. Earlier
the writer put the BSD signal number directly into that field (#1576,
commit 9cad572), which works as long as the consumer doesn't try to
decode the field — but minidump-rs, the Breakpad processor, and
Crashpad's own minidump tools all read it as a Mach exception type
and produced wrong crash-reason labels (e.g. ``MacGeneral(EXC_RESOURCE,
0)`` for a plain SIGSEGV, since 11 = SIGSEGV in BSD signals AND
EXC_RESOURCE in the Mach exception enum).

This commit reverses the macOS kernel's signal-translation: given a
(signum, siginfo) pair we infer the Mach exception type + subcode that
produced it, write those into ``exception_code`` / ``exception_flags``
exactly like Breakpad's ``MinidumpGenerator::WriteExceptionStream``
does, and keep the BSD signal available to consumers via
``exception_information[0]`` so the previous "lldb wants the signal"
use case still works.

The translation table mirrors Apple's BSD ↔ Mach mapping:

  SIGSEGV → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS / PROTECTION_FAILURE
            from si_code)
  SIGBUS  → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS / PROTECTION_FAILURE)
  SIGILL  → EXC_BAD_INSTRUCTION
  SIGFPE  → EXC_ARITHMETIC
  SIGTRAP → EXC_BREAKPOINT
  SIGABRT → EXC_CRASH (with signal encoded in code[0] low bits)
  SIGSYS  → EXC_SOFTWARE / EXC_SOFT_SIGNAL
  other   → EXC_SOFTWARE / EXC_SOFT_SIGNAL

Verified end-to-end with minidump-rs reading the regenerated UAF dump:
``crash_reason_debug`` now decodes as ``MacBadAccessKern(...)`` instead
of ``MacGeneral(EXC_RESOURCE, 0)``.

Tests:

  * ``test_native_minidump_streams`` extended to assert
    ``exception_code`` is one of the valid Mach exception enum values
    and ``exception_information[0]`` carries a plausible BSD signal
    number. Catches regressions to the BSD-signum-as-exception-code
    convention used by the prior commit.

Verified on:

  * macOS 26 arm64 (local): pytest tests/test_integration_native.py
    -> 23 passed, 2 skipped (Windows-only WER).
  * Linux Ubuntu 24.04 arm64 (Docker): both new tests pass.
mujacica added a commit that referenced this pull request May 20, 2026
``MINIDUMP_EXCEPTION.exception_code`` on macOS must carry the **Mach
exception type** (EXC_BAD_ACCESS = 1, EXC_BREAKPOINT = 6, ...) per the
Breakpad / Crashpad convention every minidump reader respects. Earlier
the writer put the BSD signal number directly into that field (#1576,
commit 9cad572), which works as long as the consumer doesn't try to
decode the field — but minidump-rs, the Breakpad processor, and
Crashpad's own minidump tools all read it as a Mach exception type
and produced wrong crash-reason labels (e.g. ``MacGeneral(EXC_RESOURCE,
0)`` for a plain SIGSEGV, since 11 = SIGSEGV in BSD signals AND
EXC_RESOURCE in the Mach exception enum).

This commit reverses the macOS kernel's signal-translation: given a
(signum, siginfo) pair we infer the Mach exception type + subcode that
produced it, write those into ``exception_code`` / ``exception_flags``
exactly like Breakpad's ``MinidumpGenerator::WriteExceptionStream``
does, and keep the BSD signal available to consumers via
``exception_information[0]`` so the previous "lldb wants the signal"
use case still works.

The translation table mirrors Apple's BSD ↔ Mach mapping:

  SIGSEGV → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS / PROTECTION_FAILURE
            from si_code)
  SIGBUS  → EXC_BAD_ACCESS (KERN_INVALID_ADDRESS / PROTECTION_FAILURE)
  SIGILL  → EXC_BAD_INSTRUCTION
  SIGFPE  → EXC_ARITHMETIC
  SIGTRAP → EXC_BREAKPOINT
  SIGABRT → EXC_CRASH (with signal encoded in code[0] low bits)
  SIGSYS  → EXC_SOFTWARE / EXC_SOFT_SIGNAL
  other   → EXC_SOFTWARE / EXC_SOFT_SIGNAL

Verified end-to-end with minidump-rs reading the regenerated UAF dump:
``crash_reason_debug`` now decodes as ``MacBadAccessKern(...)`` instead
of ``MacGeneral(EXC_RESOURCE, 0)``.

Tests:

  * ``test_native_minidump_streams`` extended to assert
    ``exception_code`` is one of the valid Mach exception enum values
    and ``exception_information[0]`` carries a plausible BSD signal
    number. Catches regressions to the BSD-signum-as-exception-code
    convention used by the prior commit.

Verified on:

  * macOS 26 arm64 (local): pytest tests/test_integration_native.py
    -> 23 passed, 2 skipped (Windows-only WER).
  * Linux Ubuntu 24.04 arm64 (Docker): both new tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants