1use asmkit::core::buffer::{perform_relocations, CodeBuffer, ExternalName, RelocDistance};
2use asmkit::core::jit_allocator::JitAllocator;
3use asmkit::x86::*;
4use formatter::pretty_disassembler;
5
6extern "C" {
7 fn puts(_: *const i8);
8}
9
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 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 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}