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 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; } }