Skip to content

Implement RISC-V dynamic linking#323

Draft
DrXiao wants to merge 4 commits intosysprog21:masterfrom
DrXiao:feat/dynlink-for-rv32
Draft

Implement RISC-V dynamic linking#323
DrXiao wants to merge 4 commits intosysprog21:masterfrom
DrXiao:feat/dynlink-for-rv32

Conversation

@DrXiao
Copy link
Copy Markdown
Collaborator

@DrXiao DrXiao commented Apr 23, 2026

The proposed changes primarily improve the ELF generation and the RISC-V backend, enabling the build system to generate a dynamically linked shecc targeting the RISC-V architecture.

Although the current changes allow both bootstrapping and test suite to complete successfully, this is still a work in progress. The TODO items are listed as follows:

  • Enhance code quality, comments and commit messages.
  • Confirm the RISC-V ABI compliance.
  • Add a new script (riscv-abi.sh) to validate the RISC-V ABI.
  • Improve the documentation and README.
  • Consolidate arm.mk and riscv.mk into a common build logic (e.g.: configure RUNNER_LD_PREFIX).
  • (Any new requirements ...)

Summary by cubic

Implements dynamic linking for RISC-V (rv32) with RELA-based PLT/GOT and ABI-compliant PLT generation; external calls go via PLT and startup uses __libc_start_main. CI and builds now validate dynamic rv32 and arm targets.

  • New Features

    • Enable RV32 dynamic linking with .rela.plt (RELA entries); PLT0=32B, PLT stubs=16B; RESERVED_GOT_NUM per-arch (RV32=2, ARM=3); DYN_LINKER set to /lib/ld-linux-riscv32-ilp32d.so.1.
    • Generate RV32 PLT per the ABI and call externs via PLT; entry uses __libc_start_main; 16-byte stack alignment and ra preservation; keep syscall trampoline for static builds.
    • ELF updates: select REL vs RELA via use_relaplt and ELF_MACHINE_* (ARM32, RV32); add .rela.plt buffer, correct dynamic tags (RELA/RELASZ/RELAENT/JMPREL/PLTREL/PLTRELSZ), and GOT init using RESERVED_GOT_NUM.
    • Build/test: allow DYNLINK=1 for RISC-V, add RV32 dynamic snapshots (hello, fib), and run static/dynamic matrices for ARM and RISC-V.
  • Dependencies

    • CI downloads a RISC-V glibc toolchain and adds /opt/riscv/bin to PATH; mk/riscv.mk auto-detects the sysroot and sets RUNNER_LD_PREFIX with -L <ld-linux path> under QEMU for dynamic runs.

Written for commit 44f2f47. Summary will update on new commits.

@DrXiao
Copy link
Copy Markdown
Collaborator Author

DrXiao commented Apr 23, 2026

As the apt package manager only provides a 64-bit RISC-V GNU cross-compilation toolchain, I utilize riscv-gnu-toolchain , which is a 32-bit variant, and leverage its artifacts for RISC-V dynamic linking development and validation.

The updated GitHub Actions also downloads the 32-bit variant to validate RISC-V dynamic linking.

@jserv
Copy link
Copy Markdown
Collaborator

jserv commented Apr 23, 2026

As the apt package manager only provides a 64-bit RISC-V GNU cross-compilation toolchain, I utilize riscv-gnu-toolchain , which is a 32-bit variant, and leverage its artifacts for RISC-V dynamic linking development and validation.
The updated GitHub Actions also downloads the 32-bit variant to validate RISC-V dynamic linking.

Evaluate Run 32-bit applications on 64-bit Linux kernel, which is exactly RV32-on-RV64 userspace compatibility, not emulation.

@DrXiao
Copy link
Copy Markdown
Collaborator Author

DrXiao commented Apr 24, 2026

Evaluate Run 32-bit applications on 64-bit Linux kernel, which is exactly RV32-on-RV64 userspace compatibility, not emulation.

I'm not sure whether I understand correctly. Do you mean that the proposed changes should be verified on a RISC-V machine?

@jserv
Copy link
Copy Markdown
Collaborator

jserv commented Apr 24, 2026

Do you mean that the proposed changes should be verified on a RISC-V machine?

See sysprog21/kbox#18
The RISE RISC-V Runners is a managed GitHub Actions runner service that executes CI/CD workflows on real RISC-V hardware.

DrXiao added 4 commits April 29, 2026 21:49
Introduce ELF_MACHINE_ARM32 (0x28) and ELF_MACHINE_RV32 (0xf3) to
support architecture-specific logic in future developments.
This commit primarily improves the ELF handling and code generator to
enable the compiler to produce a dynamically linked executable targeting
the RISC-V architecture.

- Allow the ELF handling to generate RELA relocation table.
  - Use REL relocation when the target architecture is Arm. Othereise,
    use RELA relocation for RISC-V.
- Improve GOT generation process.
  - Arm: reserve three entries.
  - RISC-V: reserve two entries.
- Implement PLT generation for RISC-V.
  - The generation process follows the RISC-V ABI. The first PLT entry
    uses 8 instructions to call '_dl_runtime_resolve'. The subsequent
    entry uses 4 instructions to perform an indirect function call via
    GOT.
- Refine the function call handling for the RISC-V code generator.
  - Perform a direct call for internal functions
  - Otherwise, use PLT table to peform an indirect call for external
    functions.
- Enhance the build system:
  - Allow the build system to generate dynamically linked compilers when
    targeting the RISC-V architecture.
  - Detect the sysroot path of the RISC-V GNU toolchain automatically.
Modify the 'update-snapshots' and 'check-snapshots' make targets to
include generation and validation of new snapshots for the RISC-V
architecture using dynamic linking.
The update workflow now downloads a RISC-V GNU toolchain to provide
necessary dependencies and validate the dynamically linked compiler
targeting the RISC-V architecture.
@DrXiao DrXiao force-pushed the feat/dynlink-for-rv32 branch from 446b538 to 44f2f47 Compare May 9, 2026 03:52
@DrXiao
Copy link
Copy Markdown
Collaborator Author

DrXiao commented May 9, 2026

RISE RISC-V Runners' documentation explicitly states that binaries must be compiled for riscv64. According to the FAQ - What architectures are supported?.

RISC-V 64-bit (riscv64) only. All runners execute on physical RISC-V hardware. There is no RISC-V emulation. Binaries must be compiled for riscv64.

I created another branch (feat/dynlink-for-rv32-test-rv64-runner) to verify if these RISC-V runners could support riscv32 binaries. However, the test result indicates that the runner failed to execute statically linked shecc.

Based on both the documentation and my test, it appears that RISE RISC-V runners lack support for 32-bit executables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants