16 #include <unordered_set>
18 #include <unordered_map>
29 #define PAGE_OFFSET_BITS (16LL)
30 #define PAGE_OFFSET(addr) (addr & 0xFFFF)
31 #define PAGE_OFFSET_MASK (0xFFFF)
34 #define PAGE_SIZE (1 << PAGE_OFFSET_BITS)
37 #define PTR_SIZE (sizeof(struct Status*))
38 #define LEVEL_1_PAGE_TABLE_BITS (20)
39 #define LEVEL_1_PAGE_TABLE_ENTRIES (1 << LEVEL_1_PAGE_TABLE_BITS)
40 #define LEVEL_1_PAGE_TABLE_SIZE (LEVEL_1_PAGE_TABLE_ENTRIES * PTR_SIZE)
42 #define LEVEL_2_PAGE_TABLE_BITS (12)
43 #define LEVEL_2_PAGE_TABLE_ENTRIES (1 << LEVEL_2_PAGE_TABLE_BITS)
44 #define LEVEL_2_PAGE_TABLE_SIZE (LEVEL_2_PAGE_TABLE_ENTRIES * PTR_SIZE)
46 #define LEVEL_1_PAGE_TABLE_SLOT(addr) (((addr) >> (LEVEL_2_PAGE_TABLE_BITS + PAGE_OFFSET_BITS)) & 0xfffff)
47 #define LEVEL_2_PAGE_TABLE_SLOT(addr) (((addr) >> (PAGE_OFFSET_BITS)) & 0xFFF)
51 #define READ_ACTION (0)
52 #define WRITE_ACTION (0xff)
54 #define ONE_BYTE_READ_ACTION (0)
55 #define TWO_BYTE_READ_ACTION (0)
56 #define FOUR_BYTE_READ_ACTION (0)
57 #define EIGHT_BYTE_READ_ACTION (0)
59 #define ONE_BYTE_WRITE_ACTION (0xff)
60 #define TWO_BYTE_WRITE_ACTION (0xffff)
61 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
62 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
65 #define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen) (PAGE_OFFSET((accessAddr)) <= (PAGE_OFFSET_MASK - (accessLen)))
68 #define MAX_REDUNDANT_CONTEXTS_TO_LOG (1000)
69 #define THREAD_MAX (1024)
71 #define ENCODE_ADDRESS_AND_ACCESS_LEN(addr, len) ((addr) | (((uint64_t)(len)) << 48))
72 #define DECODE_ADDRESS(addrAndLen) ((addrAndLen) & ((1L << 48) - 1))
73 #define DECODE_ACCESS_LEN(addrAndLen) ((addrAndLen) >> 48)
76 #define MAX_WRITE_OP_LENGTH (512)
77 #define MAX_WRITE_OPS_IN_INS (8)
79 #define WINDOW_ENABLE 1000000
80 #define WINDOW_DISABLE 1000000000
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)))
100 uint64_t bytesWritten;
117 template <
int start,
int end,
int incr>
119 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {
125 template <
int end,
int incr>
127 static __attribute__((always_inline))
void Body(
const function<
void(
const int)>& func) {
132 template <
int start,
int end,
int incr>
134 static __attribute__((always_inline))
bool Body(
const function<
bool(
const int)>& func) {
139 template <
int end,
int incr>
141 static __attribute__((always_inline))
bool Body(
const function<
void(
const int)>& func) {
147 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
159 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
163 snprintf(name,
sizeof(name),
"%s", envPath);
166 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
167 pid_t pid = getpid();
168 sprintf(name + strlen(name),
"%d", pid);
169 cerr <<
"\n Creating log file at:" << name <<
"\n";
174 for (
int i = 0; i < argc; i++) {
186 if (*l1Ptr ==
nullptr) {
187 *l1Ptr = (uint8_t**)mmap(
nullptr,
LEVEL_2_PAGE_TABLE_SIZE, PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
202 #ifdef MULTI_THREADED
205 unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].find(key);
206 if (it ==
RedMap[threadId].end()) {
211 #ifdef MULTI_THREADED
217 template <u
int16_t AccessLen, u
int32_t bufferOffset>
219 static __attribute__((always_inline))
bool IsWriteRedundant(
void*& addr, THREADID threadId) {
225 return *((uint8_t*)(&avPair->
value)) == *(
static_cast<uint8_t*
>(avPair->
address));
227 return *((uint16_t*)(&avPair->
value)) == *(
static_cast<uint16_t*
>(avPair->
address));
229 return *((uint32_t*)(&avPair->
value)) == *(
static_cast<uint32_t*
>(avPair->
address));
231 return *((uint64_t*)(&avPair->
value)) == *(
static_cast<uint64_t*
>(avPair->
address));
233 return memcmp(&avPair->
value, avPair->
address, AccessLen) == 0;
237 static __attribute__((always_inline)) VOID RecordNByteValueBeforeWrite(
void* addr, THREADID threadId) {
262 *((uint8_t*)(&avPair->
value)) = *(
static_cast<uint8_t*
>(addr));
265 *((uint16_t*)(&avPair->
value)) = *(
static_cast<uint16_t*
>(addr));
268 *((uint32_t*)(&avPair->
value)) = *(
static_cast<uint32_t*
>(addr));
271 *((uint64_t*)(&avPair->
value)) = *(
static_cast<uint64_t*
>(addr));
274 memcpy(&avPair->
value, addr, AccessLen);
278 static __attribute__((always_inline)) VOID CheckNByteValueAfterWrite(uint32_t opaqueHandle, THREADID threadId) {
282 bool isRedundantWrite = IsWriteRedundant(addr, threadId);
290 if (isRedundantWrite) {
292 if (isAccessWithinPageBoundary) {
300 prevIP[index] = curCtxtHandle;
308 prevIP[index] = curCtxtHandle;
316 prevIP[0] = curCtxtHandle;
325 prevIP[0] = curCtxtHandle;
331 if (isAccessWithinPageBoundary) {
334 prevIP[index] = curCtxtHandle;
342 prevIP[0] = curCtxtHandle;
370 memcpy(&(tData->
buffer[bufferOffset].
value), addr, accessLen);
374 static inline VOID
CheckAfterLargeWrite(UINT32 accessLen, uint32_t bufferOffset, uint32_t opaqueHandle, THREADID threadId) {
383 if (memcmp(&(tData->
buffer[bufferOffset].
value), addr, accessLen) == 0) {
385 for (UINT32 index = 0; index < accessLen; index++) {
391 prevIP[0] = curCtxtHandle;
395 for (UINT32 index = 0; index < accessLen; index++) {
399 prevIP[0] = curCtxtHandle;
432 #define HANDLE_CASE(NUM, BUFFER_INDEX) \
434 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RedSpyAnalysis<(NUM), (BUFFER_INDEX)>::RecordNByteValueBeforeWrite, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); \
435 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)RedSpyAnalysis<(NUM), (BUFFER_INDEX)>::CheckNByteValueAfterWrite, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_INST_PTR, IARG_END); \
441 UINT32 memOperands = INS_MemoryOperandCount(ins);
442 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
443 if (INS_MemoryOperandIsWritten(ins, memOp)) {
451 template <u
int32_t readBufferSlotIndex>
453 static __attribute__((always_inline))
void InstrumentReadValueBeforeAndAfterWriting(INS ins, UINT32 memOp, uint32_t opaqueHandle) {
454 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
464 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
RecordValueBeforeLargeWrite, IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_THREAD_ID, IARG_END);
470 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)
CheckAfterLargeWrite, IARG_MEMORYWRITE_SIZE, IARG_UINT32, readBufferSlotIndex, IARG_UINT32, opaqueHandle, IARG_THREAD_ID, IARG_END);
477 if (!INS_IsMemoryRead(ins) && !INS_IsMemoryWrite(ins))
480 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
487 if (INS_Mnemonic(ins) ==
"XSAVEC")
489 if (INS_Mnemonic(ins) ==
"XRSTOR")
491 if (INS_Mnemonic(ins) ==
"XSAVE")
532 UINT32 memOperands = INS_MemoryOperandCount(ins);
533 int readBufferSlotIndex = 0;
534 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
535 if (!INS_MemoryOperandIsWritten(ins, memOp))
538 switch (readBufferSlotIndex) {
565 readBufferSlotIndex++;
582 vector<RedundacyData> tmpList;
583 vector<RedundacyData>::iterator tmpIt;
585 uint64_t grandTotalRedundantBytes = 0;
586 fprintf(
gTraceFile,
"*************** Dump Data from Thread %d ****************\n", threadId);
587 for (unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
591 for (tmpIt = tmpList.begin(); tmpIt != tmpList.end(); ++tmpIt) {
593 if (dead == 0 || ((*tmpIt).dead) == 0) {
594 if (dead == 0 && ((*tmpIt).dead) == 0)
601 (*tmpIt).frequency += (*it).second;
602 grandTotalRedundantBytes += (*it).second;
606 if (tmpIt == tmpList.end()) {
608 tmpList.push_back(tmp);
609 grandTotalRedundantBytes += tmp.
frequency;
613 fprintf(
gTraceFile,
"\n Total redundant bytes = %f %%\n", grandTotalRedundantBytes * 100.0 /
ClientGetTLS(threadId)->bytesWritten);
616 vector<struct AnalyzedMetric_t>::iterator listIt;
618 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
620 fprintf(
gTraceFile,
"\n======= (%f) %% ======\n", (*listIt).frequency * 100.0 / grandTotalRedundantBytes);
621 if ((*listIt).dead == 0) {
622 fprintf(
gTraceFile,
"\n Prepopulated with by OS\n");
626 fprintf(
gTraceFile,
"\n---------------------Redundantly written by---------------------------\n");
636 vector<RedundacyData> tmpList;
637 vector<RedundacyData>::iterator tmpIt;
639 for (unordered_map<uint64_t, uint64_t>::iterator it =
RedMap[threadId].begin(); it !=
RedMap[threadId].end(); ++it) {
641 tmpList.push_back(tmp);
645 vector<HPCRunCCT_t*> HPCRunNodes;
647 for (vector<RedundacyData>::iterator listIt = tmpList.begin(); listIt != tmpList.end(); ++listIt) {
650 HPCRunNode->ctxtHandle1 = (*listIt).dead;
651 HPCRunNode->ctxtHandle2 = (*listIt).kill;
652 HPCRunNode->metric = (*listIt).frequency;
654 HPCRunNodes.push_back(HPCRunNode);
665 fprintf(
gTraceFile,
"\n TODO .. Multi-threading is not well supported.");
666 THREADID threadid = PIN_ThreadId();
667 fprintf(
gTraceFile,
"\nUnloading %s", IMG_Name(img).c_str());
676 static VOID
ThreadFiniFunc(THREADID threadid,
const CONTEXT* ctxt, INT32 code, VOID* v) {
699 int main(
int argc,
char* argv[]) {
701 if (PIN_Init(argc, argv))
725 PIN_AddFiniFunction(
FiniFunc,
nullptr);
#define INTERESTING_INS_MEMORY_ACCESS
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 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)
#define MAX_WRITE_OP_LENGTH
static uint8_t ** gL1PageTable[LEVEL_1_PAGE_TABLE_SIZE]
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
#define LEVEL_2_PAGE_TABLE_SIZE
#define MAX_REDUNDANT_CONTEXTS_TO_LOG
static VOID ImageUnload(IMG img, VOID *v)
#define LEVEL_1_PAGE_TABLE_SLOT(addr)
#define EIGHT_BYTE_WRITE_ACTION
static void PrintRedundancyPairs(THREADID threadId)
static const uint64_t READ_ACCESS_STATES[]
#define MAX_WRITE_OPS_IN_INS
#define ONE_BYTE_READ_ACTION
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
#define PAGE_OFFSET(addr)
static const uint8_t OVERFLOW_CHECK[]
static void HPCRunRedundancyPairs(THREADID threadId)
#define MAKE_CONTEXT_PAIR(a, b)
#define DECODE_DEAD(data)
static VOID RecordValueBeforeLargeWrite(void *addr, UINT32 accessLen, uint32_t bufferOffset, THREADID threadId)
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static void InitThreadData(RedSpyThreadData *tdata)
RedSpyThreadData * ClientGetTLS(const THREADID threadId)
__thread long long NUM_INS
static VOID FiniFunc(INT32 code, VOID *v)
#define TWO_BYTE_WRITE_ACTION
static const uint64_t WRITE_ACCESS_STATES[]
__thread bool Sample_flag
static VOID CheckAfterLargeWrite(UINT32 accessLen, uint32_t bufferOffset, uint32_t opaqueHandle, THREADID threadId)
static void AddToRedTable(uint64_t key, uint16_t value, THREADID threadId)
#define FOUR_BYTE_READ_ACTION
static uint8_t * GetOrCreateShadowBaseAddress(uint64_t address)
#define IS_ACCESS_WITHIN_PAGE_BOUNDARY(accessAddr, accessLen)
static VOID ThreadFiniFunc(THREADID threadid, const CONTEXT *ctxt, INT32 code, VOID *v)
#define LEVEL_1_PAGE_TABLE_SIZE
static int GetNumWriteOperandsInIns(INS ins, UINT32 &whichOp)
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
#define DECODE_KILL(data)
static TLS_KEY client_tls_key
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
#define HANDLE_CASE(NUM, BUFFER_INDEX)
static unordered_map< uint64_t, uint64_t > RedMap[THREAD_MAX]
#define LEVEL_2_PAGE_TABLE_SLOT(addr)
uint8_t value[MAX_WRITE_OP_LENGTH]
uint8_t value[MAX_WRITE_OP_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
AddrValPair buffer[MAX_WRITE_OPS_IN_INS]
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 bool Body(const function< bool(const int)> &func)
static __attribute__((always_inline)) void Body(const function< void(const int)> &func)
static void Body(const function< void(const int)> &func)
static __attribute__((always_inline)) void Body(const function< void(const int)> &func)