Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# binaryninja-api will result in this root workspace being picked up and used for LSP and cargo commands automatically.
[workspace]
resolver = "2"
# arm64-exarmo is a workspace of its own
exclude = ["arch/arm64"]
members = [
"rust",
"arch/riscv",
Expand Down
94 changes: 65 additions & 29 deletions arch/arm64/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

project(arch_arm64 CXX C)
project(arch_arm64 CXX)

file(GLOB SOURCES CONFIGURE_DEPENDS
*.cpp
*.c
*.h
disassembler/decode.c
disassembler/format.c
disassembler/sysregs_gen.c
disassembler/sysregs_fmt_gen.c
disassembler/regs.c
disassembler/encodings_dec.c
disassembler/encodings_fmt.c
disassembler/operations.c
disassembler/pcode.c
disassembler/decode0.c
disassembler/decode1.c
disassembler/decode2.c
disassembler/decode_fields32.c
disassembler/decode_scratchpad.c
disassembler/*.h)

list(FILTER SOURCES EXCLUDE REGEX "sysregs\\.(h|cpp)$")
*.h)

if(DEMO)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
Expand All @@ -31,13 +13,8 @@ else()
endif()


if(NOT WIN32)
set_source_files_properties(disassembler/arm64dis.c PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
endif()

target_include_directories(${PROJECT_NAME}
PRIVATE ${PROJECT_SOURCE_DIR}
PRIVATE ${PROJECT_SOURCE_DIR}/disassembler)
PRIVATE ${PROJECT_SOURCE_DIR})

if((NOT BN_API_BUILD_EXAMPLES) AND (NOT BN_INTERNAL_BUILD))
add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ${PROJECT_BINARY_DIR}/api)
Expand All @@ -52,6 +29,68 @@ else()
endif()
endif()

if(NOT BN_INTERNAL_BUILD)
get_target_property(BN_API_SOURCE_DIR binaryninjaapi SOURCE_DIR)
list(APPEND CMAKE_MODULE_PATH "${BN_API_SOURCE_DIR}/cmake")
include(RustBuild)
endif()

# Build exarmo, the AArch64 disassembler, from crates.io through the arm64-exarmo crate in this
# directory. Its build script copies the headers of the exarmo it links into the Rust target
# directory, where the plugin includes them from.
if(DEMO)
bn_get_rust_target_dir(exarmo_aarch64 EXARMO_TARGET_DIR)
else()
bn_get_rust_target_dir(exarmo_aarch64 EXARMO_TARGET_DIR STANDALONE)
endif()
set(EXARMO_INCLUDE_DIR ${EXARMO_TARGET_DIR}/arm64-exarmo/include)
set(EXARMO_HEADERS
${EXARMO_INCLUDE_DIR}/exarmo/aarch64.h
${EXARMO_INCLUDE_DIR}/exarmo/aarch64_generated.h)
target_include_directories(${PROJECT_NAME} PRIVATE ${EXARMO_INCLUDE_DIR})

if(DEMO)
# arch_arm64 is linked into the core here, so exarmo goes through the umbrella
# that holds one copy of the Rust runtime for that binary.
bn_add_rust_crate(
TARGET exarmo_aarch64
CRATE arm64-exarmo
OUTPUT_TYPE STATIC
OUTPUT_DIR ${CMAKE_BINARY_DIR}
GROUP plugins
EXTRA_SOURCES ${PROJECT_SOURCE_DIR}/Cargo.lock
BYPRODUCTS ${EXARMO_HEADERS})
else()
bn_add_rust_crate(
TARGET exarmo_aarch64
CRATE arm64-exarmo
OUTPUT_TYPE STATIC
STANDALONE
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}
EXTRA_SOURCES ${PROJECT_SOURCE_DIR}/Cargo.lock
BYPRODUCTS ${EXARMO_HEADERS})

get_target_property(EXARMO_LIBRARY exarmo_aarch64 OUTPUT_FILE_PATH)
add_library(exarmo_aarch64_capi STATIC IMPORTED GLOBAL)
set_target_properties(exarmo_aarch64_capi PROPERTIES IMPORTED_LOCATION ${EXARMO_LIBRARY})
add_dependencies(exarmo_aarch64_capi exarmo_aarch64)

bn_rust_native_static_libs(EXARMO_NATIVE_LIBS)
set_property(TARGET exarmo_aarch64_capi APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${EXARMO_NATIVE_LIBS})

target_link_libraries(${PROJECT_NAME} exarmo_aarch64_capi)
endif()

# Build exarmo first, since the plugin's sources include the headers its build script copies.
add_dependencies(${PROJECT_NAME} exarmo_aarch64)

# Keep the symbols of the static libraries linked in, exarmo and Rust's std among them, from being
# exported alongside the plugin's own.
if(UNIX AND NOT APPLE)
target_link_options(${PROJECT_NAME} PRIVATE "LINKER:--exclude-libs,ALL")
endif()

IF(DEFINED ENV{ARM64_WARNINGS})
MESSAGE(STATUS "ARM64 WARNINGS ON")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall)
Expand All @@ -63,9 +102,6 @@ set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 20
CXX_VISIBILITY_PRESET hidden
CXX_STANDARD_REQUIRED ON
C_STANDARD 11
C_STANDARD_REQUIRED ON
C_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
POSITION_INDEPENDENT_CODE ON)

Expand Down
35 changes: 35 additions & 0 deletions arch/arm64/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions arch/arm64/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Build exarmo, the AArch64 disassembler, as the static library the plugin links. build.rs copies
# the C API's headers from the exarmo-aarch64-capi this crate links.
[package]
name = "arm64-exarmo"
version = "0.1.0"
edition = "2024"
publish = false

[lib]
crate-type = ["staticlib"]

[dependencies]
# Pin the exact version so that the demo umbrella, which resolves without this crate's Cargo.lock,
# builds the same exarmo as every other build.
exarmo-aarch64-capi = "=0.1.3"

# Make this crate its own workspace to keep exarmo out of the api workspace's lock file.
[workspace]

[profile.release]
opt-level = 2
debug = "line-tables-only"
19 changes: 12 additions & 7 deletions arch/arm64/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ This is the AArch64 plugin that ships with Binary Ninja.

- [arch_arm64.cpp](./arch_arm64.cpp) implements the Architecture class
- [il.cpp](./il.cpp) contains the lifter, the translator from disassembly to intermediate language
- [disassembler/*](./disassembler/) is the disassembler
- [operands.cpp](./operands.cpp) reads the operands exarmo decodes the way the lifter needs them
- [registers.cpp](./registers.cpp) and [system_registers.cpp](./system_registers.cpp) are the two register namespaces, and map exarmo's registers into them
- [acle_intrinsics.cpp](./acle_intrinsics.cpp) lifts an instruction as the ACLE intrinsic exarmo says it implements
- [system_operations.cpp](./system_operations.cpp) names the intrinsics for AT, DC, TLBI and the other SYS aliases
- [apple_vendor.cpp](./apple_vendor.cpp) covers the Apple instructions and system registers ARM does not define

## Testing
Disassembly comes from [exarmo](https://crates.io/crates/exarmo-aarch64-capi), through its C API.

There are three tests:
## Testing

- [./disassembler/test.py](./disassembler/test.py) test of disassembler module, isolated from the architecture module or Binary Ninja
- [./test_disasm.py](./test_disasm.py) test of disassembler, using the architecture module through the binaryninja API
- [./arm64test.py](./arm64test.py) runs a very basic "lift to string and compare" test

Personal Binary Ninja users can test via the built in console:
Expand All @@ -35,7 +37,7 @@ And, of course, you can open a test binary in Binary Ninja with this architectur

1. **TEST!** If you're making an architecture or lifter change, add a test case to [arm64test.py](./arm64test.py) that fails before your change and succeeds after your change.

2. **TEST!** If you're making a disassembler change, add a test case to [disassembler/test.py](./disassembler/test.py) that fails before your change and succeeds after your change.
2. Disassembly comes from exarmo, so report disassembly bugs as issues rather than changing the plugin.
3. Compile with warnings enabled. Do this cmake invocation: `ARM64_WARNINGS=1 cmake .`

Please follow whatever formatting conventions are present in the file you edit. Pay attention to curly brackets, spacing, tabs vs. spaces, etc.
Expand All @@ -46,7 +48,10 @@ When you submit your first PR to one of Vector 35's repositories, you'll receive
## Building

Building the architecture plugin requires `cmake` 3.9 or above. You will also need the
[Binary Ninja API source](https://github.com/Vector35/binaryninja-api).
[Binary Ninja API source](https://github.com/Vector35/binaryninja-api). You also need `rustup` and
Python 3 to build exarmo. Cargo fetches exarmo from crates.io at the version [Cargo.toml](./Cargo.toml)
pins. The build uses the Rust toolchain named by `CARGO_STABLE_VERSION` in
[RustBuild.cmake](../../cmake/RustBuild.cmake).

Run `cmake`. This can be done either from a separate build directory or from the source
directory. Once that is complete, run `make` in the build directory to compile the plugin.
Expand Down
Loading
Loading