bool FPFilterFunc::filter(InstructionAPI::Instruction::Ptr inst, FPDecoder* decoder) { unsigned char buffer[64]; int size = inst->size(); memcpy(buffer, inst->ptr(), size); return decoder->filter(buffer, size); }
CFWidget::CFWidget(InstructionAPI::Instruction::Ptr insn, Address addr) : isCall_(false), isConditional_(false), isIndirect_(false), gap_(0), insn_(insn), addr_(addr), origTarget_(0) { // HACK to be sure things are parsed... insn->format(); for (Instruction::cftConstIter iter = insn->cft_begin(); iter != insn->cft_end(); ++iter) { if (iter->isCall) isCall_ = true; if (iter->isIndirect) isIndirect_ = true; if (iter->isConditional) isConditional_ = true; } #if 0 // Old way if (insn->getCategory() == c_CallInsn) { // Calls have a fallthrough but are not conditional. // TODO: conditional calls work how? isCall_ = true; } else if (insn->allowsFallThrough()) { isConditional_ = true; } #endif // This whole next section is obsolete, but IAPI's CFT interface doesn't say // what a "return" is (aka, they don't include "indirect"). So I'm using it // so that things work. // TODO: IAPI is recording all PPC64 instructions as PPC32. However, the // registers they use are still PPC64. This is a pain to fix, and therefore // I'm working around it here and in Movement-adhoc.C by checking _both_ // 32- and 64-bit. Architecture fixme = insn_->getArch(); if (fixme == Arch_ppc32) fixme = Arch_ppc64; Expression::Ptr thePC(new RegisterAST(MachRegister::getPC(insn_->getArch()))); Expression::Ptr thePCFixme(new RegisterAST(MachRegister::getPC(fixme))); Expression::Ptr exp = insn_->getControlFlowTarget(); exp->bind(thePC.get(), Result(u64, addr_)); exp->bind(thePCFixme.get(), Result(u64, addr_)); Result res = exp->eval(); if (!res.defined) { if (!isIndirect_) { isIndirect_ = true; } } }
CFPatch::CFPatch(Type a, InstructionAPI::Instruction::Ptr b, TargetInt *c, const func_instance *d, Address e) : type(a), orig_insn(b), target(c), func(d), origAddr_(e) { if (b) ugly_insn = new instruction(b->ptr()); else ugly_insn = NULL; }
bool IA_IAPI::savesFP() const { std::vector<Instruction::Ptr> insns; insns.push_back(curInsn()); #if defined(os_windows) // Windows functions can start with a noop... InstructionDecoder tmp(dec); insns.push_back(tmp.decode()); #endif for (unsigned i = 0; i < insns.size(); ++i) { InstructionAPI::Instruction::Ptr ci = insns[i]; if(ci->getOperation().getID() == e_push) { if (ci->isRead(framePtr[_isrc->getArch()])) { return true; } else return false; } } return false; }
bool SymEval::expandInsn(const InstructionAPI::Instruction::Ptr insn, const uint64_t addr, Result_t &res) { SymEvalPolicy policy(res, addr, insn->getArch(), insn); SgAsmInstruction *roseInsn; switch(insn->getArch()) { case Arch_x86: { RoseInsnX86Factory fac; roseInsn = fac.convert(insn, addr); SymbolicExpansion exp; exp.expandX86(roseInsn, policy); break; } case Arch_ppc32: { RoseInsnPPCFactory fac; roseInsn = fac.convert(insn, addr); SymbolicExpansion exp; exp.expandPPC(roseInsn, policy); break; } default: assert(0 && "Unimplemented symbolic expansion architecture"); break; } if (policy.failedTranslate()) { cerr << "Warning: failed semantic translation of instruction " << insn->format() << endl; return false; } return true; }
bool IA_x86Details::isMovAPSTable(std::vector<std::pair< Address, EdgeTypeEnum > >& outEdges) { /** * AMD-64 gcc emits a re-accuring idiom of: * jmpq *%r8 * movaps %xmm7,-0xf(%rax) * movaps %xmm6,-0x1f(%rax) * movaps %xmm5,-0x2f(%rax) * movaps %xmm4,-0x3f(%rax) * movaps %xmm3,-0x4f(%rax) * movaps %xmm2,-0x5f(%rax) * movaps %xmm1,-0x6f(%rax) * movaps %xmm0,-0x7f(%rax) * <other> * * The jump register is calculated in such a way that it'll be difficult * for our analysis to figure it out. Instead we'll recognize the pattern * of the 'movaps'. Note that the following instruction is also a valid jump * target **/ parsing_printf("\tChecking for movaps table at 0x%lx...\n", currentBlock->current); std::set<Address> found; const unsigned char *bufferBegin = (const unsigned char *)currentBlock->_isrc->getPtrToInstruction(currentBlock->current); if( bufferBegin == NULL ) { parsing_printf("%s[%d]: failed to get pointer to instruction by offset\n", FILE__, __LINE__); return false; } unsigned int size = (currentBlock->_cr->offset() + currentBlock->_cr->length()) - currentBlock->current; InstructionDecoder d(bufferBegin, size, currentBlock->_isrc->getArch()); Address cur = currentBlock->current; unsigned last_insn_size = 0; InstructionAPI::Instruction::Ptr i = d.decode(); cur += i->size(); InstructionAPI::Instruction::Ptr insn; while (NULL != (insn = d.decode())) { //All insns in sequence are movaps parsing_printf("\t\tChecking instruction %s\n", insn->format().c_str()); if (insn->getOperation().getID() != e_movapd && insn->getOperation().getID() != e_movaps) { break; } //All insns are same size if (last_insn_size == 0) last_insn_size = insn->size(); else if (last_insn_size != insn->size()) break; found.insert(cur); cur += insn->size(); } if (found.size() == 8) { found.insert(cur); //It's a match for (std::set<Address>::iterator i=found.begin(); i != found.end(); i++) { outEdges.push_back(std::make_pair(*i, INDIRECT)); } parsing_printf("\tfound\n"); return true; } parsing_printf("\tnot found (%d insns)\n", found.size()); return false; }
bool IA_powerDetails::scanForAdjustOrBase(IA_IAPI::allInsns_t::const_iterator start, IA_IAPI::allInsns_t::const_iterator end, RegisterAST::Ptr &jumpAddrReg) { std::set<RegisterAST::Ptr> scratchRegs; std::set<RegisterAST::Ptr> loadRegs; loadRegs.insert(jumpAddrReg); for (; start != end; --start) { InstructionAPI::Instruction::Ptr insn = start->second; parsing_printf("\t\t Examining 0x%lx / %s\n", start->first, start->second->format().c_str()); if ((insn->getOperation().getID() == power_op_ld || insn->getOperation().getID() == power_op_ldx) && insn->isWritten(jumpAddrReg)) { scratchRegs.clear(); insn->getReadSet(scratchRegs); loadRegs.insert(scratchRegs.begin(), scratchRegs.end()); parsing_printf("Found a load; now have %d load regs\n", loadRegs.size()); } else if(insn->getOperation().getID() == power_op_addi && !foundAdjustEntry) { parsing_printf("Found add immediate (%d load regs)...\n", loadRegs.size()); scratchRegs.clear(); insn->getWriteSet(scratchRegs); bool found = false; // This is apparently broken for (std::set<RegisterAST::Ptr>::iterator iter = loadRegs.begin(); iter != loadRegs.end(); ++iter) { RegisterAST *tmp = (*iter).get(); RegisterAST *cmp = (*(scratchRegs.begin())).get(); if (*tmp == *cmp) { found = true; break; } } if (!found) continue; parsing_printf("... that adds to a load reg\n"); foundAdjustEntry = true; toc_visitor->clear(); parsing_printf("... with operand %s\n", insn->getOperand(1).format(insn->getArch(), start->first).c_str()); insn->getOperand(1).getValue()->apply(toc_visitor.get()); adjustEntry = toc_visitor->result; if (!adjustEntry) insn->getOperand(2).getValue()->apply(toc_visitor.get()); adjustEntry = toc_visitor->result; } else if((insn->getOperation().getID() == power_op_lwz || insn->getOperation().getID() == power_op_ld) && insn->isRead(toc_reg) && insn->isWritten(jumpAddrReg)) { parsing_printf("\t found TOC load at %s\n", insn->format().c_str()); toc_visitor->clear(); insn->getOperand(1).getValue()->apply(toc_visitor.get()); tableStartAddress = toc_visitor->result; break; } } return true; }
void AbsRegionConverter::convertAll(InstructionAPI::Instruction::Ptr insn, Address addr, ParseAPI::Function *func, ParseAPI::Block *block, std::vector<AbsRegion> &used, std::vector<AbsRegion> &defined) { if (!usedCache(addr, func, used)) { std::set<RegisterAST::Ptr> regsRead; insn->getReadSet(regsRead); for (std::set<RegisterAST::Ptr>::const_iterator i = regsRead.begin(); i != regsRead.end(); ++i) { used.push_back(AbsRegionConverter::convert(*i)); } if (insn->readsMemory()) { std::set<Expression::Ptr> memReads; insn->getMemoryReadOperands(memReads); for (std::set<Expression::Ptr>::const_iterator r = memReads.begin(); r != memReads.end(); ++r) { used.push_back(AbsRegionConverter::convert(*r, addr, func, block)); } } } if (!definedCache(addr, func, defined)) { // Defined time std::set<RegisterAST::Ptr> regsWritten; insn->getWriteSet(regsWritten); for (std::set<RegisterAST::Ptr>::const_iterator i = regsWritten.begin(); i != regsWritten.end(); ++i) { defined.push_back(AbsRegionConverter::convert(*i)); } // special case for repeat-prefixed instructions on x86 // may disappear if Dyninst's representation of these instructions changes if (insn->getArch() == Arch_x86) { prefixEntryID insnPrefix = insn->getOperation().getPrefixID(); if ( (prefix_rep == insnPrefix) || (prefix_repnz == insnPrefix) ) { defined.push_back(AbsRegionConverter::convert(RegisterAST::Ptr( new RegisterAST(MachRegister::getPC(Arch_x86))))); } } if (insn->writesMemory()) { std::set<Expression::Ptr> memWrites; insn->getMemoryWriteOperands(memWrites); for (std::set<Expression::Ptr>::const_iterator r = memWrites.begin(); r != memWrites.end(); ++r) { defined.push_back(AbsRegionConverter::convert(*r, addr, func, block)); } } } if (cacheEnabled_) { used_cache_[func][addr] = used; defined_cache_[func][addr] = defined; } }