int before_block_exec(CPUState *env, TranslationBlock *tb){ if (tubtf_on) { char *llvm_fn_name = (char *) tcg_llvm_get_func_name(tb); uint32_t pc, unk; sscanf(llvm_fn_name, "tcg-llvm-tb-%d-%x", &unk, &pc); env->panda_guest_pc = pc; tubtf_write_el_64(panda_current_asid(env), pc, TUBTFE_LLVM_FN, unk, 0, 0, 0); } else { fprintf(funclog, "%s\n", tcg_llvm_get_func_name(tb)); DynValBuffer *dynval_buffer = PIFP->PIV->getDynvalBuffer(); if (dynval_buffer->cur_size > 0){ // Buffer wasn't flushed before, have to flush it now fwrite(dynval_buffer->start, dynval_buffer->cur_size, 1, memlog); } clear_dynval_buffer(dynval_buffer); } return 0; }
void write_dynval_buffer(DynValBuffer *dynval_buf, DynValEntry *entry){ if (tubtf_on) { // XXX Fixme: note that when using tubt format, we still create that DynValBuffer. Waste of memory uint64_t cr3, pc, typ; uint64_t arg1, arg2, arg3, arg4; arg1 = arg2 = arg3 = arg4 = 0; assert (tubtf->colw == TUBTF_COLW_64); uint32_t element_size = tubtf_element_size(); // assert that there must be enough room in dynval buffer uint32_t bytes_used = dynval_buf->ptr - dynval_buf->start; uint32_t bytes_left = dynval_buf->max_size - bytes_used; assert (bytes_left > element_size); cr3 = panda_current_asid(env); // virtual address space -- cr3 for x86 pc = panda_current_pc(env); typ = 0; switch (entry->entrytype) { case ADDRENTRY: { LogOp op = entry->entry.memaccess.op; assert (op == LOAD ||op == STORE); Addr *a = &(entry->entry.memaccess.addr); typ = TUBTFE_LLVM_DV_LOAD; if (op == STORE) { typ = TUBTFE_LLVM_DV_STORE; } // a->type fits easily in a byte -- 1 .. 5 arg1 = (a->typ) | ((a->flag & 0xff) << 8) | (a->off << 16); uint64_t val; switch (a->typ) { case HADDR: val = a->val.ha; break; case MADDR: val = a->val.ma; break; case IADDR: val = a->val.ia; break; case LADDR: val = a->val.la; break; case GREG: val = a->val.gr; break; case GSPEC: val = a->val.gs; break; case UNK: val = a->val.ua; break; case CONST: val = a->val.con; break; case RET: val = a->val.ret; break; default: assert (1==0); } arg2 = val; break; } case PADDRENTRY: { LogOp op = entry->entry.portaccess.op; assert (op == PLOAD ||op == PSTORE); Addr *a = &(entry->entry.portaccess.addr); typ = TUBTFE_LLVM_DV_LOAD; if (op == PSTORE) { typ = TUBTFE_LLVM_DV_STORE; } // a->type fits easily in a byte -- 1 .. 5 arg1 = (a->typ) | ((a->flag & 0xff) << 8) | (a->off << 16); uint64_t val; switch (a->typ) { case PADDR: val = a->val.pa; break; default: assert (1==0); } arg2 = val; break; } case BRANCHENTRY: { typ = TUBTFE_LLVM_DV_BRANCH; arg1 = entry->entry.branch.br; break; } case SELECTENTRY: { typ = TUBTFE_LLVM_DV_SELECT; arg1 = entry->entry.select.sel; break; } case SWITCHENTRY: { typ = TUBTFE_LLVM_DV_SWITCH; arg1 = entry->entry.switchstmt.cond; break; } case EXCEPTIONENTRY: { typ = TUBTFE_LLVM_EXCEPTION; } } tubtf_write_el_64(cr3, pc, typ, arg1, arg2, arg3, arg4); } else { uint32_t bytes_used = dynval_buf->ptr - dynval_buf->start; assert(dynval_buf->max_size - bytes_used >= sizeof(DynValEntry)); memcpy(dynval_buf->ptr, entry, sizeof(DynValEntry)); dynval_buf->ptr += sizeof(DynValEntry); dynval_buf->cur_size = dynval_buf->ptr - dynval_buf->start; } }