static unat get_blkend(RuntimeBlockInfo* blk) { if (is_code(blk)) return (unat)blk; else return (unat)blk->code+blk->host_code_size-1; }
//return true if blkl > blkr bool operator()(RuntimeBlockInfo* blkl, RuntimeBlockInfo* blkr) const { if (!is_code(blkl) && !is_code(blkr)) return (unat)blkl->code<(unat)blkr->code; unat blkr_start=get_blkstart(blkr),blkl_end=get_blkend(blkl); if (blkl_end<blkr_start) { return true; } else { return false; } }
/* Format access codes nicely and try to make an educated guess regarding memory-region */ static void access_output(int acc, long long from, long long to, void *stack_frame) { if (acc == 1) /* read only */ { if (is_code(from, to)) printf("(CODE) "); else printf("(UNKN) "); printf("read access from \t \t 0x%08llx to 0x%08llx\n", from, to); } else if (acc == 2) /* read & write */ { if (is_data(from, to)) printf("(DATA) "); else if (is_heap(from, to)) printf("(HEAP) "); else if (is_stck(from, to, stack_frame)) printf("(STCK) "); else printf("(UNKN) "); printf("read and write access from \t 0x%08llx to 0x%08llx\n", from, to); } return; }
static unat get_blkstart(RuntimeBlockInfo* blk) { if (is_code(blk)) return (unat)blk; else return (unat)blk->code; }
static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); if (enable) { int ret = -EINVAL; if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); return ret; } return m5mols_mode(info, REG_PARAMETER); }
static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); u32 code; int ret; mutex_lock(&info->lock); code = info->ffmt[info->res_type].code; if (enable) { if (is_code(code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); else ret = -EINVAL; } else { ret = m5mols_set_mode(info, REG_PARAMETER); } mutex_unlock(&info->lock); return ret; }
bool is_track(char * line) { size_t length = get_line_length(line); char * bookmark = line; if (is_upper_case_letter(line[0])) bookmark += 2; else return false; int first_part_count = 0; int second_part_count = 0; int third_part_count = 0; while(bookmark < line + length && is_code(bookmark)) { bookmark += 6; first_part_count++; } while(bookmark != NULL && bookmark < line + length && is_fraction(bookmark)) { bookmark += 6; second_part_count++; } while(bookmark != NULL && bookmark < line + length && is_code(bookmark)) { bookmark += 6; third_part_count++; } return (first_part_count && second_part_count == 4 && third_part_count); }
BasicBlock * cpu_translate_all(cpu_t *cpu, BasicBlock *bb_ret, BasicBlock *bb_trap) { // find all instructions that need labels and create basic blocks for them int bbs = 0; addr_t pc; pc = cpu->code_start; while (pc < cpu->code_end) { // Do not create the basic block if it is already present in some other function. if (is_start_of_basicblock(cpu, pc) && !(get_tag(cpu, pc) & TAG_TRANSLATED)) { create_basicblock(cpu, pc, cpu->cur_func, BB_TYPE_NORMAL); bbs++; } pc++; } LOG("bbs: %d\n", bbs); // create dispatch basicblock BasicBlock* bb_dispatch = BasicBlock::Create(_CTX(), "dispatch", cpu->cur_func, 0); Value *v_pc = new LoadInst(cpu->ptr_PC, "", false, bb_dispatch); SwitchInst* sw = SwitchInst::Create(v_pc, bb_ret, bbs, bb_dispatch); // translate basic blocks bbaddr_map &bb_addr = cpu->func_bb[cpu->cur_func]; bbaddr_map::const_iterator it; for (it = bb_addr.begin(); it != bb_addr.end(); it++) { pc = it->first; BasicBlock *cur_bb = it->second; tag_t tag; BasicBlock *bb_target = NULL, *bb_next = NULL, *bb_cont = NULL; // Tag the function as translated. or_tag(cpu, pc, TAG_TRANSLATED); LOG("basicblock: L%08llx\n", (unsigned long long)pc); // Add dispatch switch case for basic block. ConstantInt* c = ConstantInt::get(getIntegerType(cpu->info.address_size), pc); sw->addCase(c, cur_bb); do { tag_t dummy1; if (LOGGING) disasm_instr(cpu, pc); tag = get_tag(cpu, pc); /* get address of the following instruction */ addr_t new_pc, next_pc; cpu->f.tag_instr(cpu, pc, &dummy1, &new_pc, &next_pc); /* get target basic block */ if (tag & TAG_RET) bb_target = bb_dispatch; if (tag & (TAG_CALL|TAG_BRANCH)) { if (new_pc == NEW_PC_NONE) /* translate_instr() will set PC */ bb_target = bb_dispatch; else bb_target = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, new_pc, bb_ret, BB_TYPE_NORMAL); } /* get not-taken basic block */ if (tag & TAG_CONDITIONAL) bb_next = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, next_pc, bb_ret, BB_TYPE_NORMAL); bb_cont = translate_instr(cpu, pc, tag, bb_target, bb_trap, bb_next, cur_bb); pc = next_pc; } while ( /* new basic block starts here (and we haven't translated it yet)*/ (!is_start_of_basicblock(cpu, pc)) && /* end of code section */ //XXX no: this is whether it's TAG_CODE is_code(cpu, pc) && /* last intruction jumped away */ bb_cont ); /* link with next basic block if there isn't a control flow instr. already */ if (bb_cont) { BasicBlock *target = (BasicBlock*)lookup_basicblock(cpu, cpu->cur_func, pc, bb_ret, BB_TYPE_NORMAL); LOG("info: linking continue $%04llx!\n", (unsigned long long)pc); BranchInst::Create(target, bb_cont); } } return bb_dispatch; }
byte * _f_handler_inst_gen_1op(byte * inst) { dword rtype, arg1, arg2; MODREGDEC(inst+1,arg1,arg2,rtype); dword target; it_inner_entry *it; /* TODO embbed this on the mphash */ switch (arg2) { case INST_GEN_CALL: if (rtype == smod_reg_RR) { flux_staple(RADDR(inst),2); return inst+2; } target = *(dword*)(inst+2); log_debug("CALL to %X",target); if (!is_code(target,&it)) { if (it) { /* maybe examine here the arguments for ease of analysis? */ log_debug("External function (%s) (%s)",it->name,it->libname); if (!strcmp("ExitProcess",it->name)) { /* its an exit process, function ends here */ do_ret(RADDR(inst),6); log_debug("exit function reached"); return 0; } } } else { //return (byte*)target; /* queue function for analysis */ } flux_staple(RADDR(inst),6); return inst+6; case INST_GEN_JMP: target = *(dword*)(inst+2); it_inner_entry * it; if (!is_code(target,&it)) { log_debug("JMP to outside, assuming ret"); /* this is used normally to call external functions in a relloc fashion, assume RET here */ do_ret(RADDR(inst),6); return 0; } else { } flux_staple(RADDR(inst),6); return inst+6; case INST_GEN_JMPF: /* jmp far, let's check the target */ break; case INST_GEN_INC: case INST_GEN_DEC: case INST_GEN_CALLF: /* this is a register call, we must flag it, but we cannot know what was called right now */ case INST_GEN_PUSH: if (rtype == smod_reg_IR) { if (arg1 == mod_reg_EBP) { /* not really ebp here, but disp32 */ flux_staple(RADDR(inst),6); return inst+6; } if (arg1 == mod_reg_SIB) { MODREGDEC(inst+2,arg1,arg2,rtype); flux_staple(RADDR(inst),7); return inst+7; } flux_staple(RADDR(inst),2); return inst+2; } if (rtype == smod_reg_I8R) { flux_staple(RADDR(inst),3); return inst+3; } if (rtype == smod_reg_RR) { flux_staple(RADDR(inst),2); return inst+2; } flux_staple(RADDR(inst),6); return inst+6; break; } return inst; }