Skip to content

Commit ed90272

Browse files
authored
Merge pull request #164 from nix-community/rust-2024
add riscv64 port
2 parents d4dd8ee + 2d81936 commit ed90272

File tree

4 files changed

+105
-3
lines changed

4 files changed

+105
-3
lines changed

flake.nix

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"i686-linux"
1212
"x86_64-linux"
1313
"aarch64-linux"
14+
"riscv64-linux"
1415
];
1516
lib = nixpkgs.lib;
1617
forAllSystems =
@@ -30,6 +31,10 @@
3031
nix-ld = pkgs.callPackage ./package.nix { };
3132
nolibc = pkgs.callPackage ./vendor/nolibc.nix { };
3233
default = self.packages.${system}.nix-ld;
34+
35+
# Cross-compiled package for riscv64 (only available on x86_64-linux)
36+
} // lib.optionalAttrs (system == "x86_64-linux") {
37+
nix-ld-riscv64 = pkgs.pkgsCross.riscv64.callPackage ./package.nix { };
3338
}
3439
);
3540

@@ -54,7 +59,7 @@
5459
);
5560

5661
devShells = forAllSystems (
57-
{ pkgs, ... }:
62+
{ pkgs, system, ... }:
5863
{
5964
nix-ld = pkgs.mkShell {
6065
nativeBuildInputs = [
@@ -64,6 +69,7 @@
6469
pkgs.cargo-bloat
6570
pkgs.cargo-nextest
6671
pkgs.just
72+
6773
];
6874

6975
hardeningDisable = [ "stackprotector" ];
@@ -73,7 +79,20 @@
7379
NIX_LD = pkgs.stdenv.cc.bintools.dynamicLinker;
7480

7581
RUSTC_BOOTSTRAP = "1";
82+
83+
shellHook = ''
84+
echo "nix-ld development environment"
85+
'' + lib.optionalString (system == "x86_64-linux") ''
86+
echo "Available cross-compilation shell:"
87+
echo " nix develop .#cross-riscv64 - Cross compile to riscv64"
88+
'';
7689
};
90+
91+
# Default cross shell for current system
92+
default = self.devShells.${system}.nix-ld;
93+
} // lib.optionalAttrs (system == "x86_64-linux") {
94+
# Cross compilation shell for riscv64 (only available on x86_64-linux)
95+
cross-riscv64 = pkgs.pkgsCross.riscv64.callPackage ./riscv64-shell.nix { };
7796
}
7897
);
7998
}

riscv64-shell.nix

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{ mkShell
2+
, rustc
3+
, cargo
4+
, cargo-watch
5+
, cargo-bloat
6+
, cargo-nextest
7+
, just
8+
, stdenv
9+
, qemu
10+
}:
11+
12+
mkShell {
13+
nativeBuildInputs = [
14+
rustc
15+
cargo
16+
cargo-watch
17+
cargo-bloat
18+
cargo-nextest
19+
just
20+
qemu
21+
];
22+
23+
hardeningDisable = [ "stackprotector" ];
24+
25+
RUSTC_BOOTSTRAP = "1";
26+
27+
# Cross compilation environment
28+
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
29+
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER = "qemu-riscv64 -L /";
30+
CC_riscv64gc_unknown_linux_gnu = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
31+
NIX_LD_TEST_TARGET = "riscv64gc-unknown-linux-gnu";
32+
NIX_LD = "${stdenv.cc.libc}/lib/ld-linux-riscv64-lp64d.so.1";
33+
TARGET_CC = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
34+
35+
shellHook = ''
36+
echo "RISC-V 64-bit cross-compilation environment"
37+
echo "Target: riscv64gc-unknown-linux-gnu"
38+
echo "Cross compiler: ${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"
39+
echo "Usage:"
40+
echo " cargo build --target riscv64gc-unknown-linux-gnu"
41+
echo " cargo test --target riscv64gc-unknown-linux-gnu"
42+
'';
43+
}

src/arch.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub const EM_SELF: u16 = {
2626
const VALUE: u16 = EM_386;
2727
#[cfg(target_arch = "aarch64")]
2828
const VALUE: u16 = EM_AARCH64;
29+
#[cfg(target_arch = "riscv64")]
30+
const VALUE: u16 = EM_RISCV;
2931
VALUE
3032
};
3133

@@ -37,6 +39,8 @@ pub const R_RELATIVE: u32 = {
3739
const VALUE: u32 = R_386_RELATIVE;
3840
#[cfg(target_arch = "aarch64")]
3941
const VALUE: u32 = R_AARCH64_RELATIVE;
42+
#[cfg(target_arch = "riscv64")]
43+
const VALUE: u32 = R_RISCV_RELATIVE;
4044
VALUE
4145
};
4246

