size_t RiscOperators::add_subdomain(const BaseSemantics::RiscOperatorsPtr &subdomain, const std::string &name, bool activate) { assert(subdomain!=NULL); size_t idx = subdomains.size(); subdomains.push_back(subdomain); active.push_back(activate); if (idx>=formatter.subdomain_names.size()) formatter.subdomain_names.resize(idx+1, ""); formatter.subdomain_names[idx] = name; SValue::promote(get_protoval())->set_subvalue(idx, subdomain->get_protoval()); return idx; }
explicit State(const BaseSemantics::RiscOperatorsPtr &ops) : BaseSemantics::RegisterStateGeneric(ops->get_protoval(), ops->get_state()->get_register_state()->get_register_dictionary()), ops_(ops) {}
// see base class bool SgAsmX86Instruction::isFunctionCallSlow(const std::vector<SgAsmInstruction*>& insns, rose_addr_t *target, rose_addr_t *return_va) { if (isFunctionCallFast(insns, target, return_va)) return true; // The following stuff works only if we have a relatively complete AST. static const size_t EXECUTION_LIMIT = 10; // max size of basic blocks for expensive analyses if (insns.empty()) return false; SgAsmX86Instruction *last = isSgAsmX86Instruction(insns.back()); if (!last) return false; SgAsmFunction *func = SageInterface::getEnclosingNode<SgAsmFunction>(last); SgAsmInterpretation *interp = SageInterface::getEnclosingNode<SgAsmInterpretation>(func); // Slow method: Emulate the instructions and then look at the EIP and stack. If the EIP points outside the current // function and the top of the stack holds an address of an instruction within the current function, then this must be a // function call. FIXME: The implementation here assumes a 32-bit machine. [Robb P. Matzke 2013-09-06] if (interp && insns.size()<=EXECUTION_LIMIT) { using namespace rose::BinaryAnalysis; using namespace rose::BinaryAnalysis::InstructionSemantics2; using namespace rose::BinaryAnalysis::InstructionSemantics2::SymbolicSemantics; const InstructionMap &imap = interp->get_instruction_map(); const RegisterDictionary *regdict = RegisterDictionary::dictionary_for_isa(interp); SMTSolver *solver = NULL; // using a solver would be more accurate, but slower BaseSemantics::RiscOperatorsPtr ops = RiscOperators::instance(regdict, solver); DispatcherX86Ptr dispatcher = DispatcherX86::instance(ops); SValuePtr orig_esp = SValue::promote(ops->readRegister(dispatcher->REG_ESP)); try { for (size_t i=0; i<insns.size(); ++i) dispatcher->processInstruction(insns[i]); } catch (const BaseSemantics::Exception &e) { return false; } // If the next instruction address is concrete but does not point to a function entry point, then this is not a call. SValuePtr eip = SValue::promote(ops->readRegister(dispatcher->REG_EIP)); if (eip->is_number()) { rose_addr_t target_va = eip->get_number(); SgAsmFunction *target_func = SageInterface::getEnclosingNode<SgAsmFunction>(imap.get_value_or(target_va, NULL)); if (!target_func || target_va!=target_func->get_entry_va()) return false; } // If nothing was pushed onto the stack, then this isn't a function call. SValuePtr esp = SValue::promote(ops->readRegister(dispatcher->REG_ESP)); SValuePtr stack_delta = SValue::promote(ops->add(esp, ops->negate(orig_esp))); SValuePtr stack_delta_sign = SValue::promote(ops->extract(stack_delta, 31, 32)); if (stack_delta_sign->is_number() && 0==stack_delta_sign->get_number()) return false; // If the top of the stack does not contain a concrete value or the top of the stack does not point to an instruction // in this basic block's function, then this is not a function call. SValuePtr top = SValue::promote(ops->readMemory(dispatcher->REG_SS, esp, esp->undefined_(32), esp->boolean_(true))); if (top->is_number()) { rose_addr_t va = top->get_number(); SgAsmFunction *return_func = SageInterface::getEnclosingNode<SgAsmFunction>(imap.get_value_or(va, NULL)); if (!return_func || return_func!=func) { return false; } } else { return false; } // Since EIP might point to a function entry address and since the top of the stack contains a pointer to an // instruction in this function, we assume that this is a function call. if (target && eip->is_number()) *target = eip->get_number(); if (return_va && top->is_number()) *return_va = top->get_number(); return true; } // Similar to the above method, but works when all we have is the basic block (e.g., this case gets hit quite a bit from // the Partitioner). Returns true if, after executing the basic block, the top of the stack contains the fall-through // address of the basic block. We depend on our caller to figure out if EIP is reasonably a function entry address. if (!interp && insns.size()<=EXECUTION_LIMIT) { using namespace rose::BinaryAnalysis; using namespace rose::BinaryAnalysis::InstructionSemantics2; using namespace rose::BinaryAnalysis::InstructionSemantics2::SymbolicSemantics; const RegisterDictionary *regdict = RegisterDictionary::dictionary_pentium4(); SMTSolver *solver = NULL; // using a solver would be more accurate, but slower BaseSemantics::RiscOperatorsPtr ops = RiscOperators::instance(regdict, solver); DispatcherX86Ptr dispatcher = DispatcherX86::instance(ops); try { for (size_t i=0; i<insns.size(); ++i) dispatcher->processInstruction(insns[i]); } catch (const BaseSemantics::Exception &e) { return false; } // Look at the top of the stack SValuePtr top = SValue::promote(ops->readMemory(dispatcher->REG_SS, ops->readRegister(dispatcher->REG_ESP), ops->get_protoval()->undefined_(32), ops->get_protoval()->boolean_(true))); if (top->is_number() && top->get_number() == last->get_address()+last->get_size()) { if (target) { SValuePtr eip = SValue::promote(ops->readRegister(dispatcher->REG_EIP)); if (eip->is_number()) *target = eip->get_number(); } if (return_va) *return_va = top->get_number(); return true; } } return false; }