/* * MemoryWrite, StackWrite * If store occurs and that address was used for read, make a log */ VOID MemoryWrite(ADDRINT memaddr, ADDRINT writesize) { treeNode *node; ADDRINT startoffset, endoffset; PIN_RWMutexReadLock(&data_lock); node = FindAddressInRange(data_root, memaddr); PIN_RWMutexUnlock(&data_lock); if(node && node->usedforread == TRUE) { startoffset = memaddr - node->address + node->offset; endoffset = memaddr - node->address + node->offset + writesize; fprintf(trace, "%x%lx:%s:%lx:%lx:D\n", pid, node->readid, node->path, startoffset, endoffset); fflush(trace); return; } PIN_RWMutexReadLock(&malloc_lock); node = FindAddressInRange(malloc_root, memaddr); PIN_RWMutexUnlock(&malloc_lock); if(node && node->usedforread == TRUE) { startoffset = memaddr - node->address + node->offset; endoffset = memaddr - node->address + node->offset + writesize; fprintf(trace, "%x%lx:%s:%lx:%lx:M\n", pid, node->readid, node->path, startoffset, endoffset); fflush(trace); return; } }
static void DoTestReaderStress(THREAD_INFO *info, UINT32 *done) { // This test just tries to acquire and release PIN_RWMUTEX as fast as possible // as a reader lock. PIN_RWMutexReadLock(&RWMutex); PIN_RWMutexUnlock(&RWMutex); CheckIfDone(info, done); }
/* * Return * Called when native procedure returns * Delete read info of removed stack area */ VOID Return(ADDRINT sp) { PIN_THREAD_UID threadid = PIN_ThreadUid(); PIN_RWMutexReadLock(&thread_lock); THREAD* thread = FindThread(threadid); PIN_RWMutexUnlock(&thread_lock); treeNode *node = FindMinAddress(thread->stack); if(node == NULL) return; while(node->address <= sp) { thread->stack = DeleteAddress(thread->stack, node->address); node = FindMinAddress(thread->stack); if(node == NULL) return; } }
VOID StackWrite(ADDRINT memaddr, ADDRINT writesize) { treeNode *node; PIN_THREAD_UID threadid = PIN_ThreadUid(); ADDRINT startoffset, endoffset; PIN_RWMutexReadLock(&thread_lock); THREAD* thread = FindThread(threadid); PIN_RWMutexUnlock(&thread_lock); node = FindAddressInRange(thread->stack, memaddr); if(node && node->usedforread == TRUE) { startoffset = memaddr - node->address + node->offset; endoffset = memaddr - node->address + node->offset + writesize; fprintf(trace, "%x%lx:%s:%lx:%lx:S\n", pid, node->readid, node->path, startoffset, endoffset); fflush(trace); } }
static void DoTestReaderWriterIntegrity(THREAD_INFO *info, UINT32 *done) { // This test checks that a "writer" thread can never hold the lock while // there is an active reader. if (info->_workerId & 1) { // Reader thread. // PIN_RWMutexReadLock(&RWMutex); ATOMIC::OPS::Increment(&ActiveReaders, 1); if (ATOMIC::OPS::Load(&IsActiveWriter)) { std::cout << "Reader got lock while there is an active writer" << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); ATOMIC::OPS::Increment(&ActiveReaders, -1); PIN_RWMutexUnlock(&RWMutex); } else { // Writer thread. // PIN_RWMutexWriteLock(&RWMutex); ATOMIC::OPS::Store<BOOL>(&IsActiveWriter, TRUE); if (ATOMIC::OPS::Load(&ActiveReaders) != 0) { std::cout << "Writer has lock while there are active readers" << std::endl; PIN_ExitProcess(1); } ATOMIC::OPS::Delay(DELAY_COUNT); ATOMIC::OPS::Store<BOOL>(&IsActiveWriter, FALSE); PIN_RWMutexUnlock(&RWMutex); } CheckIfDone(info, done); }
static void DoTestReaderWriterStress(THREAD_INFO *info, UINT32 *done) { // This test uses a mix of "reader" and "writer" threads to acquire and // release the PIN_RWMUTEX as fast as possible. if (info->_workerId & 1) { // Reader thread. // PIN_RWMutexReadLock(&RWMutex); PIN_RWMutexUnlock(&RWMutex); } else { // Writer thread. // PIN_RWMutexWriteLock(&RWMutex); PIN_RWMutexUnlock(&RWMutex); } CheckIfDone(info, done); }
/* * SysBefore * Our focus is on "read" syscall, so it traces only read-like syscalls - read, readv, pread, preadv */ VOID SysBefore(ADDRINT ip, ADDRINT num, ADDRINT arg0, ADDRINT arg1, ADDRINT arg2, ADDRINT arg3, ADDRINT arg4, ADDRINT arg5, ADDRINT sp) { treeNode *node; struct stat stat; off_t offset; char buf[2][MAX_BUFSIZE]; int tmp; int i; long unsigned int readid; long unsigned int size; struct iovec *vec; PIN_THREAD_UID threadid = PIN_ThreadUid(); PIN_RWMutexReadLock(&thread_lock); THREAD* thread = FindThread(threadid); PIN_RWMutexUnlock(&thread_lock); assert(thread); switch(num) { case SYS_READ: case SYS_PREAD64: //arg0 : fd //arg1 : buf addr //arg2 : buf size //stdin if(arg0 == 0) break; //Get the path of current file sprintf(buf[0], "/proc/self/fd/%d", (int)arg0); tmp = readlink(buf[0], buf[1], MAX_BUFSIZE); //Skip socket, pipe, proc filesystem, etc if(buf[1][0] != '/') break; if(strncmp(buf[1], "/proc", 5) == 0) break; else if(strncmp(buf[1], "/dev/urandom", 12)== 0) break; buf[1][tmp] = '\0'; if(num == SYS_READ) { //If SYS_READ, we have to find out current file pointer offset = lseek((int)arg0, 0, SEEK_CUR); if(offset+1 == 0) offset = 0; } else { //Or pread case, file pointer is given offset = arg3; } //Get the file size size = fstat((int)arg0, &stat); assert(size == 0); size = stat.st_size; if(offset+arg2 > size) size = size - offset; else size = arg2; if(size <= 0) break; //Get Unique ID for each Read readid = GetReadId(); sprintf(thread->buffer, "%s:%lx:%lx:%lx:", buf[1], offset, size, stat.st_size); /* * Add Read Info to Data Structure * * Find the buffer address in malloc BST * if found, write the info to it * else * Buffer is in stack or data segment */ PIN_RWMutexReadLock(&malloc_lock); node = FindAddressInRange(malloc_root, arg1); PIN_RWMutexUnlock(&malloc_lock); if(node != NULL) { node->usedforread = TRUE; node->offset = offset; node->fd = (int)arg0; if(node->path != NULL) free(node->path); node->path = strdup(buf[1]); node->size = size; node->readid = readid; strcat(thread->buffer, "M"); } else if(arg1 >= sp - pagesize) { thread->stack = InsertSAddress(thread->stack, arg1, (int)arg0, size, offset, buf[1], readid); strcat(thread->buffer, "S"); } else { PIN_RWMutexWriteLock(&data_lock); data_root = InsertDAddress(data_root, arg1, (int)arg0, size, offset, buf[1], readid); PIN_RWMutexUnlock(&data_lock); strcat(thread->buffer, "D"); } fprintf(trace, "%s\n", thread->buffer); fflush(trace); break; case SYS_PREADV: case SYS_READV: //arg0 : fd //arg1 : iov //arg2 : iovcnt //iovec.iov_base : address //iovec.iov_len : length //stdin if(arg0 == 0) break; sprintf(buf[0], "/proc/self/fd/%d", (int)arg0); tmp = readlink(buf[0], buf[1], MAX_BUFSIZE); if(buf[1][0] != '/') break; if(strncmp(buf[1], "/proc", 5) == 0) break; readid = GetReadId(); buf[1][tmp] = '\0'; if(num == SYS_READV) { offset = lseek((int)arg0, 0, SEEK_CUR); if(offset+1 == 0) offset = 0; } else offset = arg3; size = fstat((int)arg0, &stat); assert(size == 0); vec = (struct iovec *)arg1; for(i=0; i < (int)arg2; i++) { size = stat.st_size; if(offset+vec[i].iov_len > size) size = size - offset; else size = vec[i].iov_len; if(size <= 0) continue; PIN_RWMutexReadLock(&malloc_lock); node = FindAddressInRange(malloc_root, (ADDRINT)vec[i].iov_base); PIN_RWMutexUnlock(&malloc_lock); sprintf(thread->buffer, "%s:%lx:%lx:%lx:",buf[1], offset, size, stat.st_size); if(node != NULL) { strcat(thread->buffer, "M"); node->usedforread = TRUE; node->offset = offset; node->fd = (int)arg0; if(node->path != NULL) free(node->path); node->path = strdup(buf[1]); node->size = size; node->readid = readid; } else if(arg1 >= sp - pagesize) { strcat(thread->buffer, "S"); thread->stack = InsertSAddress(thread->stack, arg1, (int)arg0, size, offset, buf[1], readid); } else { strcat(thread->buffer, "D"); PIN_RWMutexWriteLock(&data_lock); data_root = InsertDAddress(data_root, arg1, (int)arg0, size, offset, buf[1], readid); PIN_RWMutexUnlock(&data_lock); } fprintf(trace, "%s\n", thread->buffer); fflush(trace); } break; /* case SYS_WRITE: case SYS_PWRITE64: if(arg0 == 1 || arg0 == 2) break; if(num == SYS_WRITE) { offset = lseek((int)arg0, 0, SEEK_CUR); if(offset + 1 == 0) offset = 0; } else offset = arg3; sprintf(thread->buffer, "%lx:%lx:%lx:%lx:%lx:", num, arg0, arg1, arg2, offset); break; case SYS_PWRITEV: case SYS_WRITEV: //stdin if(arg0 == 0) break; sprintf(buf[0], "/proc/self/fd/%d", (int)arg0); tmp = readlink(buf[0], buf[1], MAX_BUFSIZE); buf[1][tmp] = '\0'; if(num == SYS_PWRITEV) { offset = lseek((int)arg0, 0, SEEK_CUR); if(offset + 1 == 0) offset = 0; } else offset = arg3; vec = (struct iovec *)arg1; for(i=0; i < (int)arg2; i++) { sprintf(thread->buffer, "%lx:%lx:%lx:%lx:%lx:", num, arg0, (ADDRINT)vec[i].iov_base, vec[i].iov_len, offset); } break; */ default : break; } }