mirror of
https://github.com/eth-act/ere.git
synced 2026-02-19 11:54:42 -05:00
Use zksync-os linker scripts (#178)
This commit is contained in:
@@ -92,6 +92,6 @@ where
|
||||
fn assert_output(&self, public_values: &[u8]) {
|
||||
let output = T::Program::compute(self.inner.clone());
|
||||
let digest = D::digest(T::Program::io_serde().serialize(&output).unwrap());
|
||||
assert_eq!(digest.as_slice(), public_values)
|
||||
assert_eq!(&*digest, public_values)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ impl AirbenderSdk {
|
||||
if !output.status.success() {
|
||||
return Err(AirbenderError::AirbenderRunFailed {
|
||||
status: output.status,
|
||||
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copied from https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/scripts/lds/link.x */
|
||||
/* Copied from https://github.com/matter-labs/zksync-os/blob/main/zksync_os/src/lds/link.x */
|
||||
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
@@ -41,6 +41,7 @@ PROVIDE(_machine_start_trap = machine_default_start_trap);
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
bss PT_LOAD;
|
||||
}
|
||||
@@ -66,17 +67,6 @@ SECTIONS
|
||||
*(.text .text.*);
|
||||
} > REGION_TEXT AT > REGION_TEXT :text
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
*(.srodata .srodata.*);
|
||||
*(.rodata .rodata.*);
|
||||
|
||||
/* 4-byte align the end (VMA) of this section.
|
||||
This is required by LLD to ensure the LMA of the following
|
||||
section will have the correct alignment. */
|
||||
. = ALIGN(4);
|
||||
} > REGION_RODATA AT > REGION_RODATA :text
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack ORIGIN(REGION_STACK) (NOLOAD) : ALIGN(4096)
|
||||
{
|
||||
@@ -86,6 +76,21 @@ SECTIONS
|
||||
_sstack = .;
|
||||
} > REGION_STACK
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_sirodata = LOADADDR(.rodata);
|
||||
_srodata = .;
|
||||
*(.srodata .srodata.*);
|
||||
*(.rodata .rodata.*);
|
||||
|
||||
/* 4-byte align the end (VMA) of this section.
|
||||
This is required by LLD to ensure the LMA of the following
|
||||
section will have the correct alignment. */
|
||||
. = ALIGN(4);
|
||||
|
||||
_erodata = .;
|
||||
} > REGION_RODATA AT > REGION_RODATAINIT :rodata
|
||||
|
||||
.data : ALIGN(4096)
|
||||
{
|
||||
_sidata = LOADADDR(.data);
|
||||
@@ -132,6 +137,9 @@ SECTIONS
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_RODATAINIT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_RODATAINIT must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
|
||||
@@ -153,6 +161,12 @@ ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
|
||||
ASSERT(_stext % 4 == 0, "
|
||||
ERROR(riscv-rt): `_stext` must be 4-byte aligned");
|
||||
|
||||
ASSERT(_srodata % 4 == 0 && _erodata % 4 == 0, "
|
||||
BUG(riscv-rt): .rodata is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sirodata % 4 == 0, "
|
||||
BUG(riscv-rt): the LMA of .rodata is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
|
||||
BUG(riscv-rt): .data is not 4-byte aligned");
|
||||
|
||||
@@ -169,6 +183,10 @@ ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
/* ASSERT(_sirodata + SIZEOF(.rodata) < ORIGIN(REGION_RODATAINIT) + LENGTH(REGION_RODATAINIT), "
|
||||
ERROR(riscv-rt): The init data for .rodata section must be placed inside the REGION_RODATAINIT region.
|
||||
Set _sirodata to an address smaller than 'ORIGIN(REGION_RODATAINIT) + LENGTH(REGION_RODATAINIT)'"); */
|
||||
|
||||
ASSERT(_sidata + SIZEOF(.data) < ORIGIN(REGION_DATAINIT) + LENGTH(REGION_DATAINIT), "
|
||||
ERROR(riscv-rt): The init data for .data section must be placed inside the REGION_DATAINIT region.
|
||||
Set _sidata to an address smaller than 'ORIGIN(REGION_DATAINIT) + LENGTH(REGION_DATAINIT)'");
|
||||
@@ -184,10 +202,4 @@ then modify your build script to compile the C code _without_ the
|
||||
-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
|
||||
details.");
|
||||
|
||||
ASSERT(SIZEOF(.data) == 0, "
|
||||
.data section detected in the input files. Global variables with non-trivial
|
||||
initialization are not supported yet. Variables with zero-initialization can be
|
||||
linked to .bss section instead, as the platform guarantees zero-initialization
|
||||
of all RAM space.");
|
||||
|
||||
/* Do not exceed this mark in the error messages above | */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copied from https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/scripts/lds/memory.x */
|
||||
/* Copied from https://github.com/matter-labs/zksync-os/blob/main/zksync_os/src/lds/memory.x */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
@@ -7,9 +7,10 @@ MEMORY
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_TEXT", ROM);
|
||||
REGION_ALIAS("REGION_RODATA", ROM);
|
||||
REGION_ALIAS("REGION_DATAINIT", ROM);
|
||||
REGION_ALIAS("REGION_RODATAINIT", ROM);
|
||||
REGION_ALIAS("REGION_STACK", RAM);
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_RODATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_HEAP", RAM);
|
||||
REGION_ALIAS("REGION_HEAP", RAM);
|
||||
@@ -42,8 +42,8 @@ pub enum AirbenderError {
|
||||
// Execution
|
||||
#[error("Failed to execute `airbender-cli run`: {0}")]
|
||||
AirbenderRun(#[source] io::Error),
|
||||
#[error("`airbender-cli run` failed with status: {status}")]
|
||||
AirbenderRunFailed { status: ExitStatus },
|
||||
#[error("`airbender-cli run` failed with status: {status}\nstderr: {stderr}")]
|
||||
AirbenderRunFailed { status: ExitStatus, stderr: String },
|
||||
#[error("Failed to parse public value from stdout: {0}")]
|
||||
ParsePublicValue(String),
|
||||
#[error("Failed to parse cycles from stdout: {0}")]
|
||||
|
||||
@@ -253,10 +253,9 @@ mod tests {
|
||||
use ere_zkvm_interface::{Compiler, NetworkProverConfig, ProofKind, ProverResourceType, zkVM};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
static BASIC_PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PROGRAM
|
||||
static PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
PROGRAM
|
||||
.get_or_init(|| {
|
||||
RustRv32imaCustomized
|
||||
.compile(&testing_guest_directory("sp1", "basic"))
|
||||
|
||||
@@ -149,10 +149,9 @@ mod tests {
|
||||
use ere_zkvm_interface::{Compiler, ProofKind, ProverResourceType, zkVM};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
static BASIC_PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PROGRAM
|
||||
static PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
PROGRAM
|
||||
.get_or_init(|| {
|
||||
RustMips32r2Customized
|
||||
.compile(&testing_guest_directory("ziren", "basic"))
|
||||
|
||||
@@ -132,10 +132,9 @@ mod tests {
|
||||
/// so we have a lock to avoid that.
|
||||
static PROVE_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
static BASIC_PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
|
||||
fn basic_program() -> Vec<u8> {
|
||||
BASIC_PROGRAM
|
||||
static PROGRAM: OnceLock<Vec<u8>> = OnceLock::new();
|
||||
PROGRAM
|
||||
.get_or_init(|| {
|
||||
RustRv64imaCustomized
|
||||
.compile(&testing_guest_directory("zisk", "basic"))
|
||||
|
||||
@@ -1,17 +1,53 @@
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use core::{
|
||||
alloc::{GlobalAlloc, Layout},
|
||||
ptr::addr_of_mut,
|
||||
};
|
||||
|
||||
core::arch::global_asm!(include_str!("./asm_reduced.S"));
|
||||
|
||||
#[link_section = ".init.rust"]
|
||||
#[export_name = "_start_rust"]
|
||||
unsafe extern "C" {
|
||||
// Boundaries of the heap
|
||||
static mut _sheap: usize;
|
||||
static mut _eheap: usize;
|
||||
|
||||
// Boundaries of the .data section (and it's part in ROM)
|
||||
static mut _sidata: usize;
|
||||
static mut _sdata: usize;
|
||||
static mut _edata: usize;
|
||||
|
||||
// Boundaries of the .rodata section
|
||||
static mut _sirodata: usize;
|
||||
static mut _srodata: usize;
|
||||
static mut _erodata: usize;
|
||||
}
|
||||
|
||||
unsafe fn load_to_ram(src: *const u8, dst_start: *mut u8, dst_end: *mut u8) {
|
||||
let offset = dst_end.addr() - dst_start.addr();
|
||||
|
||||
unsafe { core::ptr::copy_nonoverlapping(src, dst_start, offset) };
|
||||
}
|
||||
|
||||
#[unsafe(link_section = ".init.rust")]
|
||||
#[unsafe(export_name = "_start_rust")]
|
||||
unsafe extern "C" fn start_rust() -> ! {
|
||||
unsafe {
|
||||
load_to_ram(
|
||||
addr_of_mut!(_sirodata) as *const u8,
|
||||
addr_of_mut!(_srodata) as *mut u8,
|
||||
addr_of_mut!(_erodata) as *mut u8,
|
||||
);
|
||||
load_to_ram(
|
||||
addr_of_mut!(_sidata) as *const u8,
|
||||
addr_of_mut!(_sdata) as *mut u8,
|
||||
addr_of_mut!(_edata) as *mut u8,
|
||||
);
|
||||
};
|
||||
|
||||
crate::main();
|
||||
|
||||
unsafe { core::hint::unreachable_unchecked() }
|
||||
}
|
||||
|
||||
/// A simple heap allocator.
|
||||
///
|
||||
/// Allocates memory from left to right, without any deallocation.
|
||||
struct SimpleAlloc;
|
||||
|
||||
unsafe impl GlobalAlloc for SimpleAlloc {
|
||||
@@ -29,17 +65,10 @@ static mut HEAP_POS: usize = 0;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
|
||||
unsafe extern "C" {
|
||||
// start/end of heap defined in `link.x`.
|
||||
unsafe static _sheap: u8;
|
||||
unsafe static _eheap: u8;
|
||||
}
|
||||
|
||||
// SAFETY: Single threaded, so nothing else can touch this while we're working.
|
||||
let mut heap_pos = unsafe { HEAP_POS };
|
||||
|
||||
if heap_pos == 0 {
|
||||
heap_pos = unsafe { (&_sheap) as *const u8 as usize };
|
||||
heap_pos = addr_of_mut!(_sheap) as *const u8 as usize;
|
||||
}
|
||||
|
||||
let offset = heap_pos & (align - 1);
|
||||
@@ -50,11 +79,21 @@ pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u
|
||||
let ptr = heap_pos as *mut u8;
|
||||
let (heap_pos, overflowed) = heap_pos.overflowing_add(bytes);
|
||||
|
||||
let eheap = unsafe { (&_eheap) as *const u8 as usize };
|
||||
let eheap = addr_of_mut!(_eheap) as *const u8 as usize;
|
||||
if overflowed || heap_pos > eheap {
|
||||
panic!("Heap exhausted");
|
||||
panic!("heap exhausted");
|
||||
}
|
||||
|
||||
unsafe { HEAP_POS = heap_pos };
|
||||
ptr
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "riscv32", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_acquire() -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "riscv32", target_feature = "a"))]
|
||||
#[unsafe(no_mangle)]
|
||||
fn _critical_section_1_0_release(_: u32) {}
|
||||
|
||||
Reference in New Issue
Block a user