llvm/llvm-project

arm64e-apple-* target are producing "arm64e.old" objects, per Xcode's ld

glandium opened this issue · 4 comments

% echo "int main() { return 0; }" > foo.c
% ./clang -o foo.o -c foo.c --target=arm64e-apple-darwin
% ./clang -o foo foo.o --target=arm64e-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
-macosx_version_min has been renamed to -macos_version_min
ld: warning: ignoring file 'foo.o': found architecture 'arm64e.old', required architecture 'arm64e'
ld: Undefined symbols:
  _main, referenced from:
      <initial-undefines>
clang: error: linker command failed with exit code 1 (use -v to see invocation)

% otool -h foo.o
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          2  0x00           1     4        360 0x00002000
% /usr/bin/clang -o foo.o -c foo.c --target=arm64e-apple-darwin
% otool -h foo.o
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          2  0x80           1     4        360 0x00002000

I suppose the 0x80 caps is what indicates what Xcode clang produces is what ld calls "arm64e" vs. 0x00 indicating "arm64e.old".

@llvm/issue-subscribers-backend-aarch64

Author: Mike Hommey (glandium)

``` % echo "int main() { return 0; }" > foo.c % ./clang -o foo.o -c foo.c --target=arm64e-apple-darwin % ./clang -o foo foo.o --target=arm64e-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -macosx_version_min has been renamed to -macos_version_min ld: warning: ignoring file 'foo.o': found architecture 'arm64e.old', required architecture 'arm64e' ld: Undefined symbols: _main, referenced from: <initial-undefines> clang: error: linker command failed with exit code 1 (use -v to see invocation)

% otool -h foo.o
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777228 2 0x00 1 4 360 0x00002000
% /usr/bin/clang -o foo.o -c foo.c --target=arm64e-apple-darwin
% otool -h foo.o
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777228 2 0x80 1 4 360 0x00002000


I suppose the 0x80 caps is what indicates what Xcode clang produces is what ld calls "arm64e" vs. 0x00 indicating "arm64e.old".
</details>

Indeed, that 0x80 is CPU_SUBTYPE_PTRAUTH_ABI, per mach/machine.h

nico commented

FWIW, this works using the fork over at https://github.com/apple/llvm-project:

% ~/src/apple-llvm-project/build/bin/clang -o foo.o -c foo.c --target=arm64e-apple-darwin -S -o - | rg ptrauth
	.ptrauth_abi_version 0
% ~/src/apple-llvm-project/build/bin/clang -o foo.o -c foo.c --target=arm64e-apple-darwin                     
% ~/src/apple-llvm-project/build/bin/clang -o foo foo.o --target=arm64e-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

Diffing this against the upstream llvm tree finds a bunch of ptrauth code. The rust issue mentioned above links to the initial RFC for this from 2019, and the swiftlang#14 "preview".

If someone had to create arm64e binaries for some reason, it's probably possible (but fiddly) to locally patch the ptrauth bits from the fork over there onto public upstream llvm.

Is there any plan to merge those changes into the main branch of LLVM? As it stands now, the arm64e codegen is effectively broken with recent versions of Xcode