CCTLib
Calling-context and data-object attribution library for Intel Pin
zerospy_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 #include "cctlib.H"
26 #include "shadow_memory.H"
27 #include <xmmintrin.h>
28 #include <immintrin.h>
29 
30 extern "C" {
31 #include "xed-interface.h"
32 #include "xed-common-hdrs.h"
33 }
34 
35 #include <google/sparse_hash_map>
36 #include <google/dense_hash_map>
37 
38 using namespace std;
39 using namespace PinCCTLib;
40 
41 // have R, W representative macros
42 #define READ_ACTION (0)
43 #define WRITE_ACTION (0xff)
44 
45 #define ONE_BYTE_READ_ACTION (0)
46 #define TWO_BYTE_READ_ACTION (0)
47 #define FOUR_BYTE_READ_ACTION (0)
48 #define EIGHT_BYTE_READ_ACTION (0)
49 
50 #define ONE_BYTE_WRITE_ACTION (0xff)
51 #define TWO_BYTE_WRITE_ACTION (0xffff)
52 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
53 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
54 
55 #define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen) (PAGE_OFFSET((accessAddr)) <= (PAGE_OFFSET_MASK - (accessLen)))
56 
57 /* Other footprint_client settings */
58 #define MAX_REDUNDANT_CONTEXTS_TO_LOG (1000)
59 #define THREAD_MAX (1024)
60 
61 #define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len) ((addr) | (((uint64_t)(len)) << 48))
62 #define DECODE_ADDRESS(addrAndLen) ((addrAndLen) & ((1L << 48) - 1))
63 #define DECODE_ACCESS_LEN(addrAndLen) ((addrAndLen) >> 48)
64 
65 
66 #define MAX_WRITE_OP_LENGTH (512)
67 #define MAX_WRITE_OPS_IN_INS (8)
68 #define MAX_REG_LENGTH (64)
69 
70 #define MAX_SIMD_LENGTH (64)
71 #define MAX_SIMD_REGS (32)
72 
73 #define PAGE_MASK (~0xfff)
74 #define GET_PAGE_INDEX(x) ((x)&PAGE_MASK)
75 
76 #define CACHELINE_MASK (~63)
77 #define GET_CACHELINE_INDEX(x) ((x)&CACHELINE_MASK)
78 
79 //#define MERGING
80 // #define NO_APPROXMAP
81 // #define SKIP_SMALLCASE
82 
83 #ifdef ENABLE_SAMPLING
84 
85 #define WINDOW_ENABLE 1000000
86 #define WINDOW_DISABLE 100000000
87 #define WINDOW_CLEAN 10
88 #endif
89 
90 #define DECODE_DEAD(data) static_cast<uint8_t>(((data)&0xffffffffffffffff) >> 32)
91 #define DECODE_KILL(data) (static_cast<ContextHandle_t>((data)&0x00000000ffffffff))
92 
93 
94 #define MAKE_CONTEXT_PAIR(a, b) (((uint64_t)(a) << 32) | ((uint64_t)(b)))
95 
96 #define delta 0.01
97 
98 
99 /***********************************************
100  ****** shadow memory
101  ************************************************/
102 //ConcurrentShadowMemory<uint8_t, ContextHandle_t> sm;
103 
104 struct {
105  char dummy1[128];
106  xed_state_t xedState;
107  char dummy2[128];
109 
110 
111 #if 0
113 
114 
115 inline uint8_t* GetOrCreateShadowBaseAddress(uint64_t address) {
116  // No entries at all ?
117  uint8_t* shadowPage;
118  uint8_t** * l1Ptr = &gL1PageTable[LEVEL_1_PAGE_TABLE_SLOT(address)];
119 
120  if(*l1Ptr == 0) {
121  *l1Ptr = (uint8_t**) calloc(1, LEVEL_2_PAGE_TABLE_SIZE);
122  shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)] = (uint8_t*) mmap(0, SHADOW_PAGE_SIZE * (1 + sizeof(uint32_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
123  } else if((shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)]) == 0) {
124  shadowPage = (*l1Ptr)[LEVEL_2_PAGE_TABLE_SLOT(address)] = (uint8_t*) mmap(0, SHADOW_PAGE_SIZE * (1 + sizeof(uint32_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
125  }
126 
127  return shadowPage;
128 }
129 #endif
130 
131 ////////////////////////////////////////////////
132 
133 struct RedSpyThreadData {
134  uint64_t bytesLoad;
135 
136  long long numIns;
137  bool sampleFlag;
138 };
139 
140 // for metric logging
143 
144 //for statistics result
148 
149 //uint64_t localTotBytesLoad[THREAD_MAX] = {0};
150 
151 // key for accessing TLS storage in the threads. initialized once in main()
152 static TLS_KEY client_tls_key;
154 
155 // function to access thread-specific data
156 inline RedSpyThreadData* ClientGetTLS(const THREADID threadId) {
157 #ifdef MULTI_THREADED
158  RedSpyThreadData* tdata =
159  static_cast<RedSpyThreadData*>(PIN_GetThreadData(client_tls_key, threadId));
160  return tdata;
161 #else
162  return gSingleThreadedTData;
163 #endif
164 }
165 
166 static INT32 Usage() {
167  PIN_ERROR("Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() + "\n");
168  return -1;
169 }
170 
171 // Main for RedSpy, initialize the tool, register instrumentation functions and call the target program.
172 static FILE* gTraceFile;
173 
174 // Initialized the needed data structures before launching the target program
175 static void ClientInit(int argc, char* argv[]) {
176  // Create output file
177  char name[MAX_FILE_PATH] = "zeroLoad.out.";
178  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
179 
180  if (envPath) {
181  // assumes max of MAX_FILE_PATH
182  snprintf(name, sizeof(name), "%s", envPath);
183  }
184 
185  gethostname(name + strlen(name), MAX_FILE_PATH - strlen(name));
186  pid_t pid = getpid();
187  sprintf(name + strlen(name), "%d", pid);
188  cerr << "\n Creating log file at:" << name << "\n";
189  gTraceFile = fopen(name, "w");
190  // print the arguments passed
191  fprintf(gTraceFile, "\n");
192 
193  for (int i = 0; i < argc; i++) {
194  fprintf(gTraceFile, "%s ", argv[i]);
195  }
196 
197  fprintf(gTraceFile, "\n");
198 
199  // Init Xed
200  // Init XED for decoding instructions
201  xed_state_init(&LoadSpyGlobals.xedState, XED_MACHINE_MODE_LONG_64, (xed_address_width_enum_t)0, XED_ADDRESS_WIDTH_64b);
202 }
203 
204 
205 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};
206 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};
207 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};
208 
209 struct RedLogs {
210  uint64_t tot;
211  uint64_t red;
212  uint64_t fred; // full redundancy
213  uint32_t redByteMap;
214  //uint8_t AccessLen;
215 };
217  //uint64_t tot;
218  //uint64_t red;
219  uint64_t fred; // full redundancy
220  uint64_t ftot;
221  uint32_t redByteMapMan;
222  uint32_t redByteMapExp;
223  uint32_t redByteMapSign;
224  uint8_t AccessLen;
225  uint8_t size;
226  //uint8_t down;
227 };
228 //static unordered_map<uint64_t, uint64_t> validMap[THREAD_MAX];
229 static unordered_map<uint64_t, RedLogs> RedMap[THREAD_MAX];
230 static unordered_map<uint64_t, ApproxRedLogs> ApproxRedMap[THREAD_MAX];
231 #ifdef USE_COLLECT_PAGE_CACHE
232 struct DataLogs {
233  uint64_t red;
234  uint64_t tot;
235 };
236 
237 static unordered_map<uint64_t, DataLogs> PageRedMap[THREAD_MAX];
238 static unordered_map<uint64_t, DataLogs> CacheRedMap[THREAD_MAX];
239 static inline void AddToPageRedTable(uint64_t key, uint16_t value, uint16_t total, THREADID threadId) __attribute__((always_inline, flatten));
240 static inline void AddToPageRedTable(uint64_t key, uint16_t value, uint16_t total, THREADID threadId) {
241 #ifdef MULTI_THREADED
242  LOCK_RED_MAP();
243 #endif
244  unordered_map<uint64_t, DataLogs>::iterator it = PageRedMap[threadId].find(key);
245  if (it == PageRedMap[threadId].end()) {
246  DataLogs log;
247  log.red = value;
248  log.tot = total;
249  PageRedMap[threadId][key] = log;
250  } else {
251  it->second.red += value;
252  it->second.tot += total;
253  }
254 #ifdef MULTI_THREADED
255  UNLOCK_RED_MAP();
256 #endif
257 }
258 
259 static inline void AddToCacheRedTable(uint64_t key, uint16_t value, uint16_t total, THREADID threadId) __attribute__((always_inline, flatten));
260 static inline void AddToCacheRedTable(uint64_t key, uint16_t value, uint16_t total, THREADID threadId) {
261 #ifdef MULTI_THREADED
262  LOCK_RED_MAP();
263 #endif
264  unordered_map<uint64_t, DataLogs>::iterator it = CacheRedMap[threadId].find(key);
265  if (it == CacheRedMap[threadId].end()) {
266  DataLogs log;
267  log.red = value;
268  log.tot = total;
269  CacheRedMap[threadId][key] = log;
270  } else {
271  it->second.red += value;
272  it->second.tot += total;
273  }
274 #ifdef MULTI_THREADED
275  UNLOCK_RED_MAP();
276 #endif
277 }
278 #endif
279 static inline void AddToRedTable(uint64_t key, uint16_t value, uint32_t byteMap, uint16_t total, THREADID threadId) __attribute__((always_inline, flatten));
280 static inline void AddToRedTable(uint64_t key, uint16_t value, uint32_t byteMap, uint16_t total, THREADID threadId) {
281 #ifdef MULTI_THREADED
282  LOCK_RED_MAP();
283 #endif
284  unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].find(key);
285  if (it == RedMap[threadId].end()) {
286  RedLogs log;
287  log.red = value;
288  log.tot = total;
289  log.fred = (value == total);
290  log.redByteMap = byteMap;
291  //log.AccessLen = total;
292  //if(total < value) cerr << "ERROR : total " << total << " < value " << value << endl;
293  RedMap[threadId][key] = log;
294  //printf("Bucket size : %ld\n",RedMap[threadId].bucket_count());
295  } else {
296  it->second.red += value;
297  it->second.tot += total;
298  it->second.fred += (value == total);
299  it->second.redByteMap &= byteMap;
300  //if(total < value) cerr << "ERROR : total " << total << " < value " << value << endl;
301  //assert(it->second.AccessLen == total && "AccessLen not match");
302  }
303  //localTotBytesLoad[threadId] += total;
304 #ifdef MULTI_THREADED
305  UNLOCK_RED_MAP();
306 #endif
307 }
308 
309 static inline void AddToApproximateRedTable(uint64_t key, uint32_t byteMapMan, uint32_t byteMapExp, uint32_t byteMapSign, uint16_t total, uint16_t zeros, uint16_t nums, uint8_t size, THREADID threadId) __attribute__((always_inline, flatten));
310 static inline void AddToApproximateRedTable(uint64_t key, uint32_t byteMapMan, uint32_t byteMapExp, uint32_t byteMapSign, uint16_t total, uint16_t zeros, uint16_t nums, uint8_t size, THREADID threadId) {
311 #ifdef MULTI_THREADED
312  LOCK_RED_MAP();
313 #endif
314  unordered_map<uint64_t, ApproxRedLogs>::iterator it = ApproxRedMap[threadId].find(key);
315  if (it == ApproxRedMap[threadId].end()) {
316  ApproxRedLogs log;
317  //log.red = value;
318  //log.tot = total;
319  log.fred = zeros;
320  log.ftot = nums;
321  log.redByteMapMan = byteMapMan;
322  log.redByteMapExp = byteMapExp;
323  log.redByteMapSign = byteMapSign;
324  log.AccessLen = total;
325  log.size = size;
326  //log.down = down;
327  //if(total < value) cerr << "ERROR : total " << total << " < value " << value << endl;
328  ApproxRedMap[threadId][key] = log;
329  } else {
330  //it->second.red += value;
331  //it->second.tot += total;
332  it->second.fred += zeros;
333  it->second.ftot += nums;
334  it->second.redByteMapMan &= byteMapMan;
335  it->second.redByteMapExp &= byteMapExp;
336  it->second.redByteMapSign &= byteMapSign;
337  //it->second.down &= down;
338  //if(total < value) cerr << "ERROR : total " << total << " < value " << value << endl;
339  //assert(it->second.AccessLen == total && "AccessLen not match");
340  }
341  //localTotBytesLoad[threadId] += total;
342 #ifdef MULTI_THREADED
343  UNLOCK_RED_MAP();
344 #endif
345 }
346 
347 
348 #ifdef ENABLE_SAMPLING
349 
350 static ADDRINT IfEnableSample(THREADID threadId) {
351  RedSpyThreadData* const tData = ClientGetTLS(threadId);
352  return tData->sampleFlag;
353 }
354 
355 #endif
356 
357 // Certain FP instructions should not be approximated
358 static inline bool IsOkToApproximate(xed_decoded_inst_t& xedd) {
359  xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
360  switch (iclass) {
361  case XED_ICLASS_FLDENV:
362  case XED_ICLASS_FNSTENV:
363  case XED_ICLASS_FNSAVE:
364  case XED_ICLASS_FLDCW:
365  case XED_ICLASS_FNSTCW:
366  case XED_ICLASS_FXRSTOR:
367  case XED_ICLASS_FXRSTOR64:
368  case XED_ICLASS_FXSAVE:
369  case XED_ICLASS_FXSAVE64:
370  return false;
371  default:
372  return true;
373  }
374 }
375 
376 static inline bool IsFloatInstructionAndOkToApproximate(ADDRINT ip) {
377  xed_decoded_inst_t xedd;
378  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
379 
380  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
381  xed_category_enum_t cat = xed_decoded_inst_get_category(&xedd);
382  switch (cat) {
383  case XED_CATEGORY_AES:
384  case XED_CATEGORY_CONVERT:
385  case XED_CATEGORY_PCLMULQDQ:
386  case XED_CATEGORY_SSE:
387  case XED_CATEGORY_AVX2:
388  case XED_CATEGORY_AVX:
389  case XED_CATEGORY_MMX:
390  case XED_CATEGORY_DATAXFER: {
391  // Get the mem operand
392 
393  const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
394  int noperands = xed_inst_noperands(xi);
395  int memOpIdx = -1;
396  for (int i = 0; i < noperands; i++) {
397  const xed_operand_t* op = xed_inst_operand(xi, i);
398  xed_operand_enum_t op_name = xed_operand_name(op);
399  if (XED_OPERAND_MEM0 == op_name) {
400  memOpIdx = i;
401  break;
402  }
403  }
404  if (memOpIdx == -1) {
405  return false;
406  }
407 
408  // TO DO MILIND case XED_OPERAND_MEM1:
409  xed_operand_element_type_enum_t eType = xed_decoded_inst_operand_element_type(&xedd, memOpIdx);
410  switch (eType) {
411  case XED_OPERAND_ELEMENT_TYPE_FLOAT16:
412  case XED_OPERAND_ELEMENT_TYPE_SINGLE:
413  case XED_OPERAND_ELEMENT_TYPE_DOUBLE:
414  case XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE:
415  case XED_OPERAND_ELEMENT_TYPE_LONGBCD:
416  return IsOkToApproximate(xedd);
417  default:
418  return false;
419  }
420  } break;
421  case XED_CATEGORY_X87_ALU:
422  case XED_CATEGORY_FCMOV:
423  //case XED_CATEGORY_LOGICAL_FP:
424  // assumption, the access length must be either 4 or 8 bytes else assert!!!
425  //assert(*accessLen == 4 || *accessLen == 8);
426  return IsOkToApproximate(xedd);
427  case XED_CATEGORY_XSAVE:
428  case XED_CATEGORY_AVX2GATHER:
429  case XED_CATEGORY_STRINGOP:
430  default:
431  return false;
432  }
433  } else {
434  assert(0 && "failed to disassemble instruction");
435  // printf("\n Diassembly failure\n");
436  return false;
437  }
438 }
439 
440 static inline bool IsFloatInstructionOld(ADDRINT ip) {
441  xed_decoded_inst_t xedd;
442  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
443 
444  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
445  xed_iclass_enum_t iclassType = xed_decoded_inst_get_iclass(&xedd);
446  if (iclassType >= XED_ICLASS_F2XM1 && iclassType <= XED_ICLASS_FYL2XP1) {
447  return true;
448  }
449  if (iclassType >= XED_ICLASS_VBROADCASTSD && iclassType <= XED_ICLASS_VDPPS) {
450  return true;
451  }
452  if (iclassType >= XED_ICLASS_VRCPPS && iclassType <= XED_ICLASS_VSQRTSS) {
453  return true;
454  }
455  if (iclassType >= XED_ICLASS_VSUBPD && iclassType <= XED_ICLASS_VXORPS) {
456  return true;
457  }
458  switch (iclassType) {
459  case XED_ICLASS_ADDPD:
460  case XED_ICLASS_ADDPS:
461  case XED_ICLASS_ADDSD:
462  case XED_ICLASS_ADDSS:
463  case XED_ICLASS_ADDSUBPD:
464  case XED_ICLASS_ADDSUBPS:
465  case XED_ICLASS_ANDNPD:
466  case XED_ICLASS_ANDNPS:
467  case XED_ICLASS_ANDPD:
468  case XED_ICLASS_ANDPS:
469  case XED_ICLASS_BLENDPD:
470  case XED_ICLASS_BLENDPS:
471  case XED_ICLASS_BLENDVPD:
472  case XED_ICLASS_BLENDVPS:
473  case XED_ICLASS_CMPPD:
474  case XED_ICLASS_CMPPS:
475  case XED_ICLASS_CMPSD:
476  case XED_ICLASS_CMPSD_XMM:
477  case XED_ICLASS_COMISD:
478  case XED_ICLASS_COMISS:
479  case XED_ICLASS_CVTDQ2PD:
480  case XED_ICLASS_CVTDQ2PS:
481  case XED_ICLASS_CVTPD2PS:
482  case XED_ICLASS_CVTPI2PD:
483  case XED_ICLASS_CVTPI2PS:
484  case XED_ICLASS_CVTPS2PD:
485  case XED_ICLASS_CVTSD2SS:
486  case XED_ICLASS_CVTSI2SD:
487  case XED_ICLASS_CVTSI2SS:
488  case XED_ICLASS_CVTSS2SD:
489  case XED_ICLASS_DIVPD:
490  case XED_ICLASS_DIVPS:
491  case XED_ICLASS_DIVSD:
492  case XED_ICLASS_DIVSS:
493  case XED_ICLASS_DPPD:
494  case XED_ICLASS_DPPS:
495  case XED_ICLASS_HADDPD:
496  case XED_ICLASS_HADDPS:
497  case XED_ICLASS_HSUBPD:
498  case XED_ICLASS_HSUBPS:
499  case XED_ICLASS_MAXPD:
500  case XED_ICLASS_MAXPS:
501  case XED_ICLASS_MAXSD:
502  case XED_ICLASS_MAXSS:
503  case XED_ICLASS_MINPD:
504  case XED_ICLASS_MINPS:
505  case XED_ICLASS_MINSD:
506  case XED_ICLASS_MINSS:
507  case XED_ICLASS_MOVAPD:
508  case XED_ICLASS_MOVAPS:
509  case XED_ICLASS_MOVD:
510  case XED_ICLASS_MOVHLPS:
511  case XED_ICLASS_MOVHPD:
512  case XED_ICLASS_MOVHPS:
513  case XED_ICLASS_MOVLHPS:
514  case XED_ICLASS_MOVLPD:
515  case XED_ICLASS_MOVLPS:
516  case XED_ICLASS_MOVMSKPD:
517  case XED_ICLASS_MOVMSKPS:
518  case XED_ICLASS_MOVNTPD:
519  case XED_ICLASS_MOVNTPS:
520  case XED_ICLASS_MOVNTSD:
521  case XED_ICLASS_MOVNTSS:
522  case XED_ICLASS_MOVSD:
523  case XED_ICLASS_MOVSD_XMM:
524  case XED_ICLASS_MOVSS:
525  case XED_ICLASS_MULPD:
526  case XED_ICLASS_MULPS:
527  case XED_ICLASS_MULSD:
528  case XED_ICLASS_MULSS:
529  case XED_ICLASS_ORPD:
530  case XED_ICLASS_ORPS:
531  case XED_ICLASS_ROUNDPD:
532  case XED_ICLASS_ROUNDPS:
533  case XED_ICLASS_ROUNDSD:
534  case XED_ICLASS_ROUNDSS:
535  case XED_ICLASS_SHUFPD:
536  case XED_ICLASS_SHUFPS:
537  case XED_ICLASS_SQRTPD:
538  case XED_ICLASS_SQRTPS:
539  case XED_ICLASS_SQRTSD:
540  case XED_ICLASS_SQRTSS:
541  case XED_ICLASS_SUBPD:
542  case XED_ICLASS_SUBPS:
543  case XED_ICLASS_SUBSD:
544  case XED_ICLASS_SUBSS:
545  case XED_ICLASS_VADDPD:
546  case XED_ICLASS_VADDPS:
547  case XED_ICLASS_VADDSD:
548  case XED_ICLASS_VADDSS:
549  case XED_ICLASS_VADDSUBPD:
550  case XED_ICLASS_VADDSUBPS:
551  case XED_ICLASS_VANDNPD:
552  case XED_ICLASS_VANDNPS:
553  case XED_ICLASS_VANDPD:
554  case XED_ICLASS_VANDPS:
555  case XED_ICLASS_VBLENDPD:
556  case XED_ICLASS_VBLENDPS:
557  case XED_ICLASS_VBLENDVPD:
558  case XED_ICLASS_VBLENDVPS:
559  case XED_ICLASS_VBROADCASTSD:
560  case XED_ICLASS_VBROADCASTSS:
561  case XED_ICLASS_VCMPPD:
562  case XED_ICLASS_VCMPPS:
563  case XED_ICLASS_VCMPSD:
564  case XED_ICLASS_VCMPSS:
565  case XED_ICLASS_VCOMISD:
566  case XED_ICLASS_VCOMISS:
567  case XED_ICLASS_VCVTDQ2PD:
568  case XED_ICLASS_VCVTDQ2PS:
569  case XED_ICLASS_VCVTPD2PS:
570  case XED_ICLASS_VCVTPH2PS:
571  case XED_ICLASS_VCVTPS2PD:
572  case XED_ICLASS_VCVTSD2SS:
573  case XED_ICLASS_VCVTSI2SD:
574  case XED_ICLASS_VCVTSI2SS:
575  case XED_ICLASS_VCVTSS2SD:
576  case XED_ICLASS_VDIVPD:
577  case XED_ICLASS_VDIVPS:
578  case XED_ICLASS_VDIVSD:
579  case XED_ICLASS_VDIVSS:
580  case XED_ICLASS_VDPPD:
581  case XED_ICLASS_VDPPS:
582  case XED_ICLASS_VMASKMOVPD:
583  case XED_ICLASS_VMASKMOVPS:
584  case XED_ICLASS_VMAXPD:
585  case XED_ICLASS_VMAXPS:
586  case XED_ICLASS_VMAXSD:
587  case XED_ICLASS_VMAXSS:
588  case XED_ICLASS_VMINPD:
589  case XED_ICLASS_VMINPS:
590  case XED_ICLASS_VMINSD:
591  case XED_ICLASS_VMINSS:
592  case XED_ICLASS_VMOVAPD:
593  case XED_ICLASS_VMOVAPS:
594  case XED_ICLASS_VMOVD:
595  case XED_ICLASS_VMOVHLPS:
596  case XED_ICLASS_VMOVHPD:
597  case XED_ICLASS_VMOVHPS:
598  case XED_ICLASS_VMOVLHPS:
599  case XED_ICLASS_VMOVLPD:
600  case XED_ICLASS_VMOVLPS:
601  case XED_ICLASS_VMOVMSKPD:
602  case XED_ICLASS_VMOVMSKPS:
603  case XED_ICLASS_VMOVNTPD:
604  case XED_ICLASS_VMOVNTPS:
605  case XED_ICLASS_VMOVSD:
606  case XED_ICLASS_VMOVSS:
607  case XED_ICLASS_VMOVUPD:
608  case XED_ICLASS_VMOVUPS:
609  case XED_ICLASS_VMULPD:
610  case XED_ICLASS_VMULPS:
611  case XED_ICLASS_VMULSD:
612  case XED_ICLASS_VMULSS:
613  case XED_ICLASS_VORPD:
614  case XED_ICLASS_VORPS:
615  case XED_ICLASS_VPABSD:
616  case XED_ICLASS_VPADDD:
617  case XED_ICLASS_VPCOMD:
618  case XED_ICLASS_VPCOMUD:
619  case XED_ICLASS_VPERMILPD:
620  case XED_ICLASS_VPERMILPS:
621  case XED_ICLASS_VPERMPD:
622  case XED_ICLASS_VPERMPS:
623  case XED_ICLASS_VPGATHERDD:
624  case XED_ICLASS_VPGATHERQD:
625  case XED_ICLASS_VPHADDBD:
626  case XED_ICLASS_VPHADDD:
627  case XED_ICLASS_VPHADDUBD:
628  case XED_ICLASS_VPHADDUWD:
629  case XED_ICLASS_VPHADDWD:
630  case XED_ICLASS_VPHSUBD:
631  case XED_ICLASS_VPHSUBWD:
632  case XED_ICLASS_VPINSRD:
633  case XED_ICLASS_VPMACSDD:
634  case XED_ICLASS_VPMACSSDD:
635  case XED_ICLASS_VPMASKMOVD:
636  case XED_ICLASS_VPMAXSD:
637  case XED_ICLASS_VPMAXUD:
638  case XED_ICLASS_VPMINSD:
639  case XED_ICLASS_VPMINUD:
640  case XED_ICLASS_VPROTD:
641  case XED_ICLASS_VPSUBD:
642  case XED_ICLASS_XORPD:
643  case XED_ICLASS_XORPS:
644  return true;
645 
646  default:
647  return false;
648  }
649  } else {
650  assert(0 && "failed to disassemble instruction");
651  return false;
652  }
653 }
654 
655 static inline uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper) {
656  xed_decoded_inst_t xedd;
657  xed_decoded_inst_zero_set_mode(&xedd, &LoadSpyGlobals.xedState);
658 
659  if (XED_ERROR_NONE == xed_decode(&xedd, (const xed_uint8_t*)(ip), 15)) {
660  xed_operand_element_type_enum_t TypeOperand = xed_decoded_inst_operand_element_type(&xedd, oper);
661  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_SINGLE || TypeOperand == XED_OPERAND_ELEMENT_TYPE_FLOAT16)
662  return 4;
663  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_DOUBLE) {
664  return 8;
665  }
666  if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE) {
667  return 16;
668  }
669  assert(0 && "float instruction with unknown operand\n");
670  return 0;
671  } else {
672  assert(0 && "failed to disassemble instruction\n");
673  return 0;
674  }
675 }
676 
677 /***************************************************************************************/
678 /*********************** memory temporal redundancy functions **************************/
679 /***************************************************************************************/
680 
681 // template<int start, int end, int incr, bool conditional, bool approx>
682 // struct UnrolledLoop{
683 // static __attribute__((always_inline)) void Body(const function<void (const int)>& func){
684 // func(start); // Real loop body
685 // UnrolledLoop<start+incr, end, incr, conditional, approx>:: Body(func); // unroll next iteration
686 // }
687 // static __attribute__((always_inline)) void BodySamePage(ContextHandle_t * __restrict__ prevIP, const ContextHandle_t handle, THREADID threadId){
688 // if(conditional) {
689 // // report in RedTable
690 // if(approx)
691 // AddToApproximateRedTable((uint64_t)handle, 0, 0, 1, false, threadId);
692 // else
693 // AddToRedTable((uint64_t)handle, 0, 0, 1, threadId);
694 // }
695 // // Update context
696 // //prevIP[start] = handle;
697 // UnrolledLoop<start+incr, end, incr, conditional, approx>:: BodySamePage(prevIP, handle, threadId); // unroll next iteration
698 // }
699 // static __attribute__((always_inline)) void BodyStraddlePage(uint64_t addr, const ContextHandle_t handle, THREADID threadId){
700 // //tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]> &t = sm.GetOrCreateShadowBaseAddress((uint64_t)addr+start);
701 // //ContextHandle_t * prevIP = &(get<1>(t)[PAGE_OFFSET(((uint64_t)addr+start))]);
702 
703 // if (conditional) {
704 // // report in RedTable
705 // if(approx)
706 // AddToApproximateRedTable((uint64_t)handle, 0, 0, 1, false, threadId);
707 // else
708 // AddToRedTable((uint64_t)handle, 0, 0, 1, threadId);
709 // }
710 // // Update context
711 // //prevIP[0] = handle;
712 // UnrolledLoop<start+incr, end, incr, conditional, approx>:: BodyStraddlePage(addr, handle, threadId); // unroll next iteration
713 // }
714 // #ifdef USE_COLLECT_PAGE_CACHE
715 // static __attribute__((always_inline)) void BodyStraddleCacheline(uint64_t addr, uint32_t map, THREADID threadId){
716 // if (conditional) {
717 // // report in RedTable
718 // AddToCacheRedTable(GET_CACHELINE_INDEX(addr),(map&(1<<start))!=0?1:0,1,threadId);
719 // }
720 // UnrolledLoop<start+incr, end, incr, conditional, approx>:: BodyStraddleCacheline(addr, map, threadId); // unroll next iteration
721 // }
722 // static __attribute__((always_inline)) void BodyStraddlePageRedTable(uint64_t addr, uint32_t map, THREADID threadId){
723 // if (conditional) {
724 // // report in RedTable
725 // AddToPageRedTable(GET_PAGE_INDEX(addr),(map&(1<<start))!=0?1:0,1,threadId);
726 // }
727 // UnrolledLoop<start+incr, end, incr, conditional, approx>:: BodyStraddlePageRedTable(addr, map, threadId); // unroll next iteration
728 // }
729 // #endif
730 // };
731 
732 // template<int end, int incr, bool conditional, bool approx>
733 // struct UnrolledLoop<end , end , incr, conditional, approx>{
734 // static __attribute__((always_inline)) void Body(const function<void (const int)>& func){}
735 // static __attribute__((always_inline)) void BodySamePage(ContextHandle_t * __restrict__ prevIP, const ContextHandle_t handle, THREADID threadId){}
736 // static __attribute__((always_inline)) void BodyStraddlePage(uint64_t addr, const ContextHandle_t handle, THREADID threadId){}
737 // #ifdef USE_COLLECT_PAGE_CACHE
738 // static __attribute__((always_inline)) void BodyStraddleCacheline(uint64_t addr, uint32_t map, THREADID threadId){}
739 // static __attribute__((always_inline)) void BodyStraddlePageRedTable(uint64_t addr, uint32_t map, THREADID threadId){}
740 // #endif
741 // };
742 
743 template <int start, int end, int incr>
744 struct UnrolledConjunction {
745  static __attribute__((always_inline)) bool Body(const function<bool(const int)>& func) {
746  return func(start) && UnrolledConjunction<start + incr, end, incr>::Body(func); // unroll next iteration
747  }
748  static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t* __restrict__ prevIP) {
749  return (prevIP[0] == prevIP[start]) && UnrolledConjunction<start + incr, end, incr>::BodyContextCheck(prevIP); // unroll next iteration
750  }
751  static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t* addr) {
752  return ((addr[end - 1] != 0) ? 0 : 1 + UnrolledConjunction<start, end - incr, incr>::BodyIsZero(addr)); // unroll next iteration
753  }
754  static __attribute__((always_inline)) uint32_t BodyByteMap(uint8_t* addr) {
755  return (start == 0 ? (addr[start] == 0) : ((addr[start] == 0) << start)) | UnrolledConjunction<start + incr, end, incr>::BodyByteMap(addr); // unroll next iteration
756  }
757 };
758 
759 template <int end, int incr>
760 struct UnrolledConjunction<end, end, incr> {
761  static __attribute__((always_inline)) bool Body(const function<void(const int)>& func) {
762  return true;
763  }
764  static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t* __restrict__ prevIP) {
765  return true;
766  }
767  static __attribute__((always_inline)) uint32_t BodyIsZero(uint8_t* addr) {
768  return 0;
769  }
770  static __attribute__((always_inline)) uint32_t BodyByteMap(uint8_t* addr) {
771  return 0;
772  }
773 };
774 
775 template <int start, int end, int step>
776 struct UnrolledCount {
777  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
779  }
780 };
781 template <int end, int step>
782 struct UnrolledCount<end, end, step> {
783  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
784  return 0;
785  }
786 };
787 
788 #ifdef BIG_ENDIAN
789 using float_cast = union {
790  float f;
791  struct {
792  uint32_t sign : 1;
793  uint32_t exponent : 8;
794  uint32_t mantisa : 23;
795  } parts;
796  struct {
797  uint32_t sign : 1;
798  uint32_t value : 31;
799  } vars;
800 };
801 
802 using double_cast = union {
803  double f;
804  struct {
805  uint64_t sign : 1;
806  uint64_t exponent : 11;
807  uint64_t mantisa : 52;
808  } parts;
809  struct {
810  uint64_t sign : 1;
811  uint64_t value : 63;
812  } vars;
813 };
814 #else
815 typedef union {
816  float f;
817  struct {
818  uint32_t mantisa : 23;
819  uint32_t exponent : 8;
820  uint32_t sign : 1;
821  } parts;
822  struct {
823  uint32_t value : 31;
824  uint32_t sign : 1;
825  } vars;
826 } float_cast;
827 
828 typedef union {
829  double f;
830  struct {
831  uint64_t mantisa : 52;
832  uint64_t exponent : 11;
833  uint64_t sign : 1;
834  } parts;
835  struct {
836  uint64_t value : 63;
837  uint64_t sign : 1;
838  } vars;
839 } double_cast;
840 #endif
841 
842 template <int start, int end, int step>
844  // floating point : sign, exponent, mantissa
845  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
846  if (step == 4) {
847  uint32_t man = (*(reinterpret_cast<float_cast*>(&addr[start]))).parts.mantisa;
848  uint8_t exp = (*(reinterpret_cast<float_cast*>(&addr[start]))).parts.exponent;
850  } else if (step == 8) {
851  uint64_t man = (*(reinterpret_cast<double_cast*>(&addr[start]))).parts.mantisa;
852  uint32_t exp = (*(reinterpret_cast<double_cast*>(&addr[start]))).parts.exponent;
854  } else {
855  assert(0 && "Not Supportted floating size! now only support for FP32 or FP64.");
857  }
858  return 0;
859  }
860 };
861 template <int end, int step>
862 struct UnrolledCountApprox<end, end, step> {
863  static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t* addr) {
864  return 0;
865  }
866 };
867 
868 template <int start, int end, int incr>
870  static __attribute__((always_inline)) uint64_t BodyByteMapMan(uint8_t* addr) {
871  // from low to high : 32 mantisa map, 31 exponent map, 1 sign map
872  if (incr == 4) {
873  uint32_t man = (*(reinterpret_cast<float_cast*>(&addr[start]))).parts.mantisa;
875  } else if (incr == 8) {
876  uint64_t man = (*(reinterpret_cast<double_cast*>(&addr[start]))).parts.mantisa;
878  } else {
879  assert(0 && "Not Supportted floating size! now only support for FP32 or FP64.");
881  }
882  return 0;
883  }
884  static __attribute__((always_inline)) uint64_t BodyByteMapExp(uint8_t* addr) {
885  // from low to high : 32 mantisa map, 31 exponent map, 1 sign map
886  if (incr == 4) {
887  uint8_t exp = (*(reinterpret_cast<float_cast*>(&addr[start]))).parts.exponent;
889  } else if (incr == 8) {
890  uint32_t exp = (*(reinterpret_cast<double_cast*>(&addr[start]))).parts.exponent;
891  return ((UnrolledConjunctionApprox<start + incr, end, incr>::BodyByteMapExp(addr)) << 2) | ((exp & 0xF) == 0) | (((exp & 0x70) == 0) << 1);
892  } else {
893  assert(0 && "Not Supportted floating size! now only support for FP32 or FP64.");
895  }
896  return 0;
897  }
898  static __attribute__((always_inline)) uint64_t BodyByteMapSign(uint8_t* addr) {
899  // from low to high : 32 mantisa map, 31 exponent map, 1 sign map
900  if (incr == 4) {
901  uint8_t sign = (*(reinterpret_cast<float_cast*>(&addr[start]))).parts.sign;
903  } else if (incr == 8) {
904  uint8_t sign = (*(reinterpret_cast<double_cast*>(&addr[start]))).parts.sign;
906  } else {
907  assert(0 && "Not Supportted floating size! now only support for FP32 or FP64.");
909  }
910  return 0;
911  }
912  // if the mantisa is 0, the value of the double/float var must be 0
913  static __attribute__((always_inline)) uint64_t BodyZeros(uint8_t* addr) {
914  if (incr == 4)
915  return ((*(reinterpret_cast<float_cast*>(&addr[start]))).vars.value == 0) + (UnrolledConjunctionApprox<start + incr, end, incr>::BodyZeros(addr));
916  else if (incr == 8)
917  return ((*(reinterpret_cast<double_cast*>(&addr[start]))).vars.value == 0) + (UnrolledConjunctionApprox<start + incr, end, incr>::BodyZeros(addr));
918  return 0;
919  }
920  static __attribute__((always_inline)) uint64_t BodyMap(uint8_t* addr) {
921  if (incr == 4)
922  return (*(reinterpret_cast<uint32_t*>(&addr[start]))) | (UnrolledConjunctionApprox<start + incr, end, incr>::BodyMap(addr));
923  else if (incr == 8)
924  return (*(reinterpret_cast<uint64_t*>(&addr[start]))) | (UnrolledConjunctionApprox<start + incr, end, incr>::BodyMap(addr));
925  return 0;
926  }
927 };
928 
929 template <int end, int incr>
930 struct UnrolledConjunctionApprox<end, end, incr> {
931  static __attribute__((always_inline)) uint64_t BodyByteMapMan(uint8_t* addr) {
932  return 0;
933  }
934  static __attribute__((always_inline)) uint64_t BodyByteMapExp(uint8_t* addr) {
935  return 0;
936  }
937  static __attribute__((always_inline)) uint64_t BodyByteMapSign(uint8_t* addr) {
938  return 0;
939  }
940  static __attribute__((always_inline)) uint64_t BodyZeros(uint8_t* addr) {
941  return 0;
942  }
943  static __attribute__((always_inline)) uint64_t BodyMap(uint8_t* addr) {
944  return 0;
945  }
946 };
947 
948 template <class T, uint32_t AccessLen, bool isApprox>
949 struct ZeroSpyAnalysis {
950  static __attribute__((always_inline)) uint64_t getRedMap(void* addr) {
951  uint8_t* bytes = static_cast<uint8_t*>(addr);
952  uint32_t redmap = UnrolledConjunction<0, AccessLen, 1>::BodyByteMap(bytes);
953  return redmap;
954  }
955  static __attribute__((always_inline)) uint64_t getRedNum(void* addr) {
956  if (isApprox) {
957  uint8_t* bytes = static_cast<uint8_t*>(addr);
958  uint32_t rednum = UnrolledCountApprox<0, AccessLen, sizeof(T)>::BodyRedZero(bytes);
959  return rednum;
960  } else {
961  uint8_t* bytes = static_cast<uint8_t*>(addr);
962  uint32_t rednum = UnrolledCount<0, AccessLen, sizeof(T)>::BodyRedZero(bytes);
963  return rednum;
964  }
965  return 0;
966  }
967  static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(void* addr, uint32_t opaqueHandle, THREADID threadId) {
968 #ifdef DEBUG_ZEROSPY
969  printf("\nINFO : In Check NBytes Value After Read\n");
970 #endif
971  //RedSpyThreadData* const tData = ClientGetTLS(threadId);
972  ContextHandle_t curCtxtHandle = GetContextHandle(threadId, opaqueHandle);
973  if (isApprox) {
974  uint32_t redbyteNum = getRedNum(addr);
975  if (redbyteNum) {
976  uint8_t* bytes = static_cast<uint8_t*>(addr);
977  uint32_t man = UnrolledConjunctionApprox<0, AccessLen, sizeof(T)>::BodyByteMapMan(bytes);
978  uint32_t exp = UnrolledConjunctionApprox<0, AccessLen, sizeof(T)>::BodyByteMapExp(bytes);
979  uint32_t sign = UnrolledConjunctionApprox<0, AccessLen, sizeof(T)>::BodyByteMapSign(bytes);
980  uint32_t zeros = UnrolledConjunctionApprox<0, AccessLen, sizeof(T)>::BodyZeros(bytes);
981  AddToApproximateRedTable((uint64_t)curCtxtHandle, man, exp, sign, AccessLen, zeros, AccessLen / sizeof(T), sizeof(T), threadId);
982  } else {
983  AddToApproximateRedTable((uint64_t)curCtxtHandle, 0, 0, 0, AccessLen, 0, AccessLen / sizeof(T), sizeof(T), threadId);
984  }
985  } else {
986  uint32_t redbyteNum = getRedNum(addr);
987  if (redbyteNum) {
988  uint32_t redbyteMap = getRedMap(addr);
989  AddToRedTable((uint64_t)MAKE_CONTEXT_PAIR(AccessLen, curCtxtHandle), redbyteNum, redbyteMap, AccessLen, threadId);
990  } else {
991  AddToRedTable((uint64_t)MAKE_CONTEXT_PAIR(AccessLen, curCtxtHandle), 0, 0, AccessLen, threadId);
992  }
993  }
994 
995 #ifdef DEBUG_ZEROSPY
996  printf("\nINFO : Exit Check NBytes Value After Read\n");
997 #endif
998  }
999 };
1000 
1001 // // Approx
1002 // template<class T, class LOWERT, uint32_t AccessLen>
1003 // struct ZeroSpyApproxAnalysis{
1004 // static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(void* addr, uint32_t opaqueHandle, THREADID threadId){
1005 // #ifdef DEBUG_ZEROSPY
1006 // printf("\nINFO : In Check NBytes Value After Read\n");
1007 // #endif
1008 // RedSpyThreadData* const tData = ClientGetTLS(threadId);
1009 // ContextHandle_t curCtxtHandle = GetContextHandle(threadId, opaqueHandle);
1010 // uint32_t redbyteNum = ZeroSpyAnalysis<T,AccessLen,true>::getRedNum(addr);
1011 // // Check if the value can be downgrade
1012 // bool down = ((*(static_cast<T*>(addr)))==(T)((LOWERT)(*(static_cast<T*>(addr)))));
1013 // if(redbyteNum) {
1014 // uint32_t redbyteMap = ZeroSpyAnalysis<T,AccessLen,true>::getRedMap(addr);
1015 // // detected redundancy
1016 // AddToApproximateRedTable((uint64_t)curCtxtHandle, redbyteNum, redbyteMap, AccessLen, down, threadId);
1017 // } else {
1018 // AddToApproximateRedTable((uint64_t)curCtxtHandle, 0, 0, AccessLen, down, threadId);
1019 // }
1020 // #ifdef DEBUG_ZEROSPY
1021 // printf("\nINFO : Exit Check NBytes Value After Read\n");
1022 // #endif
1023 // }
1024 // };
1025 
1026 static inline VOID CheckAfterLargeRead(void* addr, UINT32 accessLen, uint32_t opaqueHandle, THREADID threadId) {
1027 #ifdef DEBUG_ZEROSPY
1028  printf("\nINFO : In Check After Large Read\n");
1029  if (accessLen > 32) {
1030  printf("ERROR : AccessLen too large : %d\n", accessLen);
1031  assert(0 && (accessLen <= 32));
1032  }
1033 #endif
1034  //RedSpyThreadData* const tData = ClientGetTLS(threadId);
1035  ContextHandle_t curCtxtHandle = GetContextHandle(threadId, opaqueHandle);
1036 
1037  //tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]> &t = sm.GetOrCreateShadowBaseAddress((uint64_t)addr);
1038  //ContextHandle_t * __restrict__ prevIP = &(get<1>(t)[PAGE_OFFSET((uint64_t)addr)]);
1039  //const uint8_t prevValue = 0;
1040 
1041  // This assumes that a large read cannot straddle a page boundary -- strong assumption, but lets go with it for now.
1042  //tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]> &tt = sm.GetOrCreateShadowBaseAddress((uint64_t)addr);
1043  uint8_t* bytes = static_cast<uint8_t*>(addr);
1044  uint32_t redbytesNum = 0;
1045  for (int i = accessLen - 1; i >= 0; --i) {
1046  if (bytes[i] != 0) {
1047  break;
1048  }
1049  ++redbytesNum;
1050  }
1051 
1052  if (redbytesNum) {
1053  uint32_t redbyteMap = 0;
1054  if (bytes[0] == 0) {
1055  redbyteMap |= 1;
1056  }
1057  for (UINT32 i = 1; i < accessLen; ++i) {
1058  if (bytes[i] == 0) {
1059  redbyteMap |= (1 << i);
1060  }
1061  }
1062  /*#ifdef USE_COLLECT_PAGE_CACHE
1063  for(UINT32 i=0;i<accessLen;++i) {
1064  if(bytes[i]==0) {
1065  AddToPageRedTable(GET_PAGE_INDEX((uint64_t)(bytes+i)),1,1,threadId);
1066  AddToCacheRedTable(GET_CACHELINE_INDEX((uint64_t)(bytes+i)),1,1,threadId);
1067  } else {
1068  AddToPageRedTable(GET_PAGE_INDEX((uint64_t)(bytes+i)),0,1,threadId);
1069  AddToCacheRedTable(GET_CACHELINE_INDEX((uint64_t)(bytes+i)),0,1,threadId);
1070  }
1071  }
1072 #endif*/
1073  // report in RedTable
1074  AddToRedTable((uint64_t)MAKE_CONTEXT_PAIR(accessLen, curCtxtHandle), redbytesNum, redbyteMap, accessLen, threadId);
1075  } else {
1076  AddToRedTable((uint64_t)MAKE_CONTEXT_PAIR(accessLen, curCtxtHandle), 0, 0, accessLen, threadId);
1077  }
1078 #ifdef DEBUG_ZEROSPY
1079  printf("\nINFO : Exit Check After Large Read\n");
1080 #endif
1081 }
1082 
1083 #ifdef ENABLE_SAMPLING
1084 
1085 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
1086  INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1087  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)
1088 
1089 #define HANDLE_LARGE() \
1090  INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1091  INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1092 #else
1093 
1094 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
1095  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)
1096 
1097 // #define HANDLE_CASE_LOWER(T, LOWERT, ACCESS_LEN)
1098 // INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR) ZeroSpyApproxAnalysis<T, LOWERT, (ACCESS_LEN)>::CheckNByteValueAfterRead, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR,IARG_END)
1099 
1100 #define HANDLE_LARGE() \
1101  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1102 #endif
1103 
1104 
1105 static int GetNumReadOperandsInIns(INS ins, UINT32& whichOp) {
1106  int numReadOps = 0;
1107  UINT32 memOperands = INS_MemoryOperandCount(ins);
1108  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1109  if (INS_MemoryOperandIsRead(ins, memOp)) {
1110  numReadOps++;
1111  whichOp = memOp;
1112  }
1113  }
1114  return numReadOps;
1115 }
1116 
1117 
1118 struct LoadSpyInstrument {
1119  static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
1120 #ifdef DEBUG_ZEROSPY
1121  printf("\nINFO : In InstrumentReadValueBeforeAndAfterLoading\n");
1122 #endif
1123  UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
1124 
1125  if (IsFloatInstructionAndOkToApproximate(INS_Address(ins))) {
1126  unsigned int operSize = FloatOperandSize(INS_Address(ins), INS_MemoryOperandIndexToOperandIndex(ins, memOp));
1127  switch (refSize) {
1128  case 1:
1129  case 2:
1130  assert(0 && "memory read floating data with unexptected small size");
1131  case 4:
1132  HANDLE_CASE(float, 4, true);
1133  break;
1134  case 8:
1135  HANDLE_CASE(double, 8, true);
1136  break;
1137  // case 8: HANDLE_CASE_LOWER(double, float, 8); break;
1138  case 10:
1139  HANDLE_CASE(uint8_t, 10, true);
1140  break;
1141  case 16: {
1142  switch (operSize) {
1143  case 4:
1144  HANDLE_CASE(float, 16, true);
1145  break;
1146  case 8:
1147  HANDLE_CASE(double, 16, true);
1148  break;
1149  // case 8: HANDLE_CASE_LOWER(double, float, 16); break;
1150  default:
1151  assert(0 && "handle large mem read with unexpected operand size\n");
1152  break;
1153  }
1154  } break;
1155  case 32: {
1156  switch (operSize) {
1157  case 4:
1158  HANDLE_CASE(float, 32, true);
1159  break;
1160  case 8:
1161  HANDLE_CASE(double, 32, true);
1162  break;
1163  // case 8: HANDLE_CASE_LOWER(double, float, 32); break;
1164  default:
1165  assert(0 && "handle large mem read with unexpected operand size\n");
1166  break;
1167  }
1168  } break;
1169  default:
1170  assert(0 && "unexpected large memory read\n");
1171  break;
1172  }
1173  } else {
1174  switch (refSize) {
1175 #ifdef SKIP_SMALLCASE
1176  // do nothing when access is small
1177  case 1:
1178  break;
1179  case 2:
1180  break;
1181 #else
1182  case 1:
1183  HANDLE_CASE(uint8_t, 1, false);
1184  break;
1185  case 2:
1186  HANDLE_CASE(uint16_t, 2, false);
1187  break;
1188 #endif
1189  case 4:
1190  HANDLE_CASE(uint32_t, 4, false);
1191  break;
1192  case 8:
1193  HANDLE_CASE(uint64_t, 8, false);
1194  break;
1195 
1196  default: {
1197  HANDLE_LARGE();
1198  }
1199  }
1200  }
1201 #ifdef DEBUG_ZEROSPY
1202  printf("\nINFO : Exit InstrumentReadValueBeforeAndAfterLoading\n");
1203 #endif
1204  }
1205 };
1206 
1207 /********************* instrument analysis ************************/
1208 
1209 static inline bool INS_IsIgnorable(INS ins) {
1210  if (INS_IsFarJump(ins) || INS_IsDirectFarJump(ins) || INS_IsMaskedJump(ins))
1211  return true;
1212  else if (INS_IsRet(ins) || INS_IsIRet(ins))
1213  return true;
1214  else if (INS_IsCall(ins) || INS_IsSyscall(ins))
1215  return true;
1216  else if (INS_IsBranch(ins) || INS_IsRDTSC(ins) || INS_IsNop(ins))
1217  return true;
1218  else if (INS_IsPrefetch(ins)) // Prefetch instructions might access addresses which are invalid.
1219  return true;
1220  // XSAVEC and XRSTOR are problematic since its access length is variable.
1221  // 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.
1222  // It fails with "Cannot use IARG_MEMORYWRITE_SIZE on non-standard memory access of instruction at 0xfoo: xsavec ptr [rsp]" error.
1223  // A correct solution should use INS_hasKnownMemorySize() which is not available in Pin 2.14.
1224  if (INS_Mnemonic(ins) == "XSAVEC")
1225  return true;
1226  if (INS_Mnemonic(ins) == "XSAVE")
1227  return true;
1228  if (INS_Mnemonic(ins) == "XRSTOR")
1229  return true;
1230  return false;
1231 }
1232 
1233 static VOID InstrumentInsCallback(INS ins, VOID* v, const uint32_t opaqueHandle) {
1234 #ifdef DEBUG_ZEROSPY
1235  printf("\nINFO : In InstrumentInsCallback\n");
1236  if (!INS_HasFallThrough(ins)) {
1237  printf("\nINFO : Exit InstrumentInsCallback !INS_HasFallThrough\n");
1238  return;
1239  }
1240  if (INS_IsIgnorable(ins)) {
1241  printf("\nINFO : Exit InstrumentInsCallback INS_IsIgnorable\n");
1242  return;
1243  }
1244  if (INS_IsControlFlow(ins) || INS_IsRet(ins)) {
1245  printf("\nINFO : Exit InstrumentInsCallback INS_IsControlFlow(ins) || INS_IsRet(ins)\n");
1246  return;
1247  }
1248 #else
1249  if (!INS_HasFallThrough(ins))
1250  return;
1251  if (INS_IsIgnorable(ins))
1252  return;
1253  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1254  return;
1255 #endif
1256 
1257  //Instrument memory reads to find redundancy
1258  // Special case, if we have only one read operand
1259  UINT32 whichOp = 0;
1260  if (GetNumReadOperandsInIns(ins, whichOp) == 1) {
1261  // Read the value at location before and after the instruction
1262  LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, whichOp, opaqueHandle);
1263  } else {
1264  UINT32 memOperands = INS_MemoryOperandCount(ins);
1265  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1266  if (!INS_MemoryOperandIsRead(ins, memOp))
1267  continue;
1268  LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, memOp, opaqueHandle);
1269  }
1270  }
1271 #ifdef DEBUG_ZEROSPY
1272  printf("\nINFO : Exit InstrumentInsCallback\n");
1273 #endif
1274 }
1275 
1276 /**********************************************************************************/
1277 
1278 #ifdef ENABLE_SAMPLING
1279 #error Sampling should not be enabled as it has not been tested yet!
1280 inline VOID UpdateAndCheck(uint32_t count, uint32_t bytes, THREADID threadId) {
1281  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1282 
1283  if (tData->sampleFlag) {
1284  tData->numIns += count;
1285  if (tData->numIns > WINDOW_ENABLE) {
1286  tData->sampleFlag = false;
1287  tData->numIns = 0;
1288  }
1289  } else {
1290  tData->numIns += count;
1291  if (tData->numIns > WINDOW_DISABLE) {
1292  tData->sampleFlag = true;
1293  tData->numIns = 0;
1294  }
1295  }
1296  if (tData->sampleFlag) {
1297  tData->bytesLoad += bytes;
1298  }
1299 }
1300 
1301 inline VOID Update(uint32_t count, uint32_t bytes, THREADID threadId) {
1302  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1303  tData->numIns += count;
1304  if (tData->sampleFlag) {
1305  tData->bytesLoad += bytes;
1306  }
1307 }
1308 
1309 //instrument the trace, count the number of ins in the trace, decide to instrument or not
1310 static void InstrumentTrace(TRACE trace, void* f) {
1311  bool check = false;
1312  for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1313  uint32_t totInsInBbl = BBL_NumIns(bbl);
1314  uint32_t totBytes = 0;
1315  for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1316  if (!INS_HasFallThrough(ins))
1317  continue;
1318  if (INS_IsIgnorable(ins))
1319  continue;
1320  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1321  continue;
1322 
1323  if (INS_IsMemoryRead(ins)) {
1324  totBytes += INS_MemoryReadSize(ins);
1325  }
1326  }
1327 
1328  if (BBL_InsTail(bbl) == BBL_InsHead(bbl)) {
1329  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1330  } else if (INS_IsIndirectBranchOrCall(BBL_InsTail(bbl))) {
1331  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1332  } else {
1333  if (check) {
1334  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1335  check = false;
1336  } else {
1337  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)Update, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1338  check = true;
1339  }
1340  }
1341  }
1342 }
1343 
1344 #else
1345 
1346 inline VOID Update(uint32_t bytes, THREADID threadId) {
1347 #ifdef DEBUG_ZEROSPY
1348  printf("\nINFO : In Update\n");
1349 #endif
1350  RedSpyThreadData* const tData = ClientGetTLS(threadId);
1351  tData->bytesLoad += bytes;
1352 #ifdef DEBUG_ZEROSPY
1353  printf("\nINFO : Exit Update\n");
1354 #endif
1355 }
1356 
1357 //instrument the trace, count the number of ins in the trace, decide to instrument or not
1358 static void InstrumentTrace(TRACE trace, void* f) {
1359 #ifdef DEBUG_ZEROSPY
1360  printf("\nINFO : In InstrumentTrace\n");
1361 #endif
1362  for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1363  uint32_t totBytes = 0;
1364  for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1365  if (!INS_HasFallThrough(ins))
1366  continue;
1367  if (INS_IsIgnorable(ins))
1368  continue;
1369  if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1370  continue;
1371 
1372  if (INS_IsMemoryRead(ins)) {
1373  totBytes += INS_MemoryReadSize(ins);
1374  }
1375  }
1376  BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)Update, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_END);
1377  }
1378 #ifdef DEBUG_ZEROSPY
1379  printf("\nINFO : Exit InstrumentTrace\n");
1380 #endif
1381 }
1382 
1383 #endif
1384 
1385 struct RedundacyData {
1387  uint64_t frequency;
1388  uint64_t all0freq;
1389  uint64_t ltot;
1390  uint32_t byteMap;
1391  uint8_t accessLen;
1392 };
1393 
1396  uint64_t all0freq;
1397  uint64_t ftot;
1398  uint32_t byteMapMan;
1399  uint32_t byteMapExp;
1400  uint32_t byteMapSign;
1401  uint8_t accessLen;
1402  uint8_t size;
1403 };
1404 #ifdef USE_COLLECT_PAGE_CACHE
1405 struct DRedData {
1406  uint64_t index;
1407  uint64_t frequency;
1408  uint64_t ltot;
1409 };
1410 
1411 static inline bool DRedundacyCompare(const struct DRedData& first, const struct DRedData& second) {
1412  return first.frequency > second.frequency ? true : false;
1413 }
1414 
1415 #define LEVEL_1_RED_THRESHOLD 0.90
1416 #define LEVEL_2_RED_THRESHOLD 0.70
1417 #define LEVEL_3_RED_THRESHOLD 0.50
1418 
1419 static void PrintPageRedundancy(THREADID threadId) {
1420  vector<DRedData> tmpList;
1421  vector<DRedData>::iterator tmpIt;
1422 
1423  uint64_t grandTotalRedundantBytes = 0;
1424  uint64_t grandTotalRedundantPage_level1 = 0;
1425  uint64_t grandTotalRedundantPage_level2 = 0;
1426  uint64_t grandTotalRedundantPage_level3 = 0;
1427  uint64_t grandTotalPage = 0;
1428  float maxrate = 0;
1429  float minrate = 100;
1430  fprintf(gTraceFile, "\n--------------- Dumping PAGE Redundancy Info ----------------\n");
1431  fprintf(gTraceFile, "\n*************** Dump Data from Thread %d ****************\n", threadId);
1432 
1433  for (unordered_map<uint64_t, DataLogs>::iterator it = PageRedMap[threadId].begin(); it != PageRedMap[threadId].end(); ++it) {
1434  DRedData tmp = {(*it).first, (*it).second.red, (*it).second.tot};
1435  tmpList.push_back(tmp);
1436  grandTotalRedundantBytes += tmp.frequency;
1437  if (maxrate < (float)tmp.frequency / (float)tmp.ltot) {
1438  maxrate = (float)tmp.frequency / (float)tmp.ltot;
1439  }
1440  if (minrate > (float)tmp.frequency / (float)tmp.ltot) {
1441  minrate = (float)tmp.frequency / (float)tmp.ltot;
1442  }
1443  grandTotalPage++;
1444  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_1_RED_THRESHOLD) {
1445  grandTotalRedundantPage_level1++;
1446  }
1447  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_2_RED_THRESHOLD) {
1448  grandTotalRedundantPage_level2++;
1449  }
1450  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_3_RED_THRESHOLD) {
1451  grandTotalRedundantPage_level3++;
1452  }
1453  }
1454 
1455  __sync_fetch_and_add(&grandTotBytesRedLoad, grandTotalRedundantBytes);
1456 
1457  fprintf(gTraceFile, "\n Total redundant bytes = %f %%, rate range from [%f, %f] %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad, minrate * 100, maxrate * 100);
1458 
1459  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_1_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level1 * 100.0 / grandTotalPage);
1460  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_2_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level2 * 100.0 / grandTotalPage);
1461  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_3_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level3 * 100.0 / grandTotalPage);
1462 #ifdef PRINT_ALL_PAGE_INFO
1463  sort(tmpList.begin(), tmpList.end(), DRedundacyCompare);
1464  int cntxtNum = 0;
1465  for (vector<DRedData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1466  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1467  fprintf(gTraceFile, "\n\n======= PAGE %lx : (%f) %% of total Redundant, with local redundant %f %% (%ld Bytes / %ld Bytes) ======\n",
1468  (*listIt).index,
1469  (*listIt).frequency * 100.0 / grandTotalRedundantBytes,
1470  (*listIt).frequency * 100.0 / (*listIt).ltot,
1471  (*listIt).frequency, (*listIt).ltot);
1472  } else {
1473  break;
1474  }
1475  cntxtNum++;
1476  }
1477 #endif
1478  fprintf(gTraceFile, "\n------------ Dumping Page Redundancy Info Finish -------------\n");
1479 }
1480 
1481 static void PrintCacheRedundancy(THREADID threadId) {
1482  vector<DRedData> tmpList;
1483  vector<DRedData>::iterator tmpIt;
1484 
1485  uint64_t grandTotalRedundantBytes = 0;
1486  uint64_t grandTotalRedundantPage_level1 = 0;
1487  uint64_t grandTotalRedundantPage_level2 = 0;
1488  uint64_t grandTotalRedundantPage_level3 = 0;
1489  uint64_t grandTotalPage = 0;
1490  float maxrate = 0;
1491  float minrate = 100;
1492  fprintf(gTraceFile, "\n--------------- Dumping CACHE Redundancy Info ----------------\n");
1493  fprintf(gTraceFile, "\n*************** Dump Data from Thread %d ****************\n", threadId);
1494 
1495  for (unordered_map<uint64_t, DataLogs>::iterator it = CacheRedMap[threadId].begin(); it != CacheRedMap[threadId].end(); ++it) {
1496  DRedData tmp = {(*it).first, (*it).second.red, (*it).second.tot};
1497  tmpList.push_back(tmp);
1498  grandTotalRedundantBytes += tmp.frequency;
1499  if (maxrate < (float)tmp.frequency / (float)tmp.ltot) {
1500  maxrate = (float)tmp.frequency / (float)tmp.ltot;
1501  }
1502  if (minrate > (float)tmp.frequency / (float)tmp.ltot) {
1503  minrate = (float)tmp.frequency / (float)tmp.ltot;
1504  }
1505  grandTotalPage++;
1506  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_1_RED_THRESHOLD) {
1507  grandTotalRedundantPage_level1++;
1508  }
1509  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_2_RED_THRESHOLD) {
1510  grandTotalRedundantPage_level2++;
1511  }
1512  if ((float)tmp.frequency / (float)tmp.ltot > LEVEL_3_RED_THRESHOLD) {
1513  grandTotalRedundantPage_level3++;
1514  }
1515  }
1516 
1517  __sync_fetch_and_add(&grandTotBytesRedLoad, grandTotalRedundantBytes);
1518 
1519  fprintf(gTraceFile, "\n Total redundant bytes = %f, rate range from [%f, %f] %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad, minrate * 100, maxrate * 100);
1520 
1521  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_1_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level1 * 100.0 / grandTotalPage);
1522  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_2_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level2 * 100.0 / grandTotalPage);
1523  fprintf(gTraceFile, "\n Total redundant bytes (local redundant rate > %f %%) = %f %%\n", LEVEL_3_RED_THRESHOLD * 100.0, grandTotalRedundantPage_level3 * 100.0 / grandTotalPage);
1524 #ifdef PRINT_ALL_PAGE_INFO
1525  sort(tmpList.begin(), tmpList.end(), DRedundacyCompare);
1526  int cntxtNum = 0;
1527  for (vector<DRedData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1528  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1529  fprintf(gTraceFile, "\n\n======= CACHE %lx : (%f) %% of total Redundant, with local redundant %f %% (%ld Bytes / %ld Bytes) ======\n",
1530  (*listIt).index,
1531  (*listIt).frequency * 100.0 / grandTotalRedundantBytes,
1532  (*listIt).frequency * 100.0 / (*listIt).ltot,
1533  (*listIt).frequency, (*listIt).ltot);
1534  } else {
1535  break;
1536  }
1537  cntxtNum++;
1538  }
1539 #endif
1540  fprintf(gTraceFile, "\n------------ Dumping CACHE Redundancy Info Finish -------------\n");
1541 }
1542 #endif
1543 static inline bool RedundacyCompare(const struct RedundacyData& first, const struct RedundacyData& second) {
1544  return first.frequency > second.frequency;
1545 }
1546 static inline bool ApproxRedundacyCompare(const struct ApproxRedundacyData& first, const struct ApproxRedundacyData& second) {
1547  return first.all0freq > second.all0freq;
1548 }
1549 //#define SKIP_SMALLACCESS
1550 #ifdef SKIP_SMALLACCESS
1551 #define LOGGING_THRESHOLD 100
1552 #endif
1553 static void PrintRedundancyPairs(THREADID threadId) {
1554  vector<RedundacyData> tmpList;
1555  vector<RedundacyData>::iterator tmpIt;
1556 
1557  uint64_t grandTotalRedundantBytes = 0;
1558  uint64_t grandTotalRedundantIns = 0;
1559  tmpList.reserve(RedMap[threadId].size());
1560  printf("Dumping INTEGER Redundancy Info... Total num : %ld\n", RedMap[threadId].size());
1561  fflush(stdout);
1562  fprintf(gTraceFile, "\n--------------- Dumping INTEGER Redundancy Info ----------------\n");
1563  fprintf(gTraceFile, "\n*************** Dump Data from Thread %d ****************\n", threadId);
1564  uint64_t count = 0;
1565  uint64_t rep = -1;
1566 #ifdef MERGING
1567  fprintf(gTraceFile, "\n*************** Merging Redundancy Info, The Caller Prefix Printed is useless ****************\n");
1568  for (unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].begin(); it != RedMap[threadId].end(); ++it) {
1569  ++count;
1570  if (100 * count / RedMap[threadId].size() != rep) {
1571  rep = 100 * count / RedMap[threadId].size();
1572  printf("%ld%% Finish, current list size = %ld\n", rep, tmpList.size());
1573  fflush(stdout);
1574  }
1575  grandTotalRedundantBytes += (*it).second.red;
1576 #ifdef SKIP_SMALLACCESS
1577  if ((*it).second.tot > LOGGING_THRESHOLD * ((*it).second.AccessLen))
1578  continue;
1579 #endif
1580  ContextHandle_t cur = static_cast<ContextHandle_t>((*it).first);
1581 
1582  if (cur != 0) {
1583  for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
1584  if ((*tmpIt).cntxt == 0) {
1585  continue;
1586  }
1587  if (!HaveSameCallerPrefix(cur, (*tmpIt).cntxt)) {
1588  continue;
1589  }
1590  bool ct1 = IsSameSourceLine(cur, (*tmpIt).cntxt);
1591  if (ct1) {
1592  (*tmpIt).frequency += (*it).second.red;
1593  (*tmpIt).all0freq += (*it).second.fred;
1594  (*tmpIt).ltot += (*it).second.tot;
1595  (*tmpIt).byteMap &= (*it).second.redByteMap;
1596  // (*tmpIt).down &= (*it).second.down;
1597  grandTotalRedundantIns += 1;
1598  break;
1599  }
1600  }
1601  }
1602  if (tmpIt == tmpList.end()) {
1603  // RedundacyData tmp = { static_cast<ContextHandle_t>((*it).first), (*it).second.red,(*it).second.fred,(*it).second.tot,(*it).second.redByteMap,(*it).second.AccessLen, (*it).second.down};
1604  RedundacyData tmp = {DECODE_KILL((*it).first), (*it).second.red, (*it).second.fred, (*it).second.tot, (*it).second.redByteMap, DECODE_DEAD((*it).first)};
1605  tmpList.push_back(tmp);
1606  }
1607  }
1608 #else
1609  for (unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].begin(); it != RedMap[threadId].end(); ++it) {
1610  ++count;
1611  if (100 * count / RedMap[threadId].size() != rep) {
1612  rep = 100 * count / RedMap[threadId].size();
1613  printf("%ld%% Finish\n", rep);
1614  fflush(stdout);
1615  }
1616  RedundacyData tmp = {DECODE_KILL((*it).first), (*it).second.red, (*it).second.fred, (*it).second.tot, (*it).second.redByteMap, DECODE_DEAD((*it).first)};
1617  tmpList.push_back(tmp);
1618  grandTotalRedundantBytes += tmp.frequency;
1619  }
1620 #endif
1621 
1622  __sync_fetch_and_add(&grandTotBytesRedLoad, grandTotalRedundantBytes);
1623  printf("Extracted Raw data, now sorting...\n");
1624  fflush(stdout);
1625 
1626  fprintf(gTraceFile, "\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad);
1627  fprintf(gTraceFile, "\n INFO : Total redundant bytes = %f %% (%ld / %ld) \n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad, grandTotalRedundantBytes, ClientGetTLS(threadId)->bytesLoad);
1628 
1629  sort(tmpList.begin(), tmpList.end(), RedundacyCompare);
1630  printf("Sorted, Now generating reports...\n");
1631  fflush(stdout);
1632  int cntxtNum = 0;
1633  for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1634  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1635  fprintf(gTraceFile, "\n\n======= (%f) %% of total Redundant, with local redundant %f %% (%ld Bytes / %ld Bytes) ======\n",
1636  (*listIt).frequency * 100.0 / grandTotalRedundantBytes,
1637  (*listIt).frequency * 100.0 / (*listIt).ltot,
1638  (*listIt).frequency, (*listIt).ltot);
1639  fprintf(gTraceFile, "\n\n======= with All Zero Redundant %f %% (%ld / %ld) ======\n",
1640  (*listIt).all0freq * (*listIt).accessLen * 100.0 / (*listIt).ltot,
1641  (*listIt).all0freq, (*listIt).ltot / (*listIt).accessLen);
1642  fprintf(gTraceFile, "\n======= Redundant byte map : [0] ");
1643  for (uint32_t i = 0; i < (*listIt).accessLen; ++i) {
1644  if ((*listIt).byteMap & (1 << i)) {
1645  fprintf(gTraceFile, "00 ");
1646  } else {
1647  fprintf(gTraceFile, "XX ");
1648  }
1649  }
1650  fprintf(gTraceFile, " [AccessLen=%d] =======\n", (*listIt).accessLen);
1651  fprintf(gTraceFile, "\n---------------------Redundant load with---------------------------\n");
1652  PrintFullCallingContext((*listIt).cntxt);
1653  } else {
1654  break;
1655  }
1656  cntxtNum++;
1657  }
1658  fprintf(gTraceFile, "\n------------ Dumping INTEGER Redundancy Info Finish -------------\n");
1659  printf("INTEGER Report dumped\n");
1660  fflush(stdout);
1661 }
1662 
1663 static void PrintApproximationRedundancyPairs(THREADID threadId) {
1664  vector<ApproxRedundacyData> tmpList;
1665  vector<ApproxRedundacyData>::iterator tmpIt;
1666 
1667  uint64_t grandTotalRedundantBytes = 0;
1668  uint64_t grandTotalRedundantIns = 0;
1669  fprintf(gTraceFile, "\n--------------- Dumping Approximation Redundancy Info ----------------\n");
1670  fprintf(gTraceFile, "\n*************** Dump Data(delta=%.2f%%) from Thread %d ****************\n", delta * 100, threadId);
1671  // #ifdef MERGING
1672  fprintf(gTraceFile, "\n*************** Merging Approximation Redundancy Info, The Caller Prefix Printed is useless ****************\n");
1673  for (unordered_map<uint64_t, ApproxRedLogs>::iterator it = ApproxRedMap[threadId].begin(); it != ApproxRedMap[threadId].end(); ++it) {
1674  grandTotalRedundantBytes += (*it).second.fred * (*it).second.AccessLen;
1675 #ifdef SKIP_SMALLACCESS
1676  // only merging logs access more than LOGGING_THRESHOLD times
1677  if ((*it).second.ftot > LOGGING_THRESHOLD)
1678  continue;
1679 #endif
1680  ContextHandle_t cur = static_cast<ContextHandle_t>((*it).first);
1681 
1682  for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
1683  if (cur == 0 || ((*tmpIt).cntxt) == 0) {
1684  continue;
1685  }
1686  if (!HaveSameCallerPrefix(cur, (*tmpIt).cntxt)) {
1687  continue;
1688  }
1689  bool ct1 = IsSameSourceLine(cur, (*tmpIt).cntxt);
1690  if (ct1) {
1691  //(*tmpIt).frequency += (*it).second.red;
1692  (*tmpIt).all0freq += (*it).second.fred;
1693  //(*tmpIt).ltot += (*it).second.tot;
1694  (*tmpIt).ftot += (*it).second.ftot;
1695 #ifndef NO_APPROXMAP
1696  (*tmpIt).byteMapMan &= (*it).second.redByteMapMan;
1697  (*tmpIt).byteMapExp &= (*it).second.redByteMapExp;
1698  (*tmpIt).byteMapSign &= (*it).second.redByteMapSign;
1699 #endif
1700  grandTotalRedundantIns += 1;
1701  break;
1702  }
1703  }
1704  if (tmpIt == tmpList.end()) {
1705  ApproxRedundacyData tmp = {static_cast<ContextHandle_t>((*it).first), (*it).second.fred, (*it).second.ftot, (*it).second.redByteMapMan, (*it).second.redByteMapExp, (*it).second.redByteMapSign, (*it).second.AccessLen, (*it).second.size};
1706  tmpList.push_back(tmp);
1707  }
1708  }
1709  // #else
1710  // // for (unordered_map<uint64_t, RedLogs>::iterator it = ApproxRedMap[threadId].begin(); it != ApproxRedMap[threadId].end(); ++it) {
1711  // // RedundacyData tmp = { static_cast<ContextHandle_t>((*it).first), (*it).second.red, (*it).second.fred, (*it).second.tot, (*it).second.redByteMap, (*it).second.AccessLen, (*it).second.down};
1712  // // tmpList.push_back(tmp);
1713  // // grandTotalRedundantZeros += tmp.all0freq;
1714  // // }
1715  // #endif
1716 
1717  __sync_fetch_and_add(&grandTotBytesApproxRedLoad, grandTotalRedundantBytes);
1718 
1719  fprintf(gTraceFile, "\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad);
1720  fprintf(gTraceFile, "\n INFO : Total redundant bytes = %f %% (%ld / %ld) \n", grandTotalRedundantBytes * 100.0 / ClientGetTLS(threadId)->bytesLoad, grandTotalRedundantBytes, ClientGetTLS(threadId)->bytesLoad);
1721 
1722  sort(tmpList.begin(), tmpList.end(), ApproxRedundacyCompare);
1723  int cntxtNum = 0;
1724  for (vector<ApproxRedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1725  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1726  //fprintf(gTraceFile, "\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
1727  fprintf(gTraceFile, "\n======= (%f) %% of total Redundant, with local redundant %f %% (%ld Zeros / %ld Reads) ======\n",
1728  (*listIt).all0freq * 100.0 / grandTotalRedundantBytes,
1729  (*listIt).all0freq * 100.0 / (*listIt).ftot,
1730  (*listIt).all0freq, (*listIt).ftot);
1731  // (*listIt).frequency * 100.0 / grandTotalRedundantBytes,
1732  // (*listIt).frequency * 100.0 / (*listIt).ltot,
1733  // (*listIt).frequency,(*listIt).ltot);
1734  // fprintf(gTraceFile, "\n\n======= with All Zero Redundant %f %% (%ld / %ld) ======\n",
1735  // (*listIt).all0freq * 100.0 / (*listIt).ftot,
1736  // (*listIt).all0freq,(*listIt).ftot);
1737 #ifndef NO_APPROXMAP
1738  fprintf(gTraceFile, "\n======= Redundant byte map : [mantiss | exponent | sign] ========\n");
1739 #ifdef BIG_ENDIAN
1740  if ((*listIt).size == 4) {
1741  fprintf(gTraceFile, ((*listIt).byteMapMan & (4)) ? "00 " : "XX ");
1742  fprintf(gTraceFile, ((*listIt).byteMapMan & (2)) ? "00 " : "XX ");
1743  fprintf(gTraceFile, ((*listIt).byteMapMan & (1)) ? "00 | " : "XX | ");
1744  fprintf(gTraceFile, ((*listIt).byteMapExp & (1)) ? "00 | " : "XX | ");
1745  fprintf(gTraceFile, ((*listIt).byteMapSign & (1)) ? "0 " : "X ");
1746  for (uint32_t i = 1; i < (*listIt).accessLen / 4; i++) {
1747  fprintf(gTraceFile, " , ");
1748  fprintf(gTraceFile, ((*listIt).byteMapMan & (4 << (3 * i))) ? "00 " : "XX ");
1749  fprintf(gTraceFile, ((*listIt).byteMapMan & (2 << (3 * i))) ? "00 " : "XX ");
1750  fprintf(gTraceFile, ((*listIt).byteMapMan & (1 << (3 * i))) ? "00 | " : "XX | ");
1751  fprintf(gTraceFile, ((*listIt).byteMapExp & (1 << (i))) ? "00 | " : "XX | ");
1752  fprintf(gTraceFile, ((*listIt).byteMapSign & (1 << i)) ? "0 " : "X ");
1753  }
1754  } else {
1755  fprintf(gTraceFile, ((*listIt).byteMapMan & (64)) ? "00 " : "XX ");
1756  fprintf(gTraceFile, ((*listIt).byteMapMan & (32)) ? "00 " : "XX ");
1757  fprintf(gTraceFile, ((*listIt).byteMapMan & (16)) ? "00 " : "XX ");
1758  fprintf(gTraceFile, ((*listIt).byteMapMan & (8)) ? "00 " : "XX ");
1759  fprintf(gTraceFile, ((*listIt).byteMapMan & (4)) ? "00 " : "XX ");
1760  fprintf(gTraceFile, ((*listIt).byteMapMan & (2)) ? "00 " : "XX ");
1761  fprintf(gTraceFile, ((*listIt).byteMapMan & (1)) ? "00 | " : "XX | ");
1762  fprintf(gTraceFile, ((*listIt).byteMapExp & (2)) ? "00 " : "XX ");
1763  fprintf(gTraceFile, ((*listIt).byteMapExp & (1)) ? "00 | " : "XX | ");
1764  fprintf(gTraceFile, ((*listIt).byteMapSign & (1)) ? "0 " : "X ");
1765  for (uint32_t i = 1; i < (*listIt).accessLen / 8; i++) {
1766  fprintf(gTraceFile, " , ");
1767  // Shift literals promoted to uint64_t so the shift is
1768  // well-defined even for larger accessLen values that
1769  // would otherwise UB-shift a plain int by >= 32.
1770  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{64} << (7 * i))) ? "00 " : "XX ");
1771  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{32} << (7 * i))) ? "00 " : "XX ");
1772  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{16} << (7 * i))) ? "00 " : "XX ");
1773  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{8} << (7 * i))) ? "00 " : "XX ");
1774  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{4} << (7 * i))) ? "00 " : "XX ");
1775  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{2} << (7 * i))) ? "00 " : "XX ");
1776  fprintf(gTraceFile, ((*listIt).byteMapMan & (uint64_t{1} << (7 * i))) ? "00 | " : "XX | ");
1777  fprintf(gTraceFile, ((*listIt).byteMapExp & (2 << (2 * i))) ? "00 " : "XX ");
1778  fprintf(gTraceFile, ((*listIt).byteMapExp & (1 << (2 * i))) ? "00 | " : "XX | ");
1779  fprintf(gTraceFile, ((*listIt).byteMapSign & (1 << i)) ? "0 " : "X ");
1780  }
1781  }
1782 #else
1783  if ((*listIt).size == 4) {
1784  fprintf(gTraceFile, ((*listIt).byteMapMan & (1)) ? "00 " : "XX ");
1785  fprintf(gTraceFile, ((*listIt).byteMapMan & (2)) ? "00 " : "XX ");
1786  fprintf(gTraceFile, ((*listIt).byteMapMan & (4)) ? "00 | " : "XX | ");
1787  fprintf(gTraceFile, ((*listIt).byteMapExp & (1)) ? "00 | " : "XX | ");
1788  fprintf(gTraceFile, ((*listIt).byteMapSign & (1)) ? "0 " : "X ");
1789  for (uint32_t i = 1; i < (*listIt).accessLen / 4; i++) {
1790  fprintf(gTraceFile, " , ");
1791  fprintf(gTraceFile, ((*listIt).byteMapMan & (1 << (3 * i))) ? "00 " : "XX ");
1792  fprintf(gTraceFile, ((*listIt).byteMapMan & (2 << (3 * i))) ? "00 " : "XX ");
1793  fprintf(gTraceFile, ((*listIt).byteMapMan & (4 << (3 * i))) ? "00 | " : "XX | ");
1794  fprintf(gTraceFile, ((*listIt).byteMapExp & (2 << (i))) ? "00 | " : "XX | ");
1795  fprintf(gTraceFile, ((*listIt).byteMapSign & (1 << i)) ? "0 " : "X ");
1796  }
1797  } else {
1798  fprintf(gTraceFile, ((*listIt).byteMapMan & (1)) ? "00 " : "XX ");
1799  fprintf(gTraceFile, ((*listIt).byteMapMan & (2)) ? "00 " : "XX ");
1800  fprintf(gTraceFile, ((*listIt).byteMapMan & (4)) ? "00 " : "XX ");
1801  fprintf(gTraceFile, ((*listIt).byteMapMan & (8)) ? "00 " : "XX ");
1802  fprintf(gTraceFile, ((*listIt).byteMapMan & (16)) ? "00 " : "XX ");
1803  fprintf(gTraceFile, ((*listIt).byteMapMan & (32)) ? "00 " : "XX ");
1804  fprintf(gTraceFile, ((*listIt).byteMapMan & (64)) ? "00 | " : "XX | ");
1805  fprintf(gTraceFile, ((*listIt).byteMapExp & (1)) ? "00 " : "XX ");
1806  fprintf(gTraceFile, ((*listIt).byteMapExp & (2)) ? "00 | " : "XX | ");
1807  fprintf(gTraceFile, ((*listIt).byteMapSign & (1)) ? "0 " : "X ");
1808  for (uint32_t i = 1; i < (*listIt).accessLen / 8; i++) {
1809  fprintf(gTraceFile, " , ");
1810  fprintf(gTraceFile, ((*listIt).byteMapMan & (1 << (7 * i))) ? "00 " : "XX ");
1811  fprintf(gTraceFile, ((*listIt).byteMapMan & (2 << (7 * i))) ? "00 " : "XX ");
1812  fprintf(gTraceFile, ((*listIt).byteMapMan & (4 << (7 * i))) ? "00 " : "XX ");
1813  fprintf(gTraceFile, ((*listIt).byteMapMan & (8 << (7 * i))) ? "00 " : "XX ");
1814  fprintf(gTraceFile, ((*listIt).byteMapMan & (16 << (7 * i))) ? "00 " : "XX ");
1815  fprintf(gTraceFile, ((*listIt).byteMapMan & (32 << (7 * i))) ? "00 " : "XX ");
1816  fprintf(gTraceFile, ((*listIt).byteMapMan & (64 << (7 * i))) ? "00 | " : "XX | ");
1817  fprintf(gTraceFile, ((*listIt).byteMapExp & (1 << (2 * i))) ? "00 " : "XX ");
1818  fprintf(gTraceFile, ((*listIt).byteMapExp & (2 << (2 * i))) ? "00 | " : "XX | ");
1819  fprintf(gTraceFile, ((*listIt).byteMapSign & (1 << i)) ? "0 " : "X ");
1820  }
1821  }
1822 #endif
1823 #endif
1824  fprintf(gTraceFile, "\n===== [AccessLen=%d, typesize=%d] =======\n", (*listIt).accessLen, (*listIt).size);
1825  fprintf(gTraceFile, "\n---------------------Redundant load with---------------------------\n");
1826  //PrintFullCallingContext((*listIt).kill);
1827  PrintFullCallingContext((*listIt).cntxt);
1828  } else {
1829  break;
1830  }
1831  cntxtNum++;
1832  }
1833  fprintf(gTraceFile, "\n------------ Dumping Approximation Redundancy Info Finish -------------\n");
1834 }
1835 /*
1836 static void HPCRunRedundancyPairs(THREADID threadId) {
1837  vector<RedundacyData> tmpList;
1838  vector<RedundacyData>::iterator tmpIt;
1839 
1840  for (unordered_map<uint64_t, RedLogs>::iterator it = RedMap[threadId].begin(); it != RedMap[threadId].end(); ++it) {
1841  RedundacyData tmp = { DECODE_DEAD ((*it).first), DECODE_KILL((*it).first), (*it).second.red, (*it).second.tot};
1842  tmpList.push_back(tmp);
1843  }
1844 
1845  sort(tmpList.begin(), tmpList.end(), RedundacyCompare);
1846  vector<HPCRunCCT_t*> HPCRunNodes;
1847  int cntxtNum = 0;
1848  for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1849  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1850  HPCRunCCT_t *HPCRunNode = new HPCRunCCT_t();
1851  HPCRunNode->ctxtHandle1 = (*listIt).dead;
1852  HPCRunNode->ctxtHandle2 = (*listIt).kill;
1853  HPCRunNode->metric = (*listIt).frequency;
1854  HPCRunNode->metric_id = redload_metric_id;
1855  HPCRunNodes.push_back(HPCRunNode);
1856  }
1857  else {
1858  break;
1859  }
1860  cntxtNum++;
1861  }
1862  newCCT_hpcrun_build_cct(HPCRunNodes, threadId);
1863 }
1864 
1865 static void HPCRunApproxRedundancyPairs(THREADID threadId) {
1866  vector<RedundacyData> tmpList;
1867  vector<RedundacyData>::iterator tmpIt;
1868 
1869  for (unordered_map<uint64_t, RedLogs>::iterator it = ApproxRedMap[threadId].begin(); it != ApproxRedMap[threadId].end(); ++it) {
1870  RedundacyData tmp = { DECODE_DEAD ((*it).first), DECODE_KILL((*it).first), (*it).second.red, (*it).second.tot};
1871  tmpList.push_back(tmp);
1872  }
1873 
1874  sort(tmpList.begin(), tmpList.end(), RedundacyCompare);
1875  vector<HPCRunCCT_t*> HPCRunNodes;
1876  int cntxtNum = 0;
1877  for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1878  if (cntxtNum < MAX_REDUNDANT_CONTEXTS_TO_LOG) {
1879  HPCRunCCT_t *HPCRunNode = new HPCRunCCT_t();
1880  HPCRunNode->ctxtHandle1 = (*listIt).dead;
1881  HPCRunNode->ctxtHandle2 = (*listIt).kill;
1882  HPCRunNode->metric = (*listIt).frequency;
1883  HPCRunNode->metric_id = redload_approx_metric_id;
1884  HPCRunNodes.push_back(HPCRunNode);
1885  }
1886  else {
1887  break;
1888  }
1889  cntxtNum++;
1890  }
1891  newCCT_hpcrun_build_cct(HPCRunNodes, threadId);
1892 }
1893 */
1894 // On each Unload of a loaded image, the accummulated redundancy information is dumped
1895 static VOID ImageUnload(IMG img, VOID* v) {
1896  printf("\nImage %s Unloading...\n", IMG_Name(img).c_str());
1897  fflush(stdout);
1898  fprintf(gTraceFile, "\n TODO .. Multi-threading is not well supported.");
1899  THREADID threadid = PIN_ThreadId();
1900  fprintf(gTraceFile, "\nUnloading %s", IMG_Name(img).c_str());
1901  if (RedMap[threadid].empty() && ApproxRedMap[threadid].empty())
1902  return;
1903  printf("Now locking client for updating...\n");
1904  fflush(stdout);
1905  // Update gTotalInstCount first
1906  PIN_LockClient();
1907  printf("Client locked, now generate report\n");
1908  fflush(stdout);
1909  PrintRedundancyPairs(threadid);
1910  printf("Generate Floating point report\n");
1911  fflush(stdout);
1913  printf("all generated\n");
1914  fflush(stdout);
1915 #ifdef USE_COLLECT_PAGE_CACHE
1916  PrintPageRedundancy(threadid);
1917  PrintCacheRedundancy(threadid);
1918 #endif
1919  PIN_UnlockClient();
1920  printf("Unlocked\n");
1921  fflush(stdout);
1922  // clear redmap now
1923  RedMap[threadid].clear();
1924  ApproxRedMap[threadid].clear();
1925  printf("...Finish\n");
1926  fflush(stdout);
1927 }
1928 
1929 static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT* ctxt, INT32 code, VOID* v) {
1930  __sync_fetch_and_add(&grandTotBytesLoad, ClientGetTLS(threadid)->bytesLoad);
1931  /*
1932  // output the CCT for hpcviewer format
1933  HPCRunRedundancyPairs(threadid);
1934  HPCRunApproxRedundancyPairs(threadid);
1935  newCCT_hpcrun_selection_write(threadid);*/
1936 }
1937 
1938 static VOID FiniFunc(INT32 code, VOID* v) {
1939  // do whatever you want to the full CCT with footpirnt
1940  uint64_t redReadTmp = 0;
1941  uint64_t approxRedReadTmp = 0;
1942  for (int i = 0; i < THREAD_MAX; ++i) {
1943  unordered_map<uint64_t, RedLogs>::iterator it;
1944  if (!RedMap[i].empty()) {
1945  for (it = RedMap[i].begin(); it != RedMap[i].end(); ++it) {
1946  redReadTmp += (*it).second.red;
1947  }
1948  }
1949  unordered_map<uint64_t, ApproxRedLogs>::iterator ait;
1950  if (!ApproxRedMap[i].empty()) {
1951  for (ait = ApproxRedMap[i].begin(); ait != ApproxRedMap[i].end(); ++ait) {
1952  approxRedReadTmp += (*ait).second.fred;
1953  }
1954  }
1955  }
1956  grandTotBytesRedLoad += redReadTmp;
1957  grandTotBytesApproxRedLoad += approxRedReadTmp;
1958 
1959  fprintf(gTraceFile, "\n#Redundant Read:");
1960  fprintf(gTraceFile, "\nTotalBytesLoad: %lu \n", grandTotBytesLoad);
1961  fprintf(gTraceFile, "\nRedundantBytesLoad: %lu %.2f\n", grandTotBytesRedLoad, grandTotBytesRedLoad * 100.0 / grandTotBytesLoad);
1962  fprintf(gTraceFile, "\nApproxRedundantBytesLoad: %lu %.2f\n", grandTotBytesApproxRedLoad, grandTotBytesApproxRedLoad * 100.0 / grandTotBytesLoad);
1963 }
1964 
1965 static void InitThreadData(RedSpyThreadData* tdata) {
1966  tdata->bytesLoad = 0;
1967  tdata->sampleFlag = true;
1968  tdata->numIns = 0;
1969  /* for (int i = 0; i < THREAD_MAX; ++i) {
1970  RedMap[i].set_empty_key(0);
1971  ApproxRedMap[i].set_empty_key(0);
1972  }
1973 */
1974 }
1975 
1976 static VOID ThreadStart(THREADID threadid, CONTEXT* ctxt, INT32 flags, VOID* v) {
1977  RedSpyThreadData* tdata = (RedSpyThreadData*)memalign(32, sizeof(RedSpyThreadData));
1978  InitThreadData(tdata);
1979  RedMap[threadid].reserve(10000000);
1980  ApproxRedMap[threadid].rehash(10000000);
1981  // __sync_fetch_and_add(&gClientNumThreads, 1);
1982 #ifdef MULTI_THREADED
1983  PIN_SetThreadData(client_tls_key, tdata, threadid);
1984 #else
1985  gSingleThreadedTData = tdata;
1986 #endif
1987 }
1988 
1989 // user-defined function for metric computation
1990 // hpcviewer can only show the numbers for the metric
1991 uint64_t computeMetricVal(void* metric) {
1992  if (!metric)
1993  return 0;
1994  return (uint64_t)metric;
1995 }
1996 
1997 int main(int argc, char* argv[]) {
1998  // Initialize PIN
1999  if (PIN_Init(argc, argv))
2000  return Usage();
2001 
2002  // Initialize Symbols, we need them to report functions and lines
2003  PIN_InitSymbols();
2004 
2005  // Init Client
2006  ClientInit(argc, argv);
2007  // Intialize CCTLib
2009  /*
2010  // Init hpcrun format output
2011  init_hpcrun_format(argc, argv, NULL, NULL, false);
2012  // Create new metrics
2013  redload_metric_id = hpcrun_create_metric("RED_LOAD");
2014  redload_approx_metric_id = hpcrun_create_metric("RED_LOAD_APPROX");
2015  */
2016  // Obtain a key for TLS storage.
2017  client_tls_key = PIN_CreateThreadDataKey(nullptr /*TODO have a destructir*/);
2018  // Register ThreadStart to be called when a thread starts.
2019  PIN_AddThreadStartFunction(ThreadStart, nullptr);
2020 
2021 
2022  // fini function for post-mortem analysis
2023  PIN_AddThreadFiniFunction(ThreadFiniFunc, nullptr);
2024  PIN_AddFiniFunction(FiniFunc, nullptr);
2025 
2026  TRACE_AddInstrumentFunction(InstrumentTrace, nullptr);
2027 
2028  // Register ImageUnload to be called when an image is unloaded
2029  IMG_AddUnloadFunction(ImageUnload, nullptr);
2030 
2031  // Launch program now
2032  PIN_StartProgram();
2033  return 0;
2034 }
#define MAX_FILE_PATH
Definition: cctlib.H:18
#define INTERESTING_INS_ALL
Definition: cctlib.H:85
uint8_t ** gL1PageTable[LEVEL_1_PAGE_TABLE_SIZE]
uint8_t * GetOrCreateShadowBaseAddress(void *address)
uint64_t metric
Definition: cctlib.H:60
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
bool HaveSameCallerPrefix(ContextHandle_t ctxt1, ContextHandle_t ctxt2)
Definition: cctlib.cpp:3241
bool IsSameSourceLine(ContextHandle_t ctxt1, ContextHandle_t ctxt2)
Definition: cctlib.cpp:3255
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
Definition: cctlib.cpp:1356
uint32_t ContextHandle_t
Definition: cctlib.H:22
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]
void * address
#define LEVEL_2_PAGE_TABLE_SIZE
Definition: shadow_memory.H:27
#define LEVEL_1_PAGE_TABLE_SLOT(addr)
Definition: shadow_memory.H:29
#define SHADOW_PAGE_SIZE
Definition: shadow_memory.H:17
#define LEVEL_1_PAGE_TABLE_SIZE
Definition: shadow_memory.H:23
#define LEVEL_2_PAGE_TABLE_SLOT(addr)
Definition: shadow_memory.H:30
uint32_t redByteMapSign
uint32_t redByteMapMan
uint32_t redByteMapExp
ContextHandle_t cntxt
uint64_t frequency
static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins
uint64_t red
uint64_t tot
uint32_t redByteMap
uint64_t fred
ContextHandle_t cntxt
static __attribute__((always_inline)) uint64_t BodyByteMapExp(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyZeros(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyMap(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyByteMapSign(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyByteMapMan(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyByteMapSign(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyByteMapMan(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyMap(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyZeros(uint8_t *addr)
static __attribute__((always_inline)) uint64_t BodyByteMapExp(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)) uint32_t BodyByteMap(uint8_t *addr)
static __attribute__((always_inline)) bool Body(const function< bool(const int)> &func)
static __attribute__((always_inline)) uint32_t BodyByteMap(uint8_t *addr)
static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t *__restrict__ prevIP)
static bool Body(const function< bool(const int)> &func)
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)) uint32_t BodyRedZero(uint8_t *addr)
static __attribute__((always_inline)) uint32_t BodyRedZero(uint8_t *addr)
static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(void *addr
static __attribute__((always_inline)) uint64_t getRedNum(void *addr)
static __attribute__((always_inline)) uint64_t getRedMap(void *addr)
void f()
Definition: test1.c:23
uint64_t exponent
uint64_t mantisa
uint32_t exponent
uint32_t mantisa
uint32_t value
static bool DRedundacyCompare(const struct DRedData &first, const struct DRedData &second)
#define LEVEL_1_RED_THRESHOLD
#define LEVEL_2_RED_THRESHOLD
#define LEVEL_3_RED_THRESHOLD
static void PrintCacheRedundancy(THREADID threadId)
static void PrintPageRedundancy(THREADID threadId)
uint64_t computeMetricVal(void *metric)
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
#define HANDLE_LARGE()
static FILE * gTraceFile
uint64_t grandTotBytesRedLoad
xed_state_t xedState
#define MAX_REDUNDANT_CONTEXTS_TO_LOG
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)
static RedSpyThreadData * gSingleThreadedTData
#define EIGHT_BYTE_WRITE_ACTION
static void PrintRedundancyPairs(THREADID threadId)
char dummy2[128]
static const uint64_t READ_ACCESS_STATES[]
static void AddToApproximateRedTable(uint64_t key, uint32_t byteMapMan, uint32_t byteMapExp, uint32_t byteMapSign, uint16_t total, uint16_t zeros, uint16_t nums, uint8_t size, THREADID threadId) __attribute__((always_inline
#define THREAD_MAX
#define ONE_BYTE_READ_ACTION
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
int redload_approx_metric_id
static INT32 Usage()
static bool IsFloatInstructionOld(ADDRINT ip)
static unordered_map< uint64_t, ApproxRedLogs > ApproxRedMap[THREAD_MAX]
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
struct @17 LoadSpyGlobals
static void AddToRedTable(uint64_t key, uint16_t value, uint32_t byteMap, uint16_t total, THREADID threadId) __attribute__((always_inline
static uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper)
static const uint8_t OVERFLOW_CHECK[]
static void flatten
#define MAKE_CONTEXT_PAIR(a, b)
VOID Update(uint32_t bytes, THREADID threadId)
#define DECODE_DEAD(data)
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 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 bool IsOkToApproximate(xed_decoded_inst_t &xedd)
char dummy1[128]
static bool ApproxRedundacyCompare(const struct ApproxRedundacyData &first, const struct ApproxRedundacyData &second)
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
#define DECODE_KILL(data)
static TLS_KEY client_tls_key
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
int redload_metric_id