CCTLib
Calling-context and data-object attribution library for Intel Pin
zerospy_spatial_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 <atomic>
10 #include <malloc.h>
11 #include <iostream>
12 #include <unistd.h>
13 #include <assert.h>
14 #include <string.h>
15 #include <sys/mman.h>
16 #include <sstream>
17 #include <functional>
18 #include <unordered_set>
19 #include <vector>
20 #include <unordered_map>
21 #include <algorithm>
22 #include <list>
23 #include "pin.H"
24 #include "pin_isa_compat.H"
25 
26 #define SKIP_SMALL_VARS
27 #ifdef SKIP_SMALL_VARS
28 #define SMALL_VAR_THRESHOLD 16
29 #endif
30 
31 //enable Data-centric
32 #define USE_TREE_BASED_FOR_DATA_CENTRIC
33 #define USE_TREE_WITH_ADDR
34 //#define USE_SHADOW_FOR_DATA_CENTRIC
35 //#define USE_ADDR_RANGE
36 #include "cctlib.H"
37 
38 #define OBJTYPE2STRING(t) ((t == DYNAMIC_OBJECT) ? "DYNAMIC" : ((t == STATIC_OBJECT) ? "STATIC" : ((t == STACK_OBJECT) ? "STACK" : "UNKNOWN")))
39 #define SYMNAME2STRING(t, s) ((t == DYNAMIC_OBJECT) ? "DYNAMIC" : ((t == STATIC_OBJECT) ? GetStringFromStringPool(s) : ((t == STACK_OBJECT) ? "STACK" : "UNKNOWN")))
40 
41 #include "shadow_memory.H"
42 #include <xmmintrin.h>
43 #include <immintrin.h>
44 
45 extern "C" {
46 #include "xed-interface.h"
47 #include "xed-common-hdrs.h"
48 }
49 
50 #include <google/sparse_hash_map>
51 #include <google/dense_hash_map>
52 
53 using namespace std;
54 using namespace PinCCTLib;
55 
56 // have R, W representative macros
57 #define READ_ACTION (0)
58 #define WRITE_ACTION (0xff)
59 
60 #define ONE_BYTE_READ_ACTION (0)
61 #define TWO_BYTE_READ_ACTION (0)
62 #define FOUR_BYTE_READ_ACTION (0)
63 #define EIGHT_BYTE_READ_ACTION (0)
64 
65 #define ONE_BYTE_WRITE_ACTION (0xff)
66 #define TWO_BYTE_WRITE_ACTION (0xffff)
67 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
68 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
69 
70 #define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen) (PAGE_OFFSET((accessAddr)) <= (PAGE_OFFSET_MASK - (accessLen)))
71 
72 /* Other footprint_client settings */
73 //#define MAX_REDUNDANT_CONTEXTS_TO_LOG (1000)
74 #define MAX_OBJS_TO_LOG 100
75 #define MAX_REDUNDANT_CONTEXTS_PER_OBJ_TO_LOG 10
76 #define MAX_REDUNDANT_CONTEXTS_TO_LOG (1000)
77 #define THREAD_MAX (1024)
78 
79 #define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len) ((addr) | (((uint64_t)(len)) << 48))
80 #define DECODE_ADDRESS(addrAndLen) ((addrAndLen) & ((1L << 48) - 1))
81 #define DECODE_ACCESS_LEN(addrAndLen) ((addrAndLen) >> 48)
82 
83 #define MAX_WRITE_OP_LENGTH (512)
84 #define MAX_WRITE_OPS_IN_INS (8)
85 #define MAX_REG_LENGTH (64)
86 
87 #define MAX_SIMD_LENGTH (64)
88 #define MAX_SIMD_REGS (32)
89 
90 
91 #ifdef ENABLE_SAMPLING
92 
93 #define WINDOW_ENABLE 1000000
94 #define WINDOW_DISABLE 100000000
95 #define WINDOW_CLEAN 10
96 #endif
97 
98 #define MAKE_OBJID(a, b) (((uint64_t)(a) << 32) | (b))
99 #define DECODE_TYPE(a) (((uint64_t)(a) & (0xffffffffffffffff)) >> 32)
100 #define DECODE_NAME(b) ((uint64_t)(b) & (0x00000000ffffffff))
101 
102 #define MAKE_CNTXT(a, b, c) (((uint64_t)(a) << 32) | ((uint64_t)(b) << 16) | (uint64_t)(c))
103 #define DECODE_CNTXT(a) (static_cast<ContextHandle_t>((((a) & (0xffffffffffffffff)) >> 32)))
104 #define DECODE_ACCLN(b) (((uint64_t)(b) & (0x00000000ffff0000)) >> 16)
105 #define DECODE_TYPSZ(c) ((uint64_t)(c) & (0x000000000000ffff))
106 
107 #define delta 0.01
108 
109 #define CACHE_LINE_SIZE (64)
110 #undef PAGE_SIZE
111 #define PAGE_SIZE (4 * 1024)
112 
113 
114 /***********************************************
115  ****** shadow memory
116  ************************************************/
117 //ConcurrentShadowMemory<uint8_t, DataHandle_t> sm;
118 
119 struct {
120  char dummy1[128];
121  xed_state_t xedState;
122  char dummy2[128];
124 
125 ////////////////////////////////////////////////
126 
127 struct RedSpyThreadData {
128  uint64_t bytesLoad;
129 
130  long long numIns;
131  bool sampleFlag;
132 };
133 
134 // for metric logging
137 
138 //for statistics result
142 
143 // key for accessing TLS storage in the threads. initialized once in main()
144 static TLS_KEY client_tls_key;
146 
147 // function to access thread-specific data
148 inline RedSpyThreadData* ClientGetTLS(const THREADID threadId) {
149 #ifdef MULTI_THREADED
150  RedSpyThreadData* tdata =
151  static_cast<RedSpyThreadData*>(PIN_GetThreadData(client_tls_key, threadId));
152  return tdata;
153 #else
154  return gSingleThreadedTData;
155 #endif
156 }
157 
158 static INT32 Usage() {
159  PIN_ERROR("Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() + "\n");
160  return -1;
161 }
162 
163 // Main for RedSpy, initialize the tool, register instrumentation functions and call the target program.
164 static FILE* gTraceFile;
165 
166 // Initialized the needed data structures before launching the target program
167 static void ClientInit(int argc, char* argv[]) {
168  // Create output file
169  char name[MAX_FILE_PATH] = "zeroLoad.dataCentric.out.";
170  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
171 
172  if (envPath) {
173  // assumes max of MAX_FILE_PATH
174  snprintf(name, sizeof(name), "%s", envPath);
175  }
176 
177  gethostname(name + strlen(name), MAX_FILE_PATH - strlen(name));
178  pid_t pid = getpid();
179  sprintf(name + strlen(name), "%d", pid);
180  cerr << "\n Creating log file at:" << name << "\n";
181  gTraceFile = fopen(name, "w");
182  // print the arguments passed
183  fprintf(gTraceFile, "\n");
184 
185  for (int i = 0; i < argc; i++) {
186  fprintf(gTraceFile, "%s ", argv[i]);
187  }
188 
189  fprintf(gTraceFile, "\n");
190 
191  // Init Xed
192  // Init XED for decoding instructions
193  xed_state_init(&LoadSpyGlobals.xedState, XED_MACHINE_MODE_LONG_64, (xed_address_width_enum_t)0, XED_ADDRESS_WIDTH_64b);
194 }
195 
196 
197 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};
198 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};
199 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};
200 
201 #define DATA_STATE_NOT_VISIT 0
202 #define DATA_STATE_ONLY_ZERO 1
203 #define DATA_STATE_NOT_ZERO 2
204 
205 struct RedLogs {
206  uint64_t red; // how many byte zero
207  uint64_t tot;
208  uint64_t beg_addr;
209  uint64_t end_addr;
210  //unordered_map<uint32_t, uint32_t> red_addr; // first : addr, second : bytemap
211  vector<uint8_t> state;
212 };
213 
214 static unordered_map<uint64_t, RedLogs> RedMap[THREAD_MAX];
215 static unordered_map<uint64_t, RedLogs> ApproxRedMap[THREAD_MAX];
216 
217 static inline void AddToRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) __attribute__((always_inline, flatten));
218 static inline void AddToRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) {
219 #ifdef MULTI_THREADED
220  LOCK_RED_MAP();
221 #endif
222  uint64_t key = MAKE_OBJID(data.objectType, data.symName);
223  unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].find(key);
224  if (it == RedMap[threadId].end()) {
225  RedLogs log;
226  log.red = value;
227  log.beg_addr = data.beg_addr;
228  log.end_addr = data.end_addr;
229  log.tot = typesz;
230  RedMap[threadId][key] = log;
231  RedMap[threadId][key].state.resize(data.end_addr - data.beg_addr, DATA_STATE_NOT_VISIT);
232 #pragma unroll
233  for (int i = 0; i < total; ++i)
234  RedMap[threadId][key].state[addr + i] = redmap[i];
235  } else {
236  it->second.red += value;
237 #pragma unroll
238  for (int i = 0; i < total; ++i)
239  it->second.state[addr + i] |= redmap[i];
240  // unordered_map<uint32_t, uint32_t>::iterator it3 = it->second.red_addr.find(addr);
241  // if(it3 == it->second.red_addr.end())
242  // it->second.red_addr[addr] = redmap;
243  // else
244  // it->second.red_addr[addr] &= redmap;
245  }
246 #ifdef MULTI_THREADED
247  UNLOCK_RED_MAP();
248 #endif
249 }
250 
251 #ifdef BIG_ENDIAN
252 using float_cast = union {
253  float f;
254  struct {
255  uint32_t sign : 1;
256  uint32_t exponent : 8;
257  uint32_t mantisa : 23;
258  } parts;
259  struct {
260  uint32_t sign : 1;
261  uint32_t value : 31;
262  } vars;
263 };
264 
265 using double_cast = union {
266  double f;
267  struct {
268  uint64_t sign : 1;
269  uint64_t exponent : 11;
270  uint64_t mantisa : 52;
271  } parts;
272  struct {
273  uint64_t sign : 1;
274  uint64_t value : 63;
275  } vars;
276 };
277 #else
278 typedef union {
279  float f;
280  struct {
281  uint32_t mantisa : 23;
282  uint32_t exponent : 8;
283  uint32_t sign : 1;
284  } parts;
285  struct {
286  uint32_t value : 31;
287  uint32_t sign : 1;
288  } vars;
289 } float_cast;
290 
291 typedef union {
292  double f;
293  struct {
294  uint64_t mantisa : 52;
295  uint64_t exponent : 11;
296  uint64_t sign : 1;
297  } parts;
298  struct {
299  uint64_t value : 63;
300  uint64_t sign : 1;
301  } vars;
302 } double_cast;
303 #endif
304 
305 static inline void AddToApproximateRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) __attribute__((always_inline, flatten));
306 static inline void AddToApproximateRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) {
307 #ifdef MULTI_THREADED
308  LOCK_RED_MAP();
309 #endif
310  //printf("Enter %d %d %d %d, %ld\n",addr,value,total,typesz,data.end_addr-data.beg_addr);
311  uint64_t key = MAKE_OBJID(data.objectType, data.symName);
312  unordered_map<uint64_t, RedLogs>::iterator it = ApproxRedMap[threadId].find(key);
313  if (value > total) {
314  cerr << "** Warning AddToApproximateTable : value " << value << ", total " << total << " **" << endl;
315  assert(0 && "** BUG #0 Detected. Existing **");
316  }
317  if (it == ApproxRedMap[threadId].end()) {
318  RedLogs log;
319  log.red = value;
320  log.beg_addr = data.beg_addr;
321  log.end_addr = data.end_addr;
322  log.tot = typesz;
323  //printf("+++ insert finish\n");
324  ApproxRedMap[threadId][key] = log;
325  //printf("+++ RESIZE : %ld\n",data.end_addr-data.beg_addr);
326  ApproxRedMap[threadId][key].state.resize(data.end_addr - data.beg_addr, DATA_STATE_NOT_VISIT);
327 //printf("+++ RESIZE FINISH\n");
328 #pragma unroll
329  for (int i = 0; i < total; i += typesz)
330  ApproxRedMap[threadId][key].state[addr + i] = redmap[i];
331  //printf("+++ state finish\n");
332  } else {
333  it->second.red += value;
334 #pragma unroll
335  for (int i = 0; i < total; i += typesz)
336  it->second.state[addr + i] |= redmap[i];
337  // unordered_map<uint32_t, uint32_t>::iterator it3 = it->second.red_addr.find(addr);
338  // if(it3 == it->second.red_addr.end())
339  // it->second.red_addr[addr] = redmap;
340  // else
341  // it->second.red_addr[addr] &= redmap;
342  }
343  //printf("Exit\n");
344  //fflush(stdout);
345 #ifdef MULTI_THREADED
346  UNLOCK_RED_MAP();
347 #endif
348 }
349 
350 
351 #ifdef ENABLE_SAMPLING
352 
353 static ADDRINT IfEnableSample(THREADID threadId) {
354  RedSpyThreadData* const tData = ClientGetTLS(threadId);
355  return tData->sampleFlag;
356 }
357 
358 #endif
359 
360 // Certain FP instructions should not be approximated
361 static inline bool IsOkToApproximate(xed_decoded_inst_t& xedd) {
362  xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
363  switch (iclass) {
364  case XED_ICLASS_FLDENV:
365  case XED_ICLASS_FNSTENV:
366  case XED_ICLASS_FNSAVE:
367  case XED_ICLASS_FLDCW:
368  case XED_ICLASS_FNSTCW:
369  case XED_ICLASS_FXRSTOR:
370  case XED_ICLASS_FXRSTOR64:
371  case XED_ICLASS_FXSAVE:
372  case XED_ICLASS_FXSAVE64:
373  return false;
374  default:
375  return true;
376  }
377 }
378 
379 static inline bool IsFloatInstructionAndOkToApproximate(ADDRINT ip) {
380  xed_decoded_inst_t xedd;
381  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
382 
383  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
384  xed_category_enum_t cat = xed_decoded_inst_get_category(&xedd);
385  switch (cat) {
386  case XED_CATEGORY_AES:
387  case XED_CATEGORY_CONVERT:
388  case XED_CATEGORY_PCLMULQDQ:
389  case XED_CATEGORY_SSE:
390  case XED_CATEGORY_AVX2:
391  case XED_CATEGORY_AVX:
392  case XED_CATEGORY_MMX:
393  case XED_CATEGORY_DATAXFER: {
394  // Get the mem operand
395 
396  const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
397  int noperands = xed_inst_noperands(xi);
398  int memOpIdx = -1;
399  for (int i = 0; i < noperands; i++) {
400  const xed_operand_t* op = xed_inst_operand(xi, i);
401  xed_operand_enum_t op_name = xed_operand_name(op);
402  if (XED_OPERAND_MEM0 == op_name) {
403  memOpIdx = i;
404  break;
405  }
406  }
407  if (memOpIdx == -1) {
408  return false;
409  }
410 
411  // TO DO MILIND case XED_OPERAND_MEM1:
412  xed_operand_element_type_enum_t eType = xed_decoded_inst_operand_element_type(&xedd, memOpIdx);
413  switch (eType) {
414  case XED_OPERAND_ELEMENT_TYPE_FLOAT16:
415  case XED_OPERAND_ELEMENT_TYPE_SINGLE:
416  case XED_OPERAND_ELEMENT_TYPE_DOUBLE:
417  case XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE:
418  case XED_OPERAND_ELEMENT_TYPE_LONGBCD:
419  return IsOkToApproximate(xedd);
420  default:
421  return false;
422  }
423  } break;
424  case XED_CATEGORY_X87_ALU:
425  case XED_CATEGORY_FCMOV:
426  //case XED_CATEGORY_LOGICAL_FP:
427  // assumption, the access length must be either 4 or 8 bytes else assert!!!
428  //assert(*accessLen == 4 || *accessLen == 8);
429  return IsOkToApproximate(xedd);
430  case XED_CATEGORY_XSAVE:
431  case XED_CATEGORY_AVX2GATHER:
432  case XED_CATEGORY_STRINGOP:
433  default:
434  return false;
435  }
436  } else {
437  assert(0 && "failed to disassemble instruction");
438  // printf("\n Diassembly failure\n");
439  return false;
440  }
441 }
442 
443 static inline bool IsFloatInstructionOld(ADDRINT ip) {
444  xed_decoded_inst_t xedd;
445  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
446 
447  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
448  xed_iclass_enum_t iclassType = xed_decoded_inst_get_iclass(&xedd);
449  if (iclassType >= XED_ICLASS_F2XM1 && iclassType <= XED_ICLASS_FYL2XP1) {
450  return true;
451  }
452  if (iclassType >= XED_ICLASS_VBROADCASTSD && iclassType <= XED_ICLASS_VDPPS) {
453  return true;
454  }
455  if (iclassType >= XED_ICLASS_VRCPPS && iclassType <= XED_ICLASS_VSQRTSS) {
456  return true;
457  }
458  if (iclassType >= XED_ICLASS_VSUBPD && iclassType <= XED_ICLASS_VXORPS) {
459  return true;
460  }
461  switch (iclassType) {
462  case XED_ICLASS_ADDPD:
463  case XED_ICLASS_ADDPS:
464  case XED_ICLASS_ADDSD:
465  case XED_ICLASS_ADDSS:
466  case XED_ICLASS_ADDSUBPD:
467  case XED_ICLASS_ADDSUBPS:
468  case XED_ICLASS_ANDNPD:
469  case XED_ICLASS_ANDNPS:
470  case XED_ICLASS_ANDPD:
471  case XED_ICLASS_ANDPS:
472  case XED_ICLASS_BLENDPD:
473  case XED_ICLASS_BLENDPS:
474  case XED_ICLASS_BLENDVPD:
475  case XED_ICLASS_BLENDVPS:
476  case XED_ICLASS_CMPPD:
477  case XED_ICLASS_CMPPS:
478  case XED_ICLASS_CMPSD:
479  case XED_ICLASS_CMPSD_XMM:
480  case XED_ICLASS_COMISD:
481  case XED_ICLASS_COMISS:
482  case XED_ICLASS_CVTDQ2PD:
483  case XED_ICLASS_CVTDQ2PS:
484  case XED_ICLASS_CVTPD2PS:
485  case XED_ICLASS_CVTPI2PD:
486  case XED_ICLASS_CVTPI2PS:
487  case XED_ICLASS_CVTPS2PD:
488  case XED_ICLASS_CVTSD2SS:
489  case XED_ICLASS_CVTSI2SD:
490  case XED_ICLASS_CVTSI2SS:
491  case XED_ICLASS_CVTSS2SD:
492  case XED_ICLASS_DIVPD:
493  case XED_ICLASS_DIVPS:
494  case XED_ICLASS_DIVSD:
495  case XED_ICLASS_DIVSS:
496  case XED_ICLASS_DPPD:
497  case XED_ICLASS_DPPS:
498  case XED_ICLASS_HADDPD:
499  case XED_ICLASS_HADDPS:
500  case XED_ICLASS_HSUBPD:
501  case XED_ICLASS_HSUBPS:
502  case XED_ICLASS_MAXPD:
503  case XED_ICLASS_MAXPS:
504  case XED_ICLASS_MAXSD:
505  case XED_ICLASS_MAXSS:
506  case XED_ICLASS_MINPD:
507  case XED_ICLASS_MINPS:
508  case XED_ICLASS_MINSD:
509  case XED_ICLASS_MINSS:
510  case XED_ICLASS_MOVAPD:
511  case XED_ICLASS_MOVAPS:
512  case XED_ICLASS_MOVD:
513  case XED_ICLASS_MOVHLPS:
514  case XED_ICLASS_MOVHPD:
515  case XED_ICLASS_MOVHPS:
516  case XED_ICLASS_MOVLHPS:
517  case XED_ICLASS_MOVLPD:
518  case XED_ICLASS_MOVLPS:
519  case XED_ICLASS_MOVMSKPD:
520  case XED_ICLASS_MOVMSKPS:
521  case XED_ICLASS_MOVNTPD:
522  case XED_ICLASS_MOVNTPS:
523  case XED_ICLASS_MOVNTSD:
524  case XED_ICLASS_MOVNTSS:
525  case XED_ICLASS_MOVSD:
526  case XED_ICLASS_MOVSD_XMM:
527  case XED_ICLASS_MOVSS:
528  case XED_ICLASS_MULPD:
529  case XED_ICLASS_MULPS:
530  case XED_ICLASS_MULSD:
531  case XED_ICLASS_MULSS:
532  case XED_ICLASS_ORPD:
533  case XED_ICLASS_ORPS:
534  case XED_ICLASS_ROUNDPD:
535  case XED_ICLASS_ROUNDPS:
536  case XED_ICLASS_ROUNDSD:
537  case XED_ICLASS_ROUNDSS:
538  case XED_ICLASS_SHUFPD:
539  case XED_ICLASS_SHUFPS:
540  case XED_ICLASS_SQRTPD:
541  case XED_ICLASS_SQRTPS:
542  case XED_ICLASS_SQRTSD:
543  case XED_ICLASS_SQRTSS:
544  case XED_ICLASS_SUBPD:
545  case XED_ICLASS_SUBPS:
546  case XED_ICLASS_SUBSD:
547  case XED_ICLASS_SUBSS:
548  case XED_ICLASS_VADDPD:
549  case XED_ICLASS_VADDPS:
550  case XED_ICLASS_VADDSD:
551  case XED_ICLASS_VADDSS:
552  case XED_ICLASS_VADDSUBPD:
553  case XED_ICLASS_VADDSUBPS:
554  case XED_ICLASS_VANDNPD:
555  case XED_ICLASS_VANDNPS:
556  case XED_ICLASS_VANDPD:
557  case XED_ICLASS_VANDPS:
558  case XED_ICLASS_VBLENDPD:
559  case XED_ICLASS_VBLENDPS:
560  case XED_ICLASS_VBLENDVPD:
561  case XED_ICLASS_VBLENDVPS:
562  case XED_ICLASS_VBROADCASTSD:
563  case XED_ICLASS_VBROADCASTSS:
564  case XED_ICLASS_VCMPPD:
565  case XED_ICLASS_VCMPPS:
566  case XED_ICLASS_VCMPSD:
567  case XED_ICLASS_VCMPSS:
568  case XED_ICLASS_VCOMISD:
569  case XED_ICLASS_VCOMISS:
570  case XED_ICLASS_VCVTDQ2PD:
571  case XED_ICLASS_VCVTDQ2PS:
572  case XED_ICLASS_VCVTPD2PS:
573  case XED_ICLASS_VCVTPH2PS:
574  case XED_ICLASS_VCVTPS2PD:
575  case XED_ICLASS_VCVTSD2SS:
576  case XED_ICLASS_VCVTSI2SD:
577  case XED_ICLASS_VCVTSI2SS:
578  case XED_ICLASS_VCVTSS2SD:
579  case XED_ICLASS_VDIVPD:
580  case XED_ICLASS_VDIVPS:
581  case XED_ICLASS_VDIVSD:
582  case XED_ICLASS_VDIVSS:
583  case XED_ICLASS_VDPPD:
584  case XED_ICLASS_VDPPS:
585  case XED_ICLASS_VMASKMOVPD:
586  case XED_ICLASS_VMASKMOVPS:
587  case XED_ICLASS_VMAXPD:
588  case XED_ICLASS_VMAXPS:
589  case XED_ICLASS_VMAXSD:
590  case XED_ICLASS_VMAXSS:
591  case XED_ICLASS_VMINPD:
592  case XED_ICLASS_VMINPS:
593  case XED_ICLASS_VMINSD:
594  case XED_ICLASS_VMINSS:
595  case XED_ICLASS_VMOVAPD:
596  case XED_ICLASS_VMOVAPS:
597  case XED_ICLASS_VMOVD:
598  case XED_ICLASS_VMOVHLPS:
599  case XED_ICLASS_VMOVHPD:
600  case XED_ICLASS_VMOVHPS:
601  case XED_ICLASS_VMOVLHPS:
602  case XED_ICLASS_VMOVLPD:
603  case XED_ICLASS_VMOVLPS:
604  case XED_ICLASS_VMOVMSKPD:
605  case XED_ICLASS_VMOVMSKPS:
606  case XED_ICLASS_VMOVNTPD:
607  case XED_ICLASS_VMOVNTPS:
608  case XED_ICLASS_VMOVSD:
609  case XED_ICLASS_VMOVSS:
610  case XED_ICLASS_VMOVUPD:
611  case XED_ICLASS_VMOVUPS:
612  case XED_ICLASS_VMULPD:
613  case XED_ICLASS_VMULPS:
614  case XED_ICLASS_VMULSD:
615  case XED_ICLASS_VMULSS:
616  case XED_ICLASS_VORPD:
617  case XED_ICLASS_VORPS:
618  case XED_ICLASS_VPABSD:
619  case XED_ICLASS_VPADDD:
620  case XED_ICLASS_VPCOMD:
621  case XED_ICLASS_VPCOMUD:
622  case XED_ICLASS_VPERMILPD:
623  case XED_ICLASS_VPERMILPS:
624  case XED_ICLASS_VPERMPD:
625  case XED_ICLASS_VPERMPS:
626  case XED_ICLASS_VPGATHERDD:
627  case XED_ICLASS_VPGATHERQD:
628  case XED_ICLASS_VPHADDBD:
629  case XED_ICLASS_VPHADDD:
630  case XED_ICLASS_VPHADDUBD:
631  case XED_ICLASS_VPHADDUWD:
632  case XED_ICLASS_VPHADDWD:
633  case XED_ICLASS_VPHSUBD:
634  case XED_ICLASS_VPHSUBWD:
635  case XED_ICLASS_VPINSRD:
636  case XED_ICLASS_VPMACSDD:
637  case XED_ICLASS_VPMACSSDD:
638  case XED_ICLASS_VPMASKMOVD:
639  case XED_ICLASS_VPMAXSD:
640  case XED_ICLASS_VPMAXUD:
641  case XED_ICLASS_VPMINSD:
642  case XED_ICLASS_VPMINUD:
643  case XED_ICLASS_VPROTD:
644  case XED_ICLASS_VPSUBD:
645  case XED_ICLASS_XORPD:
646  case XED_ICLASS_XORPS:
647  return true;
648 
649  default:
650  return false;
651  }
652  } else {
653  assert(0 && "failed to disassemble instruction");
654  return false;
655  }
656 }
657 
658 static inline uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper) {
659  xed_decoded_inst_t xedd;
660  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
661 
662  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
663  xed_operand_element_type_enum_t TypeOperand = xed_decoded_inst_operand_element_type(&xedd, oper);
664  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_SINGLE || TypeOperand == XED_OPERAND_ELEMENT_TYPE_FLOAT16)
665  return 4;
666  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_DOUBLE) {
667  return 8;
668  }
669  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE) {
670  return 16;
671  }
672  assert(0 && "float instruction with unknown operand\n");
673  return 0;
674  } else {
675  assert(0 && "failed to disassemble instruction\n");
676  return 0;
677  }
678 }
679 
680 /***************************************************************************************/
681 /*********************** memory temporal redundancy functions **************************/
682 /***************************************************************************************/
683 /*
684 template<int start, int end, int incr, bool conditional, bool approx>
685 struct UnrolledLoop{
686  static __attribute__((always_inline)) void Body(const function<void (const int)>& func){
687  func(start); // Real loop body
688  UnrolledLoop<start+incr, end, incr, conditional, approx>:: Body(func); // unroll next iteration
689  }
690  static __attribute__((always_inline)) void BodyStraddlePage(uint64_t addr, const DataHandle_t handle, const ContextHandle_t cntxt, THREADID threadId){
691  if (conditional) {
692  // report in RedTable
693  if(approx)
694  AddToApproximateRedTable(addr, handle, cntxt, 0, 1, 0, threadId);
695  else
696  AddToRedTable(addr, handle, cntxt, 0, 1, 0, threadId);
697  }
698  UnrolledLoop<start+incr, end, incr, conditional, approx>:: BodyStraddlePage(addr, handle, cntxt, threadId); // unroll next iteration
699  }
700 };
701 
702 template<int end, int incr, bool conditional, bool approx>
703 struct UnrolledLoop<end , end , incr, conditional, approx>{
704  static __attribute__((always_inline)) void Body(const function<void (const int)>& func){}
705  static __attribute__((always_inline)) void BodyStraddlePage(uint64_t addr, const DataHandle_t handle, const ContextHandle_t cntxt, THREADID threadId){}
706 };
707 */
708 template <int start, int end, int incr>
709 struct UnrolledConjunction {
710  static __attribute__((always_inline)) bool Body(const function<bool(const int)>& func) {
711  return func(start) && UnrolledConjunction<start + incr, end, incr>::Body(func); // unroll next iteration
712  }
713  static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t* __restrict__ prevIP) {
714  return (prevIP[0] == prevIP[start]) && UnrolledConjunction<start + incr, end, incr>::BodyContextCheck(prevIP); // unroll next iteration
715  }
716  static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t* addr) {
717  return ((addr[end - 1] != 0) ? 0 : 1 + UnrolledConjunction<start, end - incr, incr>::BodyIsZero(addr)); // unroll next iteration
718  }
719  static __attribute__((always_inline)) void BodyByteMap(uint8_t* addr, uint8_t redmap[32]) {
720  redmap[start] = addr[start] == 0 ? DATA_STATE_ONLY_ZERO : DATA_STATE_NOT_ZERO;
721  UnrolledConjunction<start + incr, end, incr>::BodyByteMap(addr, redmap); // unroll next iteration
722  }
723  static __attribute__((always_inline)) void BodyByteMapApprox(uint8_t* addr, uint8_t redmap[32]) {
724  if (incr == 4) {
725  redmap[start] = (*(reinterpret_cast<float_cast*>(&addr[start]))).vars.value == 0 ? DATA_STATE_ONLY_ZERO : DATA_STATE_NOT_ZERO;
726  } else {
727  redmap[start] = (*(reinterpret_cast<double_cast*>(&addr[start]))).vars.value == 0 ? DATA_STATE_ONLY_ZERO : DATA_STATE_NOT_ZERO;
728  }
729  UnrolledConjunction<start + incr, end, incr>::BodyByteMapApprox(addr, redmap); // unroll next iteration
730  }
731 };
732 
733 template <int end, int incr>
734 struct UnrolledConjunction<end, end, incr> {
735  static __attribute__((always_inline)) bool Body(const function<void(const int)>& func) {
736  return true;
737  }
738  static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t* __restrict__ prevIP) {
739  return true;
740  }
741  static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t* addr) {
742  return 0;
743  }
744  static __attribute__((always_inline)) void BodyByteMap(uint8_t* addr, uint8_t redmap[32]) {
745  }
746  static __attribute__((always_inline)) void BodyByteMapApprox(uint8_t* addr, uint8_t redmap[32]) {
747  }
748 };
749 
750 template <int start, int end, int step>
751 struct UnrolledCount {
752  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
754  }
755 };
756 template <int end, int step>
757 struct UnrolledCount<end, end, step> {
758  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
759  return 0;
760  }
761 };
762 //#define DEBUG_ZEROSPY_SPATIAL
763 template <class T, uint32_t AccessLen, bool isApprox>
764 struct ZeroSpyAnalysis {
765  static __attribute__((always_inline)) void getRedMap(void* addr, uint8_t redbyteMap[32]) {
766  if (isApprox) {
767  uint8_t* bytes = static_cast<uint8_t*>(addr);
768  UnrolledConjunction<0, AccessLen, sizeof(T)>::BodyByteMapApprox(bytes, redbyteMap);
769  } else {
770  uint8_t* bytes = static_cast<uint8_t*>(addr);
772  }
773  }
774  static __attribute__((always_inline)) uint64_t getRedNum(void* addr) {
775  if (isApprox) {
776  uint8_t* bytes = static_cast<uint8_t*>(addr);
777  uint32_t rednum = UnrolledCount<0, AccessLen, sizeof(T)>::BodyRedZero(bytes);
778  return rednum;
779  } else {
780  uint8_t* bytes = static_cast<uint8_t*>(addr);
781  uint32_t rednum = UnrolledCount<0, AccessLen, sizeof(T)>::BodyRedZero(bytes);
782  return rednum;
783  }
784  return 0;
785  }
786  static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(void* addr, uint32_t opaqueHandle, THREADID threadId) {
787 #ifdef DEBUG_ZEROSPY_SPATIAL
788  printf("\n In CheckNByteValueAfterRead Begin : %p %d %d\n", addr, opaqueHandle, threadId);
789 #endif
790  RedSpyThreadData* const tData = ClientGetTLS(threadId);
791  ContextHandle_t curCtxt = GetContextHandle(threadId, opaqueHandle);
792  DataHandle_t curDataHandle = GetDataObjectHandle(addr, threadId);
793  if (curDataHandle.objectType != DYNAMIC_OBJECT && curDataHandle.objectType != STATIC_OBJECT) {
794  return;
795  }
796 #ifdef SKIP_SMALL_VARS
797  // if it is a small var, skip logging
798  if (curDataHandle.end_addr - curDataHandle.beg_addr <= SMALL_VAR_THRESHOLD)
799  return;
800 #endif
801  uint32_t redbyteNum = getRedNum(addr);
802  uint8_t redbyteMap[32] = {0};
803  if (redbyteNum)
804  getRedMap(addr, redbyteMap);
805  else
806  memset(redbyteMap, DATA_STATE_NOT_ZERO, 32);
807  if (isApprox)
808  AddToApproximateRedTable((uint32_t)((uint64_t)addr - curDataHandle.beg_addr), curDataHandle, curCtxt, redbyteNum, AccessLen, redbyteMap, sizeof(T), threadId);
809  else
810  AddToRedTable((uint32_t)((uint64_t)addr - curDataHandle.beg_addr), curDataHandle, curCtxt, redbyteNum, AccessLen, redbyteMap, sizeof(T), threadId);
811 #ifdef DEBUG_ZEROSPY_SPATIAL
812  printf("\n In CheckNByteValueAfterRead Finish \n");
813 #endif
814  }
815 };
816 
817 
818 static inline VOID CheckAfterLargeRead(void* addr, UINT32 accessLen, uint32_t opaqueHandle, THREADID threadId) {
819 #ifdef DEBUG_ZEROSPY_SPATIAL
820  printf("\n In CheckAfterLargeRead Begin : %p %d %d %d\n", addr, accessLen, opaqueHandle, threadId);
821 #endif
822  ContextHandle_t curCtxt = GetContextHandle(threadId, opaqueHandle);
823  DataHandle_t curDataHandle = GetDataObjectHandle(addr, threadId);
824  if (curDataHandle.objectType != DYNAMIC_OBJECT && curDataHandle.objectType != STATIC_OBJECT) {
825  return;
826  }
827 #ifdef SKIP_SMALL_VARS
828  // if it is a small var, skip logging
829  if (curDataHandle.end_addr - curDataHandle.beg_addr <= SMALL_VAR_THRESHOLD)
830  return;
831 #endif
832  uint8_t* bytes = static_cast<uint8_t*>(addr);
833  uint32_t redbyteNum = 0;
834  uint8_t redbyteMap[32] = {0};
835  for (int i = accessLen - 1; i >= 0; --i) {
836  if (bytes[i] != 0) {
837  break;
838  }
839  ++redbyteNum;
840  }
841  if (redbyteNum) {
842  for (UINT32 i = 0; i < accessLen; ++i) {
843  if (bytes[i] == 0)
844  redbyteMap[i] |= DATA_STATE_ONLY_ZERO;
845  else
846  redbyteMap[i] |= DATA_STATE_NOT_ZERO;
847  }
848  // report in RedTable
849  AddToRedTable((uint32_t)((uint64_t)addr - curDataHandle.beg_addr), curDataHandle, curCtxt, redbyteNum, accessLen, redbyteMap, accessLen, threadId);
850  }
851 #ifdef DEBUG_ZEROSPY_SPATIAL
852  printf("\n In CheckAfterLargeRead Finish \n");
853 #endif
854 }
855 #undef DEBUG_ZEROSPY_SPATIAL
856 
857 #ifdef ENABLE_SAMPLING
858 
859 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
860  INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
861  INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)ZeroSpyAnalysis<T, (ACCESS_LEN), (IS_APPROX)>::CheckNByteValueAfterRead, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
862 
863 #define HANDLE_LARGE() \
864  INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
865  INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
866 #else
867 
868 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
869  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)ZeroSpyAnalysis<T, (ACCESS_LEN), (IS_APPROX)>::CheckNByteValueAfterRead, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
870 
871 #define HANDLE_LARGE() \
872  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
873 #endif
874 
875 
876 static int GetNumReadOperandsInIns(INS ins, UINT32& whichOp) {
877  int numReadOps = 0;
878  UINT32 memOperands = INS_MemoryOperandCount(ins);
879  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
880  if (INS_MemoryOperandIsRead(ins, memOp)) {
881  numReadOps++;
882  whichOp = memOp;
883  }
884  }
885  return numReadOps;
886 }
887 
888 
889 struct LoadSpyInstrument {
890  static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
891  UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
892 
893  if (IsFloatInstructionAndOkToApproximate(INS_Address(ins))) {
894  unsigned int operSize = FloatOperandSize(INS_Address(ins), INS_MemoryOperandIndexToOperandIndex(ins, memOp));
895  switch (refSize) {
896  case 1:
897  case 2:
898  assert(0 && "memory read floating data with unexptected small size");
899  case 4:
900  HANDLE_CASE(float, 4, true);
901  break;
902  case 8:
903  HANDLE_CASE(double, 8, true);
904  break;
905  case 10:
906  HANDLE_CASE(uint8_t, 10, true);
907  break;
908  case 16: {
909  switch (operSize) {
910  case 4:
911  HANDLE_CASE(float, 16, true);
912  break;
913  case 8:
914  HANDLE_CASE(double, 16, true);
915  break;
916  default:
917  assert(0 && "handle large mem read with unexpected operand size\n");
918  break;
919  }
920  } break;
921  case 32: {
922  switch (operSize) {
923  case 4:
924  HANDLE_CASE(float, 32, true);
925  break;
926  case 8:
927  HANDLE_CASE(double, 32, true);
928  break;
929  default:
930  assert(0 && "handle large mem read with unexpected operand size\n");
931  break;
932  }
933  } break;
934  default:
935  assert(0 && "unexpected large memory read\n");
936  break;
937  }
938  } else {
939  switch (refSize) {
940  case 1:
941  HANDLE_CASE(uint8_t, 1, false);
942  break;
943  case 2:
944  HANDLE_CASE(uint16_t, 2, false);
945  break;
946  case 4:
947  HANDLE_CASE(uint32_t, 4, false);
948  break;
949  case 8:
950  HANDLE_CASE(uint64_t, 8, false);
951  break;
952 
953  default: {
954  HANDLE_LARGE();
955  }
956  }
957  }
958  }
959 };
960 
961 /********************* instrument analysis ************************/
962 
963 static inline bool INS_IsIgnorable(INS ins) {
964  if (INS_IsFarJump(ins) || INS_IsDirectFarJump(ins) || INS_IsMaskedJump(ins))
965  return true;
966  else if (INS_IsRet(ins) || INS_IsIRet(ins))
967  return true;
968  else if (INS_IsCall(ins) || INS_IsSyscall(ins))
969  return true;
970  else if (INS_IsBranch(ins) || INS_IsRDTSC(ins) || INS_IsNop(ins))
971  return true;
972  else if (INS_IsPrefetch(ins)) // Prefetch instructions might access addresses which are invalid.
973  return true;
974  // XSAVEC and XRSTOR are problematic since its access length is variable.
975  // Execution of XSAVEC is similar to that of XSAVE. XSAVEC differs from XSAVE in that it uses compaction and that it may use the init optimization.
976  // It fails with "Cannot use IARG_MEMORYWRITE_SIZE on non-standard memory access of instruction at 0xfoo: xsavec ptr [rsp]" error.
977  // A correct solution should use INS_hasKnownMemorySize() which is not available in Pin 2.14.
978  if (INS_Mnemonic(ins) == "XSAVEC")
979  return true;
980  if (INS_Mnemonic(ins) == "XSAVE")
981  return true;
982  if (INS_Mnemonic(ins) == "XRSTOR")
983  return true;
984  return false;
985 }
986 
987 static VOID InstrumentInsCallback(INS ins, VOID* v, const uint32_t opaqueHandle) {
988  if (!INS_HasFallThrough(ins))
989  return;
990  if (INS_IsIgnorable(ins))
991  return;
992  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
993  return;
994  //printf("\n In InstrumentInsCallback Begin \n");
995  //Instrument memory reads to find redundancy
996  // Special case, if we have only one read operand
997  UINT32 whichOp = 0;
998  if (GetNumReadOperandsInIns(ins, whichOp) == 1) {
999  // Read the value at location before and after the instruction
1000  LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, whichOp, opaqueHandle);
1001  } else {
1002  UINT32 memOperands = INS_MemoryOperandCount(ins);
1003  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1004  if (!INS_MemoryOperandIsRead(ins, memOp))
1005  continue;
1006  LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, memOp, opaqueHandle);
1007  }
1008  }
1009  //printf("\n In InstrumentInsCallback Finished \n");
1010 }
1011 
1012 /**********************************************************************************/
1013 
1014 #ifdef ENABLE_SAMPLING
1015 
1016 inline VOID UpdateAndCheck(uint32_t count, uint32_t bytes, THREADID threadId) {
1017  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1018 
1019  if (tData->sampleFlag) {
1020  tData->numIns += count;
1021  if (tData->numIns > WINDOW_ENABLE) {
1022  tData->sampleFlag = false;
1023  tData->numIns = 0;
1024  }
1025  } else {
1026  tData->numIns += count;
1027  if (tData->numIns > WINDOW_DISABLE) {
1028  tData->sampleFlag = true;
1029  tData->numIns = 0;
1030  }
1031  }
1032  if (tData->sampleFlag) {
1033  tData->bytesLoad += bytes;
1034  }
1035 }
1036 
1037 inline VOID Update(uint32_t count, uint32_t bytes, THREADID threadId) {
1038  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1039  tData->numIns += count;
1040  if (tData->sampleFlag) {
1041  tData->bytesLoad += bytes;
1042  }
1043 }
1044 
1045 //instrument the trace, count the number of ins in the trace, decide to instrument or not
1046 static void InstrumentTrace(TRACE trace, void* f) {
1047  bool check = false;
1048  for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1049  uint32_t totInsInBbl = BBL_NumIns(bbl);
1050  uint32_t totBytes = 0;
1051  for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1052  if (!INS_HasFallThrough(ins))
1053  continue;
1054  if (INS_IsIgnorable(ins))
1055  continue;
1056  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1057  continue;
1058 
1059  if (INS_IsMemoryRead(ins)) {
1060  totBytes += INS_MemoryReadSize(ins);
1061  }
1062  }
1063 
1064  if (BBL_InsTail(bbl) == BBL_InsHead(bbl)) {
1065  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1066  } else if (INS_IsIndirectBranchOrCall(BBL_InsTail(bbl))) {
1067  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1068  } else {
1069  if (check) {
1070  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1071  check = false;
1072  } else {
1073  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)Update, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1074  check = true;
1075  }
1076  }
1077  }
1078 }
1079 
1080 #else
1081 
1082 inline VOID Update(uint32_t bytes, THREADID threadId) {
1083  //printf("\nUpdate Begin\n");
1084  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1085  tData->bytesLoad += bytes;
1086  //printf("\nUpdate Finish\n");
1087 }
1088 
1089 //instrument the trace, count the number of ins in the trace, decide to instrument or not
1090 static void InstrumentTrace(TRACE trace, void* f) {
1091  //printf("\nInstrumentTrace Begin\n");
1092  for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1093  uint32_t totBytes = 0;
1094  for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1095  if (!INS_HasFallThrough(ins))
1096  continue;
1097  if (INS_IsIgnorable(ins))
1098  continue;
1099  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1100  continue;
1101 
1102  if (INS_IsMemoryRead(ins)) {
1103  totBytes += INS_MemoryReadSize(ins);
1104  }
1105  }
1106  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)Update, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_END);
1107  }
1108  //printf("\nInstrumentTrace Finish\n");
1109 }
1110 
1111 #endif
1112 
1113 // redundant data for a object
1115  uint64_t objID;
1116  uint64_t bytes;
1117  uint64_t dsize;
1118  uint64_t typesz;
1119 };
1120 
1121 static inline bool ObjRedundancyCompare(const struct ObjRedundancy& first, const struct ObjRedundancy& second) {
1122  return first.bytes > second.bytes;
1123 }
1124 
1125 static inline void PrintSize(uint64_t size, char unit = 'B') {
1126  if (size >= (1 << 20)) {
1127  fprintf(gTraceFile, "%lf M%c", (double)size / (double)(1 << 20), unit);
1128  } else if (size >= (1 << 10)) {
1129  fprintf(gTraceFile, "%lf K%c", (double)size / (double)(1 << 10), unit);
1130  } else {
1131  fprintf(gTraceFile, "%ld %c", size, unit);
1132  }
1133 }
1134 
1135 #define MAX_REDMAP_PRINT_SIZE 128
1136 // only print top 5 redundancy with full redmap to file
1137 #define MAX_PRINT_FULL 5
1138 
1139 static void PrintRedundancyPairs(THREADID threadId) {
1140  vector<ObjRedundancy> tmpList;
1141 
1142  uint64_t grandTotalRedundantBytes = 0;
1143  fprintf(gTraceFile, "\n--------------- Dumping Data Redundancy Info ----------------\n");
1144  fprintf(gTraceFile, "\n*************** Dump Data from Thread %d ****************\n", threadId);
1145 
1146  int count = 0;
1147  int rep = -1;
1148  int total = RedMap[threadId].size();
1149  for (unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].begin(); it != RedMap[threadId].end(); ++it) {
1150  ++count;
1151  if (100 * count / total != rep) {
1152  rep = 100 * count / total;
1153  printf("Stage 1 : %d%% Finish\n", rep);
1154  fflush(stdout);
1155  }
1156  grandTotalRedundantBytes += (*it).second.red;
1157  ObjRedundancy tmp = {(*it).first, (*it).second.red, (*it).second.end_addr - (*it).second.beg_addr, (*it).second.tot};
1158  tmpList.push_back(tmp);
1159  }
1160 
1161  __sync_fetch_and_add(&grandTotBytesRedLoad, grandTotalRedundantBytes);
1162  fprintf(gTraceFile, "\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad);
1163  sort(tmpList.begin(), tmpList.end(), ObjRedundancyCompare);
1164 
1165  int objNum = 0;
1166  rep = -1;
1167  total = tmpList.size() < MAX_OBJS_TO_LOG ? tmpList.size() : MAX_OBJS_TO_LOG;
1168  for (vector<ObjRedundancy>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1169  if (objNum++ >= MAX_OBJS_TO_LOG)
1170  break;
1171  if (100 * objNum / total != rep) {
1172  rep = 100 * count / total;
1173  printf("Stage 2 : %d%% Finish\n", rep);
1174  fflush(stdout);
1175  }
1176  if ((uint8_t)DECODE_TYPE((*listIt).objID) == DYNAMIC_OBJECT) {
1177  fprintf(gTraceFile, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1178  PrintFullCallingContext(DECODE_NAME((*listIt).objID)); // segfault might happen if the shadow memory based data centric is used
1179  } else
1180  fprintf(gTraceFile, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Static Object: %s ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", GetStringFromStringPool((uint32_t)DECODE_NAME((*listIt).objID)));
1181 
1182  fprintf(gTraceFile, "\n\n==========================================\n");
1183  fprintf(gTraceFile, "Redundancy Ratio = %f %% (%ld Bytes)\n", (*listIt).bytes * 100.0 / grandTotalRedundantBytes, (*listIt).bytes);
1184 
1185  uint64_t dfreq = 0;
1186  uint64_t dread = 0;
1187  for (vector<uint8_t>::iterator addrIt = RedMap[threadId][(*listIt).objID].state.begin(); addrIt != RedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1188  if (*addrIt == DATA_STATE_ONLY_ZERO)
1189  dfreq++;
1190  if (*addrIt)
1191  dread++;
1192  }
1193 
1194  fprintf(gTraceFile, "\n\n======= DATA SIZE : ");
1195  PrintSize((*listIt).dsize);
1196  fprintf(gTraceFile, "( Not Accessed Data %f %% (%ld Bytes), Redundant Data %f %% (%ld Bytes) )",
1197  ((*listIt).dsize - dread) * 100.0 / (*listIt).dsize, (*listIt).dsize - dread,
1198  dfreq * 100.0 / (*listIt).dsize, dfreq);
1199 
1200  fprintf(gTraceFile, "\n======= Redundant byte map : [0] ");
1201  uint32_t num = 0;
1202  for (vector<uint8_t>::iterator addrIt = RedMap[threadId][(*listIt).objID].state.begin(); addrIt != RedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1203  switch (*addrIt) {
1204  case DATA_STATE_NOT_VISIT:
1205  fprintf(gTraceFile, "?? ");
1206  break;
1207  case DATA_STATE_ONLY_ZERO:
1208  fprintf(gTraceFile, "00 ");
1209  break;
1210  default:
1211  fprintf(gTraceFile, "XX ");
1212  break;
1213  }
1214  ++num;
1215  if (num > MAX_REDMAP_PRINT_SIZE) {
1216  fprintf(gTraceFile, "... ");
1217  break;
1218  }
1219  }
1220  if (objNum <= MAX_PRINT_FULL) {
1221  char fn[50] = {};
1222  sprintf(fn, "%lx.redmap", (*listIt).objID);
1223  FILE* fp = fopen(fn, "w");
1224  if ((uint8_t)DECODE_TYPE((*listIt).objID) == DYNAMIC_OBJECT) {
1225  fprintf(fp, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
1226  PrintFullCallingContext(DECODE_NAME((*listIt).objID)); // segfault might happen if the shadow memory based data centric is used
1227  } else
1228  fprintf(fp, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Static Object: %s ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", GetStringFromStringPool((uint32_t)DECODE_NAME((*listIt).objID)));
1229  for (vector<uint8_t>::iterator addrIt = RedMap[threadId][(*listIt).objID].state.begin(); addrIt != RedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1230  switch (*addrIt) {
1231  case DATA_STATE_NOT_VISIT:
1232  fprintf(fp, "?");
1233  break;
1234  case DATA_STATE_ONLY_ZERO:
1235  fprintf(fp, "0");
1236  break;
1237  default:
1238  fprintf(fp, "X");
1239  break;
1240  }
1241  }
1242  }
1243  }
1244  fprintf(gTraceFile, "\n------------ Dumping Redundancy Info Finish -------------\n");
1245 }
1246 
1247 // TODO : redundant bytes rates are abnormal, need debugging
1248 static void PrintApproximationRedundancyPairs(THREADID threadId) {
1249  vector<ObjRedundancy> tmpList;
1250 
1251  uint64_t grandTotalRedundantBytes = 0;
1252  fprintf(gTraceFile, "\n--------------- Dumping Data Approximation Redundancy Info ----------------\n");
1253  fprintf(gTraceFile, "\n*************** Dump Data(delta=%.2f%%) from Thread %d ****************\n", delta * 100, threadId);
1254 
1255  for (unordered_map<uint64_t, RedLogs>::iterator it = ApproxRedMap[threadId].begin(); it != ApproxRedMap[threadId].end(); ++it) {
1256  grandTotalRedundantBytes += (*it).second.red;
1257  ObjRedundancy tmp = {(*it).first, (*it).second.red, (*it).second.end_addr - (*it).second.beg_addr, (*it).second.tot};
1258  tmpList.push_back(tmp);
1259  }
1260 
1261  __sync_fetch_and_add(&grandTotBytesApproxRedLoad, grandTotalRedundantBytes);
1262 
1263  fprintf(gTraceFile, "\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad);
1264  sort(tmpList.begin(), tmpList.end(), ObjRedundancyCompare);
1265 
1266  int objNum = 0;
1267  for (vector<ObjRedundancy>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1268  if (objNum++ >= MAX_OBJS_TO_LOG)
1269  break;
1270  if ((uint8_t)DECODE_TYPE((*listIt).objID) == DYNAMIC_OBJECT) {
1271  fprintf(gTraceFile, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1272  PrintFullCallingContext(DECODE_NAME((*listIt).objID)); // segfault might happen if the shadow memory based data centric is used
1273  } else
1274  fprintf(gTraceFile, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Static Object: %s ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", GetStringFromStringPool((uint32_t)DECODE_NAME((*listIt).objID)));
1275 
1276  fprintf(gTraceFile, "\n\n==========================================\n");
1277  fprintf(gTraceFile, "Redundancy Ratio = %f %% (%ld Bytes)\n", (*listIt).bytes * 100.0 / grandTotalRedundantBytes, (*listIt).bytes);
1278 
1279  uint64_t dfreq = 0;
1280  uint64_t dread = 0;
1281  for (vector<uint8_t>::iterator addrIt = ApproxRedMap[threadId][(*listIt).objID].state.begin(); addrIt != ApproxRedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1282  if (*addrIt == DATA_STATE_ONLY_ZERO)
1283  dfreq += (*listIt).typesz;
1284  if (*addrIt)
1285  dread += (*listIt).typesz;
1286  }
1287 
1288  fprintf(gTraceFile, "\n\n======= DATA SIZE : ");
1289  PrintSize((*listIt).dsize);
1290  fprintf(gTraceFile, "( Not Accessed Data %f %% (%ld Bytes), Redundant Data %f %% (%ld Bytes) )",
1291  ((*listIt).dsize - dread) * 100.0 / (*listIt).dsize, (*listIt).dsize - dread,
1292  dfreq * 100.0 / (*listIt).dsize, dfreq);
1293 
1294  fprintf(gTraceFile, "\n======= Redundant byte map : [0] ");
1295  uint32_t num = 0;
1296  for (uint32_t i = 0; i < ApproxRedMap[threadId][(*listIt).objID].state.size(); i += (*listIt).typesz) {
1297  switch (ApproxRedMap[threadId][(*listIt).objID].state[i]) {
1298  case DATA_STATE_NOT_VISIT:
1299  fprintf(gTraceFile, "?? ");
1300  break;
1301  case DATA_STATE_ONLY_ZERO:
1302  fprintf(gTraceFile, "00 ");
1303  break;
1304  default:
1305  fprintf(gTraceFile, "XX ");
1306  break;
1307  }
1308  ++num;
1309  if (num > MAX_REDMAP_PRINT_SIZE) {
1310  fprintf(gTraceFile, "... ");
1311  break;
1312  }
1313  }
1314  if (objNum <= MAX_PRINT_FULL) {
1315  char fn[50] = {};
1316  sprintf(fn, "%lx.redmap", (*listIt).objID);
1317  FILE* fp = fopen(fn, "w");
1318  if ((uint8_t)DECODE_TYPE((*listIt).objID) == DYNAMIC_OBJECT) {
1319  fprintf(fp, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: %lx^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", (*listIt).objID);
1320  } else
1321  fprintf(fp, "\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Static Object: %s, %lx ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", GetStringFromStringPool((uint32_t)DECODE_NAME((*listIt).objID)), (*listIt).objID);
1322  for (uint32_t i = 0; i < ApproxRedMap[threadId][(*listIt).objID].state.size(); i += (*listIt).typesz) {
1323  switch (ApproxRedMap[threadId][(*listIt).objID].state[i]) {
1324  case DATA_STATE_NOT_VISIT:
1325  fprintf(fp, "?? ");
1326  break;
1327  case DATA_STATE_ONLY_ZERO:
1328  fprintf(fp, "00 ");
1329  break;
1330  default:
1331  fprintf(fp, "XX ");
1332  break;
1333  }
1334  }
1335  }
1336  }
1337  fprintf(gTraceFile, "\n------------ Dumping Approx Redundancy Info Finish -------------\n");
1338 }
1339 // On each Unload of a loaded image, the accummulated redundancy information is dumped
1340 static VOID ImageUnload(IMG img, VOID* v) {
1341  printf("==== PIN CLIENT ZEROSPY : Unloading %s, now collecting analysis data ===\n", IMG_Name(img).c_str());
1342  fprintf(gTraceFile, "\n TODO .. Multi-threading is not well supported.");
1343  THREADID threadid = PIN_ThreadId();
1344  fprintf(gTraceFile, "\nUnloading %s", IMG_Name(img).c_str());
1345  if (RedMap[threadid].empty() && ApproxRedMap[threadid].empty())
1346  return;
1347  // Update gTotalInstCount first
1348  PIN_LockClient();
1349  printf("==== PIN CLIENT ZEROSPY : Print Redundancy info ... ===\n");
1350  PrintRedundancyPairs(threadid);
1351  printf("==== PIN CLIENT ZEROSPY : Print Approximation Redundancy info ... ===\n");
1353 #ifdef PRINT_MEM_INFO
1354  printf("==== PIN CLIENT ZEROSPY : Print Cacheline Redundancy info ... ===\n");
1355  PrintMemoryRedundancy<CACHE_LINE_SIZE>("Cacheline", threadid);
1356  printf("==== PIN CLIENT ZEROSPY : Print Page Redundancy info ... ===\n");
1357  PrintMemoryRedundancy<PAGE_SIZE>("Page", threadid);
1358 #endif
1359  PIN_UnlockClient();
1360  // clear redmap now
1361  RedMap[threadid].clear();
1362  ApproxRedMap[threadid].clear();
1363 }
1364 
1365 static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT* ctxt, INT32 code, VOID* v) {
1366  __sync_fetch_and_add(&grandTotBytesLoad, ClientGetTLS(threadid)->bytesLoad);
1367  /*
1368  // output the CCT for hpcviewer format
1369  HPCRunRedundancyPairs(threadid);
1370  HPCRunApproxRedundancyPairs(threadid);
1371  newCCT_hpcrun_selection_write(threadid);*/
1372 }
1373 
1374 static VOID FiniFunc(INT32 code, VOID* v) {
1375  // do whatever you want to the full CCT with footpirnt
1376  uint64_t redReadTmp = 0;
1377  uint64_t approxRedReadTmp = 0;
1378  for (int i = 0; i < THREAD_MAX; ++i) {
1379  if (!RedMap[i].empty()) {
1380  for (unordered_map<uint64_t, RedLogs>::iterator it = RedMap[i].begin(); it != RedMap[i].end(); ++it) {
1381  redReadTmp += (*it).second.red;
1382  }
1383  }
1384  if (!ApproxRedMap[i].empty()) {
1385  for (unordered_map<uint64_t, RedLogs>::iterator it = ApproxRedMap[i].begin(); it != ApproxRedMap[i].end(); ++it) {
1386  approxRedReadTmp += (*it).second.red;
1387  }
1388  }
1389  }
1390 
1391  grandTotBytesRedLoad += redReadTmp;
1392  grandTotBytesApproxRedLoad += approxRedReadTmp;
1393  fprintf(gTraceFile, "\n#Redundant Read:");
1394  fprintf(gTraceFile, "\nTotalBytesLoad: %lu \n", grandTotBytesLoad);
1395  fprintf(gTraceFile, "\nRedundantBytesLoad: %lu %.2f\n", grandTotBytesRedLoad, grandTotBytesRedLoad * 100.0 / grandTotBytesLoad);
1396  fprintf(gTraceFile, "\nApproxRedundantBytesLoad: %lu %.2f\n", grandTotBytesApproxRedLoad, grandTotBytesApproxRedLoad * 100.0 / grandTotBytesLoad);
1397 }
1398 
1399 static void InitThreadData(RedSpyThreadData* tdata) {
1400  tdata->bytesLoad = 0;
1401  tdata->sampleFlag = true;
1402  tdata->numIns = 0;
1403  fprintf(gTraceFile, "\nInit Thread Data Finish\n");
1404  /* for (int i = 0; i < THREAD_MAX; ++i) {
1405  RedMap[i].set_empty_key(0);
1406  ApproxRedMap[i].set_empty_key(0);
1407  }
1408 */
1409 }
1410 
1411 static VOID ThreadStart(THREADID threadid, CONTEXT* ctxt, INT32 flags, VOID* v) {
1412  RedSpyThreadData* tdata = (RedSpyThreadData*)memalign(32, sizeof(RedSpyThreadData));
1413  InitThreadData(tdata);
1414  // __sync_fetch_and_add(&gClientNumThreads, 1);
1415  PIN_SetThreadData(client_tls_key, tdata, threadid);
1416 #ifdef MULTI_THREADED
1417  PIN_SetThreadData(client_tls_key, tdata, threadid);
1418 #else
1419  gSingleThreadedTData = tdata;
1420 #endif
1421  fprintf(gTraceFile, "\nInit ThreadStart Finish\n");
1422 }
1423 
1424 // user-defined function for metric computation
1425 // hpcviewer can only show the numbers for the metric
1426 uint64_t computeMetricVal(void* metric) {
1427  if (!metric)
1428  return 0;
1429  return (uint64_t)metric;
1430 }
1431 
1432 int main(int argc, char* argv[]) {
1433  // Initialize PIN
1434  if (PIN_Init(argc, argv))
1435  return Usage();
1436 
1437  // Initialize Symbols, we need them to report functions and lines
1438  PIN_InitSymbols();
1439 
1440  // Init Client
1441  ClientInit(argc, argv);
1442  // Intialize CCTLib
1443  PinCCTLibInit(INTERESTING_INS_ALL, gTraceFile, InstrumentInsCallback, nullptr, /*Do data centric work*/ true);
1444 
1445  // Obtain a key for TLS storage.
1446  client_tls_key = PIN_CreateThreadDataKey(nullptr /*TODO have a destructir*/);
1447  // Register ThreadStart to be called when a thread starts.
1448  PIN_AddThreadStartFunction(ThreadStart, nullptr);
1449 
1450  // fini function for post-mortem analysis
1451  PIN_AddThreadFiniFunction(ThreadFiniFunc, nullptr);
1452  PIN_AddFiniFunction(FiniFunc, nullptr);
1453 
1454  TRACE_AddInstrumentFunction(InstrumentTrace, nullptr);
1455 
1456  // Register ImageUnload to be called when an image is unloaded
1457  IMG_AddUnloadFunction(ImageUnload, nullptr);
1458  printf("==== PIN CLIENT : Launch program now ===\n");
1459  // Launch program now
1460  PIN_StartProgram();
1461  return 0;
1462 }
#define MAX_FILE_PATH
Definition: cctlib.H:18
#define INTERESTING_INS_ALL
Definition: cctlib.H:85
uint64_t metric
Definition: cctlib.H:60
DataHandle_t GetDataObjectHandle(VOID *address, const THREADID threadId)
Definition: cctlib.cpp:2495
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
Definition: cctlib.cpp:3132
hpcrun_metricFlags_t flags
Definition: cctlib.cpp:3425
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
Definition: cctlib.cpp:2346
@ DYNAMIC_OBJECT
Definition: cctlib.H:26
@ STATIC_OBJECT
Definition: cctlib.H:27
struct DataHandle_t { uint8_t objectType DataHandle_t
Definition: cctlib.H:32
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
Definition: cctlib.cpp:1356
uint32_t ContextHandle_t
Definition: cctlib.H:22
char * GetStringFromStringPool(const uint32_t index)
Definition: cctlib.cpp:802
DataraceInfo_t data
static USIZE INS_MemoryReadSize(INS ins)
static BOOL INS_IsMaskedJump(INS ins)
static BOOL INS_IsIndirectBranchOrCall(INS ins)
#define WINDOW_ENABLE
#define WINDOW_DISABLE
struct RedSpyThreadData __attribute__
uint8_t value[MAX_WRITE_OP_LENGTH]
static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins
uint64_t red
uint64_t tot
vector< uint8_t > state
static __attribute__((always_inline)) void BodyByteMap(uint8_t *addr
static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t *__restrict__ prevIP)
static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t *addr)
static __attribute__((always_inline)) bool Body(const function< void(const int)> &func)
static __attribute__((always_inline)) bool Body(const function< bool(const int)> &func)
static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t *__restrict__ prevIP)
static bool Body(const function< bool(const int)> &func)
static __attribute__((always_inline)) void BodyByteMapApprox(uint8_t *addr
static __attribute__((always_inline)) void BodyByteMap(uint8_t *addr
static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t *addr)
static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t *addr)
static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t *addr)
static __attribute__((always_inline)) void getRedMap(void *addr
void f()
Definition: test1.c:23
uint64_t computeMetricVal(void *metric)
static void ClientInit(int argc, char *argv[])
#define DECODE_TYPE(a)
#define DATA_STATE_NOT_ZERO
int main(int argc, char *argv[])
#define HANDLE_LARGE()
static FILE * gTraceFile
static void PrintSize(uint64_t size, char unit='B')
uint64_t grandTotBytesRedLoad
xed_state_t xedState
static bool ObjRedundancyCompare(const struct ObjRedundancy &first, const struct ObjRedundancy &second)
static unordered_map< uint64_t, RedLogs > RedMap[THREAD_MAX]
static int GetNumReadOperandsInIns(INS ins, UINT32 &whichOp)
static VOID ImageUnload(IMG img, VOID *v)
#define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX)
#define DATA_STATE_ONLY_ZERO
#define MAX_PRINT_FULL
static RedSpyThreadData * gSingleThreadedTData
#define MAX_OBJS_TO_LOG
#define EIGHT_BYTE_WRITE_ACTION
static void PrintRedundancyPairs(THREADID threadId)
#define MAKE_OBJID(a, b)
char dummy2[128]
static const uint64_t READ_ACCESS_STATES[]
#define THREAD_MAX
#define DATA_STATE_NOT_VISIT
#define ONE_BYTE_READ_ACTION
int redload_approx_metric_id
static INT32 Usage()
static void AddToApproximateRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) __attribute__((always_inline
static bool IsFloatInstructionOld(ADDRINT ip)
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
static uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper)
static const uint8_t OVERFLOW_CHECK[]
static void flatten
VOID Update(uint32_t bytes, THREADID threadId)
#define DECODE_NAME(b)
struct @22 LoadSpyGlobals
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static void InstrumentTrace(TRACE trace, void *f)
static void InitThreadData(RedSpyThreadData *tdata)
static bool INS_IsIgnorable(INS ins)
RedSpyThreadData * ClientGetTLS(const THREADID threadId)
#define MAX_REDMAP_PRINT_SIZE
#define delta
static bool IsFloatInstructionAndOkToApproximate(ADDRINT ip)
static VOID FiniFunc(INT32 code, VOID *v)
#define TWO_BYTE_WRITE_ACTION
static const uint64_t WRITE_ACCESS_STATES[]
static VOID CheckAfterLargeRead(void *addr, UINT32 accessLen, uint32_t opaqueHandle, THREADID threadId)
uint64_t grandTotBytesLoad
#define FOUR_BYTE_READ_ACTION
static void PrintApproximationRedundancyPairs(THREADID threadId)
uint64_t grandTotBytesApproxRedLoad
static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v)
static void AddToRedTable(uint32_t addr, DataHandle_t data, ContextHandle_t cntxt, uint16_t value, uint16_t total, const uint8_t redmap[32], uint32_t typesz, THREADID threadId) __attribute__((always_inline
static bool IsOkToApproximate(xed_decoded_inst_t &xedd)
char dummy1[128]
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
#define SMALL_VAR_THRESHOLD
static TLS_KEY client_tls_key
static unordered_map< uint64_t, RedLogs > ApproxRedMap[THREAD_MAX]
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
int redload_metric_id