6 #define __STDC_FORMAT_MACROS
11 #include <unordered_map>
15 #include <sys/types.h>
18 #include <semaphore.h>
24 #include <sys/syscall.h>
35 #include <google/sparse_hash_map>
36 #include <google/dense_hash_map>
44 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
45 #define MAP_ANONYMOUS MAP_ANON
50 #define CONTINUOUS_DEADINFO
53 #define MAX_CCT_PRINT_DEPTH (20)
54 #define MAX_FILE_PATH (200)
55 #ifndef MAX_DEAD_CONTEXTS_TO_LOG
56 #define MAX_DEAD_CONTEXTS_TO_LOG (1000)
60 #define PAGE_OFFSET_BITS (16LL)
61 #define PAGE_OFFSET(addr) (addr & 0xFFFF)
62 #define PAGE_OFFSET_MASK (0xFFFF)
65 #define PAGE_SIZE (1 << PAGE_OFFSET_BITS)
68 #define PTR_SIZE (sizeof(void*))
69 #define LEVEL_1_PAGE_TABLE_BITS (20)
70 #define LEVEL_1_PAGE_TABLE_ENTRIES (1 << LEVEL_1_PAGE_TABLE_BITS)
71 #define LEVEL_1_PAGE_TABLE_SIZE (LEVEL_1_PAGE_TABLE_ENTRIES * PTR_SIZE)
73 #define LEVEL_2_PAGE_TABLE_BITS (12)
74 #define LEVEL_2_PAGE_TABLE_ENTRIES (1 << LEVEL_2_PAGE_TABLE_BITS)
75 #define LEVEL_2_PAGE_TABLE_SIZE (LEVEL_2_PAGE_TABLE_ENTRIES * PTR_SIZE)
77 #define LEVEL_1_PAGE_TABLE_SLOT(addr) ((((uint64_t)addr) >> (LEVEL_2_PAGE_TABLE_BITS + PAGE_OFFSET_BITS)) & 0xfffff)
78 #define LEVEL_2_PAGE_TABLE_SLOT(addr) ((((uint64_t)addr) >> (PAGE_OFFSET_BITS)) & 0xFFF)
82 #define READ_ACTION (0)
83 #define WRITE_ACTION (0xff)
85 #define ONE_BYTE_READ_ACTION (0)
86 #define TWO_BYTE_READ_ACTION (0)
87 #define FOUR_BYTE_READ_ACTION (0)
88 #define EIGHT_BYTE_READ_ACTION (0)
90 #define ONE_BYTE_WRITE_ACTION (0xff)
91 #define TWO_BYTE_WRITE_ACTION (0xffff)
92 #define FOUR_BYTE_WRITE_ACTION (0xffffffff)
93 #define EIGHT_BYTE_WRITE_ACTION (0xffffffffffffffff)
97 uint64_t gFullyKilling1;
98 uint64_t gFullyKilling2;
99 uint64_t gFullyKilling4;
100 uint64_t gFullyKilling8;
101 uint64_t gFullyKilling10;
102 uint64_t gFullyKilling16;
103 uint64_t gFullyKillingLarge;
105 uint64_t gPartiallyKilling1;
106 uint64_t gPartiallyKilling2;
107 uint64_t gPartiallyKilling4;
108 uint64_t gPartiallyKilling8;
109 uint64_t gPartiallyKilling10;
110 uint64_t gPartiallyKilling16;
111 uint64_t gPartiallyKillingLarge;
113 uint64_t gPartiallyDeadBytes1;
114 uint64_t gPartiallyDeadBytes2;
115 uint64_t gPartiallyDeadBytes4;
116 uint64_t gPartiallyDeadBytes8;
117 uint64_t gPartiallyDeadBytes10;
118 uint64_t gPartiallyDeadBytes16;
119 uint64_t gPartiallyDeadBytesLarge;
162 KNOB<UINT32>
KnobTopN(KNOB_MODE_WRITEONCE,
"pintool",
"d",
"0",
"how many top contexts to log");
173 volatile bool gDSLock;
177 }
while(!__sync_bool_compare_and_swap(&gDSLock, 0, 1));
206 #if defined(CONTINUOUS_DEADINFO)
214 dense_hash_map<uint64_t, DeadInfo>
DeadMap;
215 dense_hash_map<uint64_t, DeadInfo>::iterator
gDeadMapIt;
225 #ifdef MULTI_THREADED
226 uint64_t gTotalMTDead = 0;
232 VOID
Instruction(INS ins, VOID* v,
const uint32_t opaqueHandle);
262 for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
263 uint32_t inst1ByteSize = 0;
264 uint32_t inst2ByteSize = 0;
265 uint32_t inst4ByteSize = 0;
266 uint32_t inst8ByteSize = 0;
267 uint32_t inst10ByteSize = 0;
268 uint32_t inst16ByteSize = 0;
269 uint32_t instLargeByteSize = 0;
271 for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
274 if (INS_IsMemoryWrite(ins)) {
279 UINT32 nOps = INS_MemoryOperandCount(ins);
280 for (UINT32 op = 0; op < nOps; op++) {
281 if (INS_MemoryOperandIsWritten(ins, op)) {
282 writeSize += INS_MemoryOperandSize(ins, op);
312 instLargeByteSize += writeSize;
339 if (instLargeByteSize)
353 if (*l1Ptr ==
nullptr) {
355 shadowPage = (*l1Ptr)[
LEVEL_2_PAGE_TABLE_SLOT(
address)] = (uint8_t*)mmap(
nullptr,
PAGE_SIZE * (1 +
sizeof(uint32_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
357 shadowPage = (*l1Ptr)[
LEVEL_2_PAGE_TABLE_SLOT(
address)] = (uint8_t*)mmap(
nullptr,
PAGE_SIZE * (1 +
sizeof(uint32_t)), PROT_WRITE | PROT_READ, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
371 if (*l1Ptr ==
nullptr) {
385 #define CONTEXT_HASH_128BITS_TO_64BITS(curCtxt, oldCtxt, hashVar) \
387 uint64_t key = (uint64_t)(((void**)oldCtxt) - gPreAllocatedContextBuffer); \
388 hashVar = key << 32; \
389 key = (uint64_t)(((void**)curCtxt) - gPreAllocatedContextBuffer); \
395 #define CONTEXT_HASH_128BITS_TO_64BITS(curCtxt, oldCtxt, hashVar) \
397 uint64_t key = (uint64_t)(oldCtxt); \
398 hashVar = key << 32; \
399 key = (uint64_t)(curCtxt); \
406 #define OLD_CTXT (*lastIP)
410 #if defined(CONTINUOUS_DEADINFO)
412 #define DECLARE_HASHVAR(name) uint64_t name
414 #define REPORT_DEAD(curCtxt, lastCtxt, hashVar, size) \
416 CONTEXT_HASH_128BITS_TO_64BITS(curCtxt, lastCtxt, hashVar) \
417 if ((gDeadMapIt = DeadMap.find(hashVar)) == DeadMap.end()) { \
418 DeadMap.insert(std::pair<uint64_t, uint64_t>(hashVar, size)); \
420 (gDeadMapIt->second) += size; \
425 #define DECLARE_HASHVAR(name) uint64_t name
427 #define REPORT_DEAD(curCtxt, lastCtxt, hashVar, size) \
429 CONTEXT_HASH_128BITS_TO_64BITS(curCtxt, lastCtxt, hashVar) \
430 if ((gDeadMapIt = DeadMap.find(hashVar)) == DeadMap.end()) { \
431 DeadInfo deadInfo = {lastCtxt, curCtxt, size}; \
432 DeadMap.insert(std::pair<uint64_t, DeadInfo>(hashVar, deadInfo)); \
434 (gDeadMapIt->second.count) += size; \
440 #define REPORT_IF_DEAD(mask, curCtxt, lastCtxt, hashVar) \
442 if (state & (mask)) { \
443 REPORT_DEAD(curCtxt, lastCtxt, hashVar, 1); \
449 #define RecordNByteMemWrite(type, size, sizeSTR) \
451 uint8_t* status = GetOrCreateShadowBaseAddress(addr); \
452 if (PAGE_OFFSET((uint64_t)addr) < (PAGE_OFFSET_MASK - size - 2)) { \
453 type state = *((type*)(status + PAGE_OFFSET((uint64_t)addr))); \
454 if (state != sizeSTR##_BYTE_READ_ACTION) { \
455 if (state == sizeSTR##_BYTE_WRITE_ACTION) { \
456 gFullyKilling##size++; \
458 gPartiallyKilling##size++; \
459 for (type s = state; s != 0; s >>= 8) \
461 gPartiallyDeadBytes##size++; \
464 *((type*)(status + PAGE_OFFSET((uint64_t)addr))) = sizeSTR##_BYTE_WRITE_ACTION; \
466 type state = *((uint8_t*)(status + PAGE_OFFSET((uint64_t)addr))); \
467 *((uint8_t*)(status + PAGE_OFFSET((uint64_t)addr))) = ONE_BYTE_WRITE_ACTION; \
468 uint8_t deadBytes = state == ONE_BYTE_WRITE_ACTION ? 1 : 0; \
469 for (uint8_t i = 1; i < size; i++) { \
470 status = GetOrCreateShadowBaseAddress(((char*)addr) + i); \
471 state = *((uint8_t*)(status + PAGE_OFFSET((((uint64_t)addr) + i)))); \
472 if (state == ONE_BYTE_WRITE_ACTION) \
474 *((uint8_t*)(status + PAGE_OFFSET((((uint64_t)addr) + i)))) = ONE_BYTE_WRITE_ACTION; \
476 if (deadBytes == size) \
477 gFullyKilling##size++; \
478 else if (deadBytes) { \
479 gPartiallyKilling##size++; \
480 gPartiallyDeadBytes##size += deadBytes; \
526 *lastIP = curCtxtHandle;
535 *lastIP = curCtxtHandle;
561 RecordNByteMemWrite(uint16_t, 2, TWO);
594 lastIP[0] = curCtxtHandle;
595 lastIP[1] = curCtxtHandle;
616 for (
int nonOverflowBytes = 0; nonOverflowBytes < 4 - overflow; nonOverflowBytes++) {
624 for (; overflow; overflow--) {
633 RecordNByteMemWrite(uint32_t, 4, FOUR);
648 uint32_t ipZero = lastIP[0];
652 ipZero == lastIP[0] && ipZero == lastIP[1] && ipZero == lastIP[2] && ipZero == lastIP[3]) {
673 lastIP[0] = curCtxtHandle;
674 lastIP[1] = curCtxtHandle;
675 lastIP[2] = curCtxtHandle;
676 lastIP[3] = curCtxtHandle;
699 for (
int nonOverflowBytes = 0; nonOverflowBytes < 8 - overflow; nonOverflowBytes++) {
707 for (; overflow; overflow--) {
716 RecordNByteMemWrite(uint64_t, 8, EIGHT);
731 uint32_t ipZero = lastIP[0];
735 ipZero == lastIP[1] && ipZero == lastIP[2] &&
736 ipZero == lastIP[3] && ipZero == lastIP[4] &&
737 ipZero == lastIP[5] && ipZero == lastIP[6] && ipZero == lastIP[7]) {
743 REPORT_IF_DEAD(0x00000000000000ff, curCtxtHandle, ipZero, myhash);
745 REPORT_IF_DEAD(0x000000000000ff00, curCtxtHandle, lastIP[1], myhash);
747 REPORT_IF_DEAD(0x0000000000ff0000, curCtxtHandle, lastIP[2], myhash);
749 REPORT_IF_DEAD(0x00000000ff000000, curCtxtHandle, lastIP[3], myhash);
751 REPORT_IF_DEAD(0x000000ff00000000, curCtxtHandle, lastIP[4], myhash);
753 REPORT_IF_DEAD(0x0000ff0000000000, curCtxtHandle, lastIP[5], myhash);
755 REPORT_IF_DEAD(0x00ff000000000000, curCtxtHandle, lastIP[6], myhash);
757 REPORT_IF_DEAD(0xff00000000000000, curCtxtHandle, lastIP[7], myhash);
766 lastIP[0] = curCtxtHandle;
767 lastIP[1] = curCtxtHandle;
768 lastIP[2] = curCtxtHandle;
769 lastIP[3] = curCtxtHandle;
770 lastIP[4] = curCtxtHandle;
771 lastIP[5] = curCtxtHandle;
772 lastIP[6] = curCtxtHandle;
773 lastIP[7] = curCtxtHandle;
817 gPartiallyKilling10++;
819 for (uint64_t s = state1; s != 0; s >>= 8)
821 gPartiallyDeadBytes10++;
823 for (uint16_t s = state2; s != 0; s >>= 8)
825 gPartiallyDeadBytes10++;
836 for (uint8_t i = 1; i < 10; i++) {
848 else if (deadBytes) {
849 gPartiallyKilling10++;
850 gPartiallyDeadBytes10 += deadBytes;
867 uint32_t ipZero = lastIP[0];
871 ipZero == lastIP[1] && ipZero == lastIP[2] &&
872 ipZero == lastIP[3] && ipZero == lastIP[4] &&
873 ipZero == lastIP[5] && ipZero == lastIP[6] && ipZero == lastIP[7]) {
879 REPORT_IF_DEAD(0x00000000000000ff, curCtxtHandle, ipZero, myhash);
881 REPORT_IF_DEAD(0x000000000000ff00, curCtxtHandle, lastIP[1], myhash);
883 REPORT_IF_DEAD(0x0000000000ff0000, curCtxtHandle, lastIP[2], myhash);
885 REPORT_IF_DEAD(0x00000000ff000000, curCtxtHandle, lastIP[3], myhash);
887 REPORT_IF_DEAD(0x000000ff00000000, curCtxtHandle, lastIP[4], myhash);
889 REPORT_IF_DEAD(0x0000ff0000000000, curCtxtHandle, lastIP[5], myhash);
891 REPORT_IF_DEAD(0x00ff000000000000, curCtxtHandle, lastIP[6], myhash);
893 REPORT_IF_DEAD(0xff00000000000000, curCtxtHandle, lastIP[7], myhash);
908 uint32_t ipZero = lastIP[8];
912 ipZero == lastIP[9]) {
929 lastIP[0] = curCtxtHandle;
930 lastIP[1] = curCtxtHandle;
931 lastIP[2] = curCtxtHandle;
932 lastIP[3] = curCtxtHandle;
933 lastIP[4] = curCtxtHandle;
934 lastIP[5] = curCtxtHandle;
935 lastIP[6] = curCtxtHandle;
936 lastIP[7] = curCtxtHandle;
937 lastIP[8] = curCtxtHandle;
938 lastIP[9] = curCtxtHandle;
940 for (
int i = 0; i < 10; i++) {
978 gPartiallyKilling16++;
980 for (uint64_t s = state1; s != 0; s >>= 8)
982 gPartiallyDeadBytes16++;
984 for (uint64_t s = state2; s != 0; s >>= 8)
986 gPartiallyDeadBytes16++;
997 for (uint8_t i = 1; i < 16; i++) {
1007 if (deadBytes == 16)
1009 else if (deadBytes) {
1010 gPartiallyKilling16++;
1011 gPartiallyDeadBytes16 += deadBytes;
1028 uint32_t ipZero = lastIP[0];
1032 ipZero == lastIP[1] && ipZero == lastIP[2] &&
1033 ipZero == lastIP[3] && ipZero == lastIP[4] &&
1034 ipZero == lastIP[5] && ipZero == lastIP[6] && ipZero == lastIP[7]) {
1040 REPORT_IF_DEAD(0x00000000000000ff, curCtxtHandle, ipZero, myhash);
1042 REPORT_IF_DEAD(0x000000000000ff00, curCtxtHandle, lastIP[1], myhash);
1044 REPORT_IF_DEAD(0x0000000000ff0000, curCtxtHandle, lastIP[2], myhash);
1046 REPORT_IF_DEAD(0x00000000ff000000, curCtxtHandle, lastIP[3], myhash);
1048 REPORT_IF_DEAD(0x000000ff00000000, curCtxtHandle, lastIP[4], myhash);
1050 REPORT_IF_DEAD(0x0000ff0000000000, curCtxtHandle, lastIP[5], myhash);
1052 REPORT_IF_DEAD(0x00ff000000000000, curCtxtHandle, lastIP[6], myhash);
1054 REPORT_IF_DEAD(0xff00000000000000, curCtxtHandle, lastIP[7], myhash);
1067 uint32_t ipZero = lastIP[8];
1071 ipZero == lastIP[9] && ipZero == lastIP[10] && ipZero == lastIP[11] &&
1072 ipZero == lastIP[12] && ipZero == lastIP[13] &&
1073 ipZero == lastIP[14] && ipZero == lastIP[15]) {
1079 REPORT_IF_DEAD(0x00000000000000ff, curCtxtHandle, ipZero, myhash);
1081 REPORT_IF_DEAD(0x000000000000ff00, curCtxtHandle, lastIP[9], myhash);
1083 REPORT_IF_DEAD(0x0000000000ff0000, curCtxtHandle, lastIP[10], myhash);
1085 REPORT_IF_DEAD(0x00000000ff000000, curCtxtHandle, lastIP[11], myhash);
1087 REPORT_IF_DEAD(0x000000ff00000000, curCtxtHandle, lastIP[12], myhash);
1089 REPORT_IF_DEAD(0x0000ff0000000000, curCtxtHandle, lastIP[13], myhash);
1091 REPORT_IF_DEAD(0x00ff000000000000, curCtxtHandle, lastIP[14], myhash);
1093 REPORT_IF_DEAD(0xff00000000000000, curCtxtHandle, lastIP[15], myhash);
1102 lastIP[0] = curCtxtHandle;
1103 lastIP[1] = curCtxtHandle;
1104 lastIP[2] = curCtxtHandle;
1105 lastIP[3] = curCtxtHandle;
1106 lastIP[4] = curCtxtHandle;
1107 lastIP[5] = curCtxtHandle;
1108 lastIP[6] = curCtxtHandle;
1109 lastIP[7] = curCtxtHandle;
1110 lastIP[8] = curCtxtHandle;
1111 lastIP[9] = curCtxtHandle;
1112 lastIP[10] = curCtxtHandle;
1113 lastIP[11] = curCtxtHandle;
1114 lastIP[12] = curCtxtHandle;
1115 lastIP[13] = curCtxtHandle;
1116 lastIP[14] = curCtxtHandle;
1117 lastIP[15] = curCtxtHandle;
1119 for (
int i = 0; i < 16; i++) {
1129 for (UINT32 i = 0; i < size; i++) {
1138 #ifdef TESTING_BYTES
1143 uint8_t deadBytes = 0;
1145 for (uint8_t i = 0; i < size; i++) {
1155 if (deadBytes == size) {
1156 gFullyKillingLarge++;
1157 }
else if (deadBytes) {
1158 gPartiallyKillingLarge++;
1162 gPartiallyDeadBytesLarge += deadBytes;
1170 for (UINT32 i = 0; i < size; i++) {
1179 << addr <<
":" << sz;
1194 #ifdef MULTI_THREADED
1195 if (INS_IsControlFlow(ins) || INS_IsRet(ins)) {
1205 if (INS_Mnemonic(ins) ==
"XSAVEC")
1207 if (INS_Mnemonic(ins) ==
"XSAVE")
1209 if (INS_Mnemonic(ins) ==
"XRSTOR")
1219 if (INS_IsPrefetch(ins))
1223 UINT32 memOperands = INS_MemoryOperandCount(ins);
1224 #ifdef MULTI_THREADED
1227 bool lockNeeded =
false;
1230 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1231 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
TakeLock, IARG_END);
1242 for (UINT32 memOp = 0; memOp < memOperands; memOp++) {
1243 UINT32 refSize = INS_MemoryOperandSize(ins, memOp);
1247 if (INS_MemoryOperandIsRead(ins, memOp)) {
1248 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record1ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1251 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1252 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1254 IARG_MEMORYOP_EA, memOp,
1255 IARG_UINT32, opaqueHandle,
1256 IARG_THREAD_ID, IARG_END);
1261 if (INS_MemoryOperandIsRead(ins, memOp)) {
1262 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record2ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1265 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1266 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1268 IARG_MEMORYOP_EA, memOp,
1269 IARG_UINT32, opaqueHandle,
1270 IARG_THREAD_ID, IARG_END);
1275 if (INS_MemoryOperandIsRead(ins, memOp)) {
1276 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record4ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1279 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1280 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1282 IARG_MEMORYOP_EA, memOp,
1283 IARG_UINT32, opaqueHandle,
1284 IARG_THREAD_ID, IARG_END);
1289 if (INS_MemoryOperandIsRead(ins, memOp)) {
1290 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record8ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1293 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1294 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1296 IARG_MEMORYOP_EA, memOp,
1297 IARG_UINT32, opaqueHandle,
1298 IARG_THREAD_ID, IARG_END);
1303 if (INS_MemoryOperandIsRead(ins, memOp)) {
1304 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record10ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1307 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1308 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1310 IARG_MEMORYOP_EA, memOp,
1311 IARG_UINT32, opaqueHandle,
1312 IARG_THREAD_ID, IARG_END);
1317 if (INS_MemoryOperandIsRead(ins, memOp)) {
1318 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
Record16ByteMemRead, IARG_MEMORYOP_EA, memOp, IARG_END);
1321 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1322 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1324 IARG_MEMORYOP_EA, memOp,
1325 IARG_UINT32, opaqueHandle,
1326 IARG_THREAD_ID, IARG_END);
1332 if (INS_MemoryOperandIsRead(ins, memOp)) {
1333 INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)
RecordLargeMemRead, IARG_MEMORYOP_EA, memOp, IARG_MEMORYREAD_SIZE, IARG_END);
1336 if (INS_MemoryOperandIsWritten(ins, memOp)) {
1337 INS_InsertPredicatedCall(ins, IPOINT_BEFORE,
1339 IARG_MEMORYOP_EA, memOp, IARG_MEMORYWRITE_SIZE,
1340 IARG_UINT32, opaqueHandle,
1341 IARG_THREAD_ID, IARG_END);
1348 #ifdef MULTI_THREADED
1353 INS_InsertPredicatedCall(ins, IPOINT_AFTER, (AFUNPTR)
ReleaseLock, IARG_END);
1359 #ifdef TESTING_BYTES
1361 inline VOID PrintInstructionBreakdown() {
1362 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g1ByteWriteInstrCount, gFullyKilling1, gPartiallyKilling1, gPartiallyDeadBytes1);
1363 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g2ByteWriteInstrCount, gFullyKilling2, gPartiallyKilling2, gPartiallyDeadBytes2);
1364 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g4ByteWriteInstrCount, gFullyKilling4, gPartiallyKilling4, gPartiallyDeadBytes4);
1365 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g8ByteWriteInstrCount, gFullyKilling8, gPartiallyKilling8, gPartiallyDeadBytes8);
1366 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g10ByteWriteInstrCount, gFullyKilling10, gPartiallyKilling10, gPartiallyDeadBytes10);
1367 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu ", g16ByteWriteInstrCount, gFullyKilling16, gPartiallyKilling16, gPartiallyDeadBytes16);
1368 fprintf(
gTraceFile,
"\n%lu,%lu,%lu,%lu,%lu ", gLargeByteWriteInstrCount, gFullyKillingLarge, gPartiallyKillingLarge, gLargeByteWriteByteCount, gPartiallyDeadBytesLarge);
1425 return measurementBaseCount;
1447 fprintf(
gTraceFile,
"\nGrandTotalWrites = %" PRIu64, measurementBaseCount);
1449 #ifdef MULTI_THREADED
1450 fprintf(
gTraceFile,
"\nGrandTotalMTDead = %" PRIu64
" = %e%%", gTotalMTDead, gTotalMTDead * 100.0 / measurementBaseCount);
1462 VOID
SyscallEntry(THREADID threadIndex, CONTEXT* ctxt, SYSCALL_STANDARD std,
1464 ADDRINT number = PIN_GetSyscallNumber(ctxt, std);
1468 char* bufStart = (
char*)PIN_GetSyscallArgument(ctxt, std, 1);
1469 char* bufEnd = bufStart + (
size_t)PIN_GetSyscallArgument(ctxt, std, 2);
1471 printf(
"\n WRITE %p - %p\n", bufStart, bufEnd);
1474 while (bufStart < bufEnd)
1493 return (this->context1 < x.
context1) ||
1510 for (IMG img = APP_ImgHead(); IMG_Valid(img); img = IMG_Next(img)) {
1511 if ((ADDRINT)di.
firstIP >= IMG_LowAddress(img) && (ADDRINT)di.
firstIP <= IMG_HighAddress(img)) {
1520 for (IMG img = APP_ImgHead(); IMG_Valid(img); img = IMG_Next(img)) {
1521 if ((ADDRINT)di.
secondIP >= IMG_LowAddress(img) && (ADDRINT)di.
secondIP <= IMG_HighAddress(img)) {
1533 fprintf(
gTraceFile,
"\n-------------------------------------------------------\n");
1535 fprintf(
gTraceFile,
"\n***********************\n");
1537 fprintf(
gTraceFile,
"\n-------------------------------------------------------\n");
1543 fprintf(
gTraceFile,
"\nUnloading %s", IMG_Name(img).c_str());
1546 fprintf(
gTraceFile,
"\nTotal Instr = %" PRIu64, measurementBaseCount);
1548 unordered_map<uint64_t, uint64_t>::iterator mapIt =
DeadMap.begin();
1549 map<MergedDeadInfo, uint64_t> mergedDeadInfoMap;
1551 for (; mapIt !=
DeadMap.end(); mapIt++) {
1553 uint64_t hash = mapIt->first;
1554 uint32_t ctxt1 = (hash >> 32);
1555 uint32_t ctxt2 = (hash & 0xffffffff);
1556 tmpMergedDeadInfo.
context1 = ctxt1;
1557 tmpMergedDeadInfo.
context2 = ctxt2;
1558 map<MergedDeadInfo, uint64_t>::iterator tmpIt;
1560 if ((tmpIt = mergedDeadInfoMap.find(tmpMergedDeadInfo)) == mergedDeadInfoMap.end()) {
1561 mergedDeadInfoMap[tmpMergedDeadInfo] = mapIt->second;
1563 tmpIt->second += mapIt->second;
1569 map<MergedDeadInfo, uint64_t>::iterator it = mergedDeadInfoMap.begin();
1570 list<DeadInfoForPresentation> deadList;
1572 for (; it != mergedDeadInfoMap.end(); it++) {
1575 deadInfoForPresentation.
count = it->second;
1576 deadList.push_back(deadInfoForPresentation);
1581 list<DeadInfoForPresentation>::iterator dipIter = deadList.begin();
1585 for (; dipIter != deadList.end(); dipIter++) {
1586 #ifdef MULTI_THREADED
1599 #ifdef PRINT_ALL_CTXT
1600 fprintf(
gTraceFile,
"\nCTXT_DEAD_CNT:%lu = %e", dipIter->count, dipIter->count * 100.0 / measurementBaseCount);
1608 static bool done =
false;
1612 dipIter = deadList.begin();
1616 for (UINT32 topN = 0; dipIter != deadList.end() && (topN <
KnobTopN.Value()); dipIter++, topN++) {
1618 << (*dipIter).count <<
":" << (*dipIter).count * 1.0 /
gTotalDead <<
":";
1619 LogContexts(
topnStream, (*dipIter).pMergedDeadInfo->context2 , (*dipIter).pMergedDeadInfo->context1);
1624 #ifdef TESTING_BYTES
1625 PrintInstructionBreakdown();
1630 mergedDeadInfoMap.clear();
1640 char* envPath = getenv(
"DEADSPY_OUTPUT_FILE");
1644 snprintf(name,
sizeof(name),
"%s", envPath);
1647 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
1648 pid_t pid = getpid();
1649 sprintf(name + strlen(name),
"%d", pid);
1650 cerr <<
"\n Creating log file at:" << name <<
"\n";
1655 for (
int i = 0; i < argc; i++) {
1661 topnStream.open(
string(name) +
".topn", std::fstream::out | std::fstream::trunc);
1663 for (
int i = 0; i < argc; i++) {
1670 string statFileName(name);
1671 statFileName +=
".stats";
1672 statsFile = fopen(statFileName.c_str(),
"w");
1673 fprintf(statsFile,
"\n");
1675 for (
int i = 0; i < argc; i++) {
1676 fprintf(statsFile,
"%s ", argv[i]);
1679 fprintf(statsFile,
"\n");
1684 PIN_ERROR(
"DeadSPy is a PinTool which tracks each memory access and reports dead writes.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
1701 if (PIN_Init(argc, argv))
1721 PIN_AddFiniFunction(
Fini,
nullptr);
#define INTERESTING_INS_MEMORY_ACCESS
VOID Instruction(INS ins, VOID *v, const uint32_t opaqueHandle)
VOID Record1ByteMemRead(VOID *addr)
unordered_map< uint64_t, uint64_t >::iterator gDeadMapIt
VOID Record8ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
uint8_t ** gL1PageTable[LEVEL_1_PAGE_TABLE_SIZE]
int main(int argc, char *argv[])
VOID Record8ByteMemRead(VOID *addr)
VOID SyscallEntry(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
void InitDeadSpy(int argc, char *argv[])
#define LEVEL_2_PAGE_TABLE_SIZE
bool IsValidIP(DeadInfo di)
VOID InstructionContributionOfBBL16Byte(uint32_t count, THREADID threadId)
#define LEVEL_1_PAGE_TABLE_SLOT(addr)
void PrintEachSizeWrite()
#define EIGHT_BYTE_WRITE_ACTION
DeadSpyThreadData * ClientGetTLS(const THREADID threadId)
VOID RecordLargeMemRead(VOID *addr, UINT32 size)
VOID RecordLargeMemWrite(VOID *addr, UINT32 size, const uint32_t opaqueHandle, THREADID threadId)
VOID InstructionContributionOfBBL4Byte(uint32_t count, THREADID threadId)
VOID Record16ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
VOID Record1ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
#define ONE_BYTE_READ_ACTION
#define DECLARE_HASHVAR(name)
VOID Record2ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
VOID InstructionContributionOfBBL10Byte(uint32_t count, THREADID threadId)
#define EIGHT_BYTE_READ_ACTION
#define TWO_BYTE_READ_ACTION
#define PAGE_OFFSET(addr)
uint8_t * GetOrCreateShadowBaseAddress(void *address)
uint64_t GetTotalNByteWrites(uint32_t size)
bool MergedDeadInfoComparer(const DeadInfoForPresentation &first, const DeadInfoForPresentation &second)
VOID Record2ByteMemRead(VOID *addr)
KNOB< UINT32 > KnobTopN(KNOB_MODE_WRITEONCE, "pintool", "d", "0", "how many top contexts to log")
#define REPORT_DEAD(curCtxt, lastCtxt, hashVar, size)
VOID InstructionContributionOfBBL1Byte(uint32_t count, THREADID threadId)
VOID InstructionContributionOfBBLLargeByte(uint32_t count, THREADID threadId)
#define MAX_DEAD_CONTEXTS_TO_LOG
bool DeadInfoComparer(const DeadInfo &first, const DeadInfo &second)
static void InstrumentTrace(TRACE trace, void *f)
VOID Record10ByteMemRead(VOID *addr)
#define TWO_BYTE_WRITE_ACTION
VOID InstructionContributionOfBBL8Byte(uint32_t count, THREADID threadId)
VOID Fini(INT32 code, VOID *v)
unordered_map< uint64_t, uint64_t > DeadMap
uint8_t * GetShadowBaseAddress(void *address)
#define FOUR_BYTE_READ_ACTION
void InspectMemRead(VOID *addr, UINT32 sz)
VOID InstructionContributionOfBBL2Byte(uint32_t count, THREADID threadId)
VOID ImageUnload(IMG img, VOID *v)
volatile uint32_t gClientNumThreads
void InitThreadData(DeadSpyThreadData *const tdata)
#define LEVEL_1_PAGE_TABLE_SIZE
VOID Record10ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
#define ONE_BYTE_WRITE_ACTION
#define FOUR_BYTE_WRITE_ACTION
VOID Record16ByteMemRead(VOID *addr)
static TLS_KEY client_tls_key
VOID Record1ByteMemWriteWithoutDead(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
#define REPORT_IF_DEAD(mask, curCtxt, lastCtxt, hashVar)
VOID Record4ByteMemRead(VOID *addr)
VOID PrintIPAndCallingContexts(const DeadInfoForPresentation &di, uint64_t measurementBaseCount)
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
VOID Record4ByteMemWrite(VOID *addr, const uint32_t opaqueHandle, THREADID threadId)
uint64_t GetMeasurementBaseCount()
#define LEVEL_2_PAGE_TABLE_SLOT(addr)
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
hpcrun_metricFlags_t flags
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
void SerializeMetadata(const std::string &directoryForSerializationFiles="")
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
void LogContexts(std::iostream &ios, ContextHandle_t ctxt1, ContextHandle_t ctxt2)
void AppendLoadModulesToStream(std::iostream &ios)
const MergedDeadInfo * pMergedDeadInfo
uint64_t gLargeByteWriteInstrCount
uint64_t g16ByteWriteInstrCount
uint64_t g8ByteWriteInstrCount
uint64_t g2ByteWriteInstrCount
uint64_t g4ByteWriteInstrCount
uint64_t gLargeByteWriteByteCount
uint64_t g10ByteWriteInstrCount
uint64_t g1ByteWriteInstrCount
bool operator<(const MergedDeadInfo &x) const
bool operator==(const MergedDeadInfo &x) const