CCTLib
Calling-context and data-object attribution library for Intel Pin
address_compare.cpp
Go to the documentation of this file.
1 // @COPYRIGHT@
2 // Licensed under MIT license.
3 // See LICENSE.TXT file in the project root for more information.
4 // ==============================================================
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <iostream>
10 #include <unistd.h>
11 #include <assert.h>
12 #include <string.h>
13 #include <sstream>
14 #include "pin.H"
15 
16 extern "C" {
17 #include "xed-interface.h"
18 }
19 
20 #define MAX_FILE_PATH (1000)
21 
22 using namespace std;
23 
24 INT32 Usage2() {
25  PIN_ERROR("CCTLib client Pin tool to gather calling context on each instruction.\n" + KNOB_BASE::StringKnobSummary() + "\n");
26  return -1;
27 }
28 
29 
30 // Main for DeadSpy, initialize the tool, register instrumentation functions and call the target program.
31 FILE* gTraceFile;
32 
33 xed_state_t xedState;
34 
35 // Initialized the needed data structures before launching the target program
36 void ClientInit(int argc, char* argv[]) {
37  // Create output file
38  char name[MAX_FILE_PATH] = "client.out.";
39  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
40 
41  if (envPath) {
42  // assumes max of MAX_FILE_PATH
43  snprintf(name, sizeof(name), "%s", envPath);
44  }
45 
46  gethostname(name + strlen(name), MAX_FILE_PATH - strlen(name));
47  pid_t pid = getpid();
48  sprintf(name + strlen(name), "%d", pid);
49  cerr << "\n Creating log file at:" << name << "\n";
50  gTraceFile = fopen(name, "w");
51  // print the arguments passed
52  fprintf(gTraceFile, "\n");
53 
54  for (int i = 0; i < argc; i++) {
55  fprintf(gTraceFile, "%s ", argv[i]);
56  }
57 
58  fprintf(gTraceFile, "\n");
59 
60 
61  xed_uint64_t watchpointRegisterValueCallback(xed_reg_enum_t reg, void* _ctxt, xed_bool_t* error);
62 
63  xed_tables_init();
64  xed_state_init(&xedState, XED_MACHINE_MODE_LONG_64, XED_ADDRESS_WIDTH_64b, XED_ADDRESS_WIDTH_64b);
66 }
67 
68 xed_uint64_t watchpointRegisterValueCallback(xed_reg_enum_t reg, void* _ctxt, xed_bool_t* error) {
69  const CONTEXT* ctxt = (const CONTEXT*)_ctxt;
70  *error = 0;
71  switch (reg) {
72  case XED_REG_RAX:
73  case XED_REG_EAX:
74  case XED_REG_AX:
75  case XED_REG_AL:
76  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RAX);
77  case XED_REG_AH:
78  assert(0 && "NYI");
79  *error = 1;
80 
81 
82  case XED_REG_RCX:
83  case XED_REG_ECX:
84  case XED_REG_CX:
85  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RCX);
86  case XED_REG_CH:
87  assert(0 && "NYI");
88  *error = 1;
89 
90  case XED_REG_RDX:
91  case XED_REG_EDX:
92  case XED_REG_DX:
93  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RDX);
94  case XED_REG_DH:
95  assert(0 && "NYI");
96  *error = 1;
97 
98  case XED_REG_RBX:
99  case XED_REG_EBX:
100  case XED_REG_BX:
101  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RBX);
102  case XED_REG_BH:
103  assert(0 && "NYI");
104  *error = 1;
105 
106  case XED_REG_RSP:
107  case XED_REG_ESP:
108  case XED_REG_SP:
109  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RSP);
110 
111  case XED_REG_RBP:
112  case XED_REG_EBP:
113  case XED_REG_BP:
114  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RBP);
115 
116  case XED_REG_RSI:
117  case XED_REG_ESI:
118  case XED_REG_SI:
119  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RSI);
120 
121  case XED_REG_RDI:
122  case XED_REG_EDI:
123  case XED_REG_DI:
124  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RDI);
125 
126  case XED_REG_R8:
127  case XED_REG_R8D:
128  case XED_REG_R8W:
129  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R8);
130 
131  case XED_REG_R9:
132  case XED_REG_R9D:
133  case XED_REG_R9W:
134  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R9);
135 
136  case XED_REG_R10:
137  case XED_REG_R10D:
138  case XED_REG_R10W:
139  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R10);
140 
141  case XED_REG_R11:
142  case XED_REG_R11D:
143  case XED_REG_R11W:
144  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R11);
145 
146  case XED_REG_R12:
147  case XED_REG_R12D:
148  case XED_REG_R12W:
149  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R12);
150 
151  case XED_REG_R13:
152  case XED_REG_R13D:
153  case XED_REG_R13W:
154  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R13);
155 
156  case XED_REG_R14:
157  case XED_REG_R14D:
158  case XED_REG_R14W:
159  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R14);
160 
161  case XED_REG_R15:
162  case XED_REG_R15D:
163  case XED_REG_R15W:
164  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_R15);
165 
166  case XED_REG_EFLAGS:
167  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_EFLAGS);
168 
169  case XED_REG_RIP:
170  case XED_REG_EIP:
171  case XED_REG_IP:
172  return PIN_GetContextReg(ctxt, LEVEL_BASE::REG_RIP);
173 
174  case XED_REG_DS:
175  *error = 1;
176  assert(0 && "NYI");
177  break;
178  case XED_REG_ES:
179  *error = 1;
180  assert(0 && "NYI");
181  break;
182  case XED_REG_SS:
183  *error = 1;
184  assert(0 && "NYI");
185  break;
186 
187  case XED_REG_CS:
188  /* Linux stores CS, GS, FS, PAD into one 64b word. */
189  return (uint32_t)PIN_GetContextReg(ctxt, LEVEL_BASE::REG_SEG_CS);
190  case XED_REG_FS:
191  return (uint32_t)PIN_GetContextReg(ctxt, LEVEL_BASE::REG_SEG_FS);
192  case XED_REG_GS:
193  return (uint32_t)PIN_GetContextReg(ctxt, LEVEL_BASE::REG_SEG_GS);
194  default:
195  *error = 1;
196  assert(0 && "NYI");
197  }
198  return 0;
199 }
200 #include <unordered_set>
201 
202 std::unordered_set<ADDRINT> hm;
203 
204 VOID Checker(ADDRINT addr, ADDRINT ip, const CONTEXT* ctxt, UINT32 idx) {
205  xed_decoded_inst_t xedd;
206  xed_decoded_inst_zero_set_mode(&xedd, &xedState);
207 
208  if (XED_ERROR_NONE != xed_decode(&xedd, (const xed_uint8_t*)(ip), 15 /* max bytes to decode*/)) {
209  //printf("get_mem_access_length_and_type failed to disassemble instruction\n");
210  return;
211  }
212  ADDRINT address = 0;
213  if (XED_ERROR_NONE != xed_agen(&xedd, idx /* memop idx*/, (void*)ctxt, (xed_uint64_t*)(&address))) {
214  return;
215  }
216  if (addr != (ADDRINT)(address)) {
217  if (hm.find(addr) == hm.end()) {
218  char buf[200];
219  if (0 == xed_format_context(XED_SYNTAX_ATT, &xedd, buf, 200, ip, nullptr, nullptr))
220  strcpy(buf, "xed_decoded_inst_dump_att_format failed");
221  printf("\n %s, %p, %p", buf, (void*)addr, (void*)address);
222  hm.insert(addr);
223  } else {
224  }
225  }
226 }
227 
228 // Pin calls this function every time a new instruction is encountered
229 VOID Instruction(INS ins, VOID* v) {
230  if (INS_IsControlFlow(ins) || INS_IsRet(ins)) {
231  return;
232  }
233 
234  // How may memory operations?
235  UINT32 memOperands = INS_MemoryOperandCount(ins);
236  for (UINT32 i = 0; i < memOperands; i++) {
237  INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)Checker, IARG_MEMORYOP_EA, i, IARG_INST_PTR, IARG_CONST_CONTEXT, IARG_UINT32, i, IARG_END);
238  }
239 }
240 
241 VOID Fini(INT32 code, VOID* v) {
242 }
243 
244 int main(int argc, char* argv[]) {
245  // Initialize PIN
246  if (PIN_Init(argc, argv))
247  return Usage2();
248 
249  // Initialize Symbols, we need them to report functions and lines
250  PIN_InitSymbols();
251  // Init Client
252  ClientInit(argc, argv);
253 
254  // Register Instruction to be called to instrument instructions
255  INS_AddInstrumentFunction(Instruction, nullptr);
256 
257  // Register Fini to be called when the application exits
258  PIN_AddFiniFunction(Fini, nullptr);
259 
260  // Launch program now
261  PIN_StartProgram();
262  return 0;
263 }
int main(int argc, char *argv[])
FILE * gTraceFile
xed_state_t xedState
#define MAX_FILE_PATH
VOID Checker(ADDRINT addr, ADDRINT ip, const CONTEXT *ctxt, UINT32 idx)
void ClientInit(int argc, char *argv[])
std::unordered_set< ADDRINT > hm
INT32 Usage2()
VOID Fini(INT32 code, VOID *v)
xed_uint64_t watchpointRegisterValueCallback(xed_reg_enum_t reg, void *_ctxt, xed_bool_t *error)
VOID Instruction(INS ins, VOID *v)
static uint64_t buf[ITERS]
void * address