Auto merge of #127897 - nyurik:add-qnx-70-target, r=saethlin
add `aarch64_unknown_nto_qnx700` target - QNX 7.0 support for aarch64le This backports the QNX 7.1 aarch64 implementation to 7.0. * [x] required `-lregex` disabled, see https://github.com/rust-lang/libc/pull/3775 (released in libc 0.2.156) * [x] uses `libgcc.a` instead of `libgcc_s.so` (7.0 used ancient GCC 5.4 which didn't have gcc_s) * [x] a fix in `backtrace` crate to support stack traces https://github.com/rust-lang/backtrace-rs/pull/648 This PR bumps libc dependency to 0.2.158 CC: to the folks who did the [initial implementation](https://doc.rust-lang.org/rustc/platform-support/nto-qnx.html): `@flba-eb,` `@gh-tr,` `@jonathanpallant,` `@japaric` # Compile target ```bash # Configure qcc build environment source _path_/_to_/qnx7.0/qnxsdp-env.sh # Tell rust to use qcc when building QNX 7.0 targets export build_env=' CC_aarch64-unknown-nto-qnx700=qcc CFLAGS_aarch64-unknown-nto-qnx700=-Vgcc_ntoaarch64le_cxx CXX_aarch64-unknown-nto-qnx700=qcc AR_aarch64_unknown_nto_qnx700=ntoaarch64-ar' # Build rust compiler, libs, and the remote test server env $build_env ./x.py build \ --target x86_64-unknown-linux-gnu,aarch64-unknown-nto-qnx700 \ rustc library/core library/alloc library/std src/tools/remote-test-server rustup toolchain link stage1 build/host/stage1 ``` # Compile "hello world" ```bash source _path_/_to_/qnx7.0/qnxsdp-env.sh cargo new hello_world cd hello_world cargo +stage1 build --release --target aarch64-unknown-nto-qnx700 ``` # Configure a remote for testing Do this from a new shell - we will need to run more commands in the previous one. I ran into these two issues, and found some workarounds. * Temporary dir might not work properly * Default `remote-test-server` has issues binding to an address ``` # ./remote-test-server starting test server thread 'main' panicked at src/tools/remote-test-server/src/main.rs:175:29: called `Result::unwrap()` on an `Err` value: Os { code: 249, kind: AddrNotAvailable, message: "Can't assign requested address" } note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` Specifying `--bind` param actually fixes that, and so does setting `TMPDIR` properly. ```bash # Copy remote-test-server to remote device. You may need to use sftp instead. # ATTENTION: Note that the path is different from the one in the remote testing documentation for some reason scp ./build/x86_64-unknown-linux-gnu/stage1-tools-bin/remote-test-server qnxdevice:/path/ # Run ssh with port forwarding - so that rust tester can connect to the local port instead ssh -L 12345:127.0.0.1:12345 qnxdevice # on the device, run rm -rf tmp && mkdir -p tmp && TMPDIR=$PWD/tmp ./remote-test-server --bind 0.0.0.0:12345 ``` # Run test suit Assume all previous environment variables are still set, or re-init them ```bash export TEST_DEVICE_ADDR="localhost:12345" # tidy needs to be skipped due to using un-published libc dependency export exclude_tests=' --exclude src/bootstrap --exclude src/tools/error_index_generator --exclude src/tools/linkchecker --exclude src/tools/tidy --exclude tests/ui-fulldeps --exclude rustc --exclude rustdoc --exclude tests/run-make-fulldeps' env $build_env ./x.py test $exclude_tests --stage 1 --target aarch64-unknown-nto-qnx700 ``` try-job: dist-x86_64-msvc
This commit is contained in:
commit
1a1cc050d8
@ -1837,6 +1837,7 @@ fn $module() {
|
||||
|
||||
("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),
|
||||
|
@ -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()
|
||||
},
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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.
|
||||
|
@ -19,7 +19,8 @@
|
||||
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 @@ unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
|
||||
#[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<pid_t, io::Error> {
|
||||
cvt(libc::fork())
|
||||
@ -199,7 +201,8 @@ unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
|
||||
// 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<pid_t, io::Error> {
|
||||
use crate::sys::os::errno;
|
||||
|
||||
@ -537,7 +540,7 @@ fn pidfd_spawnp(
|
||||
// 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,
|
||||
|
@ -165,8 +165,15 @@
|
||||
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")]
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user