javm_transpiler/
linker.rs1use crate::TranspileError;
9use crate::layout::{PVM_PAGE_SIZE, cap_index};
10use javm_cap::Key;
11use javm_cap::abi::BARE_YIELD_RECEIVER_SLOT;
12use javm_cap::image::{EndpointDef, Image, ImageBuilder, MemoryMapping};
13use javm_cap::slot::SlotPath;
14use nub_program::{ProgramBlob, RegionKind};
15
16pub fn link_elf(elf_data: &[u8]) -> Result<Image, TranspileError> {
19 Ok(image_from_blob(&nub_linker::link_elf(elf_data)?))
20}
21
22pub fn image_from_blob(program: &ProgramBlob) -> Image {
39 let page_bytes = u64::from(PVM_PAGE_SIZE);
40 let mut builder = ImageBuilder::new();
41 let mut mappings: Vec<MemoryMapping> = Vec::new();
42
43 for region in program.regions.iter() {
44 let slot = Key::from(cap_index(region.kind));
45 let size = u64::from(region.page_count) * page_bytes;
46 mappings.push(MemoryMapping {
47 start: region.start(),
48 size,
49 source: SlotPath::root(slot.clone()),
50 });
51 let bytes = program.region_data(region.kind).unwrap_or(&[]).to_vec();
53 builder = if region.kind == RegionKind::Ro {
54 builder.pinned_data(slot, bytes, size)
55 } else {
56 builder.initial_data(slot, bytes, size)
57 };
58 }
59
60 builder = builder.code(program.code.clone());
61 for (&index, endpoint) in &program.endpoints {
62 builder = builder.endpoint(
63 Key::from(index),
64 EndpointDef {
65 entry_pc: endpoint.entry_pc,
66 arg_registers: endpoint.arg_registers,
67 arg_cnode_size: endpoint.arg_meta,
68 initial_regs: endpoint.initial_regs.clone(),
69 },
70 );
71 }
72 for mapping in mappings {
73 builder = builder.mapping(mapping);
74 }
75
76 builder
77 .yield_receiver_slot(Some(Key::from(BARE_YIELD_RECEIVER_SLOT)))
78 .build()
79}