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.

202 lines
6.1 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 <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <map>
#include "pin.H"
#include "instlib.H"
using std::iostream;
using std::ostringstream;
std::map<ADDRINT, std::string> disAssemblyMap;
static ADDRINT dl_debug_state_Addr = 0;
static ADDRINT dl_debug_state_AddrEnd = 0;
static BOOL justFoundDlDebugState = FALSE;
static char nibble_to_ascii_hex(UINT8 i) {
if (i<10) return i+'0';
if (i<16) return i-10+'A';
return '?';
}
static void print_hex_line(char* buf, const UINT8* array, const int length) {
int n = length;
int i=0;
if (length == 0)
n = XED_MAX_INSTRUCTION_BYTES;
for( i=0 ; i< n; i++) {
buf[2*i+0] = nibble_to_ascii_hex(array[i]>>4);
buf[2*i+1] = nibble_to_ascii_hex(array[i]&0xF);
}
buf[2*i]=0;
}
static string
disassemble(UINT64 start, UINT64 stop) {
UINT64 pc = start;
xed_state_t dstate;
xed_syntax_enum_t syntax = XED_SYNTAX_INTEL;
xed_error_enum_t xed_error;
xed_decoded_inst_t xedd;
ostringstream os;
if (sizeof(ADDRINT) == 4)
xed_state_init(&dstate,
XED_MACHINE_MODE_LEGACY_32,
XED_ADDRESS_WIDTH_32b,
XED_ADDRESS_WIDTH_32b);
else
xed_state_init(&dstate,
XED_MACHINE_MODE_LONG_64,
XED_ADDRESS_WIDTH_64b,
XED_ADDRESS_WIDTH_64b);
/*while( pc < stop )*/ {
xed_decoded_inst_zero_set_mode(&xedd, &dstate);
UINT32 len = 15;
if (stop - pc < 15)
len = stop-pc;
xed_error = xed_decode(&xedd, reinterpret_cast<const UINT8*>(pc), len);
bool okay = (xed_error == XED_ERROR_NONE);
iostream::fmtflags fmt = os.flags();
os << std::setfill('0')
<< "XDIS "
<< std::hex
<< std::setw(sizeof(ADDRINT)*2)
<< pc
<< std::dec
<< ": "
<< std::setfill(' ')
<< std::setw(4);
if (okay) {
char buffer[200];
unsigned int dec_len, sp;
os << xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd));
dec_len = xed_decoded_inst_get_length(&xedd);
print_hex_line(buffer, reinterpret_cast<UINT8*>(pc), dec_len);
os << " " << buffer;
for ( sp=dec_len; sp < 12; sp++) // pad out the instruction bytes
os << " ";
os << " ";
memset(buffer,0,200);
int dis_okay = xed_format_context(syntax, &xedd, buffer, 200, pc, 0, 0);
if (dis_okay)
os << buffer << endl;
else
os << "Error disasassembling pc 0x" << std::hex << pc << std::dec << endl;
pc += dec_len;
}
else { // print the byte and keep going.
UINT8 memval = *reinterpret_cast<UINT8*>(pc);
os << "???? " // no extension
<< std::hex
<< std::setw(2)
<< std::setfill('0')
<< static_cast<UINT32>(memval)
<< std::endl;
pc += 1;
}
os.flags(fmt);
}
return os.str();
}
VOID ImageLoad(IMG img, VOID *v)
{
printf ("ImageLoad %s\n", IMG_Name(img).c_str());
for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
{
for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn))
{
if (strcmp(RTN_Name(rtn).c_str(), "_dl_debug_state") == 0)
{
printf (" RTN %s at %p\n", RTN_Name(rtn).c_str(), reinterpret_cast<void *>(RTN_Address(rtn)));
printf (" ** found _dl_debug_state\n");
dl_debug_state_Addr = RTN_Address(rtn);
justFoundDlDebugState = TRUE;
}
else if (justFoundDlDebugState)
{
printf (" RTN %s at %p\n", RTN_Name(rtn).c_str(), reinterpret_cast<void *>(RTN_Address(rtn)));
dl_debug_state_AddrEnd = RTN_Address(rtn);
justFoundDlDebugState = FALSE;
printf (" ** _dl_debug_state from %p to %p\n", reinterpret_cast<void *>(dl_debug_state_Addr), reinterpret_cast<void *>(dl_debug_state_AddrEnd));
}
}
}
}
static VOID AtBranch(ADDRINT ip, ADDRINT target, BOOL taken)
{
if (target >= dl_debug_state_Addr && target < dl_debug_state_AddrEnd)
{
string s = disassemble ((ip),(ip)+15);
printf (" branch %s branches to range of interest %p taken %d\n", s.c_str(), reinterpret_cast<void *>(target), taken);
fflush (stdout);
}
if (ip >= dl_debug_state_Addr && ip < dl_debug_state_AddrEnd)
{
string s = disassemble ((ip),(ip)+15);
printf (" instruction in range of interest executed %s\n", s.c_str());
fflush (stdout);
}
}
static VOID AtNonBranch(ADDRINT ip)
{
if (ip >= dl_debug_state_Addr && ip < dl_debug_state_AddrEnd)
{
string s = disassemble ((ip),(ip)+15);
printf (" instruction in range of interest executed %s\n", s.c_str());
fflush (stdout);
}
}
static VOID Instruction(INS ins, VOID *v)
{
//disAssemblyMap[INS_Address(ins)] = INS_Disassemble(ins);
if (INS_IsControlFlow(ins))
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)AtBranch, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END);
else
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)AtNonBranch, IARG_INST_PTR, IARG_END);
}
int main(INT32 argc, CHAR **argv)
{
PIN_Init(argc, argv);
PIN_InitSymbols();
INS_AddInstrumentFunction(Instruction, 0);
IMG_AddInstrumentFunction(ImageLoad, 0);
PIN_StartProgram();
return 0;
}