Mach-O: Answer the section predicates from the section - #762
Conversation
MachOSection.only_contains_uninitialized_data returned a hardcoded False, so a consumer asking whether a section holds nothing but zeroes was told no for __bss, __common, __thread_bss and __noptrbss alike, and read the zeroes CLE pads the segment with as if the program had put them there. The format states it. The low byte of a section's flags is its type, which MachOSection.type already exposes, and S_ZEROFILL, S_GB_ZEROFILL and S_THREAD_LOCAL_ZEROFILL have no bytes in the file at all. Name the section types in macho_enums and answer the property from them.
MachOSection.is_executable forwarded to its parent segment. ld64 marks the whole of __TEXT r-x, so every constant pool, string literal, unwind table and Swift or Objective-C metadata section in it reported as executable, and CFGFast scanned them: on one x86_64 dylib 413 of 35,985 blocks began inside __const, __cstring and __gcc_except_tab, one of them on the bytes of the string "/string". The section states it. S_ATTR_PURE_INSTRUCTIONS and S_ATTR_SOME_INSTRUCTIONS occupy the high bytes of a section's flags, which MachOSection.attributes already exposes, and they separate code from data inside an r-x segment exactly as SHF_EXECINSTR does for an ELF whose .rodata shares a load segment with .text. ELFSection and PESection both answer this property from their own section flags; Mach-O was the only backend that did not. Measured across 29,184 thin Mach-O images: 33,241 of 100,001 sections in an executable segment carry an instruction attribute, and the section names that do are __text, __stubs, __stub_helper, __objc_stubs, __StaticInit, __symbol_stub1, __symbolstub1, __text_startup, text_env, and __TEXT_EXEC's __text and __auth_stubs, with nothing else. No section carries the attribute outside an executable segment or on a zero-fill type, so the new answer is a subset of the old one. Against the addresses the files themselves name as function entries, all 438,738 LC_FUNCTION_STARTS entries of 704 images fall inside a section that states instructions, and none outside. 307 of the 29,184 state no instructions anywhere: 304 relocatable objects whose only content is __LLVM,__bitcode, __DWARF or __DATA,__data, and 3 stub dylibs. Those files hold no instructions, so reporting none is the right answer. This lands together with the preceding commit, which repairs only_contains_uninitialized_data in the same class for the same reason: both predicates answered a question about a section with something other than the section.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
The gate's own worktree check reports a change to the shared In this run the difference is three such stores being removed between the Every suite passed on the exact publication state: cle 227 passed and 9 skipped; An earlier attempt failed the same check in the other direction, on a store a Worst single object found, x86_64 Mach-O Evidence for
A/B over every Mach-O fixture in
Evidence for Corpus objects are identified by digest only; they come from a private dataset. |
|
Corpus decompilation diffs can be found at angr/dec-snapshots@master...angr/cle_762 |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
MachOSectionanswers two questions about a section with something that is notthe section:
is_executableforwards to the parent segment, andonly_contains_uninitialized_datareturns a hardcodedFalse. ld64 marks thewhole of
__TEXTr-x, so the first reports every constant pool, stringliteral and unwind table as executable and CFGFast decodes them as code.
Both now come from the section's own flags, as
ELFSectionandPESectionalready do: the
S_ATTR_*INSTRUCTIONSattributes for the first, the zero-fillsection types for the second. Nothing reads page protection from a
Section—memory setup uses segments.
Covered by tests over
tests/x86_64/fauxware.macho, whose__TEXTholds__cstringand__unwind_infobeside its code, andtests/aarch64/dyld_ios15.macho.Reported as angr/angr#6860 and angr/angr#6856.
Validation: #762 (comment)