17 #include <unordered_set>
19 #include <unordered_map>
26 #include <xmmintrin.h>
27 #include <immintrin.h>
30 #include "xed-interface.h"
31 #include "xed-common-hdrs.h"
34 #include <google/sparse_hash_map>
35 #include <google/dense_hash_map>
36 using google::dense_hash_map;
43 #define READ_ACTION (0)
44 #define WRITE_ACTION (0xff)
46 #define ONE_BYTE_READ_ACTION (0)
47 #define TWO_BYTE_READ_ACTION (0)
48 #define FOUR_BYTE_READ_ACTION (0)
49 #define EIGHT_BYTE_READ_ACTION (0)
51 #define ONE_BYTE_WRITE_ACTION (0xff)
52 #define TWO_BYTE_WRITE_ACTION (0xffff)
53 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
54 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
57 #define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen) (PAGE_OFFSET((accessAddr)) <= (PAGE_OFFSET_MASK - (accessLen)))
60 #define MAX_REDUNDANT_CONTEXTS_TO_LOG (1000)
61 #define THREAD_MAX (1024)
63 #define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len) ((addr) | (((uint64_t)(len)) << 48))
64 #define DECODE_ADDRESS(addrAndLen) ((addrAndLen) & ((1L << 48) - 1))
65 #define DECODE_ACCESS_LEN(addrAndLen) ((addrAndLen) >> 48)
68 #define MAX_WRITE_OP_LENGTH (512)
69 #define MAX_WRITE_OPS_IN_INS (8)
70 #define MAX_REG_LENGTH (64)
72 #define MAX_SIMD_LENGTH (64)
73 #define MAX_SIMD_REGS (32)
75 #define MAX_ALIAS_REGS (16)
76 #define MAX_ALIAS_REG_SIZE (8)
77 #define MAX_ALIAS_TYPE (3)
107 #if __BYTE_ORDER == __LITTLE_ENDIAN
109 #define ALIAS_BYTES_INDEX_64 (0)
110 #define ALIAS_BYTES_INDEX_32 (0)
111 #define ALIAS_BYTES_INDEX_16 (0)
112 #define ALIAS_BYTES_INDEX_8_L (0)
113 #define ALIAS_BYTES_INDEX_8_H (1)
115 #elif __BYTE_ORDER == __BIG_ENDIAN
117 #define ALIAS_BYTES_INDEX_64 (0)
118 #define ALIAS_BYTES_INDEX_32 (4)
119 #define ALIAS_BYTES_INDEX_16 (6)
120 #define ALIAS_BYTES_INDEX_8_L (7)
121 #define ALIAS_BYTES_INDEX_8_H (6)
125 #error "unknown endianness"
130 #ifdef ENABLE_SAMPLING
132 #define WINDOW_ENABLE 1000000
133 #define WINDOW_DISABLE 100000000
134 #define WINDOW_CLEAN 10
137 #define DECODE_DEAD(data) static_cast<ContextHandle_t>(((data)&0xffffffffffffffff) >> 32)
138 #define DECODE_KILL(data) (static_cast<ContextHandle_t>((data)&0x00000000ffffffff))
141 #define MAKE_CONTEXT_PAIR(a, b) (((uint64_t)(a) << 32) | ((uint64_t)(b)))
159 uint32_t regCtxt[REG_LAST];
165 uint64_t bytesWritten;
178 #ifdef MULTI_THREADED
188 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
206 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
210 snprintf(name,
sizeof(name),
"%s", envPath);
213 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
214 pid_t pid = getpid();
215 sprintf(name + strlen(name),
"%d", pid);
216 cerr <<
"\n Creating log file at:" << name <<
"\n";
221 for (
int i = 0; i < argc; i++) {
229 xed_state_init(&
RedSpyGlobals.xedState, XED_MACHINE_MODE_LONG_64, (xed_address_width_enum_t)0, XED_ADDRESS_WIDTH_64b);
242 #ifdef MULTI_THREADED
245 dense_hash_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].find(key);
246 if (it ==
RedMap[threadId].end()) {
251 #ifdef MULTI_THREADED
258 #ifdef MULTI_THREADED
261 dense_hash_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].find(key);
267 #ifdef MULTI_THREADED
273 #ifdef ENABLE_SAMPLING
276 memset(&tData->
regCtxt, 0,
sizeof(uint32_t) * REG_LAST);
282 static ADDRINT IfEnableSample(THREADID threadId) {
290 xed_decoded_inst_t xedd;
291 xed_decoded_inst_zero_set_mode(&xedd, &
RedSpyGlobals.xedState);
293 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
294 xed_category_enum_t cat = xed_decoded_inst_get_category(&xedd);
296 case XED_CATEGORY_AES:
297 case XED_CATEGORY_CONVERT:
298 case XED_CATEGORY_PCLMULQDQ:
299 case XED_CATEGORY_SSE:
300 case XED_CATEGORY_AVX2:
301 case XED_CATEGORY_AVX:
302 case XED_CATEGORY_MMX:
303 case XED_CATEGORY_DATAXFER: {
306 const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
307 int noperands = xed_inst_noperands(xi);
309 for (
int i = 0; i < noperands; i++) {
310 const xed_operand_t* op = xed_inst_operand(xi, i);
311 xed_operand_enum_t op_name = xed_operand_name(op);
312 if (XED_OPERAND_MEM0 == op_name) {
317 if (memOpIdx == -1) {
322 xed_operand_element_type_enum_t eType = xed_decoded_inst_operand_element_type(&xedd, memOpIdx);
324 case XED_OPERAND_ELEMENT_TYPE_FLOAT16:
325 case XED_OPERAND_ELEMENT_TYPE_SINGLE:
326 case XED_OPERAND_ELEMENT_TYPE_DOUBLE:
327 case XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE:
328 case XED_OPERAND_ELEMENT_TYPE_LONGBCD:
334 case XED_CATEGORY_X87_ALU:
335 case XED_CATEGORY_FCMOV:
340 case XED_CATEGORY_XSAVE:
341 case XED_CATEGORY_AVX2GATHER:
342 case XED_CATEGORY_STRINGOP:
347 assert(0 &&
"failed to disassemble instruction");
355 xed_decoded_inst_t xedd;
356 xed_decoded_inst_zero_set_mode(&xedd, &
RedSpyGlobals.xedState);
358 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
359 xed_iclass_enum_t iclassType = xed_decoded_inst_get_iclass(&xedd);
360 if (iclassType >= XED_ICLASS_F2XM1 && iclassType <= XED_ICLASS_FYL2XP1) {
363 if (iclassType >= XED_ICLASS_VBROADCASTSD && iclassType <= XED_ICLASS_VDPPS) {
366 if (iclassType >= XED_ICLASS_VRCPPS && iclassType <= XED_ICLASS_VSQRTSS) {
369 if (iclassType >= XED_ICLASS_VSUBPD && iclassType <= XED_ICLASS_VXORPS) {
372 switch (iclassType) {
373 case XED_ICLASS_ADDPD:
374 case XED_ICLASS_ADDPS:
375 case XED_ICLASS_ADDSD:
376 case XED_ICLASS_ADDSS:
377 case XED_ICLASS_ADDSUBPD:
378 case XED_ICLASS_ADDSUBPS:
379 case XED_ICLASS_ANDNPD:
380 case XED_ICLASS_ANDNPS:
381 case XED_ICLASS_ANDPD:
382 case XED_ICLASS_ANDPS:
383 case XED_ICLASS_BLENDPD:
384 case XED_ICLASS_BLENDPS:
385 case XED_ICLASS_BLENDVPD:
386 case XED_ICLASS_BLENDVPS:
387 case XED_ICLASS_CMPPD:
388 case XED_ICLASS_CMPPS:
389 case XED_ICLASS_CMPSD:
390 case XED_ICLASS_CMPSD_XMM:
391 case XED_ICLASS_COMISD:
392 case XED_ICLASS_COMISS:
393 case XED_ICLASS_CVTDQ2PD:
394 case XED_ICLASS_CVTDQ2PS:
395 case XED_ICLASS_CVTPD2PS:
396 case XED_ICLASS_CVTPI2PD:
397 case XED_ICLASS_CVTPI2PS:
398 case XED_ICLASS_CVTPS2PD:
399 case XED_ICLASS_CVTSD2SS:
400 case XED_ICLASS_CVTSI2SD:
401 case XED_ICLASS_CVTSI2SS:
402 case XED_ICLASS_CVTSS2SD:
403 case XED_ICLASS_DIVPD:
404 case XED_ICLASS_DIVPS:
405 case XED_ICLASS_DIVSD:
406 case XED_ICLASS_DIVSS:
407 case XED_ICLASS_DPPD:
408 case XED_ICLASS_DPPS:
409 case XED_ICLASS_HADDPD:
410 case XED_ICLASS_HADDPS:
411 case XED_ICLASS_HSUBPD:
412 case XED_ICLASS_HSUBPS:
413 case XED_ICLASS_MAXPD:
414 case XED_ICLASS_MAXPS:
415 case XED_ICLASS_MAXSD:
416 case XED_ICLASS_MAXSS:
417 case XED_ICLASS_MINPD:
418 case XED_ICLASS_MINPS:
419 case XED_ICLASS_MINSD:
420 case XED_ICLASS_MINSS:
421 case XED_ICLASS_MOVAPD:
422 case XED_ICLASS_MOVAPS:
423 case XED_ICLASS_MOVD:
424 case XED_ICLASS_MOVHLPS:
425 case XED_ICLASS_MOVHPD:
426 case XED_ICLASS_MOVHPS:
427 case XED_ICLASS_MOVLHPS:
428 case XED_ICLASS_MOVLPD:
429 case XED_ICLASS_MOVLPS:
430 case XED_ICLASS_MOVMSKPD:
431 case XED_ICLASS_MOVMSKPS:
432 case XED_ICLASS_MOVNTPD:
433 case XED_ICLASS_MOVNTPS:
434 case XED_ICLASS_MOVNTSD:
435 case XED_ICLASS_MOVNTSS:
436 case XED_ICLASS_MOVSD:
437 case XED_ICLASS_MOVSD_XMM:
438 case XED_ICLASS_MOVSS:
439 case XED_ICLASS_MULPD:
440 case XED_ICLASS_MULPS:
441 case XED_ICLASS_MULSD:
442 case XED_ICLASS_MULSS:
443 case XED_ICLASS_ORPD:
444 case XED_ICLASS_ORPS:
445 case XED_ICLASS_ROUNDPD:
446 case XED_ICLASS_ROUNDPS:
447 case XED_ICLASS_ROUNDSD:
448 case XED_ICLASS_ROUNDSS:
449 case XED_ICLASS_SHUFPD:
450 case XED_ICLASS_SHUFPS:
451 case XED_ICLASS_SQRTPD:
452 case XED_ICLASS_SQRTPS:
453 case XED_ICLASS_SQRTSD:
454 case XED_ICLASS_SQRTSS:
455 case XED_ICLASS_SUBPD:
456 case XED_ICLASS_SUBPS:
457 case XED_ICLASS_SUBSD:
458 case XED_ICLASS_SUBSS:
459 case XED_ICLASS_VADDPD:
460 case XED_ICLASS_VADDPS:
461 case XED_ICLASS_VADDSD:
462 case XED_ICLASS_VADDSS:
463 case XED_ICLASS_VADDSUBPD:
464 case XED_ICLASS_VADDSUBPS:
465 case XED_ICLASS_VANDNPD:
466 case XED_ICLASS_VANDNPS:
467 case XED_ICLASS_VANDPD:
468 case XED_ICLASS_VANDPS:
469 case XED_ICLASS_VBLENDPD:
470 case XED_ICLASS_VBLENDPS:
471 case XED_ICLASS_VBLENDVPD:
472 case XED_ICLASS_VBLENDVPS:
473 case XED_ICLASS_VBROADCASTSD:
474 case XED_ICLASS_VBROADCASTSS:
475 case XED_ICLASS_VCMPPD:
476 case XED_ICLASS_VCMPPS:
477 case XED_ICLASS_VCMPSD:
478 case XED_ICLASS_VCMPSS:
479 case XED_ICLASS_VCOMISD:
480 case XED_ICLASS_VCOMISS:
481 case XED_ICLASS_VCVTDQ2PD:
482 case XED_ICLASS_VCVTDQ2PS:
483 case XED_ICLASS_VCVTPD2PS:
484 case XED_ICLASS_VCVTPH2PS:
485 case XED_ICLASS_VCVTPS2PD:
486 case XED_ICLASS_VCVTSD2SS:
487 case XED_ICLASS_VCVTSI2SD:
488 case XED_ICLASS_VCVTSI2SS:
489 case XED_ICLASS_VCVTSS2SD:
490 case XED_ICLASS_VDIVPD:
491 case XED_ICLASS_VDIVPS:
492 case XED_ICLASS_VDIVSD:
493 case XED_ICLASS_VDIVSS:
494 case XED_ICLASS_VDPPD:
495 case XED_ICLASS_VDPPS:
496 case XED_ICLASS_VMASKMOVPD:
497 case XED_ICLASS_VMASKMOVPS:
498 case XED_ICLASS_VMAXPD:
499 case XED_ICLASS_VMAXPS:
500 case XED_ICLASS_VMAXSD:
501 case XED_ICLASS_VMAXSS:
502 case XED_ICLASS_VMINPD:
503 case XED_ICLASS_VMINPS:
504 case XED_ICLASS_VMINSD:
505 case XED_ICLASS_VMINSS:
506 case XED_ICLASS_VMOVAPD:
507 case XED_ICLASS_VMOVAPS:
508 case XED_ICLASS_VMOVD:
509 case XED_ICLASS_VMOVHLPS:
510 case XED_ICLASS_VMOVHPD:
511 case XED_ICLASS_VMOVHPS:
512 case XED_ICLASS_VMOVLHPS:
513 case XED_ICLASS_VMOVLPD:
514 case XED_ICLASS_VMOVLPS:
515 case XED_ICLASS_VMOVMSKPD:
516 case XED_ICLASS_VMOVMSKPS:
517 case XED_ICLASS_VMOVNTPD:
518 case XED_ICLASS_VMOVNTPS:
519 case XED_ICLASS_VMOVSD:
520 case XED_ICLASS_VMOVSS:
521 case XED_ICLASS_VMOVUPD:
522 case XED_ICLASS_VMOVUPS:
523 case XED_ICLASS_VMULPD:
524 case XED_ICLASS_VMULPS:
525 case XED_ICLASS_VMULSD:
526 case XED_ICLASS_VMULSS:
527 case XED_ICLASS_VORPD:
528 case XED_ICLASS_VORPS:
529 case XED_ICLASS_VPABSD:
530 case XED_ICLASS_VPADDD:
531 case XED_ICLASS_VPCOMD:
532 case XED_ICLASS_VPCOMUD:
533 case XED_ICLASS_VPERMILPD:
534 case XED_ICLASS_VPERMILPS:
535 case XED_ICLASS_VPERMPD:
536 case XED_ICLASS_VPERMPS:
537 case XED_ICLASS_VPGATHERDD:
538 case XED_ICLASS_VPGATHERQD:
539 case XED_ICLASS_VPHADDBD:
540 case XED_ICLASS_VPHADDD:
541 case XED_ICLASS_VPHADDUBD:
542 case XED_ICLASS_VPHADDUWD:
543 case XED_ICLASS_VPHADDWD:
544 case XED_ICLASS_VPHSUBD:
545 case XED_ICLASS_VPHSUBWD:
546 case XED_ICLASS_VPINSRD:
547 case XED_ICLASS_VPMACSDD:
548 case XED_ICLASS_VPMACSSDD:
549 case XED_ICLASS_VPMASKMOVD:
550 case XED_ICLASS_VPMAXSD:
551 case XED_ICLASS_VPMAXUD:
552 case XED_ICLASS_VPMINSD:
553 case XED_ICLASS_VPMINUD:
554 case XED_ICLASS_VPROTD:
555 case XED_ICLASS_VPSUBD:
556 case XED_ICLASS_XORPD:
557 case XED_ICLASS_XORPS:
564 assert(0 &&
"failed to disassemble instruction");
585 xed_decoded_inst_t xedd;
586 xed_decoded_inst_zero_set_mode(&xedd, &
RedSpyGlobals.xedState);
588 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
589 xed_operand_element_type_enum_t TypeOperand = xed_decoded_inst_operand_element_type(&xedd, oper);
590 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_SINGLE || TypeOperand == XED_OPERAND_ELEMENT_TYPE_FLOAT16)
592 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_DOUBLE) {
595 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE) {
598 assert(0 &&
"float instruction with unknown operand\n");
601 assert(0 &&
"failed to disassemble instruction\n");
611 template <
class T, AliasGroup aliasGroup>
613 static __attribute__((always_inline))
void CheckUpdateGenericAlias(uint8_t regId, T
value, uint32_t opaqueHandle, THREADID threadId) {
618 #if __BYTE_ORDER == __LITTLE_ENDIAN
621 #error "unknown endianness"
637 tData->
aliasCtxt[regId][aliasGroup] = curCtxtHandle;
643 template <
class T, u
int8_t len>
645 static __attribute__((always_inline))
void CheckValues(T
value, REG reg, uint32_t opaqueHandle, THREADID threadId) {
660 template <u
int8_t lenInt64>
669 uint64_t* oldValue = (uint64_t*)&(tData->
regValue[regID][0]);
670 if (*oldValue == regRef->qword[0])
673 *oldValue = regRef->qword[0];
675 tData->
regCtxt[regID] = curCtxtHandle;
676 }
else if (lenInt64 == 2) {
677 uint64_t* oldValue1 = (uint64_t*)&(tData->
simdValue[regID].
value);
678 uint64_t* oldValue2 = (uint64_t*)&(tData->
simdValue[regID].
value[8]);
679 if (*oldValue1 == regRef->qword[0] && *oldValue2 == regRef->qword[1])
682 *oldValue1 = regRef->qword[0];
683 *oldValue2 = regRef->qword[1];
685 tData->
simdCtxt[regID] = curCtxtHandle;
689 bool isRedundant =
true;
690 for (
int i = 0, j = 0; i < lenInt64; ++i, j += 8) {
692 if (*oldValue != regRef->qword[i]) {
694 *oldValue = regRef->qword[i];
705 static __attribute__((always_inline))
void CheckSIMDRegValues(
PIN_REGISTER* regRef, uint8_t simdID, uint32_t opaqueHandle, THREADID threadId) {
711 uint64_t* oldValue1 = (uint64_t*)&(tData->
simdValue[simdID].
value[0]);
712 uint64_t* oldValue2 = (uint64_t*)&(tData->
simdValue[simdID].
value[8]);
713 if (*oldValue1 == regRef->qword[0] && *oldValue2 == regRef->qword[1])
716 *oldValue1 = regRef->qword[0];
717 *oldValue2 = regRef->qword[1];
721 bool isRedundant =
true;
722 for (
int i = 0, j = 0; i < lenInt64; ++i, j += 8) {
724 if (*oldValue != regRef->qword[i]) {
726 *oldValue = regRef->qword[i];
733 tData->
simdCtxt[simdID] = curCtxtHandle;
739 static void Check10BytesReg(CONTEXT* ctxt, REG reg, uint32_t opaqueHandle, THREADID threadId) {
744 valueAfter = (UINT8*)malloc(10 *
sizeof(UINT8));
745 PIN_GetContextRegval(ctxt, reg, valueAfter);
747 uint64_t* upperOld = (uint64_t*)&(tData->
regValue[reg][2]);
748 uint64_t* upperNew = (uint64_t*)&(valueAfter[2]);
750 uint16_t* lowOld = (uint16_t*)&(tData->
regValue[reg][0]);
751 uint16_t* lowNew = (uint16_t*)(valueAfter);
753 if ((*lowOld & 0xfff0) == (*lowNew & 0xfff0) && *upperNew == *upperOld) {
757 memcpy(&tData->
regValue[reg][0], valueAfter, 10);
758 tData->
regCtxt[reg] = curCtxtHandle;
762 template <
class T,
bool isAlias>
770 uint8_t byteOffset = 0;
774 newValue = regRef->dbl[0];
776 newValue = regRef->flt[0];
778 T oldValue = *((T*)(&tData->
aliasValue[reg][byteOffset]));
779 T rate = (newValue - oldValue) / oldValue;
780 if (rate <= delta && rate >= -
delta) {
783 if (newValue != oldValue)
784 *((T*)(&tData->
aliasValue[reg][byteOffset])) = newValue;
793 newValue = regRef->dbl[0];
795 newValue = regRef->flt[0];
798 T rate = (newValue - oldValue) / oldValue;
799 if (rate <= delta && rate >= -
delta) {
802 if (newValue != oldValue)
803 *((T*)(&tData->
regValue[reg][0])) = newValue;
810 template <
class T, u
int8_t simdType>
812 static __attribute__((always_inline))
void CheckValues(
PIN_REGISTER* regRef, uint8_t regInd, uint32_t opaqueHandle, THREADID threadId) {
818 if (
sizeof(T) == 4) {
819 __m128 oldValue = _mm_load_ps(
reinterpret_cast<const float*
>(&(tData->
simdValue[regInd].
value[0])));
820 __m128 newValue = _mm_loadu_ps(
reinterpret_cast<const float*
>(regRef));
822 __m128 result = _mm_sub_ps(newValue, oldValue);
824 result = _mm_div_ps(result, oldValue);
826 _mm_store_ps(rates, result);
828 uint8_t redCount = 0;
840 _mm_store_ps(
reinterpret_cast<float*
>(&(tData->
simdValue[regInd].
value[0])), newValue);
842 }
else if (
sizeof(T) == 8) {
843 __m128d oldValue = _mm_load_pd(
reinterpret_cast<const double*
>(&(tData->
simdValue[regInd].
value[0])));
844 __m128d newValue = _mm_loadu_pd(
reinterpret_cast<const double*
>(regRef));
846 __m128d result = _mm_sub_pd(newValue, oldValue);
848 result = _mm_div_pd(result, oldValue);
851 _mm_storel_pd(&rate[0], result);
852 _mm_storeh_pd(&rate[1], result);
854 uint8_t redCount = 0;
862 _mm_store_pd(
reinterpret_cast<double*
>(&(tData->
simdValue[regInd].
value[0])), newValue);
866 }
else if (simdType == 1) {
867 if (
sizeof(T) == 4) {
868 __m256 oldValue = _mm256_load_ps(
reinterpret_cast<const float*
>(&(tData->
simdValue[regInd].
value[0])));
869 __m256 newValue = _mm256_loadu_ps(
reinterpret_cast<const float*
>(regRef));
871 __m256 result = _mm256_sub_ps(newValue, oldValue);
873 result = _mm256_div_ps(result, oldValue);
875 _mm256_store_ps(rates, result);
877 uint8_t redCount = 0;
878 for (
int i = 0; i < 7; ++i)
884 _mm256_store_ps(
reinterpret_cast<float*
>(&(tData->
simdValue[regInd].
value[0])), newValue);
886 }
else if (
sizeof(T) == 8) {
887 __m256d oldValue = _mm256_load_pd(
reinterpret_cast<const double*
>(&(tData->
simdValue[regInd].
value[0])));
888 __m256d newValue = _mm256_loadu_pd(
reinterpret_cast<const double*
>(regRef));
890 __m256d result = _mm256_sub_pd(newValue, oldValue);
892 result = _mm256_div_pd(result, oldValue);
895 _mm256_store_pd(rate, result);
897 uint8_t redCount = 0;
909 _mm256_store_pd(
reinterpret_cast<double*
>(&(tData->
simdValue[regInd].
value[0])), newValue);
960 uint8_t regGroup = 0;
964 case LEVEL_BASE::REG_RAX:
990 case LEVEL_BASE::REG_RBX:
1016 case LEVEL_BASE::REG_RCX:
1042 case LEVEL_BASE::REG_RDX:
1068 case LEVEL_BASE::REG_RBP:
1089 case LEVEL_BASE::REG_RDI:
1110 case LEVEL_BASE::REG_RSI:
1131 case LEVEL_BASE::REG_RSP:
1152 case LEVEL_BASE::REG_R8:
1173 case LEVEL_BASE::REG_R9:
1194 case LEVEL_BASE::REG_R10:
1215 case LEVEL_BASE::REG_R11:
1236 case LEVEL_BASE::REG_R12:
1257 case LEVEL_BASE::REG_R13:
1278 case LEVEL_BASE::REG_R14:
1299 case LEVEL_BASE::REG_R15:
1321 assert(0 &&
"not alias registers! should not reach here!");
1324 uint32_t aliasGroupByteType = ((uint32_t)regGroup << 16) | ((uint32_t)byteInd << 8) | ((uint32_t)type);
1325 return aliasGroupByteType;
1330 case LEVEL_BASE::REG_RAX:
1331 case LEVEL_BASE::REG_RBX:
1332 case LEVEL_BASE::REG_RCX:
1333 case LEVEL_BASE::REG_RDX:
1350 case LEVEL_BASE::REG_RBP:
1354 case LEVEL_BASE::REG_RDI:
1358 case LEVEL_BASE::REG_RSI:
1362 case LEVEL_BASE::REG_RSP:
1366 case LEVEL_BASE::REG_R8:
1370 case LEVEL_BASE::REG_R9:
1374 case LEVEL_BASE::REG_R10:
1378 case LEVEL_BASE::REG_R11:
1382 case LEVEL_BASE::REG_R12:
1386 case LEVEL_BASE::REG_R13:
1390 case LEVEL_BASE::REG_R14:
1394 case LEVEL_BASE::REG_R15:
1404 #ifdef ENABLE_SAMPLING
1406 #define HANDLE_SPECIALREG(LEN, REG_ID) \
1407 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1408 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleSpecialRegisters<LEN>::CheckRegValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1410 #define HANDLE_LARGEREG_APPROX(T, SIMD_TYPE, REG_ID) \
1411 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1412 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)ApproxLargeRegisters<T, SIMD_TYPE>::CheckValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1414 #define HANDLE_ALIAS_REG(T, ALIAS_GRP, ID) \
1415 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1416 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleAliasRegisters<T, ALIAS_GRP>::CheckUpdateGenericAlias, IARG_UINT32, ID, IARG_REG_VALUE, reg, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1418 #define HANDLE_GENERAL(T) \
1419 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1420 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleGeneralRegisters<T, 1>::CheckValues, IARG_REG_VALUE, reg, IARG_UINT32, reg, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1422 #define HANDLE_APPROXREG(T, IS_ALIAS, REG_ID) \
1423 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1424 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)ApproxGeneralRegisters<T, IS_ALIAS>::CheckValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1426 #define HANDLE_10BYTES_APPROX(REG_ID) \
1427 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1428 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)Check10BytesReg, IARG_CONTEXT, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1432 #define HANDLE_SPECIALREG(LEN, REG_ID) \
1433 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleSpecialRegisters<LEN>::CheckRegValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1435 #define HANDLE_LARGEREG_APPROX(T, SIMD_TYPE, REG_ID) \
1436 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)ApproxLargeRegisters<T, SIMD_TYPE>::CheckValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1438 #define HANDLE_ALIAS_REG(T, ALIAS_GRP, ID) \
1439 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleAliasRegisters<T, ALIAS_GRP>::CheckUpdateGenericAlias, IARG_UINT32, ID, IARG_REG_VALUE, reg, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1441 #define HANDLE_GENERAL(T) \
1442 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)HandleGeneralRegisters<T, 1>::CheckValues, IARG_REG_VALUE, reg, IARG_UINT32, reg, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1444 #define HANDLE_APPROXREG(T, IS_ALIAS, REG_ID) \
1445 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)ApproxGeneralRegisters<T, IS_ALIAS>::CheckValues, IARG_REG_CONST_REFERENCE, reg, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1447 #define HANDLE_10BYTES_APPROX(REG_ID) \
1448 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)Check10BytesReg, IARG_CONTEXT, IARG_UINT32, REG_ID, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1459 uint32_t regSize = REG_Size(reg);
1461 uint8_t regId =
static_cast<uint8_t
>(((aliasIDs)&0x00ffffff) >> 16);
1488 if (REG_is_Lower8(reg)) {
1520 if (!REG_valid_for_iarg_reg_value(reg))
1522 uint32_t regSize = REG_Size(reg);
1547 assert(0 &&
"handle large reg with large operand size\n");
1560 assert(0 &&
"handle large reg with large operand size\n");
1573 assert(0 &&
"handle large reg with large operand size\n");
1578 assert(0 &&
"not recoganized register size for floating instruction!\n");
1608 assert(0 &&
"not recoganized register size for integer instruction!\n");
1618 template <
int start,
int end,
int incr,
bool conditional,
bool approx>
1620 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {
1633 prevIP[start] = handle;
1637 uint8_t*
status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + start));
1652 template <
int end,
int incr,
bool conditional,
bool approx>
1653 struct UnrolledLoop<end, end, incr, conditional, approx> {
1654 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {}
1659 template <
int start,
int end,
int incr>
1661 static __attribute__((always_inline))
bool Body(
const function<
bool(
const int)>& func) {
1669 template <
int end,
int incr>
1671 static __attribute__((always_inline))
bool Body(
const function<
void(
const int)>& func) {
1680 template <
class T, u
int32_t AccessLen, u
int32_t bufferOffset,
bool isApprox>
1682 static __attribute__((always_inline))
bool IsWriteRedundant(
void*& addr, THREADID threadId) {
1688 if (AccessLen >= 32) {
1689 if (
sizeof(T) == 4) {
1690 __m256 oldValue = _mm256_load_ps(
reinterpret_cast<const float*
>(&avPair->
value));
1691 __m256 newValue = _mm256_loadu_ps(
reinterpret_cast<const float*
>(avPair->
address));
1693 __m256 result = _mm256_sub_ps(newValue, oldValue);
1695 result = _mm256_div_ps(result, oldValue);
1697 _mm256_store_ps(rates, result);
1699 for (
int i = 0; i < 8; ++i) {
1706 }
else if (
sizeof(T) == 8) {
1707 __m256d oldValue = _mm256_load_pd(
reinterpret_cast<const double*
>(&avPair->
value));
1708 __m256d newValue = _mm256_loadu_pd(
reinterpret_cast<const double*
>(avPair->
address));
1710 __m256d result = _mm256_sub_pd(newValue, oldValue);
1712 result = _mm256_div_pd(result, oldValue);
1715 _mm256_store_pd(rates, result);
1717 for (
int i = 0; i < 4; ++i) {
1724 }
else if (AccessLen == 16) {
1725 if (
sizeof(T) == 4) {
1726 __m128 oldValue = _mm_load_ps(
reinterpret_cast<const float*
>(&avPair->
value));
1727 __m128 newValue = _mm_loadu_ps(
reinterpret_cast<const float*
>(avPair->
address));
1729 __m128 result = _mm_sub_ps(newValue, oldValue);
1731 result = _mm_div_ps(result, oldValue);
1733 _mm_store_ps(rates, result);
1735 for (
int i = 0; i < 4; ++i) {
1742 }
else if (
sizeof(T) == 8) {
1743 __m128d oldValue = _mm_load_pd(
reinterpret_cast<const double*
>(&avPair->
value));
1744 __m128d newValue = _mm_loadu_pd(
reinterpret_cast<const double*
>(avPair->
address));
1746 __m128d result = _mm_sub_pd(newValue, oldValue);
1748 result = _mm_div_pd(result, oldValue);
1751 _mm_storel_pd(&rate[0], result);
1752 _mm_storeh_pd(&rate[1], result);
1760 }
else if (AccessLen == 10) {
1762 memcpy(newValue, addr, AccessLen);
1764 uint64_t* upperOld = (uint64_t*)&(avPair->
value[2]);
1765 uint64_t* upperNew = (uint64_t*)&(newValue[2]);
1767 uint16_t* lowOld = (uint16_t*)&(avPair->
value[0]);
1768 uint16_t* lowNew = (uint16_t*)&(newValue[0]);
1770 return (*lowOld & 0xfff0) == (*lowNew & 0xfff0) && *upperNew == *upperOld;
1772 T newValue = *(
static_cast<T*
>(avPair->
address));
1773 T oldValue = *((T*)(&avPair->
value));
1775 T rate = (newValue - oldValue) / oldValue;
1776 return static_cast<bool>(rate <= delta && rate >= -
delta);
1779 return *((T*)(&avPair->
value)) == *(
static_cast<T*
>(avPair->
address));
1784 static __attribute__((always_inline)) VOID RecordNByteValueBeforeWrite(
void* addr, THREADID threadId) {
1790 if (AccessLen >= 32) {
1791 if (
sizeof(T) == 4) {
1792 __m256 newValue = _mm256_loadu_ps(
reinterpret_cast<const float*
>(addr));
1793 _mm256_store_ps(
reinterpret_cast<float*
>(&avPair->
value), newValue);
1795 }
else if (
sizeof(T) == 8) {
1796 __m256d newValue = _mm256_loadu_pd(
reinterpret_cast<const double*
>(addr));
1797 _mm256_store_pd(
reinterpret_cast<double*
>(&avPair->
value), newValue);
1799 }
else if (AccessLen == 16) {
1800 if (
sizeof(T) == 4) {
1801 __m128 newValue = _mm_loadu_ps(
reinterpret_cast<const float*
>(addr));
1802 _mm_store_ps(
reinterpret_cast<float*
>(&avPair->
value), newValue);
1804 }
else if (
sizeof(T) == 8) {
1805 __m128d newValue = _mm_loadu_pd(
reinterpret_cast<const double*
>(addr));
1806 _mm_store_pd(
reinterpret_cast<double*
>(&avPair->
value), newValue);
1808 }
else if (AccessLen == 10) {
1809 memcpy(&avPair->
value, addr, AccessLen);
1811 *((T*)(&avPair->
value)) = *(
static_cast<T*
>(addr));
1814 static __attribute__((always_inline)) VOID CheckNByteValueAfterWrite(uint32_t opaqueHandle, THREADID threadId) {
1817 bool isRedundantWrite = IsWriteRedundant(addr, threadId);
1821 uint8_t*
status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr));
1824 if (isRedundantWrite) {
1826 if (isAccessWithinPageBoundary) {
1835 UnrolledLoop<0, AccessLen, 1,
false, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
1838 UnrolledLoop<0, AccessLen, 1,
true, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
1848 prevIP[0] = curCtxtHandle;
1851 UnrolledLoop<1, AccessLen, 1,
true, isApprox>::BodyStraddlePage((uint64_t)addr, curCtxtHandle, threadId);
1856 if (isAccessWithinPageBoundary) {
1858 UnrolledLoop<0, AccessLen, 1,
false, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
1862 prevIP[0] = curCtxtHandle;
1865 UnrolledLoop<1, AccessLen, 1,
false, isApprox>::BodyStraddlePage((uint64_t)addr, curCtxtHandle, threadId);
1869 static __attribute__((always_inline)) VOID ApproxCheckAfterWrite(uint32_t opaqueHandle, THREADID threadId) {
1872 bool isRedundantWrite = IsWriteRedundant(addr, threadId);
1876 UINT32
const interv =
sizeof(T);
1877 uint8_t*
status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr));
1880 if (isRedundantWrite) {
1881 for (UINT32 index = 0; index < AccessLen; index += interv) {
1882 status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + index));
1887 prevIP[0] = curCtxtHandle;
1890 for (UINT32 index = 0; index < AccessLen; index += interv) {
1891 status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + index));
1894 prevIP[0] = curCtxtHandle;
1903 memcpy(&(tData->
buffer[bufferOffset].
value), addr, accessLen);
1907 static inline VOID
CheckAfterLargeWrite(UINT32 accessLen, uint32_t bufferOffset, uint32_t opaqueHandle, THREADID threadId) {
1914 if (memcmp(&(tData->
buffer[bufferOffset].
value), addr, accessLen) == 0) {
1916 for (UINT32 index = 0; index < accessLen; index++) {
1917 status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + index));
1922 prevIP[0] = curCtxtHandle;
1926 for (UINT32 index = 0; index < accessLen; index++) {
1927 status = (uint8_t*)get<0>(
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + index));
1930 prevIP[0] = curCtxtHandle;
1935 #ifdef ENABLE_SAMPLING
1937 #define HANDLE_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX) \
1938 INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1939 INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::RecordNByteValueBeforeWrite, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); \
1940 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1941 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::CheckNByteValueAfterWrite, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
1943 #define HANDLE_APPROX_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX) \
1944 INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1945 INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::RecordNByteValueBeforeWrite, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); \
1946 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1947 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::ApproxCheckAfterWrite, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
1949 #define HANDLE_LARGE() \
1950 INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1951 INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordValueBeforeLargeWrite, IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_THREAD_ID, IARG_END); \
1952 INS_InsertIfPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
1953 INS_InsertThenPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)CheckAfterLargeWrite, IARG_MEMORYREAD_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1957 #define HANDLE_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX) \
1958 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::RecordNByteValueBeforeWrite, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); \
1959 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::CheckNByteValueAfterWrite, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
1961 #define HANDLE_APPROX_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX) \
1962 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::RecordNByteValueBeforeWrite, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); \
1963 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (BUFFER_INDEX), (IS_APPROX)>::ApproxCheckAfterWrite, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
1965 #define HANDLE_LARGE() \
1966 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordValueBeforeLargeWrite, IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_THREAD_ID, IARG_END); \
1967 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)CheckAfterLargeWrite, IARG_MEMORYREAD_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
1973 int numWriteOps = 0;
1974 UINT32 memOperands = INS_MemoryOperandCount(ins);
1975 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1976 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1984 template <u
int32_t readBufferSlotIndex>
1986 static __attribute__((always_inline))
void InstrumentReadValueBeforeAndAfterWriting(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
1987 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
1990 unsigned int operSize =
FloatOperandSize(INS_Address(ins), INS_MemoryOperandIndexToOperandIndex(ins, memOp));
1994 assert(0 &&
"memory write floating data with unexptected small size");
2013 assert(0 &&
"handle large mem write with unexpected operand size\n");
2026 assert(0 &&
"handle large mem write with unexpected operand size\n");
2031 assert(0 &&
"unexpected large memory writes\n");
2037 HANDLE_CASE(uint8_t, 1, readBufferSlotIndex,
false);
2040 HANDLE_CASE(uint16_t, 2, readBufferSlotIndex,
false);
2043 HANDLE_CASE(uint32_t, 4, readBufferSlotIndex,
false);
2046 HANDLE_CASE(uint64_t, 8, readBufferSlotIndex,
false);
2060 if (INS_IsFarJump(ins) || INS_IsDirectFarJump(ins) ||
INS_IsMaskedJump(ins))
2062 if (INS_IsRet(ins) || INS_IsIRet(ins))
2064 if (INS_IsCall(ins) || INS_IsSyscall(ins))
2066 if (INS_IsBranch(ins) || INS_IsRDTSC(ins) || INS_IsNop(ins))
2072 if (INS_Mnemonic(ins) ==
"XSAVEC")
2074 if (INS_Mnemonic(ins) ==
"XSAVE")
2076 if (INS_Mnemonic(ins) ==
"XRSTOR")
2082 if (REG_is_seg(reg))
2084 else if (REG_is_pin_gr(reg))
2086 else if (reg == REG_MXCSR)
2088 else if (REG_is_flags(reg))
2094 if (!INS_HasFallThrough(ins))
2098 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
2108 UINT32 memOperands = INS_MemoryOperandCount(ins);
2109 int readBufferSlotIndex = 0;
2110 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
2111 if (!INS_MemoryOperandIsWritten(ins, memOp))
2114 switch (readBufferSlotIndex) {
2140 readBufferSlotIndex++;
2145 UINT32 numOperands = INS_OperandCount(ins);
2147 for (UINT32 oper = 0; oper < numOperands; oper++) {
2148 if (!INS_OperandWritten(ins, oper) || !INS_OperandIsReg(ins, oper))
2151 REG reg = INS_OperandReg(ins, oper);
2166 #ifdef ENABLE_SAMPLING
2168 inline VOID UpdateAndCheck(uint32_t count, uint32_t bytes, THREADID threadId) {
2190 inline VOID
Update(uint32_t count, uint32_t bytes, THREADID threadId) {
2201 for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2202 uint32_t totInsInBbl = BBL_NumIns(bbl);
2203 uint32_t totBytes = 0;
2204 for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
2205 if (!INS_HasFallThrough(ins))
2209 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
2212 if (INS_IsMemoryWrite(ins)) {
2215 UINT32 numOperands = INS_OperandCount(ins);
2217 for (UINT32 Oper = 0; Oper < numOperands; Oper++) {
2218 if (!INS_OperandWritten(ins, Oper) || !INS_OperandIsReg(ins, Oper))
2221 REG curReg = INS_OperandReg(ins, Oper);
2226 totBytes += REG_Size(curReg);
2230 if (BBL_InsTail(bbl) == BBL_InsHead(bbl)) {
2231 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
2233 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
2236 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
2239 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)
Update, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
2248 inline VOID
Update(uint32_t bytes, THREADID threadId) {
2255 for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
2256 uint32_t totBytes = 0;
2257 for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
2258 if (!INS_HasFallThrough(ins))
2262 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
2265 if (INS_IsMemoryWrite(ins)) {
2268 UINT32 numOperands = INS_OperandCount(ins);
2270 for (UINT32 Oper = 0; Oper < numOperands; Oper++) {
2271 if (!INS_OperandWritten(ins, Oper) || !INS_OperandIsReg(ins, Oper))
2274 REG curReg = INS_OperandReg(ins, Oper);
2279 totBytes += REG_Size(curReg);
2282 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)
Update, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_END);
2299 vector<RedundacyData> tmpList;
2300 vector<RedundacyData>::iterator tmpIt;
2302 uint64_t grandTotalRedundantBytes = 0;
2303 fprintf(
gTraceFile,
"*************** Dump Data from Thread %d ****************\n", threadId);
2306 for (dense_hash_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
2310 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
2311 if (dead == 0 || ((*tmpIt).dead) == 0) {
2323 (*tmpIt).frequency += (*it).second;
2324 grandTotalRedundantBytes += (*it).second;
2328 if (tmpIt == tmpList.end()) {
2330 tmpList.push_back(tmp);
2331 grandTotalRedundantBytes += tmp.
frequency;
2335 for (dense_hash_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
2337 tmpList.push_back(tmp);
2338 grandTotalRedundantBytes += tmp.
frequency;
2342 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesWritten);
2345 vector<struct AnalyzedMetric_t>::iterator listIt;
2347 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
2349 fprintf(
gTraceFile,
"\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
2350 if ((*listIt).dead == 0) {
2351 fprintf(
gTraceFile,
"\n Prepopulated with by OS\n");
2355 fprintf(
gTraceFile,
"\n---------------------Redundantly written by---------------------------\n");
2365 vector<RedundacyData> tmpList;
2366 vector<RedundacyData>::iterator tmpIt;
2368 uint64_t grandTotalRedundantBytes = 0;
2369 fprintf(
gTraceFile,
"*************** Dump Data(delta=%.2f%%) from Thread %d ****************\n",
delta * 100, threadId);
2372 for (dense_hash_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].begin(); it !=
ApproxRedMap[threadId].end(); ++it) {
2376 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
2377 if (dead == 0 || ((*tmpIt).dead) == 0) {
2389 (*tmpIt).frequency += (*it).second;
2390 grandTotalRedundantBytes += (*it).second;
2391 grandTotalRedundantIns += 1;
2395 if (tmpIt == tmpList.end()) {
2397 tmpList.push_back(tmp);
2398 grandTotalRedundantBytes += tmp.
frequency;
2402 for (dense_hash_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].begin(); it !=
ApproxRedMap[threadId].end(); ++it) {
2404 tmpList.push_back(tmp);
2405 grandTotalRedundantBytes += tmp.
frequency;
2409 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesWritten);
2412 vector<struct AnalyzedMetric_t>::iterator listIt;
2414 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
2416 fprintf(
gTraceFile,
"\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
2417 if ((*listIt).dead == 0) {
2418 fprintf(
gTraceFile,
"\n Prepopulated with by OS\n");
2422 fprintf(
gTraceFile,
"\n---------------------Redundantly written by---------------------------\n");
2433 fprintf(
gTraceFile,
"\n TODO .. Multi-threading is not well supported.");
2434 THREADID threadid = PIN_ThreadId();
2435 fprintf(
gTraceFile,
"\nUnloading %s", IMG_Name(img).c_str());
2442 RedMap[threadid].clear();
2446 static VOID
ThreadFiniFunc(THREADID threadid,
const CONTEXT* ctxt, INT32 code, VOID* v) {
2459 RedMap[i].set_empty_key(0);
2468 #ifdef MULTI_THREADED
2478 if (PIN_Init(argc, argv))
2498 PIN_AddFiniFunction(
FiniFunc,
nullptr);
#define INTERESTING_INS_ALL
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
hpcrun_metricFlags_t flags
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
bool HaveSameCallerPrefix(ContextHandle_t ctxt1, ContextHandle_t ctxt2)
bool IsSameSourceLine(ContextHandle_t ctxt1, ContextHandle_t ctxt2)
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
static BOOL INS_IsMaskedJump(INS ins)
static BOOL INS_IsIndirectBranchOrCall(INS ins)
static USIZE INS_MemoryWriteSize(INS ins)
PINTOOL_REGISTER PIN_REGISTER
static BOOL REG_is_in_X87(REG reg)
static void CheckRegValues(CONTEXT *ctxt, THREADID threadId)
#define HANDLE_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX)
#define MAX_WRITE_OP_LENGTH
#define HANDLE_10BYTES_APPROX(REG_ID)
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
static bool IsFloatInstruction(ADDRINT ip)
#define MAX_REDUNDANT_CONTEXTS_TO_LOG
static VOID ImageUnload(IMG img, VOID *v)
static RedSpyThreadData * gSingleThreadedTData
#define EIGHT_BYTE_WRITE_ACTION
static void AddToRedTable(uint64_t key, uint16_t value, THREADID threadId) __attribute__((always_inline
static void PrintRedundancyPairs(THREADID threadId)
static bool REG_IsIgnorable(REG reg)
#define HANDLE_APPROXREG(T, IS_ALIAS, REG_ID)
static const uint64_t READ_ACCESS_STATES[]
#define ALIAS_BYTES_INDEX_64
#define MAX_WRITE_OPS_IN_INS
#define MAX_ALIAS_REG_SIZE
#define ONE_BYTE_READ_ACTION
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
static bool IsFloatInstructionOld(ADDRINT ip)
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
#define ALIAS_BYTES_INDEX_32
#define HANDLE_APPROX_CASE(T, ACCESS_LEN, BUFFER_INDEX, IS_APPROX)
#define ALIAS_BYTES_INDEX_8_L
static dense_hash_map< uint64_t, uint64_t > RedMap[THREAD_MAX]
static uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper)
static const uint8_t OVERFLOW_CHECK[]
#define MAKE_CONTEXT_PAIR(a, b)
static ConcurrentShadowMemory< ContextHandle_t > sm
#define HANDLE_SPECIALREG(LEN, REG_ID)
VOID Update(uint32_t bytes, THREADID threadId)
#define DECODE_DEAD(data)
static VOID RecordValueBeforeLargeWrite(void *addr, UINT32 accessLen, uint32_t bufferOffset, THREADID threadId)
#define HANDLE_LARGEREG_APPROX(T, SIMD_TYPE, REG_ID)
struct RedSpyThreadData __attribute__
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static void InstrumentTrace(TRACE trace, void *f)
uint8_t value[MAX_WRITE_OP_LENGTH]
static void Check10BytesReg(CONTEXT *ctxt, REG reg, uint32_t opaqueHandle, THREADID threadId)
static void InitThreadData(RedSpyThreadData *tdata)
static bool INS_IsIgnorable(INS ins)
RedSpyThreadData * ClientGetTLS(const THREADID threadId)
static void AddToApproximateRedTable(uint64_t key, uint16_t value, THREADID threadId) __attribute__((always_inline
static VOID FiniFunc(INT32 code, VOID *v)
#define TWO_BYTE_WRITE_ACTION
static const uint64_t WRITE_ACCESS_STATES[]
static VOID CheckAfterLargeWrite(UINT32 accessLen, uint32_t bufferOffset, uint32_t opaqueHandle, THREADID threadId)
#define FOUR_BYTE_READ_ACTION
#define ALIAS_BYTES_INDEX_8_H
static void PrintApproximationRedundancyPairs(THREADID threadId)
#define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen)
static uint32_t GetAliasIDs(REG reg)
#define HANDLE_ALIAS_REG(T, ALIAS_GRP, ID)
static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v)
static int GetNumWriteOperandsInIns(INS ins, UINT32 &whichOp)
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
static void InstrumentGeneralReg(INS ins, REG reg, uint16_t oper, uint32_t opaqueHandle)
#define DECODE_KILL(data)
static TLS_KEY client_tls_key
#define ALIAS_BYTES_INDEX_16
#define HANDLE_GENERAL(T)
static void InstrumentAliasReg(INS ins, REG reg, uint16_t oper, uint32_t opaqueHandle)
bool RegHasAlias(REG reg)
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
static dense_hash_map< uint64_t, uint64_t > ApproxRedMap[THREAD_MAX]
#define PAGE_OFFSET(addr)
uint8_t value[MAX_WRITE_OP_LENGTH]
static __attribute__((always_inline)) void CheckValues(PIN_REGISTER *regRef
static __attribute__((always_inline)) void CheckValues(PIN_REGISTER *regRef
static __attribute__((always_inline)) void CheckUpdateGenericAlias(uint8_t regId
static __attribute__((always_inline)) void CheckValues(T value
static __attribute__((always_inline)) void CheckRegValues(PIN_REGISTER *regRef
static __attribute__((always_inline)) void CheckSIMDRegValues(PIN_REGISTER *regRef
UINT8 value[MAX_SIMD_LENGTH]
static __attribute__((always_inline)) bool IsWriteRedundant(void *&addr
static __attribute__((always_inline)) VOID CheckNByteValueAfterWrite(uint32_t opaqueHandle
static __attribute__((always_inline)) VOID RecordNByteValueBeforeWrite(void *addr
static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterWriting(INS ins
struct LargeReg simdValue[MAX_SIMD_REGS]
uint32_t simdCtxt[MAX_SIMD_REGS]
uint32_t aliasCtxt[MAX_ALIAS_REGS][MAX_ALIAS_TYPE]
AddrValPair buffer[MAX_WRITE_OPS_IN_INS]
uint32_t regCtxt[REG_LAST]
UINT8 aliasValue[MAX_ALIAS_REGS][MAX_ALIAS_REG_SIZE]
UINT8 regValue[REG_LAST][MAX_REG_LENGTH]
static __attribute__((always_inline)) bool BodyContextCheck(ContextHandle_t *__restrict__ prevIP)
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 BodySamePage(ContextHandle_t *__restrict__ prevIP
static __attribute__((always_inline)) void Body(const function< void(const int)> &func)
static __attribute__((always_inline)) void BodyStraddlePage(uint64_t addr
static void Body(const function< void(const int)> &func)
static __attribute__((always_inline)) void BodySamePage(ContextHandle_t *__restrict__ prevIP
static __attribute__((always_inline)) void Body(const function< void(const int)> &func)