fix(minidump): add module header pages to MemoryList and fix exception code#1576
fix(minidump): add module header pages to MemoryList and fix exception code#1576
Conversation
…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>
| while ((n = read(fd, buf + total, buf_size - total - 1)) > 0) { | ||
| total += n; | ||
| if (total >= buf_size - 1) { | ||
| break; | ||
| } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
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; | ||
| } | ||
| } |
There was a problem hiding this comment.
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)
| // still succeeds (kernel copies what it can) or we get a | ||
| // short write which is fine. | ||
| write(hdr_fd, base, 4096); | ||
| } |
There was a problem hiding this comment.
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.


Three fixes for the native minidump writer:
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.
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.
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.