21 #include <unordered_set>
23 #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(void*))
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)
52 #define MAX_FOOTPRINT_CONTEXTS_TO_LOG (1000)
69 #define THREAD_MAX (1024)
73 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
81 __thread
struct timeval
tv2;
82 __thread
struct timeval
tv3;
88 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
92 snprintf(name,
sizeof(name),
"%s", envPath);
95 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
97 sprintf(name + strlen(name),
"%d", pid);
98 cerr <<
"\n Creating log file at:" << name <<
"\n";
103 for (
int i = 0; i < argc; i++) {
115 if (*l1Ptr ==
nullptr) {
117 shadowPage = (*l1Ptr)[
LEVEL_2_PAGE_TABLE_SLOT(
address)] = (uint8_t*)mmap(
nullptr,
PAGE_SIZE * (
sizeof(
bool) +
sizeof(uint64_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
119 shadowPage = (*l1Ptr)[
LEVEL_2_PAGE_TABLE_SLOT(
address)] = (uint8_t*)mmap(
nullptr,
PAGE_SIZE * (
sizeof(
bool) +
sizeof(uint64_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
125 uint32_t lineNo1, lineNo2;
126 string filePath1, filePath2;
129 PIN_GetSourceLocation(prevAddr,
nullptr, (INT32*)&lineNo1, &filePath1);
130 PIN_GetSourceLocation(curAddr,
nullptr, (INT32*)&lineNo2, &filePath2);
133 return static_cast<bool>((filePath1 == filePath2) && (lineNo1 <= lineNo2));
136 VOID
MemFunc(THREADID
id,
void* addr,
bool rwFlag, UINT32 refSize) {
137 uint64_t Addr = (uint64_t)addr;
144 void**
metric = GetIPNodeMetric(
id, 0);
150 (
hmap_vector[id])[ctxthndl].addressSet.insert(Addr | (((uint64_t)refSize) << 48));
155 if (rwFlag && (*prevFlag))
156 (
hmap_vector[
id])[ctxthndl].dependentNum += refSize;
158 (
static_cast<struct
node_metric_t*
>(*metric))->addressSet.insert(Addr | (((uint64_t)refSize) << 48));
159 (
static_cast<struct
node_metric_t*
>(*metric))->accessNum += refSize;
160 if (!rwFlag && (*prevFlag))
169 if (!INS_IsMemoryRead(ins) && !INS_IsMemoryWrite(ins))
171 if (INS_IsStackRead(ins) || INS_IsStackWrite(ins))
173 if (INS_IsControlFlow(ins) || INS_IsRet(ins))
175 UINT32 memOperands = INS_MemoryOperandCount(ins);
176 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
177 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
178 if (INS_IsMemoryRead(ins))
179 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
MemFunc, IARG_THREAD_ID, IARG_MEMORYOP_EA, memOp, IARG_BOOL,
false, IARG_UINT32, refSize, IARG_END);
181 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
MemFunc, IARG_THREAD_ID, IARG_MEMORYOP_EA, memOp, IARG_BOOL,
true, IARG_UINT32, refSize, IARG_END);
186 if (*myMetric ==
nullptr)
189 unordered_set<uint64_t>::iterator it;
191 uint64_t refSize = (*it) >> 48;
192 uint64_t addr = (*it) & ((1ULL << 48) - 1);
193 assert(refSize != 0);
194 for (
unsigned int i = 0; i < refSize; i++) {
202 if (*myMetric ==
nullptr)
206 if (*parentMetric ==
nullptr) {
207 *parentMetric = &((
hmap_vector[threadid])[parentHandle]);
226 uint64_t cntxtNum = 0;
227 vector<struct sort_format_t> TmpList;
229 fprintf(
gTraceFile,
"*************** Dump Data from Thread %d ****************\n", threadid);
230 unordered_map<uint32_t, struct node_metric_t>& hmap =
hmap_vector[threadid];
231 unordered_map<uint32_t, struct node_metric_t>::iterator it;
232 for (it = hmap.begin(); it != hmap.end(); ++it) {
235 tmp.
footprint = (uint64_t)(*it).second.addressSetDecoded.size();
236 tmp.
fpNum = (uint64_t)(*it).second.addressSet.size();
237 tmp.
accessNum = (uint64_t)(*it).second.accessNum;
239 TmpList.emplace_back(tmp);
242 vector<struct sort_format_t>::iterator ListIt;
243 for (ListIt = TmpList.begin(); ListIt != TmpList.end(); ++ListIt) {
245 fprintf(
gTraceFile,
"Footprint is %lu Bytes, #distinct memory access is %ld, reuse is %ld, write dependence is %lu, context is:", ((*ListIt).footprint), (*ListIt).fpNum, (*ListIt).accessNum - (*ListIt).footprint, (*ListIt).dependentNum);
247 fprintf(
gTraceFile,
"\n------------------------------------------------\n");
255 VOID
ThreadFiniFunc(THREADID threadid,
const CONTEXT* ctxt, INT32 code, VOID* v) {
256 gettimeofday(&
tv2,
nullptr);
262 gettimeofday(&
tv3,
nullptr);
266 fprintf(
gTraceFile,
"online collection time %lf, offline analysis time %lf\n",
tv2.tv_sec -
tv1.tv_sec + (
tv2.tv_usec -
tv1.tv_usec) / 1000000.0,
tv3.tv_sec -
tv2.tv_sec + (
tv3.tv_usec -
tv2.tv_usec) / 1000000.0);
274 int main(
int argc,
char* argv[]) {
275 gettimeofday(&
tv1,
nullptr);
277 if (PIN_Init(argc, argv))
289 PIN_AddFiniFunction(
FiniFunc,
nullptr);
#define INTERESTING_INS_MEMORY_ACCESS
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
unordered_set< uint64_t > addressSetDecoded
unordered_set< uint64_t > addressSet