Skip to content

Commit

Permalink
Add instructionAPI/printVisitor (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
hainest authored Jan 2, 2024
1 parent 1a44e1d commit c0b3edb
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_subdirectory(DynC)
add_subdirectory(instrumentAFunction)
add_subdirectory(instrumentMemoryAccess)
add_subdirectory(insertSnippet)
add_subdirectory(instructionAPI)
add_subdirectory(interceptOutput)
add_subdirectory(maxMallocSize)
add_subdirectory(memoryAccessCounter)
Expand Down
9 changes: 9 additions & 0 deletions instructionAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project(InstructionAPI LANGUAGES CXX)

add_executable(stateless_visitor stateless_visitor.cpp)
target_compile_options(stateless_visitor PRIVATE ${EXAMPLES_WARNING_FLAGS})
target_link_libraries(stateless_visitor PRIVATE Dyninst::instructionAPI)

add_executable(statefull_visitor statefull_visitor.cpp)
target_compile_options(statefull_visitor PRIVATE ${EXAMPLES_WARNING_FLAGS})
target_link_libraries(statefull_visitor PRIVATE Dyninst::instructionAPI)
84 changes: 84 additions & 0 deletions instructionAPI/statefull_visitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "BinaryFunction.h"
#include "Dereference.h"
#include "Expression.h"
#include "Immediate.h"
#include "Instruction.h"
#include "InstructionDecoder.h"
#include "Operand.h"
#include "Register.h"
#include "Visitor.h"

#include <array>
#include <iomanip>
#include <iostream>

namespace di = Dyninst::InstructionAPI;

/*
* A stateful visitor
*
* This visitor remembers the AST type that was most-recently visited.
*/

struct stateful_visitor : di::Visitor {
bool foundReg{};
bool foundImm{};
bool foundBin{};
bool foundDer{};

void visit(di::BinaryFunction*) override { foundBin = true; }

void visit(di::Immediate* imm) override { foundImm = true; }

void visit(di::RegisterAST*) override { foundReg = true; }

void visit(di::Dereference*) override { foundDer = true; }

// clang-format off
friend std::ostream& operator<<(std::ostream &os, stateful_visitor const& v) {
std::cout << std::boolalpha
<< " foundReg: " << v.foundReg << '\n'
<< " foundImm: " << v.foundImm << '\n'
<< " foundBin: " << v.foundBin << '\n'
<< " foundDer: " << v.foundDer << '\n';
return os;
}

// clang-format on
};

void print(di::Instruction const& insn) {
stateful_visitor v;
std::vector<di::Operand> operands;
insn.getOperands(operands);

std::cout << "instruction: " << insn.format() << '\n';
for(auto const& o : operands) {
std::cout << "operand '" << o.format(insn.getArch()) << "'\n";
o.getValue()->apply(&v);
std::cout << v << '\n';
}
}

int main() {
// clang-format off
std::array<const unsigned char, 15> buffer = {
0x05, 0xef, 0xbe, 0xad, 0xde, // add eax, 0xDEADBEEF
0x90, // 1-byte nop
0x66, 0x0F, 0x1F, 0x84, 0x00,
0x00, 0x00, 0x00, 0x00 // 9-byte nop (NOP DWORD ptr [rax + rax*1 + 0x00000000])

};
// clang-format on

di::InstructionDecoder decoder(buffer.data(), buffer.size(), Dyninst::Architecture::Arch_x86_64);

di::Instruction i;
do {
i = decoder.decode();
if(i.isValid()) {
print(i);
std::cout << '\n';
}
} while(i.isValid());
}
74 changes: 74 additions & 0 deletions instructionAPI/stateless_visitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "BinaryFunction.h"
#include "Dereference.h"
#include "Expression.h"
#include "Immediate.h"
#include "Instruction.h"
#include "InstructionDecoder.h"
#include "Operand.h"
#include "Register.h"
#include "Visitor.h"

#include <array>
#include <iomanip>
#include <iostream>

namespace di = Dyninst::InstructionAPI;

/*
* A stateless visitor
*
* This visitor simply accesses some property of the ASTs, but
* does not store any information about them.
*/

class printer : public di::Visitor {
public:
void visit(di::BinaryFunction* b) override {
std::cout << " BinaryFunction '" << b->format(di::defaultStyle) << "'\n";
};

void visit(di::Immediate* i) override {
std::cout << " Immediate '0x" << i->format(di::defaultStyle) << "'\n";
};

void visit(di::Dereference* d) override {
std::cout << " Dereference '" << d->format(di::defaultStyle) << "'\n";
};

void visit(di::RegisterAST* r) override {
std::cout << " Register '" << r->format(di::defaultStyle) << "'\n";
}
};

void print(di::Instruction const& insn) {
printer pv;
std::vector<di::Operand> operands;
insn.getOperands(operands);

std::cout << "instruction: " << insn.format() << '\n';
int op_num = 1;
for(auto const& o : operands) {
std::cout << "operand" << op_num << " '" << o.format(insn.getArch()) << "'\n";
o.getValue()->apply(&pv);
op_num++;
}
}

int main() {
std::array<const unsigned char, 8> buffer = {
0x05, 0xef, 0xbe, 0xad, 0xde, // add eax, 0xDEADBEEF
0x50, // push rax
0x74, 0x10 // je 0x12
};

di::InstructionDecoder decoder(buffer.data(), buffer.size(), Dyninst::Architecture::Arch_x86_64);

di::Instruction i;
do {
i = decoder.decode();
if(i.isValid()) {
print(i);
std::cout << '\n';
}
} while(i.isValid());
}

0 comments on commit c0b3edb

Please # to comment.