Mach-O: Do not back a segment that occupies no memory - #729
Conversation
A Mach-O segment occupies vmsize bytes at vmaddr, and the file contributes at most vmsize of them. Debug info that stays in the executable instead of moving into a .dSYM is emitted as a __DWARF segment with vmsize 0 and the whole of the debug info as its file content; since it takes up no address space, the linker gives the segment that follows it, __LINKEDIT, the same vmaddr. _load_segment decided whether to back a segment from its filesize alone and then backed it with filesize bytes, so __DWARF got a backer hundreds of kilobytes long sitting exactly where __LINKEDIT belongs, and the load died in add_backer with "Address ... is already backed!". Leave a segment that is not mapped at runtime unbacked, and read at most memsize bytes of file content for the ones that are. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head Reproducer, a public Homebrew bottle: That file is sha256
Caveats:
|
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_729 |
|
LGTM. Thanks! |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Unstripped Mach-O executables that keep their debug info in a
__DWARFsegment rather than a separate.dSYMfail to load withValueError: Address 0x... is already backed!.__DWARFhasvmsize0, so it occupies no address space and the linker gives__LINKEDITthe samevmaddr, but_load_segmentsized the backer fromfilesizealone and dropped hundreds of kilobytes of debug info exactly where__LINKEDITbelongs.A segment maps
vmsizebytes and the file contributes at most that many, which is this backend's invariant to keep: leave a segment that maps nothing unbacked, and clamp the rest tomemsize.Reproduced on
repomapperfrom the Homebrewreposurgeon5.9 arm64_sonoma bottle. The regression splices the same segment shape into an existing fixture, so it needs no new binary.Validation: #729 (comment)