Modificar instrucciones de aplicación en PIN

Estoy usando el PIN de Intel para modificar una instrucción en mi aplicación. Estoy usando el ejemplo de Safecopy () de este enlace como referencia.

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

Tengo el siguiente progtwig de muestra C

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

0x16 es ilegal en x86_64 y cuando ejecuto el ejecutable muestra el siguiente error como se esperaba:

 Illegal instruction (core dumped) 

Tengo un pintool que toma el ejecutable anterior como entrada y modifica la instrucción ilegal 0x16 para hacer otra cosa.

Mi Pintool es como sigue:

 #include "pin.H" #include  #include  using namespace std; KNOB 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; } 

Según entiendo la rutina de instrumentación, la instrucción se ejecuta cada vez que se encuentra una nueva instrucción y de acuerdo con mi código, se llama a la rutina de análisis antes de que se ejecute la instrucción porque estoy utilizando el argumento IPOINT_BEFORE en mi función de instrumentación para invocar la rutina de análisis. Por lo tanto, estoy revisando mi código de operación y si es 0x16, entonces estoy invocando mi rutina de análisis y borrando mi instrucción original. Dado que la instalación fue ilegal y se ha eliminado, mi rastreo debería continuar sin problemas.

Sin embargo, incluso con esta lógica, parece que mi instrucción ilegal se está ejecutando y mi progtwig falla y da el mismo error de instrucción ilegal. No puedo entender el problema ya que parece que estoy eliminando la instrucción antes de que se ejecute y estoy usando el mismo ejemplo del tutorial Pin.

¿Alguna idea si estoy invocando algo mal? También por favor corríjame si estoy equivocado en cualquier lugar arriba. Según tengo entendido, la rutina de instrumentación se invoca antes de que se ejecute la instrucción y, por lo tanto, también puedo modificar la instrucción esa vez. Por favor, corríjame si estoy equivocado.

No sé qué está mal aquí, pero esto es lo que haría: Comenzaría imprimiendo mucha más información sobre las instrucciones en la rutina de instrumentación.

  • Cuanto tiempo es
  • ¿Qué dirección tenía esta instrucción? Imprima la dirección de main () en el progtwig de prueba para ver si los dos están cerca uno del otro.
  • ¿Cuáles son los otros bytes de instrucciones? ¿Sucede que sean bytes que coincidan con las instrucciones que siguen a los bytes ilegales?

Adicionalmente

  • Asegúrese de que el archivo de salida se vacíe después de cada impresión, para asegurarse de que la falla de instrucción ilegal no ocurra para enmascarar sus impresiones de depuración
  • Recomiendo capturar la señal SIGILL que probablemente esté recibiendo su progtwig y asegurarse de que esté sucediendo en el mismo lugar con y sin Pin.

Debe darse cuenta de que se llama a INS_Delete () en el momento de la instrumentación, es decir, antes de que se ejecute realmente la instrucción, pero también antes de la llamada de su rutina de instrumentación. El orden en que ocurren los eventos es el siguiente:

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

Cuando se llama a INS_Delete (ins), debe eliminar todos los instrumentos que la acompañan, de lo contrario, su herramienta no es coherente. Suponiendo que la instrumentación permanezca, la instrucción que se asociará con la rutina de instrumentación no será la esperada, por lo tanto, la falla.

Para comprender mejor esto (lo que no es fácil de entender correctamente la primera vez), es posible que desee volver a leer cómo funciona el pin .

EDITAR: De acuerdo con algunos pintools oficiales empaquetados con la herramienta (vea los comentarios a continuación), el instrumento y luego eliminar el patrón es un patrón regular de PIN.