void terminate_IPC(int idx) { ipc_channel_t *channel = &IPC[idx]; if (channel->standalone) { dr_raw_mem_free(channel->shared_mem, sizeof(Sigil2DBISharedData)); } else { /* send terminate sequence */ uint finished = SIGIL2_IPC_FINISHED; uint last_buffer = channel->shmem_buf_idx; if(dr_write_file(channel->full_fifo, &last_buffer, sizeof(last_buffer)) != sizeof(last_buffer) || dr_write_file(channel->full_fifo, &finished, sizeof(finished)) != sizeof(finished)) DR_ABORT_MSG("error writing finish sequence sigil2 fifos"); /* wait for sigil2 to disconnect */ while(dr_read_file(channel->empty_fifo, &finished, sizeof(finished)) > 0); dr_close_file(channel->empty_fifo); dr_close_file(channel->full_fifo); dr_unmap_file(channel->shared_mem, sizeof(Sigil2DBISharedData)); } dr_global_free((void*)channel->ticket_queue.head, sizeof(ticket_queue_t)); dr_mutex_destroy(channel->queue_lock); }
static void instrace(void *drcontext) { per_thread_t *data; int num_refs; ins_ref_t *ins_ref; #ifdef OUTPUT_TEXT int i; #endif data = drmgr_get_tls_field(drcontext, tls_index); ins_ref = (ins_ref_t *)data->buf_base; num_refs = (int)((ins_ref_t *)data->buf_ptr - ins_ref); #ifdef OUTPUT_TEXT /* We use libc's fprintf as it is buffered and much faster than dr_fprintf * for repeated printing that dominates performance, as the printing does here. */ for (i = 0; i < num_refs; i++) { /* We use PIFX to avoid leading zeroes and shrink the resulting file. */ fprintf(data->logf, PIFX",%s\n", (ptr_uint_t)ins_ref->pc, decode_opcode_name(ins_ref->opcode)); ++ins_ref; } #else dr_write_file(data->log, data->buf_base, (size_t)(data->buf_ptr - data->buf_base)); #endif memset(data->buf_base, 0, MEM_BUF_SIZE); data->num_refs += num_refs; data->buf_ptr = data->buf_base; }
static inline void notify_full_buffer(ipc_channel_t *channel) { /* Tell Sigil2 that the active buffer, on the given IPC channel, * is full and ready to be consumed */ if (channel->standalone == false) dr_write_file(channel->full_fifo, &channel->shmem_buf_idx, sizeof(channel->shmem_buf_idx)); /* Flag the shared memory buffer as used (by Sigil2) */ channel->empty_buf_idx[channel->shmem_buf_idx] = false; }
static void do_mem_dump(file_t file, uint base_pc,uint size){ uint read; bool ok; byte * mem_values = dr_global_alloc(sizeof(byte) * size); ssize_t written; ok = dr_safe_read(base_pc, size, mem_values, &read); DR_ASSERT(ok); written = dr_write_file(file, mem_values, size); DEBUG_PRINT("read %d from %x of size %d and written %d\n", read, base_pc, size, written); dr_global_free(mem_values, sizeof(byte) * size); }
drcovlib_status_t drmodtrack_dump(file_t log) { drcovlib_status_t res; size_t size = 200 + module_table.vector.entries * (MAXIMUM_PATH + 40); char *buf; do { buf = dr_global_alloc(size); res = drmodtrack_dump_buf(buf, size); if (res == DRCOVLIB_SUCCESS) dr_write_file(log, buf, strlen(buf)); dr_global_free(buf, size); size *= 2; } while (res == DRCOVLIB_ERROR_BUF_TOO_SMALL); return res; }
void tb_flush(struct trace_buffer_t* tb) { size_t size; int64 pos; size_t written; void* aligned_current; tb_tlv_complete(tb); // Align current position to block boundary. aligned_current = aligned_block(tb->current); memset(tb->current, 'X', aligned_current - tb->current); tb->current = aligned_current; size = tb->current - (void*)&tb->block; if(size == sizeof(struct block_t)) { // Nothing to do. return; } tb->block.length = (uint32_t)size; tb->block.crc32 = 0; tb->block.crc32 = crc32((char*)&tb->block, size); // Write data. dr_mutex_lock(tb->mutex); pos = dr_file_tell(tb->file); if(pos == -1) { dr_fprintf(STDERR, "fatal: dr_file_tell() failed\n"); dr_exit_process(1); } dr_fprintf(STDERR, "info: flushing tb=%p file-offset=%" PRId64 " size=%u" " tb-thread=0x%" PRIx64 " current-thread=0x%" PRIx64 "\n", tb, pos, (unsigned int)size, tb->block.thread_id, (uint64_t)dr_get_thread_id(dr_get_current_drcontext())); written = dr_write_file(tb->file, &tb->block, size); dr_mutex_unlock(tb->mutex); if(written != size) { dr_fprintf(STDERR, "fatal: dr_write_file() failed\n"); dr_exit_process(1); } // Reset position. tb->current = tb + 1; }
static void memtrace(void *drcontext) { per_thread_t *data; int num_refs; mem_ref_t *mem_ref; #ifdef READABLE_TRACE int i; #endif module_data_t * mdata; data = drmgr_get_tls_field(drcontext, tls_index); mem_ref = (mem_ref_t *)data->buf_base; num_refs = (int)((mem_ref_t *)data->buf_ptr - mem_ref); #ifdef READABLE_TRACE /*dr_fprintf(data->log, "Format: <instr address>,<(r)ead/(w)rite>,<data size>,<data address>\n");*/ for (i = 0; i < num_refs; i++) { mdata = dr_lookup_module(mem_ref->pc); if (mdata != NULL){ if (((uint)mem_ref->addr > data->stack_base) || ((uint)mem_ref->addr < data->stack_limit)){ dr_fprintf(data->outfile, "%x,%x,%d,%d,"PFX"\n", mdata->start, mem_ref->pc - mdata->start , mem_ref->write ? 1 : 0 , mem_ref->size, mem_ref->addr); } dr_free_module_data(mdata); } ++mem_ref; } #else dr_write_file(data->log, data->buf_base, (size_t)(data->buf_ptr - data->buf_base)); #endif memset(data->buf_base, 0, MEM_BUF_SIZE); data->num_refs += num_refs; data->buf_ptr = data->buf_base; }
/* prints the trace and empties the instruction buffer */ static void ins_trace(void *drcontext) { per_thread_t *data; int num_refs; instr_trace_t *instr_trace; instr_t * instr; int i; int j; #ifdef READABLE_TRACE char disassembly[SHORT_STRING_LENGTH]; #else output_t * output; #endif data = drmgr_get_tls_field(drcontext, tls_index); instr_trace = (instr_trace_t *)data->buf_base; num_refs = (int)((instr_trace_t *)data->buf_ptr - instr_trace); uint mem_type; uint64 mem_addr; opnd_t opnd; #ifdef READABLE_TRACE //TODO for (i = 0; i < num_refs; i++) { instr = instr_trace->static_info_instr; instr_disassemble_to_buffer(drcontext,instr,disassembly,SHORT_STRING_LENGTH); dr_fprintf(data->outfile,"%u",instr_get_opcode(instr)); dr_fprintf(data->outfile,",%u",calculate_operands(instr,DST_TYPE)); for(j=0; j<instr_num_dsts(instr); j++){ get_address(instr_trace, j, DST_TYPE, &mem_type, &mem_addr); output_populator_printer(drcontext,instr_get_dst(instr,j),instr,mem_addr,mem_type,NULL); } dr_fprintf(data->outfile,",%u",calculate_operands(instr,SRC_TYPE)); for(j=0; j<instr_num_srcs(instr); j++){ get_address(instr_trace, j, SRC_TYPE, &mem_type, &mem_addr); opnd = instr_get_src(instr, j); if (instr_get_opcode(instr) == OP_lea && opnd_is_base_disp(opnd)){ /* four operands here for [base + index * scale + disp] */ output_populator_printer(drcontext, opnd_create_reg(opnd_get_base(opnd)), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_reg(opnd_get_index(opnd)), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_immed_int(opnd_get_scale(opnd),OPSZ_PTR), instr, mem_addr, mem_type, NULL); output_populator_printer(drcontext, opnd_create_immed_int(opnd_get_disp(opnd), OPSZ_PTR), instr, mem_addr, mem_type, NULL); } else{ output_populator_printer(drcontext, opnd, instr, mem_addr, mem_type, NULL); } } dr_fprintf(data->outfile,",%u,%u\n",instr_trace->eflags,instr_trace->pc); ++instr_trace; } #else /* we need to fill up the output array here */ for(i = 0; i< num_refs; i++){ instr = instr_trace->static_info_instr; output = &data->output_array[i]; //opcode output->opcode = instr_get_opcode(instr); output->num_dsts = 0; output->num_srcs = 0; for(j=0; j<instr_num_dsts(instr); j++){ output_populator_printer(drcontext,instr_get_dst(instr,j),instr,get_address(instr_trace,j,DST_TYPE),&output->dsts[output->num_dsts]); output->num_dsts++; } for(j=0; j<instr_num_srcs(instr); j++){ output_populator_printer(drcontext,instr_get_src(instr,j),instr,get_address(instr_trace,j,SRC_TYPE),&output->srcs[output->num_srcs]); output->num_srcs++; } output->eflags = instr_trace->eflags; ++instr_trace; } dr_write_file(data->outfile,data->output_array,num_refs * sizeof(output_t)); #endif memset(data->buf_base, 0, INSTR_BUF_SIZE); data->num_refs += num_refs; data->buf_ptr = data->buf_base; }
/* caller must hold symcache_lock */ static void symcache_write_symfile(const char *modname, mod_cache_t *modcache) { uint i; file_t f; hashtable_t *symtable = &modcache->table; char buf[SYMCACHE_BUFFER_SIZE]; size_t sofar = 0; ssize_t len; size_t bsz = BUFFER_SIZE_ELEMENTS(buf); size_t filesz_loc; char symfile[MAXIMUM_PATH]; char symfile_tmp[MAXIMUM_PATH]; int64 file_size; ASSERT(dr_mutex_self_owns(symcache_lock), "missing symcache lock"); /* if from file, we assume it's a waste of time to re-write file: * the version matched after all, unless we appended to it. */ if (modcache->from_file && !modcache->appended) return; if (symtable->entries == 0) return; /* nothing to write */ /* Open the temp symcache that we will rename. */ symcache_get_filename(modname, symfile, BUFFER_SIZE_ELEMENTS(symfile)); f = INVALID_FILE; i = 0; while (f == INVALID_FILE && i < SYMCACHE_MAX_TMP_TRIES) { dr_snprintf(symfile_tmp, BUFFER_SIZE_ELEMENTS(symfile_tmp), "%s.%04d.tmp", symfile, i); NULL_TERMINATE_BUFFER(symfile_tmp); f = dr_open_file(symfile_tmp, DR_FILE_WRITE_REQUIRE_NEW); i++; } if (f == INVALID_FILE) { NOTIFY("WARNING: Unable to create symcache temp file %s"NL, symfile_tmp); return; } BUFFERED_WRITE(f, buf, bsz, sofar, len, "%s %d\n", SYMCACHE_FILE_HEADER, SYMCACHE_VERSION); /* Leave room for file size for self-consistency check */ filesz_loc = sofar; /* XXX: Assumes that the buffer hasn't been flushed. */ BUFFERED_WRITE(f, buf, bsz, sofar, len, "%"STRINGIFY(SYMCACHE_SIZE_DIGITS)"u,", 0); #ifdef WINDOWS BUFFERED_WRITE(f, buf, bsz, sofar, len, UINT64_FORMAT_STRING","UINT64_FORMAT_STRING"," UINT64_FORMAT_STRING",%u,%u,%lu\n", modcache->module_file_size, modcache->file_version.version, modcache->product_version.version, modcache->checksum, modcache->timestamp, modcache->module_internal_size); #else BUFFERED_WRITE(f, buf, bsz, sofar, len, UINT64_FORMAT_STRING",%u", modcache->module_file_size, modcache->timestamp); # ifdef MACOS BUFFERED_WRITE(f, buf, bsz, sofar, len, ",%u,%u,", modcache->current_version, modcache->compatibility_version); /* For easy sscanf we print as 4 ints */ for (i = 0; i < 4; i++) BUFFERED_WRITE(f, buf, bsz, sofar, len, "%08x,", *(int*)(&modcache->uuid[i*4])); # endif BUFFERED_WRITE(f, buf, bsz, sofar, len, "\n"); #endif BUFFERED_WRITE(f, buf, bsz, sofar, len, "%u\n", modcache->has_debug_info); for (i = 0; i < HASHTABLE_SIZE(symtable->table_bits); i++) { hash_entry_t *he; for (he = symtable->table[i]; he != NULL; he = he->next) { offset_list_t *olist = (offset_list_t *) he->payload; offset_entry_t *e; if (olist == NULL) continue; /* skip symbol in dup entries to save space */ BUFFERED_WRITE(f, buf, bsz, sofar, len, "%s", he->key); e = olist->list; while (e != NULL) { BUFFERED_WRITE(f, buf, bsz, sofar, len, ",0x%x\n", e->offs); e = e->next; } } } /* now update size */ FLUSH_BUFFER(f, buf, sofar); if ((file_size = dr_file_tell(f)) < 0 || dr_snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "%"STRINGIFY(SYMCACHE_SIZE_DIGITS)"u", (uint)file_size) < 0 || !dr_file_seek(f, filesz_loc, DR_SEEK_SET) || dr_write_file(f, buf, SYMCACHE_SIZE_DIGITS) != SYMCACHE_SIZE_DIGITS) { /* If any steps fail, warn and give up. */ NOTIFY("WARNING: Unable to write symcache file size."NL); dr_close_file(f); dr_delete_file(symfile_tmp); return; } else { LOG(3, "Wrote symcache %s file size %u to pos "SZFMT"\n", modname, (uint)file_size, filesz_loc); ASSERT(strlen(buf) <= SYMCACHE_SIZE_DIGITS, "not enough space for file size"); } dr_close_file(f); if (!dr_rename_file(symfile_tmp, symfile, /*replace*/true)) { NOTIFY_ERROR("WARNING: Failed to rename the symcache file."NL); dr_delete_file(symfile_tmp); } }
static bool hash_write_file(file_t fd, void *ptr, size_t sz) { return (dr_write_file(fd, ptr, sz) == (ssize_t)sz); }