Skip to content

Instantly share code, notes, and snippets.

@MaxXSoft
Created October 12, 2023 07:38
Show Gist options
  • Save MaxXSoft/41507590db0682f2ff1d911710102f7c to your computer and use it in GitHub Desktop.
Save MaxXSoft/41507590db0682f2ff1d911710102f7c to your computer and use it in GitHub Desktop.
A simple example to emit code at runtime on AArch64 (ARM64) in Rust using crate `dynasmrt`.
//! A simple example to emit code at runtime on AArch64 (ARM64)
//! in Rust using crate `dynasmrt`.
//!
//! Written by MaxXing, 2023-10-12.
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
use std::io::{self, Write};
use std::{mem, slice};
fn main() {
// Create assembler.
let mut ops = dynasmrt::aarch64::Assembler::new().unwrap();
// Emit data.
let hello = "Fuck, world!\n";
let hello_len = hello.len();
dynasm!(ops
; -> hello:
; .bytes hello.as_bytes()
; .align 4 // LDR requires 4-byte align.
; -> print:
; .qword print as _
);
// Align for the executable code.
ops.align(4, 0);
// Emit code.
let hello = ops.offset();
dynasm!(ops
; .arch aarch64
; adr x0, -> hello // Message.
; mov x1, hello_len as _ // Length.
; ldr x2, -> print // Address of the `print` function.
; br x2 // Call the function (actually tail call).
);
// Create executable buffer.
let buf = ops.finalize().unwrap();
println!("buffer length = {}", buf.len());
// Call the emitted function.
let hello_fn: extern "C" fn() = unsafe { mem::transmute(buf.ptr(hello)) };
hello_fn();
}
extern "C" fn print(buf: *const u8, len: u64) {
io::stdout()
.write_all(unsafe { slice::from_raw_parts(buf, len as usize) })
.unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment