Skip to content

tools/ci: Add the FDPIC binutils to the Linux CI image. - #19992

Merged
acassis merged 1 commit into
apache:masterfrom
casaroli:ci-fdpic-binutils
Aug 28, 2026
Merged

tools/ci: Add the FDPIC binutils to the Linux CI image.#19992
acassis merged 1 commit into
apache:masterfrom
casaroli:ci-fdpic-binutils

Conversation

@casaroli

Copy link
Copy Markdown
Contributor

Summary

FDPIC modules cannot be built anywhere CI can reach, because the linker they need is not packaged by any distribution. This adds it to the Linux CI image so that the FDPIC module build can be integrated into the normal in-tree ELF build rather than living in a separate out-of-tree toolchain, which is what was asked for in the review of #19940.

An FDPIC module is compiled by the stock arm-none-eabi GCC, which emits correct FDPIC objects for both C and C++. What that toolchain cannot do is assemble or link them: its as rejects the FDPIC relocations, and its ld is configured with the armelf emulation alone.

Linking FDPIC objects with the stock ld anyway does not fail, which is the awkward part. It produces an object marked UNIX - System V instead of ARM FDPIC, and turns every import into an R_ARM_JUMP_SLOT where the ABI wants an R_ARM_FUNCDESC_VALUE. A jump slot is one word and a descriptor is two, a code address and the GOT that goes with it, so such a module links cleanly and then calls out of itself with the caller's data base still in the PIC register.

So the image builds arm-uclinuxfdpiceabi binutils in its own stage, the way the Renesas stage already builds its own binutils. Only binutils is needed, no GCC and no C library.

The tarball comes from sourceware.org, the binutils project's own host, because ftp.gnu.org is not reliably reachable from every builder. curl runs with --fail so a bad fetch says so, rather than piping an error page into tar and failing as File format not recognized, which is what happened while writing this.

Impact

Build infrastructure only. No target code, no configuration, no documentation.

The image grows by 20 MB, stripped, and the stage takes about 35 seconds. For scale, gcc-arm-none-eabi in the same image is several hundred megabytes.

Nothing in the tree uses the new toolchain yet. It is a prerequisite for the FDPIC module build, which follows.

Testing

Host: macOS 15 on Apple Silicon, Docker 29.4.0.

The stage was built on its own and the result exercised in a container.

The linker carries the emulation that the stock one does not:

$ docker run --rm nuttx-fdpic-binutils arm-uclinuxfdpiceabi-ld -V
GNU ld (GNU Binutils) 2.43
  Supported emulations:
   armelf_linux_eabi
   armelfb_linux_eabi
   armelf_linux_fdpiceabi
   armelfb_linux_fdpiceabi

against the stock toolchain, which is the failure this exists to prevent:

$ arm-none-eabi-ld -V
GNU ld (Arm GNU Toolchain 15.3.Rel1) 2.45.1
  Supported emulations:
   armelf

Linking a C++ module inside the container, one with a static global object, gives a correct FDPIC shared object:

OS/ABI:                            ARM FDPIC
Type:                              DYN (Shared object file)
Entry point address:               0x2b9
FUNCDESC relocations: 3
 0x00000019 (INIT_ARRAY)                 0x1328
 0x0000001b (INIT_ARRAYSZ)               4 (bytes)

The same objects linked with the stock arm-none-eabi-ld link without error and produce OS/ABI: UNIX - System V with three R_ARM_JUMP_SLOT entries instead, which is the silent breakage described above.

Installed size in the image:

$ docker run --rm nuttx-fdpic-binutils du -sh /tools/binutils-arm-uclinuxfdpiceabi
20M	/tools/binutils-arm-uclinuxfdpiceabi

tools/checkpatch.sh -c -u -m -g passes.

An FDPIC module is compiled by the stock arm-none-eabi GCC, which emits
correct FDPIC objects for both C and C++, but it cannot be assembled or
linked by that toolchain: its as rejects the FDPIC relocations, and its ld
carries the armelf emulation alone.

Linking FDPIC objects with the stock ld does not fail, which is the awkward
part.  It produces an object marked "UNIX - System V" instead of "ARM FDPIC"
and turns every import into an R_ARM_JUMP_SLOT where the ABI wants an
R_ARM_FUNCDESC_VALUE.  A jump slot is one word and a descriptor is two, a
code address and the GOT that goes with it, so the module links cleanly and
then calls out of itself with the caller's data base still in the PIC
register.

No distribution packages the arm-uclinuxfdpiceabi target, so the image
builds it, the way the Renesas stage already builds its own binutils.  Only
binutils is needed, no GCC and no C library, so the stage takes about a
minute and the install is 20 MB stripped.

The tarball comes from sourceware.org, the binutils project's own host,
because ftp.gnu.org is not reliably reachable from every builder.  curl runs
with --fail so that a bad fetch says so, rather than piping an error page
into tar and failing as "File format not recognized".

Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@github-actions github-actions Bot added Area: CI Size: S The size of the change in this PR is small labels Aug 28, 2026
@acassis
acassis merged commit 34f25ed into apache:master Aug 28, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: CI Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants