CCTLib
Calling-context and data-object attribution library for Intel Pin
footprint_client.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 <sys/mman.h>
14 #include <sstream>
15 #include <functional>
16 #include <unordered_set>
17 #include <vector>
18 #include <unordered_map>
19 #include <algorithm>
20 #include "pin.H"
21 #include "cctlib.H"
22 using namespace std;
23 using namespace PinCCTLib;
24 
25 /* infrastructure for shadow memory */
26 /* MACROs */
27 // 64KB shadow pages
28 #define PAGE_OFFSET_BITS (16LL)
29 #define PAGE_OFFSET(addr) (addr & 0xFFFF)
30 #define PAGE_OFFSET_MASK (0xFFFF)
31 
32 #undef PAGE_SIZE
33 #define PAGE_SIZE (1 << PAGE_OFFSET_BITS)
34 
35 // 2 level page table
36 #define PTR_SIZE (sizeof(void*))
37 #define LEVEL_1_PAGE_TABLE_BITS (20)
38 #define LEVEL_1_PAGE_TABLE_ENTRIES (1 << LEVEL_1_PAGE_TABLE_BITS)
39 #define LEVEL_1_PAGE_TABLE_SIZE (LEVEL_1_PAGE_TABLE_ENTRIES * PTR_SIZE)
40 
41 #define LEVEL_2_PAGE_TABLE_BITS (12)
42 #define LEVEL_2_PAGE_TABLE_ENTRIES (1 << LEVEL_2_PAGE_TABLE_BITS)
43 #define LEVEL_2_PAGE_TABLE_SIZE (LEVEL_2_PAGE_TABLE_ENTRIES * PTR_SIZE)
44 
45 #define LEVEL_1_PAGE_TABLE_SLOT(addr) (((addr) >> (LEVEL_2_PAGE_TABLE_BITS + PAGE_OFFSET_BITS)) & 0xfffff)
46 #define LEVEL_2_PAGE_TABLE_SLOT(addr) (((addr) >> (PAGE_OFFSET_BITS)) & 0xFFF)
47 
48 
49 // have R, W representative macros
50 #define READ_ACTION (0)
51 #define WRITE_ACTION (0xff)
52 
53 #define ONE_BYTE_READ_ACTION (0)
54 #define TWO_BYTE_READ_ACTION (0)
55 #define FOUR_BYTE_READ_ACTION (0)
56 #define EIGHT_BYTE_READ_ACTION (0)
57 
58 #define ONE_BYTE_WRITE_ACTION (0xff)
59 #define TWO_BYTE_WRITE_ACTION (0xffff)
60 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
61 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
62 
63 
64 /* Other footprint_client settings */
65 #define MAX_FOOTPRINT_CONTEXTS_TO_LOG (1000)
66 #define THREAD_MAX (1024)
67 
68 #define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len) ((addr) | (((uint64_t)(len)) << 48))
69 #define DECODE_ADDRESS(addrAndLen) ((addrAndLen) & ((1L << 48) - 1))
70 #define DECODE_ACCESS_LEN(addrAndLen) ((addrAndLen) >> 48)
71 
72 
73 struct RawMetric_t {
74  unordered_set<uint64_t> addressSet;
75  unordered_set<uint64_t> addressSetDecoded;
76  uint64_t accessNum;
79 };
80 
83  uint64_t footprint;
84  uint64_t accessNum;
87 };
88 
89 static std::unordered_map<uint32_t, struct RawMetric_t>* hmap_vector;
90 
91 
92 template <int start, int end, int incr>
93 struct UnrolledLoop {
94  static inline void Body(const function<void(const int)>& func) {
95  func(start); // Real loop body
96  UnrolledLoop<start + incr, end, incr>::Body(func); // unroll next iteration
97  }
98 };
99 
100 template <int end, int incr>
101 struct UnrolledLoop<end, end, incr> {
102  static inline void Body(const function<void(const int)>& func) {
103  // empty body
104  }
105 };
106 
107 template <int start, int end, int incr>
109  static inline bool Body(const function<bool(const int)>& func) {
110  return func(start) && UnrolledConjunction<start + incr, end, incr>::Body(func); // unroll next iteration
111  }
112 };
113 
114 template <int end, int incr>
115 struct UnrolledConjunction<end, end, incr> {
116  static inline bool Body(const function<void(const int)>& func) {
117  return true;
118  }
119 };
120 
121 static INT32 Usage() {
122  PIN_ERROR("Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() + "\n");
123  return -1;
124 }
125 
126 // Main for DeadSpy, initialize the tool, register instrumentation functions and call the target program.
127 static FILE* gTraceFile;
129 
130 // Initialized the needed data structures before launching the target program
131 static void ClientInit(int argc, char* argv[]) {
132  // Create output file
133  char name[MAX_FILE_PATH] = "client.out.";
134  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
135 
136  if (envPath) {
137  // assumes max of MAX_FILE_PATH
138  snprintf(name, sizeof(name), "%s", envPath);
139  }
140 
141  gethostname(name + strlen(name), MAX_FILE_PATH - strlen(name));
142  pid_t pid = getpid();
143  sprintf(name + strlen(name), "%d", pid);
144  cerr << "\n Creating log file at:" << name << "\n";
145  gTraceFile = fopen(name, "w");
146  // print the arguments passed
147  fprintf(gTraceFile, "\n");
148 
149  for (int i = 0; i < argc; i++) {
150  fprintf(gTraceFile, "%s ", argv[i]);
151  }
152  // Initialize hmap_vector
153  hmap_vector = new std::unordered_map<uint32_t, struct RawMetric_t, std::hash<uint32_t>>[THREAD_MAX];
154  fprintf(gTraceFile, "\n");
155 }
156 
157 
158 /* helper functions for shadow memory */
159 static uint8_t* GetOrCreateShadowBaseAddress(uint64_t address) {
160  uint8_t* shadowPage;
161  uint8_t*** l1Ptr = &gL1PageTable[LEVEL_1_PAGE_TABLE_SLOT(address)];
162  if (*l1Ptr == nullptr) {
163  *l1Ptr = (uint8_t**)calloc(1, LEVEL_2_PAGE_TABLE_SIZE);
164  shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)] = (uint8_t*)mmap(nullptr, PAGE_SIZE * (sizeof(ADDRINT)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
165  } else if ((shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)]) == nullptr) {
166  shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)] = (uint8_t*)mmap(nullptr, PAGE_SIZE * (sizeof(ADDRINT)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
167  }
168  return shadowPage;
169 }
170 
171 static inline bool CheckDependence(uint64_t curAddr, uint64_t prevAddr) {
172  uint32_t lineNo1, lineNo2;
173  string filePath1, filePath2;
174 
175  PIN_LockClient();
176  PIN_GetSourceLocation(prevAddr, nullptr, (INT32*)&lineNo1, &filePath1);
177  PIN_GetSourceLocation(curAddr, nullptr, (INT32*)&lineNo2, &filePath2);
178  PIN_UnlockClient();
179 
180  return static_cast<bool>((filePath1 == filePath2) && (lineNo1 <= lineNo2));
181 }
182 
183 #if 0
184 static VOID MemFunc(THREADID id, void* address, bool rwFlag, UINT32 refSize) {
185  uint64_t addr = (uint64_t)address;
186  uint64_t encodedAddrAndLen = ENCODE_ADDRESS_AND_ACCESS_LEN(addr, refSize);
187 
188  // at memory instruction record the footprint
189  void **metricPtr = GetIPNodeMetric(id, 0);
191 
192  if (*metricPtr == NULL) {
193  // use ctxthndl as the key to associate footprint with the trace
194  ContextHandle_t ctxthndl = GetContextHandle(id, 0);
195  *metricPtr = &(hmap_vector[id])[ctxthndl];
196  }
197  metric = (static_cast<struct RawMetric_t*>(*metricPtr));
198  metric->addressSet.insert(encodedAddrAndLen);
199  metric->accessNum+=refSize;
200 #if 0
201  uint8_t* status = GetOrCreateShadowBaseAddress((uint64_t)addr);
202  uint64_t *prevAddr = (uint64_t *)(status + PAGE_OFFSET(addr) * sizeof(uint64_t));
203  // check write-read(true and loop-carried) dependence
204  bool *prevFlag = (bool *)(status + PAGE_OFFSET(addr));
205  if (!rwFlag && (*prevFlag))// && CheckDependence((uint64_t)addr, *prevAddr))
206  metric->dependentNum+=refSize;
207  // update the current read write flag
208  *prevFlag = rwFlag;
209  *prevAddr = addr;
210 #endif
211 }
212 #endif
213 
214 static inline RawMetric_t* UpdateFootPrint(uint64_t address, THREADID threadId, uint16_t accessLen) {
215  uint64_t encodedAddrAndLen = ENCODE_ADDRESS_AND_ACCESS_LEN(address, accessLen);
216  // at memory instruction record the footprint
217  void** metricPtr = GetIPNodeMetric(threadId, 0);
219 
220  if (*metricPtr == nullptr) {
221  // use ctxthndl as the key to associate footprint with the trace
222  ContextHandle_t ctxthndl = GetContextHandle(threadId, 0);
223  *metricPtr = &(hmap_vector[threadId])[ctxthndl];
224  }
225  metric = (static_cast<struct RawMetric_t*>(*metricPtr));
226  metric->addressSet.insert(encodedAddrAndLen);
227  metric->accessNum += accessLen;
228  return metric;
229 }
230 
231 
232 static const uint64_t READ_ACCESS_STATES[] = {/*0 byte */ 0, /*1 byte */ ONE_BYTE_READ_ACTION, /*2 byte */ TWO_BYTE_READ_ACTION, /*3 byte */ 0, /*4 byte */ FOUR_BYTE_READ_ACTION, /*5 byte */ 0, /*6 byte */ 0, /*7 byte */ 0, /*8 byte */ EIGHT_BYTE_READ_ACTION};
233 static const uint64_t WRITE_ACCESS_STATES[] = {/*0 byte */ 0, /*1 byte */ ONE_BYTE_WRITE_ACTION, /*2 byte */ TWO_BYTE_WRITE_ACTION, /*3 byte */ 0, /*4 byte */ FOUR_BYTE_WRITE_ACTION, /*5 byte */ 0, /*6 byte */ 0, /*7 byte */ 0, /*8 byte */ EIGHT_BYTE_WRITE_ACTION};
234 static const uint8_t OVERFLOW_CHECK[] = {/*0 byte */ 0, /*1 byte */ 0, /*2 byte */ 0, /*3 byte */ 1, /*4 byte */ 2, /*5 byte */ 3, /*6 byte */ 4, /*7 byte */ 5, /*8 byte */ 6};
235 
236 static inline bool IsFwdDependence(ADDRINT prevIp, ADDRINT curIp) {
237  //TODO
238  return (prevIp < curIp);
239 }
240 
241 inline static VOID RecordOneByteMemWrite(void* addr, ADDRINT insPtr) {
242  uint8_t* status = GetOrCreateShadowBaseAddress((uint64_t)addr);
243  //ContextHandle_t* __restrict__ prevWriteCtxt = (ContextHandle_t*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ContextHandle_t));
244  ADDRINT* __restrict__ prevIP = (ADDRINT*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ADDRINT));
245  prevIP[0] = insPtr;
246 }
247 
248 inline static VOID RecordOneByteMemRead(void* addr, ADDRINT insPtr, RawMetric_t* metric) {
249  uint8_t* status = GetOrCreateShadowBaseAddress((uint64_t)addr);
250  //ContextHandle_t* __restrict__ prevWriteCtxt = (ContextHandle_t*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ContextHandle_t));
251  ADDRINT* __restrict__ prevIP = (ADDRINT*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ADDRINT));
252 
253  if (IsFwdDependence(prevIP[0], insPtr)) {
254  metric->forwardDependence += 1;
255  } else {
256  metric->backwardsDependence += 1;
257  }
258 }
259 template <uint16_t AccessLen>
260 struct MemAnalysis {
261  static inline VOID RecordNByteMemRead(void* addr, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId) {
262  RawMetric_t* metric = UpdateFootPrint((uint64_t)addr, threadId, AccessLen);
263  uint8_t* status = GetOrCreateShadowBaseAddress((uint64_t)addr);
264  //ContextHandle_t* __restrict__ prevWriteCtxt = (ContextHandle_t*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ContextHandle_t));
265  ADDRINT* __restrict__ prevIP = (ADDRINT*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ADDRINT));
266  //const ContextHandle_t curCtxtHandle = GetContextHandle(threadId, /* opaqueHandle */0);
267  // status == 0 if not created.
268  if (PAGE_OFFSET((uint64_t)addr) <= (PAGE_OFFSET_MASK - AccessLen)) {
269  // All from same ctxt
270  if (UnrolledConjunction<0, AccessLen, 1>::Body([&](int index) -> bool { return (prevIP[index] == prevIP[0]); })) {
271  if (IsFwdDependence(prevIP[0], insPtr)) {
272  metric->forwardDependence += AccessLen;
273  } else {
274  metric->backwardsDependence += AccessLen;
275  }
276  } else {
277  UnrolledLoop<0, AccessLen, 1>::Body([&](int index) -> VOID {
278  if (IsFwdDependence(prevIP[index], insPtr))
279  metric->forwardDependence += AccessLen;
280  else
281  metric->backwardsDependence += AccessLen;
282  });
283  }
284  } else {
285  if (IsFwdDependence(prevIP[0], insPtr)) {
286  metric->forwardDependence += AccessLen;
287  } else {
288  metric->backwardsDependence += AccessLen;
289  }
290  UnrolledLoop<1, AccessLen, 1>::Body([&](int index) -> VOID { RecordOneByteMemRead(((char*)addr) + index, insPtr, metric); });
291  }
292  }
293  static inline VOID RecordNByteMemWrite(void* addr, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId) {
294  UpdateFootPrint((uint64_t)addr, threadId, AccessLen);
295  uint8_t* status = GetOrCreateShadowBaseAddress((uint64_t)addr);
296  //const ContextHandle_t curCtxtHandle = GetContextHandle(threadId, /*opaqueHandle*/ 0);
297  //ContextHandle_t* __restrict__ prevWriteCtxt = (ContextHandle_t*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ContextHandle_t));
298  ADDRINT* __restrict__ prevIP = (ADDRINT*)(status + PAGE_OFFSET((uint64_t)addr) * sizeof(ADDRINT));
299  // status == 0 if not created.
300  if (PAGE_OFFSET((uint64_t)addr) <= (PAGE_OFFSET_MASK - AccessLen)) {
301  UnrolledLoop<0, AccessLen, 1>::Body([&](int index) -> void { prevIP[index] = insPtr; });
302  } else {
303  prevIP[0] = insPtr;
304  UnrolledLoop<1, AccessLen, 1>::Body([&](int index) -> VOID { RecordOneByteMemWrite(((char*)addr) + index, insPtr); });
305  }
306  }
307 };
308 
309 
310 static inline VOID RecordLargeMemRead(void* addr, UINT32 accessLen, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId) {
311  RawMetric_t* metric = UpdateFootPrint((uint64_t)addr, threadId, accessLen);
312  //const ContextHandle_t curCtxtHandle = GetContextHandle(threadId, /*opaqueHandle*/ 0);
313  for (UINT32 i = 0; i < accessLen; i++)
314  RecordOneByteMemRead(((char*)addr) + i, insPtr, metric);
315 }
316 
317 static inline VOID RecordLargeMemWrite(void* addr, UINT32 accessLen, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId) {
318  UpdateFootPrint((uint64_t)addr, threadId, accessLen);
319  //const ContextHandle_t curCtxtHandle = GetContextHandle(threadId, /*opaqueHandle*/ 0);
320  for (UINT32 i = 0; i < accessLen; i++)
321  RecordOneByteMemWrite(((char*)addr) + i, insPtr);
322 }
323 
324 #define HANDLE_CASE(NUM) \
325  case (NUM): { \
326  if (INS_MemoryOperandIsRead(ins, memOp)) { \
327  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)MemAnalysis<(NUM)>::RecordNByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_INST_PTR, IARG_THREAD_ID, IARG_END); \
328  } else { \
329  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)MemAnalysis<(NUM)>::RecordNByteMemWrite, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_INST_PTR, IARG_THREAD_ID, IARG_END); \
330  } \
331  } break
332 
333 
334 static VOID InstrumentInsCallback(INS ins, VOID* v, const uint32_t opaqueHandle) {
335  if (!INS_IsMemoryRead(ins) && !INS_IsMemoryWrite(ins))
336  return;
337  if (INS_IsStackRead(ins) || INS_IsStackWrite(ins))
338  return;
339  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
340  return;
341  UINT32 memOperands = INS_MemoryOperandCount(ins);
342 
343  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
344  UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
345  switch (refSize) {
346  HANDLE_CASE(1);
347  HANDLE_CASE(2);
348  HANDLE_CASE(4);
349  HANDLE_CASE(8);
350  HANDLE_CASE(10); // TODO
351  HANDLE_CASE(16); // TODO
352 
353  default: {
354  // seeing some stupid 512 (fxsave)byte operations. Suspecting REP-instructions.
355  if (INS_MemoryOperandIsRead(ins, memOp)) {
356  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordLargeMemRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_INST_PTR, IARG_THREAD_ID, IARG_END);
357  }
358 
359  if (INS_MemoryOperandIsWritten(ins, memOp)) {
360  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordLargeMemWrite, IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE,
361  IARG_UINT32, opaqueHandle, IARG_INST_PTR,
362  IARG_THREAD_ID, IARG_END);
363  }
364  } break;
365  }
366  }
367 }
368 
369 static void DecodingFootPrint(const THREADID threadid, ContextHandle_t myHandle, ContextHandle_t parentHandle, void** myMetric, void** parentMetric) {
370  if (*myMetric == nullptr)
371  return;
372  struct RawMetric_t* hset = static_cast<struct RawMetric_t*>(*myMetric);
373  unordered_set<uint64_t>::iterator it;
374  for (it = hset->addressSet.begin(); it != hset->addressSet.end(); ++it) {
375  uint64_t refSize = DECODE_ACCESS_LEN(*it);
376  uint64_t addr = DECODE_ADDRESS(*it);
377  assert(refSize != 0);
378  for (unsigned int i = 0; i < refSize; i++) {
379  hset->addressSetDecoded.insert(addr + i);
380  }
381  }
382  hset->addressSet.clear();
383 }
384 
385 static void MergeFootPrint(const THREADID threadid, ContextHandle_t myHandle, ContextHandle_t parentHandle, void** myMetric, void** parentMetric) {
386  if (*myMetric == nullptr)
387  return;
388  struct RawMetric_t* hset = static_cast<struct RawMetric_t*>(*myMetric);
389 
390  if (*parentMetric == nullptr) {
391  *parentMetric = &((hmap_vector[threadid])[parentHandle]);
392  (hmap_vector[threadid])[parentHandle].addressSetDecoded.insert(hset->addressSetDecoded.begin(), hset->addressSetDecoded.end());
393  (hmap_vector[threadid])[parentHandle].accessNum += hset->accessNum;
394  (hmap_vector[threadid])[parentHandle].forwardDependence += hset->forwardDependence;
395  (hmap_vector[threadid])[parentHandle].backwardsDependence += hset->backwardsDependence;
396 
397  } else {
398  (static_cast<struct RawMetric_t*>(*parentMetric))->addressSetDecoded.insert(hset->addressSetDecoded.begin(), hset->addressSetDecoded.end());
399  (static_cast<struct RawMetric_t*>(*parentMetric))->accessNum += hset->accessNum;
400  (hmap_vector[threadid])[parentHandle].forwardDependence += hset->forwardDependence;
401  (hmap_vector[threadid])[parentHandle].backwardsDependence += hset->backwardsDependence;
402  }
403 }
404 
405 
406 static inline bool FootPrintCompare(const struct AnalyzedMetric_t& first, const struct AnalyzedMetric_t& second) {
407  return first.footprint > second.footprint;
408 }
409 
410 static void PrintTopFootPrintPath(THREADID threadid) {
411  uint64_t cntxtNum = 0;
412  vector<struct AnalyzedMetric_t> TmpList;
413 
414  fprintf(gTraceFile, "*************** Dump Data from Thread %d ****************\n", threadid);
415  unordered_map<uint32_t, struct RawMetric_t>& hmap = hmap_vector[threadid];
416  unordered_map<uint32_t, struct RawMetric_t>::iterator it;
417  for (it = hmap.begin(); it != hmap.end(); ++it) {
418  struct AnalyzedMetric_t tmp;
419  tmp.handle = (*it).first;
420  tmp.footprint = (uint64_t)(*it).second.addressSetDecoded.size();
421  tmp.accessNum = (uint64_t)(*it).second.accessNum;
422  tmp.forwardDependence = (uint64_t)(*it).second.forwardDependence;
423  tmp.backwardsDependence = (uint64_t)(*it).second.backwardsDependence;
424  TmpList.emplace_back(tmp);
425  }
426  sort(TmpList.begin(), TmpList.end(), FootPrintCompare);
427  vector<struct AnalyzedMetric_t>::iterator ListIt;
428  for (ListIt = TmpList.begin(); ListIt != TmpList.end(); ++ListIt) {
429  if (cntxtNum < MAX_FOOTPRINT_CONTEXTS_TO_LOG) {
430  fprintf(gTraceFile, "Footprint is %lu, #reuse is %ld, fwd dependence is %lu, carried dependence is %lu context is:", ((*ListIt).footprint), (*ListIt).accessNum - (*ListIt).footprint, (*ListIt).forwardDependence, (*ListIt).backwardsDependence);
431  PrintFullCallingContext((*ListIt).handle);
432  fprintf(gTraceFile, "\n------------------------------------------------\n");
433  } else {
434  break;
435  }
436  cntxtNum++;
437  }
438 }
439 
440 static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT* ctxt, INT32 code, VOID* v) {
441  // traverse CCT bottom to up
442  // decode first
443  TraverseCCTBottomUp(threadid, DecodingFootPrint);
444  // merge second
445  TraverseCCTBottomUp(threadid, MergeFootPrint);
446  // print the footprint for functions
447  PIN_LockClient();
448  PrintTopFootPrintPath(threadid);
449  PIN_UnlockClient();
450 }
451 
452 static VOID FiniFunc(INT32 code, VOID* v) {
453  // do whatever you want to the full CCT with footpirnt
454 }
455 
456 
457 int main(int argc, char* argv[]) {
458  // Initialize PIN
459  if (PIN_Init(argc, argv))
460  return Usage();
461 
462  // Initialize Symbols, we need them to report functions and lines
463  PIN_InitSymbols();
464 
465  // Init Client
466  ClientInit(argc, argv);
467  // Intialize CCTLib
469 
470  // fini function for post-mortem analysis
471  PIN_AddThreadFiniFunction(ThreadFiniFunc, nullptr);
472  PIN_AddFiniFunction(FiniFunc, nullptr);
473  // Launch program now
474  PIN_StartProgram();
475  return 0;
476 }
#define MAX_FILE_PATH
Definition: cctlib.H:18
#define INTERESTING_INS_MEMORY_ACCESS
Definition: cctlib.H:87
VOID MemFunc(THREADID id, void *addr, bool rwFlag, UINT32 refSize)
static uint8_t ** gL1PageTable[LEVEL_1_PAGE_TABLE_SIZE]
#define DECODE_ADDRESS(addrAndLen)
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
static FILE * gTraceFile
#define LEVEL_2_PAGE_TABLE_SIZE
#define LEVEL_1_PAGE_TABLE_SLOT(addr)
static void MergeFootPrint(const THREADID threadid, ContextHandle_t myHandle, ContextHandle_t parentHandle, void **myMetric, void **parentMetric)
static VOID RecordOneByteMemRead(void *addr, ADDRINT insPtr, RawMetric_t *metric)
#define EIGHT_BYTE_WRITE_ACTION
static VOID RecordLargeMemWrite(void *addr, UINT32 accessLen, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId)
static const uint64_t READ_ACCESS_STATES[]
#define THREAD_MAX
#define ONE_BYTE_READ_ACTION
static std::unordered_map< uint32_t, struct RawMetric_t > * hmap_vector
static INT32 Usage()
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
#define PAGE_OFFSET(addr)
static void DecodingFootPrint(const THREADID threadid, ContextHandle_t myHandle, ContextHandle_t parentHandle, void **myMetric, void **parentMetric)
static VOID RecordLargeMemRead(void *addr, UINT32 accessLen, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId)
static const uint8_t OVERFLOW_CHECK[]
static void PrintTopFootPrintPath(THREADID threadid)
static bool CheckDependence(uint64_t curAddr, uint64_t prevAddr)
static bool IsFwdDependence(ADDRINT prevIp, ADDRINT curIp)
#define PAGE_SIZE
static bool FootPrintCompare(const struct AnalyzedMetric_t &first, const struct AnalyzedMetric_t &second)
#define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len)
#define HANDLE_CASE(NUM)
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static VOID RecordOneByteMemWrite(void *addr, ADDRINT insPtr)
static VOID FiniFunc(INT32 code, VOID *v)
#define TWO_BYTE_WRITE_ACTION
#define MAX_FOOTPRINT_CONTEXTS_TO_LOG
#define DECODE_ACCESS_LEN(addrAndLen)
static const uint64_t WRITE_ACCESS_STATES[]
#define FOUR_BYTE_READ_ACTION
static uint8_t * GetOrCreateShadowBaseAddress(uint64_t address)
static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v)
#define LEVEL_1_PAGE_TABLE_SIZE
#define ONE_BYTE_WRITE_ACTION
static RawMetric_t * UpdateFootPrint(uint64_t address, THREADID threadId, uint16_t accessLen)
#define FOUR_BYTE_WRITE_ACTION
#define PAGE_OFFSET_MASK
#define LEVEL_2_PAGE_TABLE_SLOT(addr)
uint64_t metric
Definition: cctlib.H:60
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
Definition: cctlib.cpp:3132
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
Definition: cctlib.cpp:2346
volatile uint8_t status
Definition: cctlib.cpp:230
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
Definition: cctlib.cpp:1356
uint32_t ContextHandle_t
Definition: cctlib.H:22
void * address
ContextHandle_t handle
uint64_t backwardsDependence
static VOID RecordNByteMemWrite(void *addr, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId)
static VOID RecordNByteMemRead(void *addr, uint32_t opaqueHandle, ADDRINT insPtr, THREADID threadId)
uint64_t backwardsDependence
uint64_t forwardDependence
uint64_t accessNum
unordered_set< uint64_t > addressSetDecoded
unordered_set< uint64_t > addressSet
static bool Body(const function< void(const int)> &func)
static bool Body(const function< bool(const int)> &func)
static void Body(const function< void(const int)> &func)
static void Body(const function< void(const int)> &func)