You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
378 lines
10 KiB
378 lines
10 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <iostream>
|
|
#include <ostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <iomanip>
|
|
|
|
#include "pin.H"
|
|
#include "CallStack.H"
|
|
#include "syscall_names.H"
|
|
#include "argv_readparam.h"
|
|
|
|
///////////////////////// Prototypes //////////////////////////////////////////
|
|
|
|
const string& Target2RtnName(ADDRINT target);
|
|
const string& Target2LibName(ADDRINT target);
|
|
|
|
///////////////////////// Global Variables ////////////////////////////////////
|
|
|
|
ostream *Output;
|
|
|
|
CallStack callStack(Target2RtnName, Target2LibName);
|
|
|
|
bool main_entry_seen = false;
|
|
bool prevIpDoesPush = FALSE;
|
|
|
|
set<void *> addrsToDump;
|
|
set<ADDRINT> pushIps;
|
|
|
|
///////////////////////// Utility functions ///////////////////////////////////
|
|
void RecordPush (INS ins)
|
|
{
|
|
pushIps.insert(INS_Address (ins));
|
|
}
|
|
|
|
bool IpDoesPush (ADDRINT ip)
|
|
{
|
|
return (pushIps.find(ip) != pushIps.end());
|
|
}
|
|
|
|
const string& Target2RtnName(ADDRINT target)
|
|
{
|
|
const string & name = RTN_FindNameByAddress(target);
|
|
|
|
if (name == "")
|
|
return *new string("[Unknown routine]");
|
|
else
|
|
return *new string(name);
|
|
}
|
|
|
|
const string& Target2LibName(ADDRINT target)
|
|
{
|
|
PIN_LockClient();
|
|
|
|
const RTN rtn = RTN_FindByAddress(target);
|
|
static const string _invalid_rtn("[Unknown image]");
|
|
|
|
string name;
|
|
|
|
if( RTN_Valid(rtn) ) {
|
|
name = IMG_Name(SEC_Img(RTN_Sec(rtn)));
|
|
} else {
|
|
name = _invalid_rtn;
|
|
}
|
|
|
|
PIN_UnlockClient();
|
|
|
|
return *new string(name);
|
|
}
|
|
|
|
///////////////////////// Analysis Functions //////////////////////////////////
|
|
|
|
void A_RegisterAddr(void *addr)
|
|
{
|
|
addrsToDump.insert((void *)addr);
|
|
}
|
|
|
|
void A_UnregisterAddr(void *addr)
|
|
{
|
|
if( addrsToDump.find(addr) == addrsToDump.end() ) {
|
|
cerr << "MAID ERROR: unregistered address " << hex << addr << dec << endl;
|
|
} else {
|
|
addrsToDump.erase(addr);
|
|
}
|
|
}
|
|
|
|
|
|
void ProcessInst (ADDRINT ip)
|
|
{
|
|
prevIpDoesPush = IpDoesPush (ip);
|
|
}
|
|
|
|
void A_ProcessSyscall(ADDRINT ip, UINT32 num, ADDRINT sp, ADDRINT arg0)
|
|
{
|
|
if( main_entry_seen ) {
|
|
//cout << callStack.Depth() << ":" << SYS_SyscallName(num) << endl;
|
|
}
|
|
//callStack.ProcessSysCall(sp, target);
|
|
}
|
|
|
|
void A_ProcessDirectCall(ADDRINT ip, ADDRINT target, ADDRINT sp)
|
|
{
|
|
//cout << "Direct call: " << Target2String(target) << endl;
|
|
callStack.ProcessCall(sp, target);
|
|
}
|
|
|
|
void A_ProcessIndirectCall(ADDRINT ip, ADDRINT target, ADDRINT sp)
|
|
{
|
|
//cout << "Indirect call: " << Target2String(target) << endl;
|
|
callStack.ProcessCall(sp, target);
|
|
}
|
|
|
|
static void
|
|
A_ProcessStub(ADDRINT ip, ADDRINT target, ADDRINT sp)
|
|
{
|
|
//cout << "Instrumenting stub: " << Target2String(target) << endl;
|
|
//cout << "STUB: ";
|
|
//cout << Target2RtnName(target) << endl;
|
|
callStack.ProcessCall(sp, target);
|
|
}
|
|
|
|
static void
|
|
A_ProcessReturn(ADDRINT ip, ADDRINT sp) {
|
|
callStack.ProcessReturn(sp, prevIpDoesPush);
|
|
}
|
|
|
|
static void
|
|
A_EnterMainImage(ADDRINT ip, ADDRINT target, ADDRINT sp)
|
|
{
|
|
|
|
//assert(current_pc == main_entry_addr);
|
|
//cout << "main" << endl;
|
|
main_entry_seen = true;
|
|
callStack.ProcessMainEntry(sp, target);
|
|
}
|
|
|
|
static void
|
|
A_DoMem(bool isStore, void *ea, ADDRINT pc)
|
|
{
|
|
string filename;
|
|
int lineno;
|
|
if( addrsToDump.find(ea) != addrsToDump.end() )
|
|
{
|
|
PIN_LockClient();
|
|
|
|
PIN_GetSourceLocation(pc, NULL, &lineno, &filename);
|
|
|
|
PIN_UnlockClient();
|
|
|
|
*Output << (isStore ? "store" : "load")
|
|
<< " pc=" << (void*)pc
|
|
<< " ea=" << ea << endl;
|
|
if( filename != "") {
|
|
*Output << filename << ":" << lineno;
|
|
} else {
|
|
*Output << "UNKNOWN:0";
|
|
}
|
|
*Output << endl;
|
|
callStack.DumpStack(Output);
|
|
*Output << endl;
|
|
}
|
|
}
|
|
|
|
///////////////////////// Instrumentation functions ///////////////////////////
|
|
|
|
static BOOL IsPLT(TRACE trace)
|
|
{
|
|
RTN rtn = TRACE_Rtn(trace);
|
|
|
|
// All .plt thunks have a valid RTN
|
|
if (!RTN_Valid(rtn))
|
|
return FALSE;
|
|
|
|
if (".plt" == SEC_Name(RTN_Sec(rtn)))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static void I_Trace(TRACE trace, void *v)
|
|
{
|
|
|
|
//FIXME if (PIN_IsSignalHandler()) {Sequence_ProcessSignalHandler(head)};
|
|
|
|
for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
|
|
|
|
INS tail = BBL_InsTail(bbl);
|
|
|
|
// All memory reads/writes
|
|
for( INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins) ) {
|
|
|
|
if( INS_IsMemoryRead(ins)
|
|
|| INS_HasMemoryRead2(ins)
|
|
|| INS_IsMemoryWrite(ins)
|
|
) {
|
|
INS_InsertCall(ins, IPOINT_BEFORE,
|
|
(AFUNPTR)A_DoMem,
|
|
IARG_BOOL, INS_IsMemoryWrite(ins),
|
|
(INS_IsMemoryWrite(ins) ? IARG_MEMORYWRITE_EA : (INS_IsMemoryRead(ins) ? IARG_MEMORYREAD_EA : IARG_MEMORYREAD2_EA)),
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
}
|
|
#if defined(TARGET_IA32) && defined (TARGET_WINDOWS)
|
|
// on ia-32 windows need to identify
|
|
// push
|
|
// ret
|
|
// in order to process callstack correctly
|
|
if (ins != tail)
|
|
{
|
|
INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
|
|
(AFUNPTR)ProcessInst,
|
|
IARG_INST_PTR,
|
|
IARG_END);
|
|
if (INS_Opcode(ins)==XED_ICLASS_PUSH)
|
|
{
|
|
RecordPush (ins);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
// All calls and returns
|
|
if( INS_IsSyscall(tail) ) {
|
|
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
|
|
(AFUNPTR)A_ProcessSyscall,
|
|
IARG_INST_PTR,
|
|
IARG_SYSCALL_NUMBER,
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_SYSARG_VALUE, 0,
|
|
IARG_END);
|
|
|
|
} else {
|
|
if( INS_IsCall(tail) ) {
|
|
if( INS_IsDirectControlFlow(tail) ) {
|
|
ADDRINT target = INS_DirectControlFlowTargetAddress(tail);
|
|
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
|
|
(AFUNPTR)A_ProcessDirectCall,
|
|
IARG_INST_PTR,
|
|
IARG_ADDRINT, target,
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_END);
|
|
} else if( !IsPLT(trace) ) {
|
|
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
|
|
(AFUNPTR)A_ProcessIndirectCall,
|
|
IARG_INST_PTR,
|
|
IARG_BRANCH_TARGET_ADDR,
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_END);
|
|
}
|
|
}
|
|
if( IsPLT(trace) ) {
|
|
INS_InsertCall(tail, IPOINT_BEFORE,
|
|
(AFUNPTR)A_ProcessStub,
|
|
IARG_INST_PTR,
|
|
IARG_BRANCH_TARGET_ADDR,
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_END);
|
|
}
|
|
if( INS_IsRet(tail) ) {
|
|
INS_InsertPredicatedCall(tail, IPOINT_BEFORE,
|
|
(AFUNPTR)A_ProcessReturn,
|
|
IARG_INST_PTR,
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_END);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
I_ImageLoad(IMG img, void *v)
|
|
{
|
|
static bool main_rtn_instrumented = false;
|
|
|
|
if( !main_rtn_instrumented ) {
|
|
RTN rtn = RTN_FindByName(img, "main");
|
|
if( rtn == RTN_Invalid() ) {
|
|
rtn = RTN_FindByName(img, "__libc_start_main");
|
|
}
|
|
// Instrument main
|
|
if( rtn != RTN_Invalid() ) {
|
|
main_rtn_instrumented = true;
|
|
RTN_Open(rtn);
|
|
RTN_InsertCall(rtn, IPOINT_BEFORE,
|
|
(AFUNPTR)A_EnterMainImage,
|
|
IARG_INST_PTR,
|
|
IARG_ADDRINT, RTN_Address(rtn),
|
|
IARG_REG_VALUE, REG_STACK_PTR,
|
|
IARG_END);
|
|
RTN_Close(rtn);
|
|
}
|
|
}
|
|
|
|
for( SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym) ) {
|
|
if( strstr(SYM_Name(sym).c_str(), "MAID_register_address" ) ) {
|
|
RTN rtn;
|
|
rtn = RTN_FindByName(img, SYM_Name(sym).c_str());
|
|
ASSERTX(RTN_Valid(rtn));
|
|
|
|
RTN_Open(rtn);
|
|
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)A_RegisterAddr, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END);
|
|
RTN_Close(rtn);
|
|
} else if( strstr(SYM_Name(sym).c_str(), "MAID_unregister_address" ) ) {
|
|
RTN rtn;
|
|
rtn = RTN_FindByName(img, SYM_Name(sym).c_str());
|
|
ASSERTX(RTN_Valid(rtn));
|
|
RTN_Open(rtn);
|
|
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)A_UnregisterAddr, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END);
|
|
RTN_Close(rtn);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////// main ////////////////////////////////////////////////
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
char *strTmp;
|
|
|
|
PIN_Init(argc, argv);
|
|
PIN_InitSymbols();
|
|
|
|
if( (strTmp = argv_getString(argc, argv, "--outfile=", NULL)) != NULL ) {
|
|
if( !(Output = new ofstream(strTmp)) ) {
|
|
perror(strTmp);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
Output = &cout;
|
|
}
|
|
|
|
if( (strTmp = argv_getString(argc, argv, "--addrfile=", NULL)) != NULL ) {
|
|
string s;
|
|
ifstream infile(strTmp);
|
|
if( !infile ) {
|
|
perror(s.c_str());
|
|
exit(1);
|
|
}
|
|
infile >> hex;
|
|
while( !infile.eof() ) {
|
|
static void *addr;
|
|
infile >> addr;
|
|
addrsToDump.insert((void *)addr);
|
|
}
|
|
}
|
|
|
|
IMG_AddInstrumentFunction(I_ImageLoad, 0);
|
|
TRACE_AddInstrumentFunction(I_Trace, 0);
|
|
PIN_StartProgram();
|
|
}
|