Skip to content

Commit

Permalink
#1121: Introducing BasicBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanSalwan committed May 24, 2022
1 parent 167b973 commit a09e067
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 27 deletions.
6 changes: 6 additions & 0 deletions src/examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ set_property(TARGET ctest_api PROPERTY CXX_STANDARD 14)
target_link_libraries(ctest_api triton)
add_test(TestAPI ctest_api)
add_dependencies(check ctest_api)

add_executable(block block.cpp)
set_property(TARGET block PROPERTY CXX_STANDARD 14)
target_link_libraries(block triton)
add_test(TestBlock block)
add_dependencies(check block)
25 changes: 0 additions & 25 deletions src/examples/cpp/Makefile

This file was deleted.

60 changes: 60 additions & 0 deletions src/examples/cpp/block.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

#include <iostream>
#include <triton/api.hpp>
#include <triton/basicBlock.hpp>

using namespace triton;
using namespace triton::arch;


int main(int ac, const char **av) {
/* Init the triton context */
triton::API api;

/* Set the arch */
api.setArchitecture(ARCH_X86_64);

BasicBlock block = BasicBlock({
Instruction((unsigned char *)"\x89\xd0", 2), /* mov eax, edx */
Instruction((unsigned char *)"\x80\xf4\x99", 3), /* xor ah, 0x99 */
Instruction((unsigned char *)"\x85\xc0", 2), /* test eax, eax */
Instruction((unsigned char *)"\x74\x08", 2), /* jz 10 */
});

api.disassembly(block);

std::cout << block << std::endl;
std::cout << "----------" << std::endl;

auto i = Instruction((unsigned char *)"\x90", 1); /* nop */
api.disassembly(i);

block.add(i);
block.add(i);
block.add(i);

std::cout << block << std::endl;
std::cout << "----------" << std::endl;

block.remove(0);

std::cout << block << std::endl;
std::cout << "----------" << std::endl;

api.disassembly(block, 0x1000);

std::cout << block << std::endl;

std::cout << "First addr: 0x" << std::hex << block.getFirstAddress() << std::endl;
std::cout << "Last addr: " << std::hex << block.getLastAddress() << std::endl;
std::cout << "Number of instructions: " << std::hex << block.size() << std::endl;

std::cout << "----------" << std::endl;

block.remove(2); /* remove the jz */
api.processing(block);

std::cout << block << std::endl;

return 0;
}
2 changes: 2 additions & 0 deletions src/libtriton/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(LIBTRITON_SOURCE_FILES
arch/arm/arm32/arm32Semantics.cpp
arch/arm/arm32/arm32Specifications.cpp
arch/arm/armOperandProperties.cpp
arch/basicBlock.cpp
arch/bitsVector.cpp
arch/immediate.cpp
arch/instruction.cpp
Expand Down Expand Up @@ -82,6 +83,7 @@ set(LIBTRITON_HEADER_FILES
includes/triton/astRepresentation.hpp
includes/triton/astRepresentationInterface.hpp
includes/triton/astSmtRepresentation.hpp
includes/triton/basicBlock.hpp
includes/triton/bitsVector.hpp
includes/triton/bitwuzlaSolver.hpp
includes/triton/callbacks.hpp
Expand Down
19 changes: 19 additions & 0 deletions src/libtriton/api/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,12 @@ namespace triton {
}


void API::disassembly(triton::arch::BasicBlock& block, triton::uint64 addr) const {
this->checkArchitecture();
this->arch.disassembly(block, addr);
}


std::vector<triton::arch::Instruction> API::disassembly(triton::uint64 addr, triton::usize count) const {
this->checkArchitecture();
return this->arch.disassembly(addr, count);
Expand Down Expand Up @@ -545,6 +551,13 @@ namespace triton {
}


bool API::processing(triton::arch::BasicBlock& block) {
this->checkArchitecture();
this->arch.disassembly(block);
return this->irBuilder->buildSemantics(block);
}



/* IR builder API ================================================================================= */

Expand All @@ -554,6 +567,12 @@ namespace triton {
}


bool API::buildSemantics(triton::arch::BasicBlock& block) {
this->checkIrBuilder();
return this->irBuilder->buildSemantics(block);
}


triton::ast::SharedAstContext API::getAstContext(void) {
return this->astCtxt;
}
Expand Down
12 changes: 12 additions & 0 deletions src/libtriton/arch/architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,18 @@ namespace triton {
}


void Architecture::disassembly(triton::arch::BasicBlock& block, triton::uint64 addr) const {
if (!this->cpu)
throw triton::exceptions::Architecture("Architecture::disassembly(): You must define an architecture.");

for (auto& inst : block.getInstructions()) {
inst.setAddress(addr);
this->cpu->disassembly(inst);
addr += inst.getSize();
}
}


std::vector<triton::arch::Instruction> Architecture::disassembly(triton::uint64 addr, triton::usize count) const {
std::vector<triton::arch::Instruction> ret;
ret.reserve(count);
Expand Down
99 changes: 99 additions & 0 deletions src/libtriton/arch/basicBlock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! \file
/*
** Copyright (C) - Triton
**
** This program is under the terms of the Apache License 2.0.
*/

#include <triton/exceptions.hpp>
#include <triton/basicBlock.hpp>



namespace triton {
namespace arch {

BasicBlock::BasicBlock() {
}


BasicBlock::BasicBlock(const std::vector<triton::arch::Instruction>& instructions) {
this->instructions = instructions;
}


BasicBlock::BasicBlock(const BasicBlock& other) {
this->instructions = other.instructions;
}


BasicBlock& BasicBlock::operator=(const BasicBlock& other) {
this->instructions = other.instructions;
return *this;
}


BasicBlock::~BasicBlock() {
this->instructions.clear();
}


void BasicBlock::add(Instruction& instruction) {
if (this->instructions.size()) {
instruction.setAddress(this->instructions.back().getNextAddress());
}
this->instructions.push_back(instruction);
}


bool BasicBlock::remove(triton::uint32 position) {
if (this->instructions.size() <= position)
return false;
this->instructions.erase(this->instructions.begin() + position);
return true;
}


std::vector<triton::arch::Instruction>& BasicBlock::getInstructions(void) {
return this->instructions;
}


triton::usize BasicBlock::size(void) const {
return this->instructions.size();
}


triton::uint64 BasicBlock::getFirstAddress(void) const {
if (this->instructions.size() == 0)
throw triton::exceptions::BasicBlock("BasicBlock::getFirstAddress(): No instruction in the block.");
return this->instructions.front().getAddress();
}


triton::uint64 BasicBlock::getLastAddress(void) const {
if (this->instructions.size() == 0)
throw triton::exceptions::BasicBlock("BasicBlock::getLastAddress(): No instruction in the block.");
return this->instructions.back().getAddress();
}


std::ostream& operator<<(std::ostream& stream, BasicBlock& block) {
triton::usize size = block.size();
for (const auto& inst : block.getInstructions()) {
stream << inst;
if (--size) {
stream << std::endl;
}
}
return stream;
}


std::ostream& operator<<(std::ostream& stream, BasicBlock* block) {
stream << *block;
return stream;
}

};
};
3 changes: 2 additions & 1 deletion src/libtriton/arch/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,8 @@ namespace triton {


std::ostream& operator<<(std::ostream& stream, const Instruction& inst) {
stream << "0x" << std::hex << inst.getAddress() << ": " << inst.getDisassembly() << std::dec;
std::string dis = inst.getDisassembly();
stream << "0x" << std::hex << inst.getAddress() << ": " << (!dis.empty() ? dis : "<not disassembled>") << std::dec;
return stream;
}

Expand Down
16 changes: 16 additions & 0 deletions src/libtriton/arch/irBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ namespace triton {
}


bool IrBuilder::buildSemantics(triton::arch::BasicBlock& block) {
triton::usize count = block.size();

for (auto& inst : block.getInstructions()) {
if (this->buildSemantics(inst) == false) {
return false;
}
if (inst.isControlFlow() && --count) {
throw triton::exceptions::IrBuilder("IrBuilder::buildSemantics(): Do not add instructions in a block after a branch instruction.");
}
}

return true;
}


void IrBuilder::preIrInit(triton::arch::Instruction& inst) {
/* Clear previous expressions if exist */
inst.symbolicExpressions.clear();
Expand Down
10 changes: 10 additions & 0 deletions src/libtriton/includes/triton/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <triton/ast.hpp>
#include <triton/astContext.hpp>
#include <triton/astRepresentation.hpp>
#include <triton/basicBlock.hpp>
#include <triton/callbacks.hpp>
#include <triton/dllexport.hpp>
#include <triton/immediate.hpp>
Expand Down Expand Up @@ -244,6 +245,9 @@ namespace triton {
//! [**architecture api**] - Disassembles the instruction and setup operands. You must define an architecture before. \sa processing().
TRITON_EXPORT void disassembly(triton::arch::Instruction& inst) const;

//! [**architecture api**] - Disassembles a block of instructions. You must define an architecture before.
TRITON_EXPORT void disassembly(triton::arch::BasicBlock& block, triton::uint64 addr=0) const;

//! [**architecture api**] - Disassembles a concrete memory area and returns a list of at most `count` disassembled instructions.
TRITON_EXPORT std::vector<triton::arch::Instruction> disassembly(triton::uint64 addr, triton::usize count) const;

Expand All @@ -257,6 +261,9 @@ namespace triton {
//! [**proccesing api**] - Processes an instruction and updates engines according to the instruction semantics. Returns true if the instruction is supported.
TRITON_EXPORT bool processing(triton::arch::Instruction& inst);

//! [**proccesing api**] - Processes a block of instructions and updates engines according to instructions semantics. Returns false if an instruction is not supported.
TRITON_EXPORT bool processing(triton::arch::BasicBlock& block);

//! [**proccesing api**] - Initializes everything.
TRITON_EXPORT void initEngines(void);

Expand All @@ -273,6 +280,9 @@ namespace triton {
//! [**IR builder api**] - Builds the instruction semantics. Returns true if the instruction is supported. You must define an architecture before. \sa processing().
TRITON_EXPORT bool buildSemantics(triton::arch::Instruction& inst);

//! [**IR builder api**] - Builds the instructions semantics of a block. Returns false if an instruction is not supported. You must define an architecture before.
TRITON_EXPORT bool buildSemantics(triton::arch::BasicBlock& block);

//! [**IR builder api**] - Returns the AST context. Used as AST builder.
TRITON_EXPORT triton::ast::SharedAstContext getAstContext(void);

Expand Down
4 changes: 4 additions & 0 deletions src/libtriton/includes/triton/architecture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <vector>

#include <triton/archEnums.hpp>
#include <triton/basicBlock.hpp>
#include <triton/callbacks.hpp>
#include <triton/cpuInterface.hpp>
#include <triton/dllexport.hpp>
Expand Down Expand Up @@ -141,6 +142,9 @@ namespace triton {
//! Disassembles the instruction according to the architecture.
TRITON_EXPORT void disassembly(triton::arch::Instruction& inst) const;

//! Disassembles a block of instructions according to the architecture.
TRITON_EXPORT void disassembly(triton::arch::BasicBlock& block, triton::uint64 addr=0) const;

//! Disassembles a concrete memory area and returns a list of at most `count` disassembled instructions.
TRITON_EXPORT std::vector<triton::arch::Instruction> disassembly(triton::uint64 addr, triton::usize count) const;

Expand Down
Loading

0 comments on commit a09e067

Please sign in to comment.