user3464190
user3464190

Reputation: 79

count consecutive basic block with BBL_NUMins < 7

I'm new in pintool and I want count number of consecutive Basic Block with BBL_NumINS < 7 and with specific Tail instruction such as Indirect Jump or Indirect Call or ret. So I wrote this code

static UINT32 consecutiveBasicBlockscount = 0;
//------------------------------------------------------------------------------------------
// This function is called before every block
VOID docount()
{
    OutFile << "Inc Consecutive Basic Block Counter From " <<consecutiveBasicBlockscount<<"\tto "<<consecutiveBasicBlockscount+1<< endl;
    OutFile << "----------------------------------------------------------------------------------------" <<endl;
    consecutiveBasicBlockscount += 1;
}

for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
    {
        INS insTail =  BBL_InsTail(bbl);              
        if(INS_IsIndirectBranchOrCall(BBL_InsTail(bbl)))
            {
                if((!INS_IsCall(insTail) && !INS_HasFallThrough(insTail) && !INS_IsHalt(insTail) && !INS_IsRet(insTail))||(INS_IsCall(insTail) && !INS_HasFallThrough(insTail) && !INS_IsHalt(insTail) && !INS_IsRet(insTail)) || INS_IsRet(insTail))
                    {
                        if (BBL_NumIns(bbl) < 7)
                            {
                                OutFile << "*****"<< hex << BBL_Address(bbl) <<"*****"<<endl;
                                for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins=INS_Next(ins))
                                    {
                                        OutFile << INS_Disassemble(ins) <<endl;
                                    }
                                OutFile << "********************************" <<endl;

                                BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END);
                  }
                             }
          }
   }

the output file

----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 0    to 1
----------------------------------------------------------------------------------------
*****b6709ba0*****
mov eax, 0xc9
call dword ptr gs:[0x10]
********************************
Inc Consecutive BasicBlock Counter From 1    to 2
----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 2    to 3
----------------------------------------------------------------------------------------
Inc Consecutive BasicBlock Counter From 3    to 4
----------------------------------------------------------------------------------------
*****b6709bac*****
ret
********************************
Inc Consecutive BasicBlock Counter From 4    to 5
----------------------------------------------------------------------------------------

I test this pintool against firefox. Why pin does not show Basic Block, when Counter is 0, 2, 3?

Upvotes: 1

Views: 828

Answers (1)

Jakob Pogulis
Jakob Pogulis

Reputation: 1210

Unless I completely misunderstood your question you want to find all instances during a concrete execution of a binary where multiple basic blocks with an indirect call/jump or ret instruction as the final instruction (tail) is executed after each other.

When starting to write PIN tools the difference between analysis code and instrumentation code can be quite confusing. Even though PIN is a dynamic binary instrumentation framework the code you write can either exist in a static context or in a dynamic context. Instrumentation code (mapped via the TRACE_AddInstrumentFunction hook for example) execute in a static context, which means that they are not executed every time a basic block is encountered, but only when a new basic block needs to be instrumented. Analysis code (mapped via the BBL_InsertCall hook for example) on the other hand exists in a dynamic context, which means that it will be executed every time a basic block is executed. In fact, the binary under analysis is recompiled in memory (called a code cache) together with the analysis code in the PIN tool.

If I've understood your question correctly your code kind of mixes these contexts in a way which causes the output for 0-1 3-4 to be an accident more than anything else. I've written a simple PIN tool to list all the chains of indirect basic blocks of length 2 or more, modifying it to print the asm instructions should be easy for you with a little more research into the BBL_InsertCall documentation.


main

This code instructs PIN to call the function instrument_trace every time a basic block that has not already been instrumented is discovered. For simplicity I also declare a couple of global variables to simplify the structure.

#include "pin.H"
#include <iostream>
#include <vector>

std::vector<ADDRINT>* consecutive_indirect_bbls = new std::vector<ADDRINT>();
std::ostream& Output = std::cout;

int main(int argc, char *argv[]) {
    if (PIN_Init(argc, argv) == 0) {
        TRACE_AddInstrumentFunction(instrument_trace, NULL);
        PIN_StartProgram();
    }

    return 0;
}

instrument_trace

This is the code that is executed every time a basic block that hasn't already been instrumented is discovered by PIN. It is basically the same code that you provided in your question with a few important changes. The instrumentation code is only meant to set up the analysis code so that the execution flow of the binary under analysis can be monitored. The binary under analysis is actually not executed when this code is executed, but could be seen as "paused".

In order to print the call chains we're interested in we also need to insert an analysis call to those basic blocks that would immediately follow such a call chain since we have no other method of displaying the call chain, or know if there was a break in the chain. This logic should be quite obvious once you've played around with it a little bit.

VOID instrument_trace(TRACE trace, VOID* vptr) {
    for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
        INS tail = BBL_InsTail(bbl);
        if ((INS_IsIndirectBranchOrCall(tail) || INS_IsRet(tail))
                && BBL_NumIns(bbl) < 7) {
            BBL_InsertCall(bbl, IPOINT_BEFORE,
                    (AFUNPTR) analysis_indirect_bbl,
                    IARG_ADDRINT, BBL_Address(bbl),
                    IARG_END);
        } else {
            BBL_InsertCall(bbl, IPOINT_BEFORE,
                    (AFUNPTR) analysis_print_vector,
                    IARG_END);
        }
    }
}

analysis_indirect_bbl

This function is called every time a basic block that ends in an indirect call/jump or ret instruction is executed in the binary that we are monitoring. Whenever this happens we push the starting address of that basic block to the global vector we use to keep track of these chains.

VOID analysis_indirect_bbl(ADDRINT address) {
    consecutive_indirect_bbls->push_back(address);
}

analysis_print_vector

This is just a function to print the call chains we are interested in to Output (std::out in this example).

VOID analysis_print_vector() {
    if (consecutive_indirect_bbls->size() > 2) {
        for (unsigned int i = 0;
                i < consecutive_indirect_bbls->size();
                ++i) {
            Output << "0x" << std::hex
                    << consecutive_indirect_bbls->at(i) << " -> ";
        }

        Output << "END" << std::endl;
        consecutive_indirect_bbls->clear();
    } else if (!consecutive_indirect_bbls->empty()) {
        consecutive_indirect_bbls->clear();
    }
}

When testing the PIN tool I would strongly advice against running a program such as firefox since it will be impossible to test changes against the exact same execution flow. I usually test against gzip myself since it is really easy to control the length of the execution.

$ lorem -w 500000 > sample.data
$ cp sample.data sample_exec-001.data
$ pin -injection child -t obj-ia32/cbbl.so -- /bin/gzip -9 sample_exec-001.data

0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775c7a8 -> 0xb774e5ab -> 0xb7745140 -> END
0xb775b9ca -> 0xb7758d7f -> 0xb77474e2 -> END
0xb5eac46b -> 0xb5eb2127 -> 0xb5eb2213 -> END
0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END
0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END

...

0xb5eac46b -> 0xb5eb3340 -> 0xb5eb499e -> END

Upvotes: 1

Related Questions