Created
October 12, 2023 07:38
-
-
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`.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! 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