Skip to content

Commit 7cf0d6a

Browse files
committed
Add stack-reorder-contract template
1 parent 1d6d331 commit 7cf0d6a

File tree

8 files changed

+266
-0
lines changed

8 files changed

+266
-0
lines changed

cargo-generate.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
sub_templates = [
33
"contract",
44
"standalone-contract",
5+
"atomics-contract",
6+
"stack-reorder-contract",
57
"c-wrapper-crate",
68
"x64-simulator-crate",
79
"workspace",

stack-reorder-contract/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/build
2+
/target

stack-reorder-contract/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "{{project-name}}"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
ckb-std = "0.15.0"
8+
9+
[build-dependencies]
10+
cc = "1.0"

stack-reorder-contract/Makefile

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# We cannot use $(shell pwd), which will return unix path format on Windows,
2+
# making it hard to use.
3+
cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
4+
5+
TOP := $(cur_dir)
6+
# RUSTFLAGS that are likely to be tweaked by developers. For example,
7+
# while we enable debug logs by default here, some might want to strip them
8+
# for minimal code size / consumed cycles.
9+
CUSTOM_RUSTFLAGS := --cfg debug_assertions
10+
# RUSTFLAGS that are less likely to be tweaked by developers. Most likely
11+
# one would want to keep the default values here.
12+
FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs $(CUSTOM_RUSTFLAGS) \
13+
-C link-arg=-T$(cur_dir)ld_interface.ld
14+
# Additional cargo args to append here. For example, one can use
15+
# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to
16+
# stdout in unit tests
17+
CARGO_ARGS :=
18+
MODE := release
19+
# Tweak this to change the clang version to use for building C code. By default
20+
# we use a bash script with somes heuristics to find clang in current system.
21+
CLANG := $(shell $(TOP)/scripts/find_clang)
22+
# When this is set to some value, the generated binaries will be copied over
23+
BUILD_DIR :=
24+
# Generated binaries to copy. By convention, a Rust crate's directory name will
25+
# likely match the crate name, which is also the name of the final binary.
26+
# However if this is not the case, you can tweak this variable. As the name hints,
27+
# more than one binary is supported here.
28+
BINARIES := $(notdir $(shell pwd))
29+
30+
ifeq (release,$(MODE))
31+
MODE_ARGS := --release
32+
endif
33+
34+
default: build test
35+
36+
build:
37+
RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" \
38+
cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS)
39+
@set -eu; \
40+
if [ "x$(BUILD_DIR)" != "x" ]; then \
41+
for binary in $(BINARIES); do \
42+
echo "Copying binary $$binary to build directory"; \
43+
cp $(TOP)/target/riscv64imac-unknown-none-elf/$(MODE)/$$binary $(TOP)/$(BUILD_DIR); \
44+
done \
45+
fi
46+
47+
# This is a newly introduced task to allow adjusting stack size.
48+
# Notice there are also other changes required for a stack-reordering
49+
# contract, for example, FULL_RUSTFLAGS is also altered for new flags.
50+
# One can compare this file with the Makefile for minimal-log sample
51+
# for complete differences
52+
STACK_SIZE := 0x80000
53+
adjust_stack_size:
54+
$(TOP)/deps/ckb-stack-reorg-bootloader/regenerate $(STACK_SIZE) $(shell pwd)
55+
.PHONY: adjust_stack_size
56+
57+
# test, check, clippy and fmt here are provided for completeness,
58+
# there is nothing wrong invoking cargo directly instead of make.
59+
test:
60+
cargo test $(CARGO_ARGS)
61+
62+
check:
63+
cargo check $(CARGO_ARGS)
64+
65+
clippy:
66+
cargo clippy $(CARGO_ARGS)
67+
68+
fmt:
69+
cargo fmt $(CARGO_ARGS)
70+
71+
# Arbitrary cargo command is supported here. For example:
72+
#
73+
# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly"
74+
#
75+
# Invokes:
76+
# cargo expand --ugly
77+
CARGO_CMD :=
78+
cargo:
79+
cargo $(CARGO_CMD) $(CARGO_ARGS)
80+
81+
clean:
82+
cargo clean
83+
84+
prepare:
85+
rustup target add riscv64imac-unknown-none-elf
86+
87+
.PHONY: build test check clippy fmt cargo clean prepare

