18 #include <unordered_set>
20 #include <unordered_map>
27 #include <xmmintrin.h>
28 #include <immintrin.h>
31 #include "xed-interface.h"
32 #include "xed-common-hdrs.h"
35 #include <google/sparse_hash_map>
36 #include <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)
76 #ifdef ENABLE_SAMPLING
78 #define WINDOW_ENABLE 1000000
79 #define WINDOW_DISABLE 100000000
80 #define WINDOW_CLEAN 10
83 #define DECODE_DEAD(data) static_cast<ContextHandle_t>(((data)&0xffffffffffffffff) >> 32)
84 #define DECODE_KILL(data) (static_cast<ContextHandle_t>((data)&0x00000000ffffffff))
87 #define MAKE_CONTEXT_PAIR(a, b) (((uint64_t)(a) << 32) | ((uint64_t)(b)))
148 #ifdef MULTI_THREADED
158 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
169 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
173 snprintf(name,
sizeof(name),
"%s", envPath);
176 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
177 pid_t pid = getpid();
178 sprintf(name + strlen(name),
"%d", pid);
179 cerr <<
"\n Creating log file at:" << name <<
"\n";
184 for (
int i = 0; i < argc; i++) {
192 xed_state_init(&
LoadSpyGlobals.xedState, XED_MACHINE_MODE_LONG_64, (xed_address_width_enum_t)0, XED_ADDRESS_WIDTH_64b);
205 #ifdef MULTI_THREADED
208 unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].find(key);
209 if (it ==
RedMap[threadId].end()) {
214 #ifdef MULTI_THREADED
221 #ifdef MULTI_THREADED
224 unordered_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].find(key);
230 #ifdef MULTI_THREADED
236 #ifdef ENABLE_SAMPLING
238 static ADDRINT IfEnableSample(THREADID threadId) {
247 xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
249 case XED_ICLASS_FLDENV:
250 case XED_ICLASS_FNSTENV:
251 case XED_ICLASS_FNSAVE:
252 case XED_ICLASS_FLDCW:
253 case XED_ICLASS_FNSTCW:
254 case XED_ICLASS_FXRSTOR:
255 case XED_ICLASS_FXRSTOR64:
256 case XED_ICLASS_FXSAVE:
257 case XED_ICLASS_FXSAVE64:
265 xed_decoded_inst_t xedd;
268 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
269 xed_category_enum_t cat = xed_decoded_inst_get_category(&xedd);
271 case XED_CATEGORY_AES:
272 case XED_CATEGORY_CONVERT:
273 case XED_CATEGORY_PCLMULQDQ:
274 case XED_CATEGORY_SSE:
275 case XED_CATEGORY_AVX2:
276 case XED_CATEGORY_AVX:
277 case XED_CATEGORY_MMX:
278 case XED_CATEGORY_DATAXFER: {
281 const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
282 int noperands = xed_inst_noperands(xi);
284 for (
int i = 0; i < noperands; i++) {
285 const xed_operand_t* op = xed_inst_operand(xi, i);
286 xed_operand_enum_t op_name = xed_operand_name(op);
287 if (XED_OPERAND_MEM0 == op_name) {
292 if (memOpIdx == -1) {
297 xed_operand_element_type_enum_t eType = xed_decoded_inst_operand_element_type(&xedd, memOpIdx);
299 case XED_OPERAND_ELEMENT_TYPE_FLOAT16:
300 case XED_OPERAND_ELEMENT_TYPE_SINGLE:
301 case XED_OPERAND_ELEMENT_TYPE_DOUBLE:
302 case XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE:
303 case XED_OPERAND_ELEMENT_TYPE_LONGBCD:
309 case XED_CATEGORY_X87_ALU:
310 case XED_CATEGORY_FCMOV:
315 case XED_CATEGORY_XSAVE:
316 case XED_CATEGORY_AVX2GATHER:
317 case XED_CATEGORY_STRINGOP:
322 assert(0 &&
"failed to disassemble instruction");
329 xed_decoded_inst_t xedd;
332 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
333 xed_iclass_enum_t iclassType = xed_decoded_inst_get_iclass(&xedd);
334 if (iclassType >= XED_ICLASS_F2XM1 && iclassType <= XED_ICLASS_FYL2XP1) {
337 if (iclassType >= XED_ICLASS_VBROADCASTSD && iclassType <= XED_ICLASS_VDPPS) {
340 if (iclassType >= XED_ICLASS_VRCPPS && iclassType <= XED_ICLASS_VSQRTSS) {
343 if (iclassType >= XED_ICLASS_VSUBPD && iclassType <= XED_ICLASS_VXORPS) {
346 switch (iclassType) {
347 case XED_ICLASS_ADDPD:
348 case XED_ICLASS_ADDPS:
349 case XED_ICLASS_ADDSD:
350 case XED_ICLASS_ADDSS:
351 case XED_ICLASS_ADDSUBPD:
352 case XED_ICLASS_ADDSUBPS:
353 case XED_ICLASS_ANDNPD:
354 case XED_ICLASS_ANDNPS:
355 case XED_ICLASS_ANDPD:
356 case XED_ICLASS_ANDPS:
357 case XED_ICLASS_BLENDPD:
358 case XED_ICLASS_BLENDPS:
359 case XED_ICLASS_BLENDVPD:
360 case XED_ICLASS_BLENDVPS:
361 case XED_ICLASS_CMPPD:
362 case XED_ICLASS_CMPPS:
363 case XED_ICLASS_CMPSD:
364 case XED_ICLASS_CMPSD_XMM:
365 case XED_ICLASS_COMISD:
366 case XED_ICLASS_COMISS:
367 case XED_ICLASS_CVTDQ2PD:
368 case XED_ICLASS_CVTDQ2PS:
369 case XED_ICLASS_CVTPD2PS:
370 case XED_ICLASS_CVTPI2PD:
371 case XED_ICLASS_CVTPI2PS:
372 case XED_ICLASS_CVTPS2PD:
373 case XED_ICLASS_CVTSD2SS:
374 case XED_ICLASS_CVTSI2SD:
375 case XED_ICLASS_CVTSI2SS:
376 case XED_ICLASS_CVTSS2SD:
377 case XED_ICLASS_DIVPD:
378 case XED_ICLASS_DIVPS:
379 case XED_ICLASS_DIVSD:
380 case XED_ICLASS_DIVSS:
381 case XED_ICLASS_DPPD:
382 case XED_ICLASS_DPPS:
383 case XED_ICLASS_HADDPD:
384 case XED_ICLASS_HADDPS:
385 case XED_ICLASS_HSUBPD:
386 case XED_ICLASS_HSUBPS:
387 case XED_ICLASS_MAXPD:
388 case XED_ICLASS_MAXPS:
389 case XED_ICLASS_MAXSD:
390 case XED_ICLASS_MAXSS:
391 case XED_ICLASS_MINPD:
392 case XED_ICLASS_MINPS:
393 case XED_ICLASS_MINSD:
394 case XED_ICLASS_MINSS:
395 case XED_ICLASS_MOVAPD:
396 case XED_ICLASS_MOVAPS:
397 case XED_ICLASS_MOVD:
398 case XED_ICLASS_MOVHLPS:
399 case XED_ICLASS_MOVHPD:
400 case XED_ICLASS_MOVHPS:
401 case XED_ICLASS_MOVLHPS:
402 case XED_ICLASS_MOVLPD:
403 case XED_ICLASS_MOVLPS:
404 case XED_ICLASS_MOVMSKPD:
405 case XED_ICLASS_MOVMSKPS:
406 case XED_ICLASS_MOVNTPD:
407 case XED_ICLASS_MOVNTPS:
408 case XED_ICLASS_MOVNTSD:
409 case XED_ICLASS_MOVNTSS:
410 case XED_ICLASS_MOVSD:
411 case XED_ICLASS_MOVSD_XMM:
412 case XED_ICLASS_MOVSS:
413 case XED_ICLASS_MULPD:
414 case XED_ICLASS_MULPS:
415 case XED_ICLASS_MULSD:
416 case XED_ICLASS_MULSS:
417 case XED_ICLASS_ORPD:
418 case XED_ICLASS_ORPS:
419 case XED_ICLASS_ROUNDPD:
420 case XED_ICLASS_ROUNDPS:
421 case XED_ICLASS_ROUNDSD:
422 case XED_ICLASS_ROUNDSS:
423 case XED_ICLASS_SHUFPD:
424 case XED_ICLASS_SHUFPS:
425 case XED_ICLASS_SQRTPD:
426 case XED_ICLASS_SQRTPS:
427 case XED_ICLASS_SQRTSD:
428 case XED_ICLASS_SQRTSS:
429 case XED_ICLASS_SUBPD:
430 case XED_ICLASS_SUBPS:
431 case XED_ICLASS_SUBSD:
432 case XED_ICLASS_SUBSS:
433 case XED_ICLASS_VADDPD:
434 case XED_ICLASS_VADDPS:
435 case XED_ICLASS_VADDSD:
436 case XED_ICLASS_VADDSS:
437 case XED_ICLASS_VADDSUBPD:
438 case XED_ICLASS_VADDSUBPS:
439 case XED_ICLASS_VANDNPD:
440 case XED_ICLASS_VANDNPS:
441 case XED_ICLASS_VANDPD:
442 case XED_ICLASS_VANDPS:
443 case XED_ICLASS_VBLENDPD:
444 case XED_ICLASS_VBLENDPS:
445 case XED_ICLASS_VBLENDVPD:
446 case XED_ICLASS_VBLENDVPS:
447 case XED_ICLASS_VBROADCASTSD:
448 case XED_ICLASS_VBROADCASTSS:
449 case XED_ICLASS_VCMPPD:
450 case XED_ICLASS_VCMPPS:
451 case XED_ICLASS_VCMPSD:
452 case XED_ICLASS_VCMPSS:
453 case XED_ICLASS_VCOMISD:
454 case XED_ICLASS_VCOMISS:
455 case XED_ICLASS_VCVTDQ2PD:
456 case XED_ICLASS_VCVTDQ2PS:
457 case XED_ICLASS_VCVTPD2PS:
458 case XED_ICLASS_VCVTPH2PS:
459 case XED_ICLASS_VCVTPS2PD:
460 case XED_ICLASS_VCVTSD2SS:
461 case XED_ICLASS_VCVTSI2SD:
462 case XED_ICLASS_VCVTSI2SS:
463 case XED_ICLASS_VCVTSS2SD:
464 case XED_ICLASS_VDIVPD:
465 case XED_ICLASS_VDIVPS:
466 case XED_ICLASS_VDIVSD:
467 case XED_ICLASS_VDIVSS:
468 case XED_ICLASS_VDPPD:
469 case XED_ICLASS_VDPPS:
470 case XED_ICLASS_VMASKMOVPD:
471 case XED_ICLASS_VMASKMOVPS:
472 case XED_ICLASS_VMAXPD:
473 case XED_ICLASS_VMAXPS:
474 case XED_ICLASS_VMAXSD:
475 case XED_ICLASS_VMAXSS:
476 case XED_ICLASS_VMINPD:
477 case XED_ICLASS_VMINPS:
478 case XED_ICLASS_VMINSD:
479 case XED_ICLASS_VMINSS:
480 case XED_ICLASS_VMOVAPD:
481 case XED_ICLASS_VMOVAPS:
482 case XED_ICLASS_VMOVD:
483 case XED_ICLASS_VMOVHLPS:
484 case XED_ICLASS_VMOVHPD:
485 case XED_ICLASS_VMOVHPS:
486 case XED_ICLASS_VMOVLHPS:
487 case XED_ICLASS_VMOVLPD:
488 case XED_ICLASS_VMOVLPS:
489 case XED_ICLASS_VMOVMSKPD:
490 case XED_ICLASS_VMOVMSKPS:
491 case XED_ICLASS_VMOVNTPD:
492 case XED_ICLASS_VMOVNTPS:
493 case XED_ICLASS_VMOVSD:
494 case XED_ICLASS_VMOVSS:
495 case XED_ICLASS_VMOVUPD:
496 case XED_ICLASS_VMOVUPS:
497 case XED_ICLASS_VMULPD:
498 case XED_ICLASS_VMULPS:
499 case XED_ICLASS_VMULSD:
500 case XED_ICLASS_VMULSS:
501 case XED_ICLASS_VORPD:
502 case XED_ICLASS_VORPS:
503 case XED_ICLASS_VPABSD:
504 case XED_ICLASS_VPADDD:
505 case XED_ICLASS_VPCOMD:
506 case XED_ICLASS_VPCOMUD:
507 case XED_ICLASS_VPERMILPD:
508 case XED_ICLASS_VPERMILPS:
509 case XED_ICLASS_VPERMPD:
510 case XED_ICLASS_VPERMPS:
511 case XED_ICLASS_VPGATHERDD:
512 case XED_ICLASS_VPGATHERQD:
513 case XED_ICLASS_VPHADDBD:
514 case XED_ICLASS_VPHADDD:
515 case XED_ICLASS_VPHADDUBD:
516 case XED_ICLASS_VPHADDUWD:
517 case XED_ICLASS_VPHADDWD:
518 case XED_ICLASS_VPHSUBD:
519 case XED_ICLASS_VPHSUBWD:
520 case XED_ICLASS_VPINSRD:
521 case XED_ICLASS_VPMACSDD:
522 case XED_ICLASS_VPMACSSDD:
523 case XED_ICLASS_VPMASKMOVD:
524 case XED_ICLASS_VPMAXSD:
525 case XED_ICLASS_VPMAXUD:
526 case XED_ICLASS_VPMINSD:
527 case XED_ICLASS_VPMINUD:
528 case XED_ICLASS_VPROTD:
529 case XED_ICLASS_VPSUBD:
530 case XED_ICLASS_XORPD:
531 case XED_ICLASS_XORPS:
538 assert(0 &&
"failed to disassemble instruction");
559 xed_decoded_inst_t xedd;
562 if (XED_ERROR_NONE == xed_decode(&xedd, (
const xed_uint8_t*)(
ip), 15)) {
563 xed_operand_element_type_enum_t TypeOperand = xed_decoded_inst_operand_element_type(&xedd, oper);
564 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_SINGLE || TypeOperand == XED_OPERAND_ELEMENT_TYPE_FLOAT16)
566 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_DOUBLE) {
569 if (TypeOperand == XED_OPERAND_ELEMENT_TYPE_LONGDOUBLE) {
572 assert(0 &&
"float instruction with unknown operand\n");
575 assert(0 &&
"failed to disassemble instruction\n");
584 template <
int start,
int end,
int incr,
bool conditional,
bool approx>
586 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {
599 prevIP[start] = handle;
603 tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]>& t =
sm.GetOrCreateShadowBaseAddress((uint64_t)addr + start);
619 template <
int end,
int incr,
bool conditional,
bool approx>
621 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {}
626 template <
int start,
int end,
int incr>
628 static __attribute__((always_inline))
bool Body(
const function<
bool(
const int)>& func) {
636 template <
int end,
int incr>
638 static __attribute__((always_inline))
bool Body(
const function<
void(
const int)>& func) {
647 template <
class T, u
int32_t AccessLen,
bool isApprox>
649 static __attribute__((always_inline))
bool IsReadRedundant(
void* addr, uint8_t* prev) {
651 if (AccessLen >= 32) {
652 if (
sizeof(T) == 4) {
653 __m256 oldValue = _mm256_loadu_ps(
reinterpret_cast<const float*
>(prev));
654 __m256 newValue = _mm256_loadu_ps(
reinterpret_cast<const float*
>(addr));
656 __m256 result = _mm256_sub_ps(newValue, oldValue);
658 result = _mm256_div_ps(result, oldValue);
660 _mm256_store_ps(rates, result);
662 _mm256_storeu_ps(
reinterpret_cast<float*
>(prev), newValue);
664 for (
int i = 0; i < 8; ++i) {
671 }
else if (
sizeof(T) == 8) {
672 __m256d oldValue = _mm256_loadu_pd(
reinterpret_cast<const double*
>(prev));
673 __m256d newValue = _mm256_loadu_pd(
reinterpret_cast<const double*
>(addr));
675 __m256d result = _mm256_sub_pd(newValue, oldValue);
677 result = _mm256_div_pd(result, oldValue);
680 _mm256_store_pd(rates, result);
682 _mm256_storeu_pd(
reinterpret_cast<double*
>(prev), newValue);
684 for (
int i = 0; i < 4; ++i) {
691 }
else if (AccessLen == 16) {
692 if (
sizeof(T) == 4) {
693 __m128 oldValue = _mm_loadu_ps(
reinterpret_cast<const float*
>(prev));
694 __m128 newValue = _mm_loadu_ps(
reinterpret_cast<const float*
>(addr));
696 __m128 result = _mm_sub_ps(newValue, oldValue);
698 result = _mm_div_ps(result, oldValue);
700 _mm_store_ps(rates, result);
702 _mm_storeu_ps(
reinterpret_cast<float*
>(prev), newValue);
704 for (
int i = 0; i < 4; ++i) {
711 }
else if (
sizeof(T) == 8) {
712 __m128d oldValue = _mm_loadu_pd(
reinterpret_cast<const double*
>(prev));
713 __m128d newValue = _mm_loadu_pd(
reinterpret_cast<const double*
>(addr));
715 __m128d result = _mm_sub_pd(newValue, oldValue);
717 result = _mm_div_pd(result, oldValue);
720 _mm_storel_pd(&rate[0], result);
721 _mm_storeh_pd(&rate[1], result);
723 _mm_storeu_pd(
reinterpret_cast<double*
>(prev), newValue);
731 }
else if (AccessLen == 10) {
733 memcpy(newValue, addr, AccessLen);
735 uint64_t* upperOld = (uint64_t*)&(prev[2]);
736 uint64_t* upperNew = (uint64_t*)&(newValue[2]);
738 uint16_t* lowOld = (uint16_t*)&(prev[0]);
739 uint16_t* lowNew = (uint16_t*)&(newValue[0]);
741 memcpy(prev, addr, AccessLen);
743 return (*lowOld & 0xfff0) == (*lowNew & 0xfff0) && *upperNew == *upperOld;
745 T newValue = *(
static_cast<T*
>(addr));
746 T oldValue = *((T*)(prev));
748 *((T*)(prev)) = *(
static_cast<T*
>(addr));
750 T rate = (newValue - oldValue) / oldValue;
751 return static_cast<bool>(rate <= delta && rate >= -
delta);
754 bool isRed = (*((T*)(prev)) == *(
static_cast<T*
>(addr)));
755 *((T*)(prev)) = *(
static_cast<T*
>(addr));
761 static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(
void* addr, uint32_t opaqueHandle, THREADID threadId) {
765 tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]>& t =
sm.GetOrCreateShadowBaseAddress((uint64_t)addr);
769 bool isRedundantRead = IsReadRedundant(addr, prevValue);
772 if (isRedundantRead) {
774 if (isAccessWithinPageBoundary) {
783 UnrolledLoop<0, AccessLen, 1,
false, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
786 UnrolledLoop<0, AccessLen, 1,
true, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
796 prevIP[0] = curCtxtHandle;
799 UnrolledLoop<1, AccessLen, 1,
true, isApprox>::BodyStraddlePage((uint64_t)addr, curCtxtHandle, threadId);
804 if (isAccessWithinPageBoundary) {
806 UnrolledLoop<0, AccessLen, 1,
false, isApprox>::BodySamePage(prevIP, curCtxtHandle, threadId);
810 prevIP[0] = curCtxtHandle;
813 UnrolledLoop<1, AccessLen, 1,
false, isApprox>::BodyStraddlePage((uint64_t)addr, curCtxtHandle, threadId);
820 static inline VOID
CheckAfterLargeRead(
void* addr, UINT32 accessLen, uint32_t opaqueHandle, THREADID threadId) {
823 tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]>& t =
sm.GetOrCreateShadowBaseAddress((uint64_t)addr);
825 uint8_t* prevValue = &(get<0>(t)[
PAGE_OFFSET((uint64_t)addr)]);
828 tuple<uint8_t[SHADOW_PAGE_SIZE], ContextHandle_t[SHADOW_PAGE_SIZE]>& tt =
sm.GetOrCreateShadowBaseAddress((uint64_t)addr);
829 if (memcmp(prevValue, addr, accessLen) == 0) {
831 for (UINT32 index = 0; index < accessLen; index++) {
835 prevIP[index] = curCtxtHandle;
839 for (UINT32 index = 0; index < accessLen; index++) {
841 prevIP[index] = curCtxtHandle;
845 memcpy(prevValue, addr, accessLen);
848 #ifdef ENABLE_SAMPLING
850 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
851 INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
852 INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<T, (ACCESS_LEN), (IS_APPROX)>::CheckNByteValueAfterRead, IARG_MEMORYOP_EA, memOp, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END)
854 #define HANDLE_LARGE() \
855 INS_InsertIfPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)IfEnableSample, IARG_THREAD_ID, IARG_END); \
856 INS_InsertThenPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
860 #define HANDLE_CASE(T, ACCESS_LEN, IS_APPROX) \
861 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<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_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)CheckAfterLargeRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END)
871 UINT32 memOperands = INS_MemoryOperandCount(ins);
872 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
873 if (INS_MemoryOperandIsRead(ins, memOp)) {
883 static __attribute__((always_inline))
void InstrumentReadValueBeforeAndAfterLoading(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
884 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
887 unsigned int operSize =
FloatOperandSize(INS_Address(ins), INS_MemoryOperandIndexToOperandIndex(ins, memOp));
891 assert(0 &&
"memory read floating data with unexptected small size");
910 assert(0 &&
"handle large mem read with unexpected operand size\n");
923 assert(0 &&
"handle large mem read with unexpected operand size\n");
928 assert(0 &&
"unexpected large memory read\n");
957 if (INS_IsFarJump(ins) || INS_IsDirectFarJump(ins) ||
INS_IsMaskedJump(ins))
959 if (INS_IsRet(ins) || INS_IsIRet(ins))
961 if (INS_IsCall(ins) || INS_IsSyscall(ins))
963 if (INS_IsBranch(ins) || INS_IsRDTSC(ins) || INS_IsNop(ins))
965 if (INS_IsPrefetch(ins))
971 if (INS_Mnemonic(ins) ==
"XSAVEC")
973 if (INS_Mnemonic(ins) ==
"XSAVE")
975 if (INS_Mnemonic(ins) ==
"XRSTOR")
981 if (!INS_HasFallThrough(ins))
985 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
993 LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, whichOp, opaqueHandle);
995 UINT32 memOperands = INS_MemoryOperandCount(ins);
996 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
997 if (!INS_MemoryOperandIsRead(ins, memOp))
999 LoadSpyInstrument::InstrumentReadValueBeforeAndAfterLoading(ins, memOp, opaqueHandle);
1006 #ifdef ENABLE_SAMPLING
1008 inline VOID UpdateAndCheck(uint32_t count, uint32_t bytes, THREADID threadId) {
1029 inline VOID
Update(uint32_t count, uint32_t bytes, THREADID threadId) {
1040 for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1041 uint32_t totInsInBbl = BBL_NumIns(bbl);
1042 uint32_t totBytes = 0;
1043 for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1044 if (!INS_HasFallThrough(ins))
1048 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1051 if (INS_IsMemoryRead(ins)) {
1056 if (BBL_InsTail(bbl) == BBL_InsHead(bbl)) {
1057 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1059 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1062 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)UpdateAndCheck, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1065 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)
Update, IARG_UINT32, totInsInBbl, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_END);
1074 inline VOID
Update(uint32_t bytes, THREADID threadId) {
1081 for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
1082 uint32_t totBytes = 0;
1083 for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
1084 if (!INS_HasFallThrough(ins))
1088 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
1091 if (INS_IsMemoryRead(ins)) {
1095 BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)
Update, IARG_UINT32, totBytes, IARG_THREAD_ID, IARG_END);
1112 vector<RedundacyData> tmpList;
1113 vector<RedundacyData>::iterator tmpIt;
1115 uint64_t grandTotalRedundantBytes = 0;
1116 fprintf(
gTraceFile,
"*************** Dump Data from Thread %d ****************\n", threadId);
1119 for (unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
1123 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
1124 if (dead == 0 || ((*tmpIt).dead) == 0) {
1136 (*tmpIt).frequency += (*it).second;
1137 grandTotalRedundantBytes += (*it).second;
1141 if (tmpIt == tmpList.end()) {
1143 tmpList.push_back(tmp);
1144 grandTotalRedundantBytes += tmp.
frequency;
1148 for (unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
1150 tmpList.push_back(tmp);
1151 grandTotalRedundantBytes += tmp.
frequency;
1157 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesLoad);
1161 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1163 fprintf(
gTraceFile,
"\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
1164 if ((*listIt).dead == 0) {
1165 fprintf(
gTraceFile,
"\n Prepopulated with by OS\n");
1169 fprintf(
gTraceFile,
"\n---------------------Redundant load with---------------------------\n");
1179 vector<RedundacyData> tmpList;
1180 vector<RedundacyData>::iterator tmpIt;
1182 uint64_t grandTotalRedundantBytes = 0;
1183 fprintf(
gTraceFile,
"*************** Dump Data(delta=%.2f%%) from Thread %d ****************\n",
delta * 100, threadId);
1186 for (unordered_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].begin(); it !=
ApproxRedMap[threadId].end(); ++it) {
1190 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
1191 if (dead == 0 || ((*tmpIt).dead) == 0) {
1203 (*tmpIt).frequency += (*it).second;
1204 grandTotalRedundantBytes += (*it).second;
1205 grandTotalRedundantIns += 1;
1209 if (tmpIt == tmpList.end()) {
1211 tmpList.push_back(tmp);
1212 grandTotalRedundantBytes += tmp.
frequency;
1216 for (unordered_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].begin(); it !=
ApproxRedMap[threadId].end(); ++it) {
1218 tmpList.push_back(tmp);
1219 grandTotalRedundantBytes += tmp.
frequency;
1225 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesLoad);
1229 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1231 fprintf(
gTraceFile,
"\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
1232 if ((*listIt).dead == 0) {
1233 fprintf(
gTraceFile,
"\n Prepopulated with by OS\n");
1237 fprintf(
gTraceFile,
"\n---------------------Redundant load with---------------------------\n");
1247 vector<RedundacyData> tmpList;
1248 vector<RedundacyData>::iterator tmpIt;
1250 for (unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
1252 tmpList.push_back(tmp);
1256 vector<HPCRunCCT_t*> HPCRunNodes;
1258 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1261 HPCRunNode->ctxtHandle1 = (*listIt).dead;
1262 HPCRunNode->ctxtHandle2 = (*listIt).kill;
1263 HPCRunNode->metric = (*listIt).frequency;
1265 HPCRunNodes.push_back(HPCRunNode);
1275 vector<RedundacyData> tmpList;
1276 vector<RedundacyData>::iterator tmpIt;
1278 for (unordered_map<uint64_t, uint64_t>::iterator it =
ApproxRedMap[threadId].begin(); it !=
ApproxRedMap[threadId].end(); ++it) {
1280 tmpList.push_back(tmp);
1284 vector<HPCRunCCT_t*> HPCRunNodes;
1286 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
1289 HPCRunNode->ctxtHandle1 = (*listIt).dead;
1290 HPCRunNode->ctxtHandle2 = (*listIt).kill;
1291 HPCRunNode->metric = (*listIt).frequency;
1293 HPCRunNodes.push_back(HPCRunNode);
1304 fprintf(
gTraceFile,
"\n TODO .. Multi-threading is not well supported.");
1305 THREADID threadid = PIN_ThreadId();
1306 fprintf(
gTraceFile,
"\nUnloading %s", IMG_Name(img).c_str());
1315 RedMap[threadid].clear();
1319 static VOID
ThreadFiniFunc(THREADID threadid,
const CONTEXT* ctxt, INT32 code, VOID* v) {
1330 uint64_t redReadTmp = 0;
1331 uint64_t approxRedReadTmp = 0;
1333 unordered_map<uint64_t, uint64_t>::iterator it;
1334 if (!
RedMap[i].empty()) {
1335 for (it =
RedMap[i].begin(); it !=
RedMap[i].end(); ++it) {
1336 redReadTmp += (*it).second;
1341 approxRedReadTmp += (*it).second;
1369 #ifdef MULTI_THREADED
1386 if (PIN_Init(argc, argv))
1411 PIN_AddFiniFunction(
FiniFunc,
nullptr);
#define INTERESTING_INS_ALL
uint8_t ** gL1PageTable[LEVEL_1_PAGE_TABLE_SIZE]
uint8_t * GetOrCreateShadowBaseAddress(void *address)
uint64_t computeMetricVal(void *metric)
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
uint64_t grandTotBytesRedLoad
#define MAX_REDUNDANT_CONTEXTS_TO_LOG
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 AddToRedTable(uint64_t key, uint16_t value, THREADID threadId) __attribute__((always_inline
static void PrintRedundancyPairs(THREADID threadId)
static const uint64_t READ_ACCESS_STATES[]
#define ONE_BYTE_READ_ACTION
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
int redload_approx_metric_id
static bool IsFloatInstructionOld(ADDRINT ip)
#define EIGHT_BYTE_READ_ACTION
static unordered_map< uint64_t, uint64_t > ApproxRedMap[THREAD_MAX]
#define TWO_BYTE_READ_ACTION
static void HPCRunApproxRedundancyPairs(THREADID threadId)
static uint16_t FloatOperandSize(ADDRINT ip, uint32_t oper)
static const uint8_t OVERFLOW_CHECK[]
static void HPCRunRedundancyPairs(THREADID threadId)
#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)
static void AddToApproximateRedTable(uint64_t key, uint16_t value, THREADID threadId) __attribute__((always_inline
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)
#define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen)
uint64_t grandTotBytesApproxRedLoad
static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v)
static bool IsOkToApproximate(xed_decoded_inst_t &xedd)
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
struct @12 LoadSpyGlobals
#define DECODE_KILL(data)
static TLS_KEY client_tls_key
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
ConcurrentShadowMemory< uint8_t, ContextHandle_t > sm
static unordered_map< uint64_t, uint64_t > RedMap[THREAD_MAX]
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
int hpcrun_create_metric(const char *name)
int newCCT_hpcrun_build_cct(std::vector< HPCRunCCT_t * > &OldNodes, THREADID threadid)
struct HPCRunCCT_t { ContextHandle_t ctxtHandle1 HPCRunCCT_t
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)
int init_hpcrun_format(int argc, char *argv[], void(*mergeFunc)(void *des, void *src)=nullptr, uint64_t(*computeMetricVal)(void *metric)=nullptr, bool skip=false)
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
int newCCT_hpcrun_selection_write(THREADID threadid)
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]
#define LEVEL_2_PAGE_TABLE_SIZE
#define LEVEL_1_PAGE_TABLE_SLOT(addr)
#define PAGE_OFFSET(addr)
#define LEVEL_1_PAGE_TABLE_SIZE
#define LEVEL_2_PAGE_TABLE_SLOT(addr)
static __attribute__((always_inline)) void InstrumentReadValueBeforeAndAfterLoading(INS ins
static __attribute__((always_inline)) bool IsReadRedundant(void *addr
static __attribute__((always_inline)) VOID CheckNByteValueAfterRead(void *addr
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)