corevm_engine/
program_data.rs

1use core::ops::Range;
2use corevm_host::PAGE_SIZE;
3use polkavm::{ArcBytes, MemoryMap};
4
5/// Static data associated with the program.
6///
7/// Includes memory map and RO/RW data arrays.
8pub struct ProgramData {
9	address_ranges: [Range<u64>; 4],
10	pub ro_data: ArcBytes,
11	pub rw_data: ArcBytes,
12}
13
14impl ProgramData {
15	pub fn new(memory_map: &MemoryMap, ro_data: ArcBytes, rw_data: ArcBytes) -> Self {
16		let heap_start = (memory_map.heap_base() as u64).next_multiple_of(PAGE_SIZE);
17		let heap_end = heap_start + memory_map.max_heap_size() as u64;
18		let heap_range = heap_start..heap_end;
19		let stack_range = memory_map.stack_range();
20		let stack_range = (stack_range.start as u64)..(stack_range.end as u64);
21		let ro_data_range = memory_map.ro_data_range();
22		let ro_data_range = (ro_data_range.start as u64)..(ro_data_range.end as u64);
23		let rw_data_range = memory_map.rw_data_range();
24		let rw_data_range = (rw_data_range.start as u64)..(rw_data_range.end as u64);
25		// Sanity checks.
26		assert!(ro_data.len() as u64 <= ro_data_range.end - ro_data_range.start);
27		assert!(rw_data.len() as u64 <= rw_data_range.end - rw_data_range.start);
28		Self {
29			address_ranges: [ro_data_range, rw_data_range, stack_range, heap_range],
30			ro_data,
31			rw_data,
32		}
33	}
34
35	/// Returns the identifier of an address range the `address` belongs to.
36	pub fn classify_address(&self, address: u64) -> Option<AddressKind> {
37		AddressKind::ALL
38			.into_iter()
39			.find(|&kind| self.address_ranges[kind as usize].contains(&address))
40	}
41
42	pub fn address_range(&self, kind: AddressKind) -> &Range<u64> {
43		&self.address_ranges[kind as usize]
44	}
45
46	/// Stack address range.
47	pub fn stack_range(&self) -> &Range<u64> {
48		self.address_range(AddressKind::Stack)
49	}
50
51	/// Heap address range.
52	pub fn heap_range(&self) -> &Range<u64> {
53		self.address_range(AddressKind::Heap)
54	}
55
56	/// Read-only data address range.
57	pub fn ro_data_range(&self) -> &Range<u64> {
58		self.address_range(AddressKind::RoData)
59	}
60
61	/// Read/write data address range.
62	pub fn rw_data_range(&self) -> &Range<u64> {
63		self.address_range(AddressKind::RwData)
64	}
65}
66
67/// Address range identifier.
68#[derive(Clone, Copy, PartialEq, Eq)]
69pub enum AddressKind {
70	RoData = 0,
71	RwData = 1,
72	Stack = 2,
73	Heap = 3,
74}
75
76impl AddressKind {
77	pub const ALL: [Self; 4] = [Self::RoData, Self::RwData, Self::Stack, Self::Heap];
78}
79
80impl core::fmt::Debug for AddressKind {
81	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82		let s = match self {
83			Self::RoData => "ro",
84			Self::RwData => "rw",
85			Self::Stack => "stack",
86			Self::Heap => "heap",
87		};
88		f.write_str(s)
89	}
90}