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.

108 lines
3.0 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 <stdio.h>
#include "pin.H"
// unmatched_syscall_ip keeps track of the IP of the last syscall encounted.
// It is set before the syscall and reset afterward. Therefore, if the
// afterward instrumentation is bypassed, which could happen due to the funny
// control flow in sysenter on x86, then we will see a non-zero value in
// unmatched_syscall_ip when we execute the next syscall.
ADDRINT unmatched_syscall_ip = 0;
THREADID myThread = INVALID_THREADID;
VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
{
if (myThread == INVALID_THREADID)
{
myThread = threadid;
}
}
VOID BeforeSyscall(ADDRINT ip)
{
if (unmatched_syscall_ip != 0)
{
printf("AfterSyscall() is not executed after the syscall at %lx\n",
(unsigned long)unmatched_syscall_ip);
fflush(stdout);
exit(1);
}
unmatched_syscall_ip = ip;
}
VOID AfterSyscall(ADDRINT ip)
{
unmatched_syscall_ip = 0;
}
VOID SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
{
if (threadIndex == myThread)
{
BeforeSyscall(PIN_GetContextReg(ctxt, REG_INST_PTR));
}
}
VOID SyscallExit(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
{
if (threadIndex == myThread)
{
AfterSyscall(PIN_GetContextReg(ctxt, REG_INST_PTR));
}
}
VOID Instruction(INS ins, VOID *v)
{
// For O/S's (macOS*) that don't support PIN_AddSyscallEntryFunction(),
// instrument the system call instruction.
if (INS_IsSyscall(ins) && INS_IsValidForIpointAfter(ins))
{
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)BeforeSyscall, IARG_INST_PTR, IARG_END);
INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)AfterSyscall, IARG_INST_PTR, IARG_END);
}
}
static VOID OnContextChange(THREADID threadIndex, CONTEXT_CHANGE_REASON reason, const CONTEXT *ctxtFrom,
CONTEXT *ctxtTo, INT32 info, VOID *v)
{
// We may jump to UPC/signal while in system call (i.e. before it is return)
// The code of this UPC may in its turn call another system call which will
// see unmatched_syscall_ip != 0.
unmatched_syscall_ip = 0;
}
int main(INT32 argc, CHAR **argv)
{
PIN_Init(argc, argv);
PIN_AddThreadStartFunction(ThreadStart, NULL);
INS_AddInstrumentFunction(Instruction, NULL);
PIN_AddSyscallEntryFunction(SyscallEntry, NULL);
PIN_AddSyscallExitFunction(SyscallExit, NULL);
PIN_AddContextChangeFunction(OnContextChange, NULL);
// Never returns
PIN_StartProgram();
return 0;
}