pub struct Span { /* private fields */ }Expand description
A memory reference returned by JitAllocator::alloc
Implementations§
Source§impl Span
impl Span
Sourcepub const fn rx(&self) -> *const u8
pub const fn rx(&self) -> *const u8
Returns a pointer having Read & Execute permissions (references executable memory).
This pointer is never NULL if the allocation succeeded, it points to an executable memory.
Examples found in repository?
examples/reloc.rs (line 42)
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 48)
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}Sourcepub const fn rw(&self) -> *mut u8
pub const fn rw(&self) -> *mut u8
Returns a pointer having Read & Write permissions (references writable memory).
Depending on the type of the allocation strategy this could either be:
- the same address as returned by
rx()if the allocator uses RWX mapping (pages have all of Read, Write, and Execute permissions) or MAP_JIT, which requires to call protect_jit_memory() manually. - a valid pointer, but not the same as
rx- this would be valid if dual mapping is used. - NULL pointer, in case that the allocation strategy doesn’t use RWX, MAP_JIT, or dual mapping. In this case only JitAllocator can copy new code into the executable memory referenced by Span.
Examples found in repository?
examples/reloc.rs (line 40)
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 43)
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 const fn size(&self) -> usize
pub fn is_icache_clean(&self) -> bool
pub fn is_directly_writeable(&self) -> bool
Auto Trait Implementations§
impl Freeze for Span
impl RefUnwindSafe for Span
impl !Send for Span
impl !Sync for Span
impl Unpin for Span
impl UnwindSafe for Span
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