stack-reorder-contract/bootloader.S

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.global __ckb_bootloader_start
2+
__ckb_bootloader_start:
3+
li t4, (0x400000 - 0x80000) /* Difference between new & old stack region */
4+
mv t1, sp
5+
sub t2, t1, t4 /* t2 points to new stack, while t1 points to old stack */
6+
ld t0, 0(t1)
7+
sd zero, 0(t1)
8+
sd t0, 0(t2)
9+
addi t1, t1, 8
10+
addi t2, t2, 8
11+
/* Load and correct argv pointers */
12+
1:
13+
beqz t0, 2f
14+
ld t6, 0(t1)
15+
sub t6, t6, t4
16+
sd zero, 0(t1)
17+
sd t6, 0(t2)
18+
addi t1, t1, 8
19+
addi t2, t2, 8
20+
addi t0, t0, -1
21+
j 1b
22+
2:
23+
/*
24+
* Copy remaining data over to new stack, this is essentially a combination
25+
* of memcpy & memset, we do it this way so stack is not used at all.
26+
*/
27+
li t5, 0x400000
28+
3:
29+
bge t1, t5, 4f
30+
ld t6, 0(t1)
31+
sd zero, 0(t1)
32+
sd t6, 0(t2)
33+
addi t1, t1, 8
34+
addi t2, t2, 8
35+
j 3b
36+
4:
37+
/* Set new sp, clear used registers */
38+
sub sp, sp, t4
39+
li t0, 0
40+
li t1, 0
41+
li t2, 0
42+
li t4, 0
43+
li t5, 0
44+
li t6, 0
45+
/* TODO: setup the first page starting as address 0 as executable */
46+
/* Boot as usual */
47+
j _start

stack-reorder-contract/build.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
fn main() {
2+
println!("cargo:rerun-if-changed=bootloader.S");
3+
println!("cargo:rerun-if-changed=ld_interface.ld");
4+
5+
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
6+
if target_arch == "riscv64" {
7+
let mut build = cc::Build::new();
8+
assert!(
9+
build.get_compiler().is_like_clang(),
10+
"Clang must be used as the compiler!"
11+
);
12+
build
13+
.file("bootloader.S")
14+
.static_flag(true)
15+
.no_default_flags(true)
16+
.flag("--target=riscv64")
17+
.flag("-march=rv64imc_zba_zbb_zbc_zbs")
18+
.flag("-O3")
19+
.compile("bootloader");
20+
}
21+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
PHDRS {
2+
dummy PT_LOAD FLAGS(5) ;
3+
text PT_LOAD FLAGS(5) ;
4+
data PT_LOAD FLAGS(6) ;
5+
6+
relro PT_GNU_RELRO FLAGS(4) ;
7+
stack PT_GNU_STACK FLAGS(6) ;
8+
}
9+
10+
ENTRY(__ckb_bootloader_start)
11+
12+
SECTIONS {
13+
. = 0x0;
14+
.ckb.vm.dummy : ALIGN(0x1000) {
15+
BYTE(0)
16+
} : dummy
17+
18+
. = 0x80000;
19+
20+
.dynsym : {
21+
*(.dynsym)
22+
}
23+
.gnu.hash : {
24+
*(.gnu.hash)
25+
}
26+
.hash : {
27+
*(.hash)
28+
}
29+
.dynstr : {
30+
*(.dynstr)
31+
}
32+
.rela : {
33+
*(.rela)
34+
*(.rela.*)
35+
}
36+
37+
.text : ALIGN(0x1000) {
38+
*(.text)
39+
*(.text.*)
40+
} : text
41+
42+
.rodata : {
43+
*(.rodata)
44+
*(.rodata.*)
45+
} : text
46+
47+
.data : ALIGN(0x1000) {
48+
*(.data)
49+
*(.data.*)
50+
} : data
51+
52+
.dynamic : {
53+
*(.dynamic)
54+
} : data : dynamic
55+
56+
.data.rel.ro : ALIGN(0x1000) {
57+
*(.data.rel.ro)
58+
*(.data.rel.ro.*)
59+
} : relro
60+
61+
.bss : {
62+
*(.bss)
63+
*(.bss.*)
64+
}
65+
66+
.stack : {
67+
*(.stack)
68+
} : stack
69+
70+
_end = .; PROVIDE (end = .);
71+
}

stack-reorder-contract/src/main.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#![no_std]
2+
#![cfg_attr(not(test), no_main)]
3+
4+
#[cfg(test)]
5+
extern crate alloc;
6+
7+
#[cfg(not(test))]
8+
use ckb_std::default_alloc;
9+
#[cfg(not(test))]
10+
ckb_std::entry!(program_entry);
11+
#[cfg(not(test))]
12+
default_alloc!();
13+
14+
pub fn program_entry() -> i8 {
15+
let mut x: u64;
16+
unsafe {
17+
core::arch::asm!(
18+
"mv {x}, sp",
19+
x = out(reg) x,
20+
);
21+
}
22+
23+
ckb_std::debug!("Current SP is {:x}", x);
24+
25+
0
26+
}

0 commit comments

Comments
 (0)