18 #include <unordered_set>
20 #include <unordered_map>
26 #define SKIP_SMALL_VARS
27 #ifdef SKIP_SMALL_VARS
28 #define SMALL_VAR_THRESHOLD 16
32 #define USE_TREE_BASED_FOR_DATA_CENTRIC
33 #define USE_TREE_WITH_ADDR
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")))
42 #include <xmmintrin.h>
43 #include <immintrin.h>
46 #include "xed-interface.h"
47 #include "xed-common-hdrs.h"
50 #include <google/sparse_hash_map>
51 #include <google/dense_hash_map>
57 #define READ_ACTION (0)
58 #define WRITE_ACTION (0xff)
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)
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)
70 #define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen) (PAGE_OFFSET((accessAddr)) <= (PAGE_OFFSET_MASK - (accessLen)))
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)
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)
83 #define MAX_WRITE_OP_LENGTH (512)
84 #define MAX_WRITE_OPS_IN_INS (8)
85 #define MAX_REG_LENGTH (64)
87 #define MAX_SIMD_LENGTH (64)
88 #define MAX_SIMD_REGS (32)
91 #ifdef ENABLE_SAMPLING
93 #define WINDOW_ENABLE 1000000
94 #define WINDOW_DISABLE 100000000
95 #define WINDOW_CLEAN 10
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))
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))
109 #define CACHE_LINE_SIZE (64)
111 #define PAGE_SIZE (4 * 1024)
149 #ifdef MULTI_THREADED
159 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
170 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
174 snprintf(name,
sizeof(name),
"%s", envPath);
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";
185 for (
int i = 0; i < argc; i++) {
193 xed_state_init(&
LoadSpyGlobals.xedState, XED_MACHINE_MODE_LONG_64, (xed_address_width_enum_t)0, XED_ADDRESS_WIDTH_64b);
201 #define DATA_STATE_NOT_VISIT 0
202 #define DATA_STATE_ONLY_ZERO 1
203 #define DATA_STATE_NOT_ZERO 2
219 #ifdef MULTI_THREADED
223 unordered_map<uint64_t, RedLogs>::iterator it =
RedMap[threadId].find(key);
224 if (it ==
RedMap[threadId].end()) {
230 RedMap[threadId][key] = log;
233 for (
int i = 0; i < total; ++i)
234 RedMap[threadId][key].state[addr + i] = redmap[i];
236 it->second.red +=
value;
238 for (
int i = 0; i < total; ++i)
239 it->second.state[addr + i] |= redmap[i];
246 #ifdef MULTI_THREADED
256 uint32_t exponent : 8;
257 uint32_t mantisa : 23;
269 uint64_t exponent : 11;
270 uint64_t mantisa : 52;
281 uint32_t mantisa : 23;
282 uint32_t exponent : 8;
294 uint64_t mantisa : 52;
295 uint64_t exponent : 11;
307 #ifdef MULTI_THREADED
312 unordered_map<uint64_t, RedLogs>::iterator it =
ApproxRedMap[threadId].find(key);
314 cerr <<
"** Warning AddToApproximateTable : value " <<
value <<
", total " << total <<
" **" << endl;
315 assert(0 &&
"** BUG #0 Detected. Existing **");
329 for (
int i = 0; i < total; i += typesz)
330 ApproxRedMap[threadId][key].state[addr + i] = redmap[i];
333 it->second.red +=
value;
335 for (
int i = 0; i < total; i += typesz)
336 it->second.state[addr + i] |= redmap[i];
345 #ifdef MULTI_THREADED
351 #ifdef ENABLE_SAMPLING
353 static ADDRINT IfEnableSample(THREADID threadId) {
362 xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
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:
380 xed_decoded_inst_t xedd;
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);
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: {
396 const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
397 int noperands = xed_inst_noperands(xi);
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) {
407 if (memOpIdx == -1) {
412 xed_operand_element_type_enum_t eType = xed_decoded_inst_operand_element_type(&xedd, memOpIdx);
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:
424 case XED_CATEGORY_X87_ALU:
425 case XED_CATEGORY_FCMOV:
430 case XED_CATEGORY_XSAVE:
431 case XED_CATEGORY_AVX2GATHER:
432 case XED_CATEGORY_STRINGOP:
437 assert(0 &&
"failed to disassemble instruction");
444 xed_decoded_inst_t xedd;
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) {
452 if (iclassType >= XED_ICLASS_VBROADCASTSD && iclassType <= XED_ICLASS_VDPPS) {
455 if (iclassType >= XED_ICLASS_VRCPPS && iclassType <= XED_ICLASS_VSQRTSS) {
458 if (iclassType >= XED_ICLASS_VSUBPD && iclassType <= XED_ICLASS_VXORPS) {
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:
653 assert(0 &&
"failed to disassemble instruction");
659 xed_decoded_inst_t xedd;
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)
666 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_DOUBLE) {
669 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE) {
672 assert(0 &&
"float instruction with unknown operand\n");
675 assert(0 &&
"failed to disassemble instruction\n");
708 template <
int start,
int end,
int incr>
710 static __attribute__((always_inline))
bool Body(
const function<
bool(
const int)>& func) {
719 static __attribute__((always_inline))
void BodyByteMap(uint8_t* addr, uint8_t redmap[32]) {
723 static __attribute__((always_inline))
void BodyByteMapApprox(uint8_t* addr, uint8_t redmap[32]) {
733 template <
int end,
int incr>
735 static __attribute__((always_inline))
bool Body(
const function<
void(
const int)>& func) {
744 static __attribute__((always_inline))
void BodyByteMap(uint8_t* addr, uint8_t redmap[32]) {
746 static __attribute__((always_inline))
void BodyByteMapApprox(uint8_t* addr, uint8_t redmap[32]) {
750 template <
int start,
int end,
int step>
756 template <
int end,
int step>
763 template <
class T, u
int32_t AccessLen,
bool isApprox>
765 static __attribute__((always_inline))
void getRedMap(
void* addr, uint8_t redbyteMap[32]) {
767 uint8_t* bytes =
static_cast<uint8_t*
>(addr);
770 uint8_t* bytes =
static_cast<uint8_t*
>(addr);
774 static __attribute__((always_inline)) uint64_t getRedNum(
void* addr) {
776 uint8_t* bytes =
static_cast<uint8_t*
>(addr);
777 uint32_t rednum =
UnrolledCount<0, AccessLen,
sizeof(T)>::BodyRedZero(bytes);
780 uint8_t* bytes =
static_cast<uint8_t*
>(addr);
781 uint32_t rednum =
UnrolledCount<0, AccessLen,
sizeof(T)>::BodyRedZero(bytes);
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);
796 #ifdef SKIP_SMALL_VARS
801 uint32_t redbyteNum = getRedNum(addr);
802 uint8_t redbyteMap[32] = {0};
804 getRedMap(addr, redbyteMap);
808 AddToApproximateRedTable((uint32_t)((uint64_t)addr - curDataHandle.beg_addr), curDataHandle,
curCtxt, redbyteNum, AccessLen, redbyteMap,
sizeof(T), threadId);
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");
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);
827 #ifdef SKIP_SMALL_VARS
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) {
842 for (UINT32 i = 0; i < accessLen; ++i) {
849 AddToRedTable((uint32_t)((uint64_t)addr - curDataHandle.beg_addr), curDataHandle,
curCtxt, redbyteNum, accessLen, redbyteMap, accessLen, threadId);
851 #ifdef DEBUG_ZEROSPY_SPATIAL
852 printf(
"\n In CheckAfterLargeRead Finish \n");
855 #undef DEBUG_ZEROSPY_SPATIAL
857 #ifdef ENABLE_SAMPLING
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)
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)
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)
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)
878 UINT32 memOperands = INS_MemoryOperandCount(ins);
879 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
880 if (INS_MemoryOperandIsRead(ins, memOp)) {
890 static __attribute__((always_inline))
void InstrumentReadValueBeforeAndAfterLoading(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
891 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
894 unsigned int operSize =
FloatOperandSize(INS_Address(ins), INS_MemoryOperandIndexToOperandIndex(ins, memOp));
898 assert(0 &&
"memory read floating data with unexptected small size");
917 assert(0 &&
"handle large mem read with unexpected operand size\n");
930 assert(0 &&
"handle large mem read with unexpected operand size\n");
935 assert(0 &&
"unexpected large memory read\n");
964 if (INS_IsFarJump(ins) || INS_IsDirectFarJump(ins) ||
INS_IsMaskedJump(ins))
966 else if (INS_IsRet(ins) || INS_IsIRet(ins))
968 else if (INS_IsCall(ins) || INS_IsSyscall(ins))
970 else if (INS_IsBranch(ins) || INS_IsRDTSC(ins) || INS_IsNop(ins))
972 else if (INS_IsPrefetch(ins))
978 if (INS_Mnemonic(ins) ==
"XSAVEC")
980 if (INS_Mnemonic(ins) ==
"XSAVE")
982 if (INS_Mnemonic(ins) ==
"XRSTOR")
988 if (!INS_HasFallThrough(ins))
992 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1000 LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, whichOp, opaqueHandle);
1002 UINT32 memOperands = INS_MemoryOperandCount(ins);
1003 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1004 if (!INS_MemoryOperandIsRead(ins, memOp))
1006 LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, memOp, opaqueHandle);
1014 #ifdef ENABLE_SAMPLING
1016 inline VOID UpdateAndCheck(uint32_t count, uint32_t bytes, THREADID threadId) {
1037 inline VOID
Update(uint32_t count, uint32_t bytes, THREADID threadId) {
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))
1056 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1059 if (INS_IsMemoryRead(ins)) {
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);
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);
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);
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);
1082 inline VOID
Update(uint32_t bytes, THREADID threadId) {
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))
1099 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1102 if (INS_IsMemoryRead(ins)) {
1106 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)
Update, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_END);
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);
1135 #define MAX_REDMAP_PRINT_SIZE 128
1137 #define MAX_PRINT_FULL 5
1140 vector<ObjRedundancy> tmpList;
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);
1148 int total =
RedMap[threadId].size();
1149 for (unordered_map<uint64_t, RedLogs>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
1151 if (100 * count / total != rep) {
1152 rep = 100 * count / total;
1153 printf(
"Stage 1 : %d%% Finish\n", rep);
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);
1162 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesLoad);
1168 for (vector<ObjRedundancy>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1171 if (100 * objNum / total != rep) {
1172 rep = 100 * count / total;
1173 printf(
"Stage 2 : %d%% Finish\n", rep);
1177 fprintf(
gTraceFile,
"\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1182 fprintf(
gTraceFile,
"\n\n==========================================\n");
1183 fprintf(
gTraceFile,
"Redundancy Ratio = %f %% (%ld Bytes)\n", (*listIt).bytes * 100.0 / grandTotalRedundantBytes, (*listIt).bytes);
1187 for (vector<uint8_t>::iterator addrIt =
RedMap[threadId][(*listIt).objID].state.begin(); addrIt !=
RedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1194 fprintf(
gTraceFile,
"\n\n======= DATA SIZE : ");
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);
1200 fprintf(
gTraceFile,
"\n======= Redundant byte map : [0] ");
1202 for (vector<uint8_t>::iterator addrIt =
RedMap[threadId][(*listIt).objID].state.begin(); addrIt !=
RedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1222 sprintf(fn,
"%lx.redmap", (*listIt).objID);
1223 FILE* fp = fopen(fn,
"w");
1225 fprintf(fp,
"\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
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) {
1244 fprintf(
gTraceFile,
"\n------------ Dumping Redundancy Info Finish -------------\n");
1249 vector<ObjRedundancy> tmpList;
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);
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);
1263 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesLoad);
1267 for (vector<ObjRedundancy>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1271 fprintf(
gTraceFile,
"\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1276 fprintf(
gTraceFile,
"\n\n==========================================\n");
1277 fprintf(
gTraceFile,
"Redundancy Ratio = %f %% (%ld Bytes)\n", (*listIt).bytes * 100.0 / grandTotalRedundantBytes, (*listIt).bytes);
1281 for (vector<uint8_t>::iterator addrIt =
ApproxRedMap[threadId][(*listIt).objID].state.begin(); addrIt !=
ApproxRedMap[threadId][(*listIt).objID].state.end(); ++addrIt) {
1283 dfreq += (*listIt).typesz;
1285 dread += (*listIt).typesz;
1288 fprintf(
gTraceFile,
"\n\n======= DATA SIZE : ");
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);
1294 fprintf(
gTraceFile,
"\n======= Redundant byte map : [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]) {
1316 sprintf(fn,
"%lx.redmap", (*listIt).objID);
1317 FILE* fp = fopen(fn,
"w");
1319 fprintf(fp,
"\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Dynamic Object: %lx^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", (*listIt).objID);
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]) {
1337 fprintf(
gTraceFile,
"\n------------ Dumping Approx Redundancy Info Finish -------------\n");
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());
1349 printf(
"==== PIN CLIENT ZEROSPY : Print Redundancy info ... ===\n");
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);
1361 RedMap[threadid].clear();
1365 static VOID
ThreadFiniFunc(THREADID threadid,
const CONTEXT* ctxt, INT32 code, VOID* v) {
1376 uint64_t redReadTmp = 0;
1377 uint64_t approxRedReadTmp = 0;
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;
1386 approxRedReadTmp += (*it).second.red;
1403 fprintf(
gTraceFile,
"\nInit Thread Data Finish\n");
1416 #ifdef MULTI_THREADED
1421 fprintf(
gTraceFile,
"\nInit ThreadStart Finish\n");
1434 if (PIN_Init(argc, argv))
1452 PIN_AddFiniFunction(
FiniFunc,
nullptr);
1458 printf(
"==== PIN CLIENT : Launch program now ===\n");
#define INTERESTING_INS_ALL
DataHandle_t GetDataObjectHandle(VOID *address, const THREADID threadId)
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
hpcrun_metricFlags_t flags
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
struct DataHandle_t { uint8_t objectType DataHandle_t
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
char * GetStringFromStringPool(const uint32_t index)
static USIZE INS_MemoryReadSize(INS ins)
static BOOL INS_IsMaskedJump(INS ins)
static BOOL INS_IsIndirectBranchOrCall(INS ins)
struct RedSpyThreadData __attribute__
uint8_t value[MAX_WRITE_OP_LENGTH]
static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins
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
uint64_t computeMetricVal(void *metric)
static void ClientInit(int argc, char *argv[])
#define DATA_STATE_NOT_ZERO
int main(int argc, char *argv[])
static void PrintSize(uint64_t size, char unit='B')
uint64_t grandTotBytesRedLoad
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
static RedSpyThreadData * gSingleThreadedTData
#define EIGHT_BYTE_WRITE_ACTION
static void PrintRedundancyPairs(THREADID threadId)
static const uint64_t READ_ACCESS_STATES[]
#define DATA_STATE_NOT_VISIT
#define ONE_BYTE_READ_ACTION
int redload_approx_metric_id
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[]
VOID Update(uint32_t bytes, THREADID threadId)
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
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)
#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)