kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

macho_block_alt_entry.sh (3008B)


      1 #!/usr/bin/env bash
      2 # Mach-O MH_SUBSECTIONS_VIA_SYMBOLS regression: relocation-anchor symbols for
      3 # switch/label blocks must be N_ALT_ENTRY symbols pinned inside their function,
      4 # not independently collectible atoms. Otherwise --gc-sections can retain the
      5 # function's entry atom while dropping a directly-branched-to switch dispatch
      6 # or common return block (intra-function branches are already resolved and do
      7 # not carry linker relocations).
      8 set -euo pipefail
      9 
     10 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     11 KIT="${KIT:-$ROOT/build/kit}"
     12 ROUNDTRIP="${ROUNDTRIP:-$ROOT/build/test/kit-roundtrip-macho}"
     13 WORK="$ROOT/build/test/opt/macho_block_alt_entry"
     14 mkdir -p "$WORK"
     15 
     16 cat > "$WORK/dispatch.c" <<'EOF'
     17 int dispatch(unsigned x) {
     18   if (x < 256) return 7;
     19   switch (x) {
     20     case 256: return 11;
     21     case 257: return 13;
     22     case 258: return 17;
     23     case 259: return 19;
     24     case 260: return 23;
     25     case 261: return 29;
     26     case 262: return 31;
     27     case 263: return 37;
     28     case 264: return 41;
     29     default: return 43;
     30   }
     31 }
     32 EOF
     33 
     34 cat > "$WORK/main.c" <<'EOF'
     35 extern int dispatch(unsigned);
     36 int main(void) { return dispatch(123) == 7 ? 0 : 1; }
     37 EOF
     38 
     39 COMMON=(-target aarch64-apple-darwin -O1 -ffunction-sections
     40         -fdata-sections -ffreestanding)
     41 "$KIT" cc "${COMMON[@]}" -c "$WORK/dispatch.c" -o "$WORK/dispatch.o" \
     42   > "$WORK/dispatch.cc.out" 2>&1
     43 "$KIT" cc "${COMMON[@]}" -c "$WORK/main.c" -o "$WORK/main.o" \
     44   > "$WORK/main.cc.out" 2>&1
     45 
     46 # Read and re-emit the defining object before linking. This makes the test
     47 # cover both halves of the format boundary: Mach-O read must collapse pinned
     48 # block symbols into their owner atom, and emit must preserve the subordinate
     49 # semantic as N_ALT_ENTRY on the second object too.
     50 "$ROUNDTRIP" --require-atom-subordinate "$WORK/dispatch.o" \
     51   "$WORK/dispatch.roundtrip.o" > "$WORK/dispatch.roundtrip.out" 2>&1
     52 
     53 # Force the serialized Mach-O reader/linker path: compiling and linking in one
     54 # driver invocation can keep the original ObjBuilder and would not exercise
     55 # MH_SUBSECTIONS_VIA_SYMBOLS reconstruction.
     56 "$KIT" cc -target aarch64-apple-darwin -nostdlib -Wl,--gc-sections \
     57   -Wl,-e,main "$WORK/main.o" "$WORK/dispatch.roundtrip.o" -o "$WORK/linked" \
     58   > "$WORK/link.out" 2>&1
     59 "$KIT" objdump -d "$WORK/linked" > "$WORK/linked.dis" 2>&1
     60 
     61 # The case body and indirect table dispatch live after block-label boundaries.
     62 # Without N_ALT_ENTRY they are collected and the surviving fast-path branches
     63 # outside __text; retaining both instructions pins the full function content.
     64 if ! grep -Eq '\bmovz[[:space:]]+w0, 0xb\b' "$WORK/linked.dis"; then
     65   printf 'macho_block_alt_entry FAILED: case block was GC-collected\n' >&2
     66   sed 's/^/  | /' "$WORK/linked.dis" >&2
     67   exit 1
     68 fi
     69 if ! grep -Eq '\bbr[[:space:]]+x[0-9]+\b' "$WORK/linked.dis"; then
     70   printf 'macho_block_alt_entry FAILED: switch dispatch was GC-collected\n' >&2
     71   sed 's/^/  | /' "$WORK/linked.dis" >&2
     72   exit 1
     73 fi
     74 
     75 printf 'macho_block_alt_entry: OK (block anchors stay pinned through Mach-O GC)\n'