cjj66619 opened a new pull request, #18888:
URL: https://github.com/apache/nuttx/pull/18888
… host
boards/sim: skip -no-pie on HOST_ARM64 to fix sim:nsh link on aarch64 host
boards/sim/sim/sim/scripts/Make.defs adds `-no-pie` to ARCHCFLAGS /
ARCHPICFLAGS / LDFLAGS for every 64-bit non-Mac sim build. The original
comment ("To compile 64-bit Sim, adding no-pie is necessary to prevent linking
errors but this may cause other issues on Ubuntu 20.") already flagged the
workaround as fragile.
On HOST_ARM64 the option is in fact actively harmful. When gcc is asked to
produce a non-PIE executable on aarch64 it switches the libgcc resolution path
from the dynamic library
`libgcc_s.so.1` to the static archive `libgcc_s.a`. Ubuntu's arm64
toolchain (and Debian / Raspbian arm64) **does not ship** `libgcc_s.a` (only
`libgcc_s.so.1`), so the link aborts with:
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s (push-state / as-needed both fail)
collect2: error: ld returned 1 exit status
`ld --verbose` shows ld searching 20+ paths for `libgcc_s.a`, finding only
`libgcc_s.so` (a linker script pointing at `libgcc_s.so.1`) which is invalid in
non-PIE mode.
x86_64 Linux is unaffected because Ubuntu ships the static `libgcc_s.a` (or
a compatible static-fallback library) in its amd64 libgcc-N-dev packaging.
macOS, Windows and Cygwin go through completely different code paths and never
reach this branch.
Gate the existing `-no-pie` block with `ifneq ($(CONFIG_HOST_ARM64),y)` so
aarch64 hosts fall through to gcc's default PIE-aware link path, which works
correctly. The default text-segment placement `-Ttext-segment=0x40000000` and
`-Wl,--gc-sections` (set in the common LDFLAGS just above this block) are
honored regardless of PIE / non-PIE.
Verified on NVIDIA Jetson Orin (Ubuntu 20.04 L4T, GCC 9.4) and Raspberry Pi
4B (Debian 13 trixie, GCC 14.2):
$ ./build.sh sim:nsh -j$(nproc)
$ ./nuttx
NuttShell (NSH)
nsh> ostest
... [38 user_main stages, 14 PASS, 0 FAIL] ...
ostest_main: Exiting with status 0
x86_64 Linux behaviour is unchanged (the `ifneq` is false there, so the
block is taken exactly as before).
Companion patch: arch/sim: rename nuttx libc memchr to avoid host glibc
collision (independent fix needed on the same aarch64 hosts).
# Summary
`boards/sim/sim/sim/scripts/Make.defs` unconditionally adds `-no-pie` /
`-Wl,-no-pie` to every 64-bit non-macOS sim build (line 322-328). The block's
own comment already flags it as fragile: _"To compile 64-bit Sim, adding no-pie
is necessary to prevent linking errors but **this may cause other issues on
Ubuntu 20.**"_ On **Ubuntu / Debian aarch64 hosts** this workaround is in fact
actively broken — the build cannot link because gcc switches to looking for the
static `libgcc_s.a` library which the Ubuntu/Debian arm64 toolchain does not
ship.
This PR gates the existing `-no-pie` block on `!CONFIG_HOST_ARM64`,
restoring sim:nsh build / run capability on aarch64 Linux hosts. x86_64
behaviour is byte-identical.
## Impact
- Affects every sim defconfig (`sim:nsh`, `sim:nsh2`, `sim:smp`,
`sim:bluetooth`, `sim:binder`, `sim:matter`, ...) on a Linux **aarch64** host.
- Concrete environments reproduced: Ubuntu 20.04 L4T (NVIDIA Jetson Orin)
and Debian 13 trixie (Raspberry Pi 4B).
- ARM64-based developer workstations (Apple M1/M2 running Linux VMs, Ampere
Altra, AWS Graviton, etc.) are also affected.
## Root Cause
1. `Make.defs:322-328` adds `ARCHCFLAGS += -no-pie`, `ARCHPICFLAGS +=
-no-pie`, `LDFLAGS += -Wl,-no-pie` whenever (a) sim is 64-bit, (b) host is not
macOS.
2. `-no-pie` causes gcc's collect2 spec to inject the libgcc resolution from
the **non-PIE** branch of the spec — which on aarch64 attempts to link against
the **static** `libgcc_s.a`.
3. Ubuntu / Debian arm64 packaging ships **only** the dynamic library
(`libgcc_s.so.1`) and a linker-script alias
(`/usr/lib/gcc/aarch64-linux-gnu/9/libgcc_s.so` → `GROUP ( libgcc_s.so.1 -lgcc
)`). There is no `libgcc_s.a`.
4. The link fails with `cannot find -lgcc_s` after ld searches 20+ standard
paths.
```
$ cc -v -fno-pic -mcmodel=large -Wl,-no-pie -o dummy dummy.c
... (collect2 invocation includes -lgcc_s but ld can't find static .a)
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
```
Same `cc` command without `-Wl,-no-pie` succeeds and produces a valid PIE
executable.
## Fix
Wrap the existing 3-line block in `ifneq ($(CONFIG_HOST_ARM64),y)`, with a
comment explaining the aarch64-host packaging mismatch:
```
else ifeq ($(CONFIG_HOST_MACOS),)
+ifneq ($(CONFIG_HOST_ARM64),y)
# To compile 64-bit Sim, adding no-pie is necessary to prevent linking
errors
# but this may cause other issues on Ubuntu 20.
+ # NOTE: On HOST_ARM64 (Ubuntu aarch64), -no-pie forces ld to look for the
+ # static libgcc_s.a which is not packaged on Ubuntu's arm64 toolchain
+ # (only the shared libgcc_s.so.1 ships). Skipping -no-pie lets gcc use
+ # the default PIE link path which works correctly on aarch64.
ARCHCFLAGS += -no-pie
ARCHPICFLAGS += -no-pie
LDFLAGS += -Wl,-no-pie
endif
+endif
```
After the patch aarch64 hosts fall through to gcc's default PIE link path,
which works correctly. The default text-segment placement
`-Ttext-segment=0x40000000` and `-Wl,--gc-sections` (set in the common LDFLAGS
above) are honored regardless of PIE / non-PIE.
## Test results
| Platform | Status |
|---|---|
| NVIDIA Jetson Orin (Ubuntu 20.04 L4T aarch64, GCC 9.4) | `sim:nsh` clean
build, NSH prompt, 18.2 ms median boot, `ostest` 38 stages PASS |
| Raspberry Pi 4B (Debian 13 trixie aarch64, GCC 14.2) | Jetson binary
cross-runs ✅, `ostest` 38 stages PASS |
| x86_64 Linux | `ifneq` is false → block taken unchanged → behaviour
byte-identical |
Detailed reproduction log + ld trace + bytecount diff in
[`test-report.md`](test-report.md).
## Companion patch
This patch alone is not sufficient to build `sim:nsh` on Ubuntu aarch64
hosts; the `nuttx.rel` link also collides on the unrenamed nuttx-libc `memchr`.
See companion PR: **`arch/sim: rename nuttx libc memchr to avoid host glibc
collision`** (single-line addition to `arch/sim/src/nuttx-names.in`).
The two PRs are independently mergeable — each fix is a strict subset
narrowing of an existing failure mode — but on aarch64 hosts you need both to
get a working sim binary.
## checkpatch
`tools/checkpatch.sh -f boards/sim/sim/sim/scripts/Make.defs` → ✔️ All
checks pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]