@@ -49,6 +53,8 @@ pub const NIX_SYSTEM: &str = match option_env!("NIX_SYSTEM") {
4953
const VALUE: &str = "i686_linux";
5054
#[cfg(target_arch = "aarch64")]
5155
const VALUE: &str = "aarch64_linux";
56+
#[cfg(target_arch = "riscv64")]
57+
const VALUE: &str = "riscv64_linux";
5258
VALUE
5359
}
5460
};
@@ -70,6 +76,8 @@ macro_rules! main_relocate_stack {
7076
core::arch::asm!("mov esp, {}; call {}", in(reg) $sp, sym $func, options(noreturn));
7177
#[cfg(target_arch = "aarch64")]
7278
core::arch::asm!("mov sp, {}; bl {}", in(reg) $sp, sym $func, options(noreturn));
79+
#[cfg(target_arch = "riscv64")]
80+
core::arch::asm!("mv sp, {}; call {}", in(reg) $sp, sym $func, options(noreturn));
7381
};
7482
}
7583
pub(crate) use main_relocate_stack;
@@ -82,6 +90,8 @@ macro_rules! elf_jmp {
8290
core::arch::asm!("mov esp, {}; jmp {}", in(reg) $sp, in(reg) $target, options(noreturn));
8391
#[cfg(target_arch = "aarch64")]
8492
core::arch::asm!("mov sp, {}; br {}", in(reg) $sp, in(reg) $target, options(noreturn));
93+
#[cfg(target_arch = "riscv64")]
94+
core::arch::asm!("mv sp, {}; jr {}", in(reg) $sp, in(reg) $target, options(noreturn));
8595
};
8696
}
8797
pub(crate) use elf_jmp;
@@ -131,6 +141,9 @@ pub const ENTRY_TRAMPOLINE: Option<unsafe extern "C" fn() -> !> = None;
131141
#[cfg(target_arch = "x86_64")]
132142
pub const ENTRY_TRAMPOLINE: Option<unsafe extern "C" fn() -> !> = Some(entry_trampoline);
133143

144+
#[cfg(target_arch = "riscv64")]
145+
pub const ENTRY_TRAMPOLINE: Option<unsafe extern "C" fn() -> !> = Some(entry_trampoline);
146+
134147
#[cfg(target_arch = "x86_64")]
135148
#[naked]
136149
unsafe extern "C" fn entry_trampoline() -> ! {
@@ -173,13 +186,36 @@ unsafe extern "C" fn entry_trampoline() -> ! {
173186
}
174187
}
175188

189+
#[cfg(target_arch = "riscv64")]
190+
#[naked]
191+
unsafe extern "C" fn entry_trampoline() -> ! {
192+
unsafe {
193+
core::arch::naked_asm!(
194+
"1:",
195+
"auipc t0, %pcrel_hi({context})",
196+
"addi t0, t0, %pcrel_lo(1b)",
197+
"ld t1, {env_entry_off}(t0)", // .env_entry
198+
"beqz t1, 2f",
199+
"ld t2, {env_string_off}(t0)", // .env_string
200+
"sd t2, 0(t1)",
201+
"2:",
202+
"ld t0, 0(t0)",
203+
"jr t0",
204+
context = sym TRAMPOLINE_CONTEXT,
205+
env_entry_off = const TrampolineContext::ENV_ENTRY_OFFSET,
206+
env_string_off = const TrampolineContext::ENV_STRING_OFFSET,
207+
)
208+
}
209+
}
210+
176211
// !!!!
177212
// After adding a trampoline, remember to enable test_ld_path_restore for
178213
// the target_arch in tests/tests.rs as well
179214
// !!!!
180215
#[cfg(all(
181216
feature = "entry_trampoline",
182217
not(target_arch = "x86_64"),
183-
not(target_arch = "aarch64")
218+
not(target_arch = "aarch64"),
219+
not(target_arch = "riscv64")
184220
))]
185221
pub const ENTRY_TRAMPOLINE: Option<unsafe extern "C" fn() -> !> = None;

tests/tests.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@ fn test_dlopen(libtest: &str) {
8484
/// Check that LD_LIBRARY_PATH is restored.
8585
#[cfg(all(
8686
feature = "entry_trampoline",
87-
any(target_arch = "x86_64", target_arch = "aarch64")
87+
any(
88+
target_arch = "x86_64",
89+
target_arch = "aarch64",
90+
target_arch = "riscv64"
91+
)
8892
))]
8993
#[rstest]
9094
fn test_ld_path_restore(libtest: &str, _dt_needed_bin: &Path) {

0 commit comments

Comments
 (0)