2
votes

I am using Intel PIN to modify an instruction in my application. I am using the Safecopy() example from this link as a reference:

https://software.intel.com/sites/landingpage/pintool/docs/81205/Pin/html/index.html#SafeCopy

I have the following sample C program:

int main()
{
    asm(".byte 0x16");
    return 0;
}

0x16 is illegal in x86_64 and when I run the executable it displays the following error as expected:

Illegal instruction (core dumped)

I have a pintool which takes the above executable as input and modifies the illegal instruction 0x16 to do something else.

My Pintool is as follows:

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

using namespace std;

KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI");

FILE * op;

//====================================================================
// Analysis Routines
//====================================================================

VOID analysis_routine(VOID *ip, UINT32 size) 
{ 

    fprintf(op,"16 came to analysis routine\n\n");
}


//====================================================================
// Instrumentation Routines
//====================================================================

VOID Instruction(INS ins, void *v) 
{

    UINT8 opcodeBytes[15];

    UINT64 fetched = PIN_SafeCopy(&opcodeBytes[0],(void *)INS_Address(ins),INS_Size(ins));

    if (fetched != INS_Size(ins))
        fprintf(op,"\nBad\n");

    else 
    {
        if(opcodeBytes[0]==0x16)
        {

            fprintf(op,"\n16 came to instrumentation routine\n");

            INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, IARG_INST_PTR, IARG_UINT64, INS_Size(ins) , IARG_END);
            INS_Delete(ins);
        }
    }
}

VOID Fini(INT32 code, VOID *v) 
{
}

INT32 Usage() {
    PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n");
    return -1;
}

int main(int argc, char *argv[]) 
{

    op = fopen("test.out", "w");

    if (PIN_Init(argc, argv)) 
        return Usage();

    PIN_InitSymbols();
    INS_AddInstrumentFunction(Instruction, 0);
    PIN_AddFiniFunction(Fini, 0);
    PIN_StartProgram();
    return 0;
}

According to my understanding the instrumentation routine Instruction is executed everytime a new instruction is encountered and according to my code, the analysis routine is called before the instruction is executed as I am using the IPOINT_BEFORE argument in my instrumentation function to invoke the analysis routine. I am thus checking for my opcode and if it is 0x16, then I am invoking my analysis routine and deleting my original instruction. Since the insturction was illegal and it has been deleted, my trace should proceed futher without any problems.

However even with this logic, it seems my illegal instruction is being executed and my program crashes and gives the same illegal instruction error. I am not able to understand the problem as I seem to be deleting the instruction before it executes and I am using the same example from the Pin tutorial.

Any ideas if I am invoking anything wrong? Also please correct me if I am wrong anywhere above. According to my understanding the instrumentation routine is invoked before the instruction executes and thus I can modify the instruction that time also. Please correct me if I am wrong.

2
Are you successfully replacing the right byte at the right address? Are you certain you are only replacing the one byte that is causing you trouble? Are you only replacing that single byte an no other byte pattern? 0x16 may not be a legal instruction by itself but how are you making sure it is not being interpreted as part of a larger instruction?nitzanms

2 Answers

1
votes

I don't know what's going wrong here, but here's what I'd do: I would start with printing far more information about the instruction in the instrumentation routine.

  • How long is it?
  • What address did this instruction have? Print the address of main() in the test program to see if the two are close to one another.
  • What are the other instruction bytes? Do they happen to be bytes matching the instructions that follow the illegal bytes?

Aditionally:

  • Make sure the output file is flushed after every print, to ensure that the illegal instruction failure doesn't happen to mask your debug prints
  • I recommend catching the SIGILL signal that your program is probably getting and making sure it's happening in the same place with and without Pin.
0
votes

You need to realize that INS_Delete() is called at instrumentation time, i.e. before the instruction is actually executed, but also before the call of your instrumentation routine. The order in which events occur is as follow:

INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, ...);
INS_Delete(ins);
analysis_routine(); /* <= BOOM ! ins had been deleted just before... */

When INS_Delete(ins) is called, you need to remove all the instrumentation that goes with it otherwise your tool is not coherent. Assuming the instrumentation remains, the instruction that will be associated with the instrumentation routine will not be the one expected, hence the crash.

To understand this better (which is not easy to get right the first time) you might want to read again how pin works.

EDIT: According to some official pintools packaged with the tool (see comments below), the instrument then delete pattern is a regular pattern of PIN.