Skip to content

Commit

Permalink
Add support for AARCH64 binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
ergrelet committed Apr 6, 2024
1 parent 088c92a commit ee66e4e
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Added

- Add support for ARM64 binaries

## [0.1.1] - 2024-04-06

### Changed
Expand Down
13 changes: 12 additions & 1 deletion src/commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ void SimplifyBasicBlockCommand(BinaryNinja::BinaryView* p_view) {
triton.setArchitecture(triton::arch::ARCH_X86_64);
} else if (architecture_name == "x86") {
triton.setArchitecture(triton::arch::ARCH_X86);
} else if (architecture_name == "aarch64") {
triton.setArchitecture(triton::arch::ARCH_AARCH64);
} else {
LogError("Unsupported architecture '%s'", architecture_name.c_str());
return;
}

auto meta_basic_blocks =
Expand Down Expand Up @@ -95,6 +100,11 @@ void SimplifyFunctionCommand(BinaryView* p_view) {
triton.setArchitecture(triton::arch::ARCH_X86_64);
} else if (architecture_name == "x86") {
triton.setArchitecture(triton::arch::ARCH_X86);
} else if (architecture_name == "aarch64") {
triton.setArchitecture(triton::arch::ARCH_AARCH64);
} else {
LogError("Unsupported architecture '%s'", architecture_name.c_str());
return;
}

// Create `MetaBasicBlock`s from the current Binja function's basic blocks
Expand Down Expand Up @@ -130,7 +140,8 @@ bool ValidateSimplifyFunctionCommand(BinaryView* p_view) {
// Check platform compatibility
const std::string architecture_name =
view.GetDefaultArchitecture()->GetName();
if (architecture_name != "x86_64" && architecture_name != "x86") {
if (architecture_name != "x86_64" && architecture_name != "x86" &&
architecture_name != "aarch64") {
LogError("Unsupported architecture");
return false;
}
Expand Down
40 changes: 35 additions & 5 deletions src/meta_basic_block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace triton_bn {

using namespace BinaryNinja;

static bool IsCallInstruction(const triton::arch::Instruction&);
static bool IsJumpInstruction(const triton::arch::Instruction& instr);
static void MergeLinkedBasicBlocks(const BasicBlockEdge& edge,
MetaBasicBlock& root_bb,
MetaBasicBlock& target_bb);
Expand Down Expand Up @@ -41,7 +43,6 @@ std::vector<MetaBasicBlock> ExtractMetaBasicBlocksFromBasicBlock(
max_instr_len, binja_instruction)) {
continue;
}
LogDebug("0x%p - %zu", (void*)cur_instr_addr, binja_instruction.length);

// Add disassembled instruction to the basic block
triton::arch::Instruction new_instr(
Expand All @@ -55,10 +56,11 @@ std::vector<MetaBasicBlock> ExtractMetaBasicBlocksFromBasicBlock(
return {};
}
triton_bb.add(new_instr);
LogDebug("0x%p - %zu - '%s'", (void*)cur_instr_addr,
binja_instruction.length, new_instr.getDisassembly().c_str());

// Split basic blocks on `call` instructions to make them simplifiable
// TODO: Fix for ARM64
if (new_instr.getDisassembly().find("call") == 0) {
if (IsCallInstruction(new_instr)) {
LogDebug("call detected: %s", new_instr.getDisassembly().c_str());
// Add basic block to the result
result.emplace_back(MetaBasicBlock(triton_bb, basic_block));
Expand Down Expand Up @@ -175,8 +177,8 @@ static void MergeLinkedBasicBlocks(const BasicBlockEdge& edge,
const triton::arch::Instruction last_instr =
cur_triton_bb.getInstructions()[last_instr_index];
// Remove last instruction if it's a `jmp`
// TODO: Fix for ARM64
if (last_instr.getDisassembly().find("jmp") == 0) {
if (IsJumpInstruction(last_instr)) {
LogDebug("jump detected: %s", last_instr.getDisassembly().c_str());
cur_triton_bb.remove(last_instr_index);
}
}
Expand All @@ -190,6 +192,34 @@ static void MergeLinkedBasicBlocks(const BasicBlockEdge& edge,
root_bb.AddOutgoingEdges(target_bb.outgoing_edges());
}

static bool IsCallInstruction(const triton::arch::Instruction& instr) {
switch (instr.getArchitecture()) {
case triton::arch::ARCH_X86_64:
case triton::arch::ARCH_X86:
return instr.getDisassembly().find("call") == 0;
case triton::arch::ARCH_AARCH64:
// Match `bl` and `blr`
return instr.getDisassembly().find("bl") == 0;
default:
return false;
}
}

static bool IsJumpInstruction(const triton::arch::Instruction& instr) {
switch (instr.getArchitecture()) {
case triton::arch::ARCH_X86_64:
case triton::arch::ARCH_X86:
return instr.getDisassembly().find("jmp") == 0;
case triton::arch::ARCH_AARCH64: {
const std::string disassembly = instr.getDisassembly();
// Match `b` but not `bl` or `bl.XX`, so we add a space at the end
return disassembly.find("b ") == 0;
}
default:
return false;
}
}

// Simplify the given `MetaBasicBlock`s with Triton's dead store elimination
// pass
std::vector<MetaBasicBlock> SimplifyMetaBasicBlocks(
Expand Down

0 comments on commit ee66e4e

Please sign in to comment.