Skip to content

Commit

Permalink
Collect examples into their own section
Browse files Browse the repository at this point in the history
A 'usage' is a short snippet. An 'example' is a complete program.
  • Loading branch information
hainest committed Dec 13, 2022
1 parent af8321a commit fa5fa45
Show file tree
Hide file tree
Showing 9 changed files with 928 additions and 928 deletions.
722 changes: 0 additions & 722 deletions docs/dyninstAPI/index.rst

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions docs/examples/binary_analysis.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

===============
Binary Analysis
===============

.. code-block:: cpp
#include "BPatch.h"
#include "BPatch_addressSpace.h"
#include "BPatch_binaryEdit.h"
#include "BPatch_flowGraph.h"
#include "BPatch_function.h"
#include "BPatch_process.h"
#include <stdio.h>
using namespace std;
using namespace Dyninst;
// Create an instance of class BPatch
BPatch bpatch;
// Different ways to perform instrumentation
typedef enum { create, attach, open } accessType_t;
BPatch_addressSpace *startInstrumenting(accessType_t accessType,
const char *name, int pid,
const char *argv[]) {
BPatch_addressSpace *handle = NULL;
switch (accessType) {
case create:
handle = bpatch.processCreate(name, argv);
if (!handle) {
fprintf(stderr, "processCreate failed\n");
}
break;
case attach:
handle = bpatch.processAttach(name, pid);
if (!handle) {
fprintf(stderr, "processAttach failed\n");
}
break;
case open:
// Open the binary file and all dependencies
handle = bpatch.openBinary(name, true);
if (!handle) {
fprintf(stderr, "openBinary failed\n");
}
break;
}
return handle;
}
int binaryAnalysis(BPatch_addressSpace *app) {
BPatch_image *appImage = app->getImage();
int insns_access_memory = 0;
std::vector<BPatch_function *> functions;
appImage->findFunction("InterestingProcedure", functions);
if (functions.size() == 0) {
fprintf(stderr, "No function InterestingProcedure\n");
return insns_access_memory;
} else if (functions.size() > 1) {
fprintf(stderr, "More than one InterestingProcedure; using the first one\n");
}
BPatch_flowGraph *fg = functions[0]->getCFG();
std::set<BPatch_basicBlock *> blocks;
fg->getAllBasicBlocks(blocks);
for (auto block_iter = blocks.begin(); block_iter != blocks.end(); ++block_iter) {
BPatch_basicBlock *block = *block_iter;
std::vector<InstructionAPI::Instruction::Ptr> insns;
block->getInstructions(insns);
for (auto insn_iter = insns.begin(); insn_iter != insns.end(); ++insn_iter) {
InstructionAPI::Instruction::Ptr insn = *insn_iter;
if (insn->readsMemory() }} insn->writesMemory()) {
insns_access_memory++;
}
}
}
return insns_access_memory;
}
int main() {
// Set up information about the program to be instrumented
const char *progName = "InterestingProgram";
int progPID = 42;
const char *progArgv[] = {"InterestingProgram", "-h", NULL};
accessType_t mode = create;
// Create/attach/open a binary
BPatch_addressSpace *app = startInstrumenting(mode, progName, progPID, progArgv);
if (!app) {
fprintf(stderr, "startInstrumenting failed\n");
exit(1);
}
int memAccesses = binaryAnalysis(app);
fprintf(stderr, "Found %d memory accesses\n", memAccesses);
}
109 changes: 109 additions & 0 deletions docs/examples/cfg.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
============================
Control flow graph traversal
============================

The following complete example uses the ParseAPI to parse a binary and
dump its control flow graph in the Graphviz file format. As an example,
it can be built with G++ as follows:
``g++ -std=c++0x -o example example.cc -L<library install path> -I<headers install path> -lparseAPI -linstructionAPI -lsymtabAPI -lsymLite -ldynDwarf -ldynElf -lcommon -L<libelf path> -lelf -L<libdwarf path> -ldwarf``.
Note: this example must be compiled with C++11x support; for G++ this is
enabled with ``-std=c++0x``, and it is on by default for Visual Studio.

