我正在使用英特尔PIN修改我的应用程序中的指令。我使用此链接中的Safecopy()示例作为参考:
https://software.intel.com/sites/landingpage/pintool/docs/81205/Pin/html/index.html#SafeCopy
我有以下示例C程序:
int main()
{
asm(".byte 0x16");
return 0;
}
0x16在x86_64中是非法的,当我运行可执行文件时,它会按预期显示以下错误:
Illegal instruction (core dumped)
我有一个pintool,它将上述可执行文件作为输入,并修改非法指令0x16以执行其他操作。
我的Pintool如下:
#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;
}
根据我的理解,每次遇到新指令时都会执行检测例程指令,根据我的代码,在执行指令之前调用分析例程,因为我在检测函数中使用IPOINT_BEFORE参数来调用分析常规。我正在检查我的操作码,如果它是0x16,那么我正在调用我的分析例程并删除我的原始指令。由于这种行为是非法的并且已被删除,我的追踪应该继续进行,没有任何问题。
然而,即使有了这个逻辑,似乎我的非法指令正在执行,我的程序崩溃并给出相同的非法指令错误。我无法理解这个问题,因为我似乎在执行之前删除了指令,并且我使用了Pin教程中的相同示例。
如果我调用任何错误的任何想法?如果我在上面的任何地方错了,请纠正我。根据我的理解,在执行指令之前调用检测例程,因此我也可以修改时间指令。如果我错了,请纠正我。
答案 0 :(得分:1)
我不知道这里出了什么问题,但这就是我要做的事情:我首先要在仪器例程中打印更多关于指令的信息。< / p>
的方法,另外:
答案 1 :(得分:0)
您需要意识到INS_Delete()是在检测时调用的,即在实际执行指令之前,也是在调用检测例程之前调用的。事件发生的顺序如下:
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)analysis_routine, ...);
INS_Delete(ins);
analysis_routine(); /* <= BOOM ! ins had been deleted just before... */
当调用INS_Delete(ins)时,您需要删除所有与它一起使用的检测,否则您的工具不一致。假设仪器仍然存在,那么与仪器例程相关联的指令将不是预期的指令,因此会发生崩溃。
为了更好地理解这一点(第一次就不容易理解),您可能想再次阅读pin works的内容。
编辑:根据该工具随附的一些官方pintools(请参阅下面的评论),仪器然后删除模式是PIN的常规模式。