Skip to content

constructor doesn't work with arm64e-apple-ios but works on arm64e-apple-darwin #139218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ds-ep opened this issue Apr 1, 2025 · 7 comments
Open
Labels
A-linkage Area: linking into static, shared libraries and binaries A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-AArch64 Armv8-A or later processors in AArch64 mode O-apple Operating system: Apple (macOS, iOS, tvOS, visionOS, watchOS) O-ios Operating system: iOS

Comments

@ds-ep
Copy link

ds-ep commented Apr 1, 2025

I am compiling a dylib targeting arm64e for macos and ios. I am using the ctor crate (https://crates.io/crates/ctor) but also ruled that out by just using the expanded code (cargo expand).

my .cargo/config.toml (using xcode14 clang to allow linking arm64e):

[target.arm64e-apple-darwin]
rustflags = ["-C", 
    "linker=xcode14/test/CLTools_Executables.pkg/Library/Developer/CommandLineTools/usr/bin/gcc", 
    "-C", 
    "link-arg=-fuse-ld=xcode14/test/CLTools_Executables.pkg/Library/Developer/CommandLineTools/usr/bin/ld",
]

[target.arm64e-apple-ios]
rustflags = ["-C", 
    "linker=xcode14/test/CLTools_Executables.pkg/Library/Developer/CommandLineTools/usr/bin/gcc", 
    "-C", 
    "link-arg=-fuse-ld=xcode14/test/CLTools_Executables.pkg/Library/Developer/CommandLineTools/usr/bin/ld",
]

my lib.rs:

#[allow(unused)]
fn constructor() {
    #[allow(unsafe_code)]
    {
        #[unsafe(link_section = "__DATA,__mod_init_func")]
        #[used]
        #[allow(non_upper_case_globals, non_snake_case)]
        #[doc(hidden)]
        static f: extern "C" fn() -> usize = {
            #[allow(non_snake_case)]
            extern "C" fn f() -> usize {
                unsafe {
                    constructor();
                    0
                }
            }
            f
        };
    }
    {
        println!("Hello from {}", "Rust");
        hooks::init_hooks();
    }
}

for macos i use: cargo +nightly build -Z build-std --target arm64e-apple-darwin
for ios i use: SDKROOT=~/Documents/ios_sdks/iPhoneOS16.0.sdk cargo +nightly build -Z build-std --target arm64e-apple-ios

when compiling this code for ios i get the error with a clean build:

clang: warning: using sysroot for 'iPhoneOS' but targeting 'MacOSX' [-Wincompatible-sysroot]
          ld: building for 'macOS', but linking in dylib (iPhoneOS16.0.sdk/usr/lib/libiconv.2.tbd) built for 'iOS'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

This error seems like something is confused and wants to build macos?

building macos then ios:

  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: ld: warning: object file built with an incompatible arm64e ABI: '/var/folders/9w/ghpc5vj54l3684jktj8vtkm00000gn/T/rustcnBeHtH/symbols.o'
          ld: warning: object file built with an incompatible arm64e ABI: 'Documents/repos/alloc_tracker/target/arm64e-apple-ios/debug/deps/alloc_tracker.5gd9524b65p18ksle2rao8sny.rcgu.rmeta'
          ld: reference to symbol (which has not been assigned an address) __ZN13alloc_tracker11constructor1f17hf2d8c9917faf02bfE for architecture arm64e
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

This error just seems like the symbol for the constructor is getting removed

Meta

rustc --version --verbose:

cargo 1.88.0-nightly (a6c604d1b 2025-03-26)
release: 1.88.0-nightly
commit-hash: a6c604d1b8a2f2a8ff1f3ba6092f9fda42f4b7e9
commit-date: 2025-03-26
host: aarch64-apple-darwin
libgit2: 1.9.0 (sys:0.20.0 vendored)
libcurl: 8.7.1 (sys:0.4.80+curl-8.12.1 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 3.4.1 11 Feb 2025
os: Mac OS 15.3.1 [64-bit]
@ds-ep ds-ep added the C-bug Category: This is a bug. label Apr 1, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 1, 2025
@ds-ep
Copy link
Author

ds-ep commented Apr 1, 2025

@madsmtm @arttet

@madsmtm
Copy link
Contributor

madsmtm commented Apr 1, 2025

The issue here probably arises from #133832, though I'm pretty sure what we're doing there is correct, the symbol relocations that we're emitting are what's needed for the newer arm64e ABI - the problem is that the rest of rustc/LLVM doesn't correctly emit arm64e, since Apple's patches aren't upstreamed yet (as can be seen by the "object file built with an incompatible arm64e ABI" warning).

I guess we could fix this (and #138481) by not special-casing arm64e in add_data_and_relocation for now, but I'm inclined to not do that, our arm64e targets are really a lie and don't actually provide the pointer authentication guarantees that you'd expect. I'd recommend that you use aarch64-apple-ios for now.

@rustbot label -needs-triage +O-apple +A-linkage A-llvm O-AArch64

@rustbot rustbot added A-linkage Area: linking into static, shared libraries and binaries A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. O-AArch64 Armv8-A or later processors in AArch64 mode O-apple Operating system: Apple (macOS, iOS, tvOS, visionOS, watchOS) and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Apr 1, 2025
@ds-ep
Copy link
Author

ds-ep commented Apr 1, 2025

So I did some more digging the first issue on a clean build is due to building the build.rs for a dependency while SDKROOT is set and therefore it builds the build.rs which is meant to run on the host with the targets sysroot (unsure if there is a proper workaround for this) but building for arm64e-apple-darwin then for arm64e-apple-ios seems to work alright.

@madsmtm as for the second issue, I dont think the issues you mentioned are related. If i do a clean build targeting arm64e-apple-darwin it builds completely fine, but for arm64e-apple-ios i get this symbol not assigned an address error. The issues you linked are specific to arm64e but not darwin vs ios. For me darwin works correctly so it must be some difference with ios and darwin in rust. Any ideas why the darwin one works but not ios?

regarding using aarch64 i am looking to inject my dylib into a process which is arm64e which requires the library being injected to also be arm64e, im not too worried if the rust code once running is actually doing pointer auth things.

@bjorn3
Copy link
Member

bjorn3 commented Apr 1, 2025

If i do a clean build targeting arm64e-apple-darwin it builds completely fine

Linker warnings are suppressed on Apple platforms. You likely still get the same warning and maybe it just falls back to building a non-arm64e dylib?

@madsmtm
Copy link
Contributor

madsmtm commented Apr 1, 2025

So I did some more digging the first issue on a clean build is due to building the build.rs for a dependency while SDKROOT is set and therefore it builds the build.rs which is meant to run on the host with the targets sysroot (unsure if there is a proper workaround for this) but building for arm64e-apple-darwin then for arm64e-apple-ios seems to work alright.

Ah, yeah, that's caused by #80817.

@madsmtm as for the second issue, I dont think the issues you mentioned are related. If i do a clean build targeting arm64e-apple-darwin it builds completely fine, but for arm64e-apple-ios i get this symbol not assigned an address error. The issues you linked are specific to arm64e but not darwin vs ios. For me darwin works correctly so it must be some difference with ios and darwin in rust. Any ideas why the darwin one works but not ios?

Hmm, no, a guess could be that the linker is more restrictive on iOS? Or that LLVM's codegen is slightly different there?

@rustbot label O-ios

@rustbot rustbot added the O-ios Operating system: iOS label Apr 1, 2025
@ds-ep
Copy link
Author

ds-ep commented Apr 1, 2025

If i do a clean build targeting arm64e-apple-darwin it builds completely fine

Linker warnings are suppressed on Apple platforms. You likely still get the same warning and maybe it just falls back to building a non-arm64e dylib?

checked with file it spits out libinject.dylib: Mach-O 64-bit dynamically linked shared library arm64e

So I did some more digging the first issue on a clean build is due to building the build.rs for a dependency while SDKROOT is set and therefore it builds the build.rs which is meant to run on the host with the targets sysroot (unsure if there is a proper workaround for this) but building for arm64e-apple-darwin then for arm64e-apple-ios seems to work alright.

Ah, yeah, that's caused by #80817.

@madsmtm as for the second issue, I dont think the issues you mentioned are related. If i do a clean build targeting arm64e-apple-darwin it builds completely fine, but for arm64e-apple-ios i get this symbol not assigned an address error. The issues you linked are specific to arm64e but not darwin vs ios. For me darwin works correctly so it must be some difference with ios and darwin in rust. Any ideas why the darwin one works but not ios?

Hmm, no, a guess could be that the linker is more restrictive on iOS? Or that LLVM's codegen is slightly different there?

@rustbot label O-ios

too bad. might just put this project on the back burner for now. i really appreciate all the work you and others are putting in on the apple ecosystem, its pretty fun to work with rust and apple devices

@madsmtm
Copy link
Contributor

madsmtm commented Apr 1, 2025

If you're up for compiling rustc yourself, the following diff would probably "fix" it (i.e. revert it to what it was before):

diff --git i/compiler/rustc_codegen_ssa/src/back/apple.rs w/compiler/rustc_codegen_ssa/src/back/apple.rs
index 2c8b0ec418d..c32b73ae34f 100644
--- i/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ w/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -88,7 +88,7 @@ pub(super) fn add_data_and_relocation(
     kind: SymbolExportKind,
 ) -> object::write::Result<()> {
     let authenticated_pointer =
-        kind == SymbolExportKind::Text && target.llvm_target.starts_with("arm64e");
+        kind == SymbolExportKind::Text && target.llvm_target.starts_with("arm64e") && false;
 
     let data: &[u8] = match target.pointer_width {
         _ if authenticated_pointer => &[0, 0, 0, 0, 0, 0, 0, 0x80],

Alternatively, use an older nightly (rustup toolchain install nightly-2025-02-24 should work) (probably fine if you're using an older Xcode as well).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-AArch64 Armv8-A or later processors in AArch64 mode O-apple Operating system: Apple (macOS, iOS, tvOS, visionOS, watchOS) O-ios Operating system: iOS
Projects
None yet
Development

No branches or pull requests

4 participants