CCTLib
Calling-context and data-object attribution library for Intel Pin
cct_data_name.cpp
Go to the documentation of this file.
1 // @COPYRIGHT@
2 // Licensed under MIT license.
3 // See LICENSE.TXT file in the project root for more information.
4 // ==============================================================
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <iostream>
10 #include <unistd.h>
11 #include <assert.h>
12 #include <string>
13 // (Boost dropped: CCTLib no longer depends on Boost. Pin RT does not
14 // support Boost anyway. The `using namespace boost;` below was never
15 // actually consumed by this file.)
16 #include <math.h> //Du
17 #include <sstream>
18 #include <locale>
19 #include <unordered_map>
20 #include "pin.H"
21 
22 #define OFFSET 20000000
23 //#define MAX_WINDOW_ALLOWED 200
24 //#define ChunkSize 512*(1<<10)
25 //#define WINDOW 100000
26 
27 #define USE_TREE_BASED_FOR_DATA_CENTRIC
28 #include "cctlib.H"
29 using namespace std;
30 // removed: using namespace boost;
31 using namespace PinCCTLib;
32 
33 
34 INT32 Usage2() {
35  PIN_ERROR("Pin tool to gather calling context on each instruction and associate each memory access to its data object (shadow memory technique).\n" + KNOB_BASE::StringKnobSummary() + "\n");
36  return -1;
37 }
38 
39 FILE* gTraceFile;
40 
41 struct DataObj {
42  long counter; // # of total accesses by all threads.
43  int threads; //# of threads.
45 };
46 
47 
48 PIN_LOCK clientLock;
49 
50 
51 long long CTR = 0;
52 int WINDOW_WIDTH = 500 * 1000;
53 int MAX_WINDOW_ALLOWED = 1000;
54 int ChunkSize = 512 * (1 << 10);
55 
56 int window;
57 int TH = 0; //thread to listen
58 //unsigned long dataSizeTh = 1 << 10;//listen on data that is larger.
59 bool outputflag = true;
60 bool errflag = true;
61 float OutputTH = 0.5; //threshold for output similar data objects.
62 unordered_map<uint32_t, DataObj> DataObjectMap;
63 unordered_map<uint32_t, long*> DataWindowMap; //(data ID, array(Windows))
64 unordered_map<uint32_t, int*> DataThreadMap; //(data ID, array(Windows))
65 
66 //unordered_map <uint32_t, vector<int>> DataWindowMap;//(data ID, Vector(Windows))
67 
68 
69 VOID ImageUnload(IMG img, VOID* v) {
70  //this routine runs only once.
71  if (outputflag == false)
72  return;
73  //printf("I AM HERE!2\n");
74  outputflag = false;
75  int ii, jj;
76  fprintf(gTraceFile, "Unloading %s\n", IMG_Name(img).c_str());
77  printf("\n [CCTLIB client] Unloading....");
78  printf("\n [CCTLIB client] Total accesses: ");
79  if (CTR > 1000000)
80  printf("%d,%.3d,%.3d.\n\n", CTR / 1000000, (CTR % 1000000) / 1000, CTR % 1000);
81  else
82  printf("%d,%.3d.\n\n", CTR / 1000, CTR % 1000);
83 
84 
85  //sort
86  int length = DataObjectMap.size();
87  uint32_t indexList[length], ind_tmp;
88  long counterList[length], temp;
89  float ratioList[length], ratio_temp;
90  DataObj tempData;
91 
92  fprintf(gTraceFile, "\n\nA total of %ld memeroy accesses.\n", CTR);
93  fprintf(gTraceFile, "Window Width: %ld .\n", WINDOW_WIDTH);
94  fprintf(gTraceFile, "total windows: %d .\n", window + 1);
95 
96 
97  ii = 0;
98  for (auto iter = DataObjectMap.begin(); iter != DataObjectMap.end(); ++iter) {
99  indexList[ii] = iter->first;
100  tempData = iter->second;
101  counterList[ii] = tempData.counter;
102  ii++;
103  }
104 
105  for (ii = 0; ii < length; ii++)
106  for (int jj = 0; jj < ii; jj++) { //sort by # of access
107  if (counterList[jj] < counterList[ii]) {
108  temp = counterList[jj];
109  counterList[jj] = counterList[ii];
110  counterList[ii] = temp; //
111  ind_tmp = indexList[jj];
112  indexList[jj] = indexList[ii];
113  indexList[ii] = ind_tmp; //
114  }
115  }
116 
117  fprintf(gTraceFile, "\n");
118 
119  for (ii = 0; ii < min(60, length); ii++) {
120  uint32_t index = indexList[ii];
121  uint32_t sysIndex;
122  int chunk = 0;
123 
124  auto search = DataObjectMap.find(index);
125  if (search != DataObjectMap.end()) {
126  tempData = search->second;
127  // printf("1index = %d, 1synName=%d, chunk = %d\n", index, tempData.data.symName, chunk);
128  if (index > OFFSET) {
129  // printf("[CCTLIB] large arrays: %d\n",index);
130  chunk = index % 100;
131  sysIndex = (uint32_t)((index - chunk - OFFSET) / 100);
132  // printf("index = %d, synName=%d, chunk = %d\n", index, tempData.data.symName, chunk);
133  } else
134  sysIndex = index;
135 
136  uint64_t head = tempData.data.beg_addr;
137  uint64_t tail = tempData.data.end_addr;
138  int sizeInBytes = (int)tail - head;
139 
140  if (tempData.data.objectType == DYNAMIC_OBJECT)
141  fprintf(gTraceFile, "\n\n\nRank %d >>>> Dynamic Data %d chunk %d accessed %ld times, range:[%p,%p]\n",
142  ii, sysIndex, chunk, tempData.counter, head, tail);
143  else if (tempData.data.objectType == STATIC_OBJECT)
144  fprintf(gTraceFile, "\n\n\nRank %d >>>> Static Data %d: \"%s\", accessed %ld times, range:[%p,%p]\n",
145  ii, sysIndex, GetStringPool() + tempData.data.symName, tempData.counter, head, tail);
146 
147  if (sizeInBytes > 1 << 20)
148  fprintf(gTraceFile, "size = %.3f MB.\n", (float)(sizeInBytes) / (float)(1 << 20));
149  else if (sizeInBytes > 1 << 10)
150  fprintf(gTraceFile, "size = %.3f KB.\n", (float)(sizeInBytes) / (float)(1 << 10));
151  else
152  fprintf(gTraceFile, "size = %d B.\n", sizeInBytes);
153 
154  //data - window
155  auto search1 = DataWindowMap.find(index);
156  if (search1 != DataWindowMap.end()) {
157  long* window_arr = search1->second;
158 
159  fprintf(gTraceFile, "distribtion among windows: \n");
160 
161  for (jj = 0; jj < min(window + 1, MAX_WINDOW_ALLOWED); jj++) {
162  fprintf(gTraceFile, "|%ld\t", window_arr[jj]);
163  }
164  fprintf(gTraceFile, "\n");
165  } else {
166  fprintf(gTraceFile, "!!not here!!\n");
167  }
168 
169  //data - thread
170  auto search2 = DataThreadMap.find(index);
171  if (search2 != DataThreadMap.end()) {
172  int* th_arr = search2->second;
173  fprintf(gTraceFile, "accessed by threads: \n");
174  for (jj = 0; jj < 32; jj++) {
175  fprintf(gTraceFile, "|%d\t", th_arr[jj]);
176  }
177  fprintf(gTraceFile, "\n");
178  } else {
179  fprintf(gTraceFile, "!!not here!!\n");
180  }
181 
182 
183  PrintFullCallingContext(sysIndex);
184  // printf("here6\n");
185  }
186  }
187 
188  fprintf(gTraceFile, "\n\n\n End...");
189 }
190 
191 
192 // Initialized the needed data structures before launching the target program
193 void ClientInit(int argc, char* argv[]) {
194  // Create output file
195  char name[MAX_FILE_PATH] = "client.out.data_pattern.";
196  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
197 
198  if (envPath) {
199  // assumes max of MAX_FILE_PATH
200  snprintf(name, sizeof(name), "%s", envPath);
201  }
202 
203  gethostname(name + strlen(name), MAX_FILE_PATH - strlen(name));
204  pid_t pid = getpid();
205  sprintf(name + strlen(name), "%d", pid);
206  cerr << "\n [CCTLIB client] Creating log file at:" << name << "\n\n";
207  gTraceFile = fopen(name, "w");
208  // print the arguments passed
209  fprintf(gTraceFile, "\n");
210 
211  for (int i = 0; i < argc; i++) {
212  fprintf(gTraceFile, "%s ", argv[i]);
213  }
214  fprintf(gTraceFile, "\n");
215 
216  // Register ImageUnload to be called when the image is unloaded
217  IMG_AddUnloadFunction(ImageUnload, 0);
218 }
219 
220 
221 VOID SimpleCCTQuery(THREADID id, const uint32_t slot) {
222  GetContextHandle(id, slot);
223 }
224 
225 
226 uint32_t getIndex(uint64_t beg, uint64_t end, void* addr, uint32_t sysIndex, THREADID threadId) {
227  int size = (int)((end - beg) / 1024);
228  int offset = (int)(((long)addr - beg) / 1024);
229 
230  int chunk = floor(offset / (ChunkSize / 1024)) + 1;
231  if (chunk > 99) {
232  if (errflag) {
233  printf("\n [CCTLIB client] !!too large array!! Results of window distribution may be iffy.\n\n");
234  PIN_GetLock(&clientLock, threadId + 1);
235  errflag = false;
236  PIN_ReleaseLock(&clientLock);
237  }
238  chunk = chunk % 100;
239  }
240 
241  uint32_t localIndex = (sysIndex * 100 + OFFSET + chunk);
242 
243  // printf(" %d, %d, %d, %d => %d\n ", size, offset, chunk, sysIndex, localIndex);
244 
245  return localIndex;
246 }
247 
248 
249 void updateDataList(void* addr, DataHandle_t data, THREADID threadId) {
250  uint32_t sysIndex = data.symName;
251  uint32_t index;
252 
253  int size = data.end_addr - data.beg_addr;
254  if (size < (800 * (1 << 10)))
255  index = sysIndex;
256  else
257  index = getIndex(data.beg_addr, data.end_addr, addr, sysIndex, threadId); //divide into chunks
258 
259  auto search = DataObjectMap.find(index);
260  if (search != DataObjectMap.end()) {
261  //update existing one:
262  __sync_fetch_and_add(&(search->second).counter, 1);
263  } else { //insert new one
264  DataObj newDataObj;
265  newDataObj.counter = 1;
266  newDataObj.data = data;
267  PIN_GetLock(&clientLock, threadId + 1);
268  DataObjectMap.insert({index, newDataObj});
269  PIN_ReleaseLock(&clientLock);
270  }
271 
272 
273  // TODO: dynamically ajust window width
274  auto search1 = DataWindowMap.find(index);
275  if (search1 != DataWindowMap.end()) {
276  if (window < MAX_WINDOW_ALLOWED) { //update existing one:
277  long* window_arr = search1->second;
278  __sync_fetch_and_add(&(window_arr[window]), 1);
279  }
280  } else { //insert new one
281  long* win_arr = new long[MAX_WINDOW_ALLOWED];
282  for (int ii = 0; ii < MAX_WINDOW_ALLOWED; ii++)
283  win_arr[ii] = 0;
284  PIN_GetLock(&clientLock, threadId + 1);
285  DataWindowMap.insert({index, win_arr});
286  PIN_ReleaseLock(&clientLock);
287  }
288 
289 
290  auto search2 = DataThreadMap.find(index);
291  if (search2 != DataThreadMap.end()) {
292  if (threadId < 32) { //update existing one:
293  int* th_arr = search2->second;
294  //if (th_arr[threadId]==0)
295  __sync_fetch_and_add(&(th_arr[threadId]), 1);
296  }
297  } else { //insert new one
298  int* th_arr = new int[32];
299  for (int ii = 0; ii < 32; ii++)
300  th_arr[ii] = 0;
301  PIN_GetLock(&clientLock, threadId + 1);
302  DataThreadMap.insert({index, th_arr});
303  PIN_ReleaseLock(&clientLock);
304  }
305 }
306 
307 
308 VOID MemAnalysisRoutine(void* addr, THREADID threadId) {
309  //{
310  __sync_fetch_and_add(&CTR, 1);
311 
312  if ((window + 1) * WINDOW_WIDTH < CTR) {
313  PIN_GetLock(&clientLock, threadId + 1);
314  window = CTR / WINDOW_WIDTH;
315  PIN_ReleaseLock(&clientLock);
316  }
317 
318  DataHandle_t d = GetDataObjectHandle(addr, threadId);
319 
320  switch (d.objectType) {
321  case STACK_OBJECT:
322  break;
323  case DYNAMIC_OBJECT: //printf("Index= %d, DYNAMIC\n",d.pathHandle);//well...
324  updateDataList(addr, d, threadId);
325  break;
326  case STATIC_OBJECT:
327  updateDataList(addr, d, threadId);
328  break;
329  default: //printf("not up in here! Index= %d\n",d.symName);//yes, executed.
330  break;
331  }
332  //}
333 }
334 
335 
336 VOID InstrumentInsCallback(INS ins, VOID* v, const uint32_t slot) {
337  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)SimpleCCTQuery, IARG_THREAD_ID, IARG_UINT32, slot, IARG_END);
338 
339  // Data centric for mem inst
340  // Skip call, ret and JMP instructions
341  if (INS_IsControlFlow(ins) || INS_IsRet(ins)) {
342  return;
343  }
344 
345  // skip stack ... actually our code handles it
346  if (INS_IsStackRead(ins) || INS_IsStackWrite(ins))
347  return;
348 
349  if (INS_IsMemoryRead(ins) || INS_IsMemoryWrite(ins)) {
350  // How may memory operations?
351  UINT32 memOperands = INS_MemoryOperandCount(ins);
352 
353  // Iterate over each memory operand of the instruction and add Analysis routine
354  for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
355  INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)MemAnalysisRoutine, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END);
356  }
357  }
358 }
359 
360 int main(int argc, char* argv[]) {
361  // Initialize PIN
362  if (PIN_Init(argc, argv))
363  return Usage2();
364 
365  // Initialize Symbols, we need them to report functions and lines
366  PIN_InitSymbols();
367  // Init Client
368  ClientInit(argc, argv);
369  // Intialize CCTLib
371  // Launch program now
372  PIN_StartProgram();
373  return 0;
374 }
int MAX_WINDOW_ALLOWED
unordered_map< uint32_t, int * > DataThreadMap
int main(int argc, char *argv[])
bool errflag
FILE * gTraceFile
#define OFFSET
bool outputflag
int TH
float OutputTH
uint32_t getIndex(uint64_t beg, uint64_t end, void *addr, uint32_t sysIndex, THREADID threadId)
void ClientInit(int argc, char *argv[])
long long CTR
VOID MemAnalysisRoutine(void *addr, THREADID threadId)
int window
int ChunkSize
PIN_LOCK clientLock
INT32 Usage2()
unordered_map< uint32_t, long * > DataWindowMap
VOID SimpleCCTQuery(THREADID id, const uint32_t slot)
void updateDataList(void *addr, DataHandle_t data, THREADID threadId)
int WINDOW_WIDTH
VOID ImageUnload(IMG img, VOID *v)
unordered_map< uint32_t, DataObj > DataObjectMap
VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t slot)
#define MAX_FILE_PATH
Definition: cctlib.H:18
#define INTERESTING_INS_ALL
Definition: cctlib.H:85
DataHandle_t GetDataObjectHandle(VOID *address, const THREADID threadId)
Definition: cctlib.cpp:2495
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
Definition: cctlib.cpp:3132
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
Definition: cctlib.cpp:2346
@ STACK_OBJECT
Definition: cctlib.H:25
@ DYNAMIC_OBJECT
Definition: cctlib.H:26
@ STATIC_OBJECT
Definition: cctlib.H:27
struct DataHandle_t { uint8_t objectType DataHandle_t
Definition: cctlib.H:32
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
Definition: cctlib.cpp:1356
DataraceInfo_t data
DataHandle_t data
long counter