.. code-block:: cpp
// Example ParseAPI program; produces a graph (in DOT format) of the
// control flow graph of the provided binary.
//
// Improvements by E. Robbins (er209 at kent dot ac dot uk)
//
#include <stdio.h>
#include <map>
#include <vector>
#include <unordered_map>
#include <sstream>
#include "CodeObject.h"
#include "CFG.h"
using namespace std;
using namespace Dyninst;
using namespace ParseAPI;
int main(int argc, char * argv[])
{
map<Address, bool> seen;
vector<Function *> funcs;
SymtabCodeSource *sts;
CodeObject *co;
// Create a new binary code object from the filename argument
sts = new SymtabCodeSource( argv[1] );
co = new CodeObject( sts );
// Parse the binary
co->parse();
cout << "digraph G {" << endl;
// Print the control flow graph
const CodeObject::funclist& all = co->funcs();
auto fit = all.begin();
for(int i = 0; fit != all.end(); ++fit, i++) { // i is index for clusters
Function *f = *fit;
// Make a cluster for nodes of this function
cout << "\t subgraph cluster_" << i
<< " { \n\t\t label=\""
<< f->name()
<< "\"; \n\t\t color=blue;" << endl;
cout << "\t\t\"" << hex << f->addr() << dec
<< "\" [shape=box";
if (f->retstatus() == NORETURN)
cout << ",color=red";
cout << "]" << endl;
// Label functions by name
cout << "\t\t\"" << hex << f->addr() << dec
<< "\" [label = \""
<< f->name() << "\\n" << hex << f->addr() << dec
<< "\"];" << endl;
stringstream edgeoutput;
auto bit = f->blocks().begin();
for( ; bit != f->blocks().end(); ++bit) {
Block *b = *bit;
// Don't revisit blocks in shared code
if(seen.find(b->start()) != seen.end())
continue;
seen[b->start()] = true;
cout << "\t\t\"" << hex << b->start() << dec <<
"\";" << endl;
auto it = b->targets().begin();
for( ; it != b->targets().end(); ++it) {
if(!*it) continue;
std::string s = "";
if((*it)->type() == CALL)
s = " [color=blue]";
else if((*it)->type() == RET)
s = " [color=green]";
// Store the edges somewhere to be printed outside of the cluster
edgeoutput << "\t\""
<< hex << (*it)->src()->start()
<< "\" -> \""
<< (*it)->trg()->start()
<< "\"" << s << endl;
}
}
// End cluster
cout << "\t}" << endl;
// Print edges
cout << edgeoutput.str() << endl;
}
cout << "}" << endl;
}
98 changes: 98 additions & 0 deletions docs/examples/function_disassembly.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@

====================
Function Disassembly
====================

The following example uses ParseAPI and InstructionAPI to disassemble
the basic blocks in a function. As an example, it can be built with G++
as follows:
``g++ -std=c++0x -o code_sample code_sample.cc -L<library install path> -I<headers install path> -lparseAPI -linstructionAPI -lsymtabAPI -lsymLite -ldynDwarf -ldynElf -lcommon -L<libelf path> -lelf -L<libdwarf path> -ldwarf``.
Note: this example must be compiled with C++11x support; for G++ this is
enabled with ``-std=c++0x``, and it is on by default for Visual Studio.

.. code-block:: cpp
/*
Copyright (C) 2015 Alin Mindroc
(mindroc dot alin at gmail dot com)
This is a sample program that shows how to use InstructionAPI in order to
6 print the assembly code and functions in a provided binary.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#include <iostream>
#include "CodeObject.h"
#include "InstructionDecoder.h"
using namespace std;
using namespace Dyninst;
using namespace ParseAPI;
using namespace InstructionAPI;
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <binary path>\n", argv[0]);
return -1;
}
char *binaryPath = argv[1];
SymtabCodeSource *sts;
CodeObject *co;
Instruction::Ptr instr;
SymtabAPI::Symtab *symTab;
std::string binaryPathStr(binaryPath);
bool isParsable = SymtabAPI::Symtab::openFile(symTab, binaryPathStr);
if(isParsable == false){
const char *error = "error: file can not be parsed";
cout << error;
return - 1;
}
sts = new SymtabCodeSource(binaryPath);
co = new CodeObject(sts);
//parse the binary given as a command line arg
co->parse();
//get list of all functions in the binary
const CodeObject::funclist &all = co->funcs();
if(all.size() == 0){
const char *error = "error: no functions in file";
cout << error;
return - 1;
}
auto fit = all.begin();
Function *f = *fit;
//create an Instruction decoder which will convert the binary opcodes to strings
InstructionDecoder decoder(f->isrc()->getPtrToInstruction(f->addr()),
InstructionDecoder::maxInstructionLength,
f->region()->getArch());
for(;fit != all.end(); ++fit){
Function *f = *fit;
//get address of entry point for current function
Address crtAddr = f->addr();
int instr_count = 0;
instr = decoder.decode((unsigned char *)f->isrc()->getPtrToInstruction(crtAddr));
auto fbl = f->blocks().end();
fbl--;
Block *b = *fbl;
Address lastAddr = b->last();
//if current function has zero instructions, don’t output it
if(crtAddr == lastAddr)
continue;
cout << "\n\n\"" << f->name() << "\" :";
while(crtAddr < lastAddr){
//decode current instruction
instr = decoder.decode((unsigned char *)f->isrc()->getPtrToInstruction(crtAddr));
cout << "\n" << hex << crtAddr;
cout << ": \"" << instr->format() << "\"";
//go to the address of the next instruction
crtAddr += instr->size();
instr_count++;
}
}
return 0;
}

0 comments on commit fa5fa45

Please sign in to comment.