pub struct CodeBufferFinalized { /* private fields */ }Expand description
A CodeBuffer once emission is completed: holds generated code and records,
without fixups. This allows the type to be independent of the backend.
Implementations§
Source§impl CodeBufferFinalized
impl CodeBufferFinalized
pub fn total_size(&self) -> usize
Sourcepub fn data(&self) -> &[u8] ⓘ
pub fn data(&self) -> &[u8] ⓘ
Examples found in repository?
examples/reloc.rs (line 33)
10fn main() {
11 let mut buf = CodeBuffer::new();
12 let mut asm = Assembler::new(&mut buf);
13
14 let str_constant = asm.add_constant("Hello, World!\0");
15 let puts_sym = asm
16 .buffer
17 .add_symbol(ExternalName::Symbol("puts".into()), RelocDistance::Far);
18
19 asm.lea64rm(RDI, ptr64_label(str_constant, 0));
20 asm.callm(ptr64_sym(puts_sym, 0));
21 asm.ret();
22
23 let result = buf.finish();
24
25 for reloc in result.relocs() {
26 println!("{:?}", reloc);
27 }
28
29 let mut jit = JitAllocator::new(Default::default());
30
31 // allocate memory for GOT table and for code itself
32 let mut span = jit
33 .alloc(result.data().len() + result.relocs().len() * 8)
34 .unwrap();
35
36 let mut got_addr_rx = std::ptr::null();
37
38 unsafe {
39 jit.write(&mut span, |span| {
40 span.rw()
41 .copy_from_nonoverlapping(result.data().as_ptr(), result.data().len());
42 got_addr_rx = span.rx().add(result.data().len());
43 span.rw()
44 .add(result.data().len())
45 .cast::<usize>()
46 .write(puts as *const u8 as usize);
47 // we only link to one symbol in GOT table, don't bother with anything else...
48 perform_relocations(
49 span.rw(),
50 span.rx(),
51 &result.relocs(),
52 |_| unreachable!(),
53 |_| got_addr_rx,
54 |_| unreachable!(),
55 );
56 })
57 .unwrap();
58
59 let mut out = String::new();
60 pretty_disassembler(
61 &mut out,
62 64,
63 std::slice::from_raw_parts(span.rx(), result.data().len()),
64 span.rx() as _,
65 )
66 .unwrap();
67
68 println!("{}", out);
69 #[cfg(target_arch = "x86_64")]
70 {
71 let f: extern "C" fn() = std::mem::transmute(span.rx());
72
73 f();
74 }
75 }
76}More examples
examples/factorial.rs (line 39)
4fn main() {
5 {
6 use asmkit::core::buffer::CodeBuffer;
7 use asmkit::x86::*;
8 use formatter::pretty_disassembler;
9 let mut buf = CodeBuffer::new();
10 let mut asm = Assembler::new(&mut buf);
11
12 let label = asm.get_label();
13 let fac = asm.get_label();
14
15 asm.bind_label(fac);
16 asm.mov64ri(RAX, imm(1));
17 asm.test64rr(RDI, RDI);
18 asm.jnz(label);
19 asm.ret();
20
21 {
22 asm.bind_label(label);
23 asm.pushr(RBX);
24 asm.mov64rr(RBX, RDI);
25 asm.lea64rm(RDI, ptr64(RDI, -1));
26 asm.call(fac);
27 asm.mov64rr(RDX, RAX);
28 asm.mov64rr(RAX, RBX);
29 asm.imul64rr(RAX, RDX);
30 asm.popr(RBX);
31 asm.ret();
32 }
33
34 let result = buf.finish();
35
36 let mut jit = JitAllocator::new(JitAllocatorOptions::default());
37
38 let mut span = jit
39 .alloc(result.data().len())
40 .expect("failed to allocate code");
41 unsafe {
42 jit.write(&mut span, |span| {
43 span.rw()
44 .copy_from_nonoverlapping(result.data().as_ptr(), result.data().len());
45 })
46 .unwrap();
47 let mut out = String::new();
48 pretty_disassembler(&mut out, 64, result.data(), span.rx() as _).unwrap();
49 println!("{}", out);
50 #[cfg(target_arch = "x86_64")]
51 {
52 let f: extern "C" fn(u64) -> u64 = std::mem::transmute(span.rx());
53
54 println!("X86 factorial(5) = {:?}", f(5));
55 }
56 }
57 }
58
59 {
60 use asmkit::core::buffer::CodeBuffer;
61 use asmkit::riscv::*;
62 use formatter::pretty_disassembler;
63 let mut buf = CodeBuffer::new();
64 let mut asm = Assembler::new(&mut buf);
65
66 let label = asm.get_label();
67 let fac = asm.get_label();
68 asm.bind_label(fac);
69 asm.bnez(A0, label);
70 asm.addi(A0, ZERO, imm(1));
71 asm.ret();
72 {
73 asm.bind_label(label);
74 asm.addi(SP, SP, imm(-16));
75 asm.sd(SP, RA, imm(8));
76 asm.sd(SP, S0, imm(0));
77 asm.mv(S0, A0);
78 asm.addi(A0, A0, imm(-1));
79
80 asm.call(fac);
81 asm.mul(A0, S0, A0);
82 asm.ld(RA, SP, imm(8));
83 asm.ld(S0, SP, imm(0));
84 asm.addi(SP, SP, imm(16));
85 asm.ret();
86 }
87
88 let result = buf.finish();
89
90 let mut jit = JitAllocator::new(JitAllocatorOptions::default());
91
92 let mut span = jit
93 .alloc(result.data().len())
94 .expect("failed to allocate code");
95 unsafe {
96 jit.write(&mut span, |span| {
97 span.rw()
98 .copy_from_nonoverlapping(result.data().as_ptr(), result.data().len());
99 })
100 .unwrap();
101
102
103 let mut out = String::new();
104 pretty_disassembler(&mut out, 64, result.data(), span.rx() as _).unwrap();
105 println!("{}", out);
106 #[cfg(target_arch = "riscv64")]
107 {
108 let f: extern "C" fn(u64) -> u64 = std::mem::transmute(span.rx());
109
110 println!("RV64 factorial(5) = {:?}", f(5));
111 }
112 }
113 }
114}pub fn data_mut(&mut self) -> &mut [u8] ⓘ
pub fn symbol_name(&self, sym: Sym) -> &ExternalName
pub fn symbol_distance(&self, sym: Sym) -> RelocDistance
Sourcepub fn relocs(&self) -> &[AsmReloc]
pub fn relocs(&self) -> &[AsmReloc]
Examples found in repository?
examples/reloc.rs (line 25)
10fn main() {
11 let mut buf = CodeBuffer::new();
12 let mut asm = Assembler::new(&mut buf);
13
14 let str_constant = asm.add_constant("Hello, World!\0");
15 let puts_sym = asm
16 .buffer
17 .add_symbol(ExternalName::Symbol("puts".into()), RelocDistance::Far);
18
19 asm.lea64rm(RDI, ptr64_label(str_constant, 0));
20 asm.callm(ptr64_sym(puts_sym, 0));
21 asm.ret();
22
23 let result = buf.finish();
24
25 for reloc in result.relocs() {
26 println!("{:?}", reloc);
27 }
28
29 let mut jit = JitAllocator::new(Default::default());
30
31 // allocate memory for GOT table and for code itself
32 let mut span = jit
33 .alloc(result.data().len() + result.relocs().len() * 8)
34 .unwrap();
35
36 let mut got_addr_rx = std::ptr::null();
37
38 unsafe {
39 jit.write(&mut span, |span| {
40 span.rw()
41 .copy_from_nonoverlapping(result.data().as_ptr(), result.data().len());
42 got_addr_rx = span.rx().add(result.data().len());
43 span.rw()
44 .add(result.data().len())
45 .cast::<usize>()
46 .write(puts as *const u8 as usize);
47 // we only link to one symbol in GOT table, don't bother with anything else...
48 perform_relocations(
49 span.rw(),
50 span.rx(),
51 &result.relocs(),
52 |_| unreachable!(),
53 |_| got_addr_rx,
54 |_| unreachable!(),
55 );
56 })
57 .unwrap();
58
59 let mut out = String::new();
60 pretty_disassembler(
61 &mut out,
62 64,
63 std::slice::from_raw_parts(span.rx(), result.data().len()),
64 span.rx() as _,
65 )
66 .unwrap();
67
68 println!("{}", out);
69 #[cfg(target_arch = "x86_64")]
70 {
71 let f: extern "C" fn() = std::mem::transmute(span.rx());
72
73 f();
74 }
75 }
76}pub fn alignment(&self) -> u32
pub fn allocate( &self, jit_allocator: &mut JitAllocator, ) -> Result<Span, AsmError>
Auto Trait Implementations§
impl Freeze for CodeBufferFinalized
impl RefUnwindSafe for CodeBufferFinalized
impl Send for CodeBufferFinalized
impl Sync for CodeBufferFinalized
impl Unpin for CodeBufferFinalized
impl UnwindSafe for CodeBufferFinalized
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more