Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Prerequisites

Rust compiler

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

AArch64 musl libraries

$ rustup target install aarch64-unknown-linux-musl

Rust nightly toolchain

This is necessary because we will be using some nightly features.

$ rustup install nightly
$ rustup default nightly

Alternatively, just override the default toolchain in your working directory:

$ rustup override set nightly

Rust default config

$ export CARGO_BUILD_TARGET=aarch64-unknown-linux-musl
$ export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc
$ export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUNNER="qemu-aarch64"

Alternatively, add the following to .cargo/config.toml:

[build]
target = "aarch64-unknown-linux-musl"

[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc"
runner = "qemu-aarch64"

AArch64 cross-compiler + binutils + sysroot

$ sudo dnf install gcc-aarch64-linux-gnu
$ sudo dnf install binutils-aarch64-linux-gnu
$ sudo dnf install sysroot-aarch64-fc41-glibc

rustfilt (optional)

If you need to manually demangle a symbol, rustfilt is very convenient:

$ cargo install rustfilt
$ echo _ZN8rust_lab4main17hf9a0ba7e2c977e69E | rustfilt
rust_lab::main

QEMU

$ sudo dnf install qemu-user

Ghidra

$ wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.3.2_build/ghidra_11.3.2_PUBLIC_20250415.zip

Test the cross-compilation setup

With a Cargo project:

$ cargo init
$ cargo build
$ cargo run --quiet
Hello, world!

Without a Cargo project:

$ echo 'fn main() { println!("Hello ARM64!"); }' > test.rs
$ rustc --target aarch64-unknown-linux-musl -C linker=aarch64-linux-gnu-gcc test.rs
$ qemu-aarch64 ./test
Hello ARM64!