diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d5f227a84a4ca..3766501821957 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1837,6 +1837,7 @@ supported_targets! { ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700), ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs new file mode 100644 index 0000000000000..ac1bec02ec8ae --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -0,0 +1,38 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + // In QNX, libc does not provide a compatible ABI between versions. + // To distinguish between QNX versions, we needed a stable conditional compilation switch, + // which is why we needed to implement different targets in the compiler. + Target { + llvm_target: "aarch64-unknown-unknown".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARM64 QNX Neutrino 7.0 RTOS".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+v8a".into(), + max_atomic_width: Some(128), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntoaarch64le_cxx"], + ), + env: "nto70".into(), + ..base::nto_qnx::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 0e5a0b9b9a545..65a1863eb391a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,35 +1,8 @@ -use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::Target; pub fn target() -> Target { - Target { - llvm_target: "aarch64-unknown-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("ARM64 QNX Neutrino 7.1 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(true), - }, - pointer_width: 64, - // from: https://llvm.org/docs/LangRef.html#data-layout - // e = little endian - // m:e = ELF mangling: Private symbols get a .L prefix - // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 - // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 - // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 - // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 - // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. - // S128 = 128 bits are the natural alignment of the stack in bits. - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), - options: TargetOptions { - features: "+v8a".into(), - max_atomic_width: Some(128), - pre_link_args: TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-Vgcc_ntoaarch64le_cxx"], - ), - env: "nto71".into(), - ..base::nto_qnx::opts() - }, - } + let mut base = super::aarch64_unknown_nto_qnx700::target(); + base.metadata.description = Some("ARM64 QNX Neutrino 7.1 RTOS".into()); + base.options.env = "nto71".into(); + base } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5f0144922ca69..82cfd603a21e3 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.153", default-features = false, features = [ +libc = { version = "0.2.156", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fc9d7e988835e..7fa147c9754b9 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1717,7 +1717,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { run_path_with_cstr(original, &|original| { run_path_with_cstr(link, &|link| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nto"))] { // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves // it implementation-defined whether `link` follows symlinks, so rely on the // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5552e9ac97753..9d091f033e07f 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -19,7 +19,8 @@ use crate::sys::process::process_common::*; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { - if #[cfg(all(target_os = "nto", target_env = "nto71"))] { + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + if #[cfg(any(target_env = "nto70", target_env = "nto71"))] { use crate::thread; use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; use crate::time::Duration; @@ -189,7 +190,8 @@ impl Command { #[cfg(not(any( target_os = "watchos", target_os = "tvos", - all(target_os = "nto", target_env = "nto71"), + target_env = "nto70", + target_env = "nto71" )))] unsafe fn do_fork(&mut self) -> Result { cvt(libc::fork()) @@ -199,7 +201,8 @@ impl Command { // or closed a file descriptor while the fork() was occurring". // Documentation says "... or try calling fork() again". This is what we do here. // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + #[cfg(any(target_env = "nto70", target_env = "nto71"))] unsafe fn do_fork(&mut self) -> Result { use crate::sys::os::errno; @@ -537,7 +540,7 @@ impl Command { // or closed a file descriptor while the posix_spawn() was occurring". // Documentation says "... or try calling posix_spawn() again". This is what we do here. // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + #[cfg(target_os = "nto")] unsafe fn retrying_libc_posix_spawnp( pid: *mut pid_t, file: *const c_char, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index b3de71f29f394..250af912e072d 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -165,8 +165,15 @@ extern "C" {} extern "C" {} #[cfg(target_os = "nto")] -#[link(name = "gcc_s")] -extern "C" {} +cfg_if::cfg_if! { + if #[cfg(target_env = "nto70")] { + #[link(name = "gcc")] + extern "C" {} + } else { + #[link(name = "gcc_s")] + extern "C" {} + } +} #[cfg(target_os = "hurd")] #[link(name = "gcc_s")] diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0d79e5f4114e3..a2641b227531a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -256,6 +256,7 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | +[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 51a397a38d209..1c240d1255a3d 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -24,6 +24,7 @@ Currently, the following QNX Neutrino versions and compilation targets are suppo |----------------------|---------------------|:------------:|:----------------:| | 7.1 | AArch64 | ✓ | ✓ | | 7.1 | x86_64 | ✓ | ✓ | +| 7.0 | AArch64 | ? | ✓ | | 7.0 | x86 | | ✓ | Adding other architectures that are supported by QNX Neutrino is possible. @@ -43,6 +44,23 @@ When linking `no_std` applications, they must link against `libc.so` (see exampl required because applications always link against the `crt` library and `crt` depends on `libc.so`. This is done automatically when using the standard library. +### Disabling RELocation Read-Only (RELRO) + +While not recommended by default, some QNX kernel setups may require the `RELRO` to be disabled with `-C relro_level=off`, e.g. by adding it to the `.cargo/config.toml` file: + +```toml +[target.aarch64-unknown-nto-qnx700] +rustflags = ["-C", "relro_level=off"] +``` + +If your QNX kernel does not allow it, and `relro` is not disabled, running compiled binary would fail with `syntax error: ... unexpected` or similar. This is due to kernel trying to interpret compiled binary with `/bin/sh`, and obviously failing. To verify that this is really the case, run your binary with the `DL_DEBUG=all` env var, and look for this output. If you see it, you should disable `relro` as described above. + +```text +Resolution scope for Executable->/bin/sh: + Executable->/bin/sh + libc.so.4->/usr/lib/ldqnx-64.so.2 +``` + ### Small example application Small `no_std` example is shown below. Applications using the standard library work as well. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 6f0a200a08cf3..b0c5eec1fe490 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -54,6 +54,9 @@ //@ revisions: aarch64_unknown_none_softfloat //@ [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat //@ [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nto_qnx700 +//@ [aarch64_unknown_nto_qnx700] compile-flags: --target aarch64-unknown-nto-qnx700 +//@ [aarch64_unknown_nto_qnx700] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_nto_qnx710 //@ [aarch64_unknown_nto_qnx710] compile-flags: --target aarch64-unknown-nto-qnx710 //@ [aarch64_unknown_nto_qnx710] needs-llvm-components: aarch64