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]

Reply via email to