bool IA_IAPI::isFrameSetupInsn(Instruction::Ptr i) const { if(i->getOperation().getID() == e_mov) { if(i->readsMemory() || i->writesMemory()) { parsing_printf("%s[%d]: discarding insn %s as stack frame preamble, not a reg-reg move\n", FILE__, __LINE__, i->format().c_str()); //return false; } if(i->isRead(stackPtr[_isrc->getArch()]) && i->isWritten(framePtr[_isrc->getArch()])) { if((unsigned) i->getOperand(0).getValue()->size() == _isrc->getAddressWidth()) { return true; } else { parsing_printf("%s[%d]: discarding insn %s as stack frame preamble, size mismatch for %d-byte addr width\n", FILE__, __LINE__, i->format().c_str(), _isrc->getAddressWidth()); } } } return false; }
bool IA_IAPI::isThunk() const { // Before we go a-wandering, check the target bool valid; Address addr; boost::tie(valid, addr) = getCFT(); if (!valid || !_isrc->isValidAddress(addr)) { parsing_printf("... Call to 0x%lx is invalid (outside code or data)\n", addr); return false; } const unsigned char *target = (const unsigned char *)_isrc->getPtrToInstruction(addr); InstructionDecoder targetChecker(target, 2*InstructionDecoder::maxInstructionLength, _isrc->getArch()); Instruction::Ptr thunkFirst = targetChecker.decode(); Instruction::Ptr thunkSecond = targetChecker.decode(); if(thunkFirst && thunkSecond && (thunkFirst->getOperation().getID() == e_mov) && (thunkSecond->getCategory() == c_ReturnInsn)) { if(thunkFirst->isRead(stackPtr[_isrc->getArch()])) { // it is not enough that the stack pointer is read; it must // be a zero-offset read from the stack pointer ThunkVisitor tv; Operand op = thunkFirst->getOperand(1); op.getValue()->apply(&tv); return tv.offset() == 0; } } return false; }