bool IA_IAPI::isIPRelativeBranch() const { // These don't exist on IA32... #if !defined(arch_x86_64) return false; #endif Instruction ci = curInsn(); bool valid; Address target; boost::tie(valid, target) = getCFT(); if(ci.getCategory() == c_BranchInsn && !valid) { Expression::Ptr cft = ci.getControlFlowTarget(); if(cft->isUsed(thePC[_isrc->getArch()])) { parsing_printf("\tIP-relative indirect jump to %s at 0x%lx\n", cft->format(ci.getArch()).c_str(), current); return true; } } return false; }
void IA_x86Details::computeTableAddress() { // Extract displacement from table insn Expression::Ptr displacementSrc; if(tableInsn.insn->getCategory() == c_BranchInsn) { Expression::Ptr op = tableInsn.insn->getOperand(0).getValue(); std::vector<Expression::Ptr> tmp; op->getChildren(tmp); if(tmp.empty()) { displacementSrc = op; } else { displacementSrc = tmp[0]; } } else { parsing_printf("\tcracking table instruction %s\n", tableInsn.insn->format().c_str()); std::vector<Expression::Ptr> tmp; Expression::Ptr op = tableInsn.insn->getOperand(1).getValue(); if(!op) { parsing_printf("\ttable insn BAD! (no second operand)\n"); return; } if(tableInsn.insn->getOperation().getID() != e_lea) { op->getChildren(tmp); if(tmp.empty()) { parsing_printf("\ttable insn BAD! (not LEA, second operand not a deref)\n"); return; } displacementSrc = tmp[0]; } else { displacementSrc = op; } } zeroAllGPRegisters z(tableInsn.addrOfInsn + tableInsn.insn->size()); displacementSrc->apply(&z); if(!z.isDefined()) { parsing_printf("\ttable insn: %s, displacement %s, bind of all GPRs FAILED\n", tableInsn.insn->format().c_str(), displacementSrc->format().c_str()); return; } else { tableInsn.addrFromInsn = z.getResult(); } parsing_printf("\ttableInsn.addrFromInsn set to 0x%lx\n",tableInsn.addrFromInsn); }
bool IA_x86Details::isTableInsn(Instruction::Ptr i) { Expression::Ptr jumpExpr = currentBlock->curInsn()->getControlFlowTarget(); parsing_printf("jumpExpr for table insn is %s\n", jumpExpr->format().c_str()); if(i->getOperation().getID() == e_mov && i->readsMemory() && i->isWritten(jumpExpr)) { return true; } if(i->getOperation().getID() == e_lea && i->isWritten(jumpExpr)) { return true; } return false; }
std::pair<bool, Address> IA_IAPI::getCFT() const { if(validCFT) return cachedCFT; Expression::Ptr callTarget = curInsn().getControlFlowTarget(); if (!callTarget) return make_pair(false, 0); // FIXME: templated bind(),dammit! callTarget->bind(thePC[_isrc->getArch()].get(), Result(s64, current)); parsing_printf("%s[%d]: binding PC %s in %s to 0x%x...", FILE__, __LINE__, thePC[_isrc->getArch()]->format(curInsn().getArch()).c_str(), curInsn().format().c_str(), current); Result actualTarget = callTarget->eval(); #if defined(os_vxworks) int reloc_target = current; #if defined(arch_x86) ++reloc_target; #endif if (actualTarget.convert<Address>() == reloc_target) { // We have a zero offset branch. Consider relocation information. SymtabCodeRegion *scr = dynamic_cast<SymtabCodeRegion *>(_cr); SymtabCodeSource *scs = dynamic_cast<SymtabCodeSource *>(_obj->cs()); if (!scr && scs) { set<CodeRegion *> regions; assert( scs->findRegions(reloc_target, regions) == 1 ); scr = dynamic_cast<SymtabCodeRegion *>(*regions.begin()); } SymtabAPI::Symbol *sym = NULL; if (scr) { std::vector<SymtabAPI::relocationEntry> relocs = scr->symRegion()->getRelocations(); for (unsigned i = 0; i < relocs.size(); ++i) { if (relocs[i].rel_addr() == reloc_target) { sym = relocs[i].getDynSym(); if (sym && sym->getOffset()) { parsing_printf(" <reloc hit> "); actualTarget = Result(s64, sym->getOffset()); } break; } } } if (sym && sym->getOffset() == 0) { // VxWorks external call. // Need some external means to find the target. Address found; const std::string &sym_name = sym->getMangledName(); if (wtxFindFunction(sym_name.c_str(), 0x0, found)) { parsing_printf(" <wtx search hit> "); actualTarget = Result(s64, found); // We've effectively found a plt call. Update linkage table. _obj->cs()->linkage()[found] = sym_name; } else { parsing_printf(" <wtx fail %s> ", sym_name.c_str()); actualTarget.defined = false; } } } #endif if(actualTarget.defined) { cachedCFT = std::make_pair(true, actualTarget.convert<Address>()); parsing_printf("SUCCESS (CFT=0x%x)\n", cachedCFT.second); } else { cachedCFT = std::make_pair(false, 0); parsing_printf("FAIL (CFT=0x%x), callTarget exp: %s\n", cachedCFT.second,callTarget->format(curInsn().getArch()).c_str()); } validCFT = true; if(isLinkerStub()) { parsing_printf("Linker stub detected: Correcting CFT. (CFT=0x%x)\n", cachedCFT.second); } return cachedCFT; }