Skip to content

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

Open
mujacica wants to merge 2 commits intomasterfrom
fix/minidump-module-header-pages
Open

fix(minidump): add module header pages to MemoryList and fix exception code#1576
mujacica wants to merge 2 commits intomasterfrom
fix/minidump-module-header-pages

Conversation

@mujacica
Copy link
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 and others added 2 commits March 12, 2026 15:18
…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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mujacica mujacica marked this pull request as ready for review March 13, 2026 02:54
Comment on lines +1617 to +1621
while ((n = read(fd, buf + total, buf_size - total - 1)) > 0) {
total += n;
if (total >= buf_size - 1) {
break;
}
Copy link

Choose a reason for hiding this comment

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

Bug: The write_linux_maps_stream function uses a fixed 32KB buffer, which can silently truncate /proc/[pid]/maps data for processes with many memory mappings, leading to incomplete minidumps.
Severity: MEDIUM

Suggested Fix

To prevent silent truncation, the buffer handling should be improved. Either dynamically reallocate the buffer to accommodate the full size of the /proc/[pid]/maps file or log a warning when the data is truncated. Reading the entire file in one operation could also be a solution.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/backends/native/minidump/sentry_minidump_linux.c#L1617-L1621

Potential issue: The `write_linux_maps_stream` function reads the `/proc/[pid]/maps`
file into a fixed-size 32KB buffer. For applications with a large number of memory
mappings, such as those with many threads, the maps file can exceed this size. When this
occurs, the `read` loop breaks silently, resulting in a truncated
`MINIDUMP_STREAM_LINUX_MAPS` stream in the generated minidump. While this does not cause
a crash and the minidump remains structurally valid, the incomplete data degrades the
effectiveness of debuggers that rely on this information for offline analysis.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link

@cursor cursor bot left a comment

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 2 potential issues.

Fix All in Cursor

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

if (region_size > MODULE_HEADER_SIZE) {
region_size = MODULE_HEADER_SIZE;
}
}
Copy link

Choose a reason for hiding this comment

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

Module header cap incorrectly truncates crash address region

Medium Severity

In SMART mode, the 4096-byte cap for module header pages is applied based purely on mapping attributes (offset == 0, named, not [-prefixed), without considering whether the region also contains the crash address. If the crash occurs within a module's first mapping at offset 0 — which is common with GNU ld's traditional layout where the first r-xp segment includes both the ELF header and executable code — the region gets truncated to 4096 bytes, losing the memory around the crash address that should_include_region explicitly marks as "most important."

Additional Locations (1)
Fix in Cursor Fix in Web

// still succeeds (kernel copies what it can) or we get a
// short write which is fine.
write(hdr_fd, base, 4096);
}
Copy link

Choose a reason for hiding this comment

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

Unchecked write() causes module header data misalignment

Low Severity

The signal handler's write(hdr_fd, base, 4096) ignores the return value. If any module's write fails (e.g., returns -1 from EFAULT), the file offset doesn't advance, causing all subsequent modules' data to shift backward by 4096 bytes. The reader in write_module_headers_from_capture assumes strict sequential 4096-byte blocks per module, so misaligned data maps wrong headers to wrong modules, corrupting offline symbolication.

Fix in Cursor Fix in Web

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.

1 participant