void TreePrinter::operator()(Function* feature) { indent_level_++; Expression::Ptr block = feature->block(); out_ << "Function\n"; print_tabs(); out_ << "name: "; out_ << feature->name() << "\n"; print_tabs(); out_ << "type: "; out_ << feature->type() << "\n"; if (Block* block = dynamic_cast<Block*>(feature->block())) { if (block->comment()) { print_tabs(); out_ << "comment:\n"; print_comment(block->comment()); } } int i = 0; for (Formal::Ptr f = feature->formals(); f; f = f->next()) { print_tabs(); out_ << "formal" << i << ": "; f(this); i++; } print_tabs(); out_ << "block: "; if (block) { block(this); } else { out_ << "\n"; } indent_level_--; }
bool PatchBlock::containsDynamicCall() { const ParseAPI::Block::edgelist & out_edges = block_->targets(); ParseAPI::Block::edgelist::const_iterator eit = out_edges.begin(); for( ; eit != out_edges.end(); ++eit) { if ( ParseAPI::CALL == (*eit)->type() ) { // see if it's a static call to a bad address if ((*eit)->sinkEdge()) { using namespace InstructionAPI; Instruction::Ptr insn = getInsn(last()); if (insn->readsMemory()) { // memory indirect return true; } else { // check for register indirect set<InstructionAST::Ptr> regs; Expression::Ptr tExpr = insn->getControlFlowTarget(); if (tExpr) tExpr->getUses(regs); for (set<InstructionAST::Ptr>::iterator rit = regs.begin(); rit != regs.end(); rit++) { if (RegisterAST::makePC(obj()->co()->cs()->getArch()).getID() != boost::dynamic_pointer_cast<RegisterAST>(*rit)->getID()) { return true; } } } } } } return false; }
bool IA_x86Details::handleAdd(IA_IAPI& block) { parsing_printf("\t found add insn %s without obvious thunk\n", block.getInstruction()->format().c_str()); // Check table insn and bail if it's not of the mov eax, [eax] form // We do this indirectly: if there was already a displacment that we // could find in the table insn, we have a "table address"; otherwise, check adds if(tableInsn.addrFromInsn != 0) { return false; } // Use the add operand as our table base; we're handling tables of the form: // <reg = index> // add reg, $base // mov reg, [reg] // jmp *reg Expression::Ptr addExpr = block.getInstruction()->getOperand(1).getValue(); zeroAllGPRegisters z(block.getAddr()); addExpr->apply(&z); thunkInsn.insn = block.getInstruction(); thunkInsn.addrFromInsn = z.getResult(); thunkInsn.addrOfInsn = block.getAddr(); parsing_printf("\t setting thunk offset to 0x%lx (EXPERIMENTAL!)\n", thunkInsn.addrFromInsn); return thunkInsn.addrFromInsn != 0; }
void CCodeGenerator::call(Function* function, Expression* args) { std::vector<Operand> val; for (Expression::Ptr a = args; a; a = a->next()) { val.push_back(emit(a)); } if (!function->type()->is_void()) { return_ = alloc_temp(function->type()); } else { line(); } out_ << function->label() << "("; Expression::Ptr arg = args; Formal::Ptr formal = function->formals(); for (int i = 0; i < val.size(); i++) { if(!formal->is_self() && !formal->type()->equals(arg->type())) { // Cast to the appropriate C-type, since C doesn't know anything // about subtypes, etc.. out_ << "("; operator()(formal->type()); out_ << ")"; } out_ << val[i]; if (i < val.size() - 1) { out_ << ", "; } formal = formal->next(); arg = arg->next(); } out_ << ");\n"; }
void CCodeGenerator::ctor_preamble(Class* clazz) { // Emits the memory alloc/vtable setup for the class. Also initializes // the reference count for dynamically allocated types. if (clazz->is_object()) { line(); operator()(clazz->type()); out_ << " self = Boot_calloc(sizeof(struct "; operator()(clazz->type()); out_ << "));\n"; line(); out_ << "self->_refcount = 1;\n"; line(); out_ << "self->_vtable = "; operator()(clazz->type()); out_ << "__vtable;\n"; } // Emit initializer code for initialized attributes for (Feature::Ptr f = clazz->features(); f; f = f->next()) { if (Attribute::Ptr attr = dynamic_cast<Attribute*>(f.pointer())) { Expression::Ptr init = attr->initializer(); if (!init || dynamic_cast<Empty*>(init.pointer())) { continue; } line(); Operand value = emit(init); out_ << "self->" << attr->name() << " = " << value << ";\n"; //free_temps(); } } }
IA_IAPI::allInsns_t::const_iterator IA_x86Details::findTableInsn() { // Check whether the jump is our table insn! Expression::Ptr cft = currentBlock->curInsn()->getControlFlowTarget(); if(cft) { std::vector<Expression::Ptr> tmp; cft->getChildren(tmp); if(tmp.size() == 1) { Expression::Ptr cftAddr = tmp[0]; zeroAllGPRegisters z(currentBlock->current); cftAddr->apply(&z); parsing_printf("\tChecking indirect jump %s for table insn\n", currentBlock->curInsn()->format().c_str()); if(z.isDefined() && z.getResult()) { parsing_printf("\tAddress in jump\n"); return currentBlock->curInsnIter; } } } IA_IAPI::allInsns_t::const_iterator c = currentBlock->curInsnIter; while(!isTableInsn(c->second) && c != currentBlock->allInsns.begin()) { --c; } if(isTableInsn(c->second)) { return c; } return currentBlock->allInsns.end(); }
void CCodeGenerator::native_operator(Call* expr) { std::string id = expr->function()->name()->string(); std::vector<Operand> args; for (Expression::Ptr a = expr->arguments(); a; a = a->next()) { args.push_back(emit(a)); } return_ = alloc_temp(expr->type()); if (id == "@add") { out_ << args[0] << "+" << args[1] << ";\n"; } else if (id == "@sub") { out_ << args[0] << "-" << args[1] << ";\n"; } else if (id == "@mul") { out_ << args[0] << "*" << args[1] << ";\n"; } else if (id == "@div") { out_ << args[0] << "/" << args[1] << ";\n"; } else if (id == "@neg") { out_ << "-" << args[0] << ";\n"; } else if (id == "@mod") { out_ << args[0] << "%" << args[1] << ";\n"; } else if (id == "@compl") { out_ << "~" << args[0] << ";\n"; } else if (id == "@equal") { out_ << args[0] << "==" << args[1] << ";\n"; } else if (id == "@less") { out_ << args[0] << "<" << args[1] << ";\n"; } }
Expression::Ptr PatternPlatform::compress(const StaticContext::Ptr &context) { const Expression::Ptr me(FunctionCall::compress(context)); if(me != this) return me; if(m_operands.at(1)->is(IDStringValue)) { const DynamicContext::Ptr dynContext(context->dynamicContext()); m_pattern = parsePattern(m_operands.at(1)->evaluateSingleton(dynContext).stringValue(), dynContext); m_compiledParts |= PatternPrecompiled; } const Expression::Ptr flagOperand(m_operands.value(m_flagsPosition)); if(!flagOperand) { m_flags = NoFlags; m_compiledParts |= FlagsPrecompiled; } else if(flagOperand->is(IDStringValue)) { const DynamicContext::Ptr dynContext(context->dynamicContext()); m_flags = parseFlags(flagOperand->evaluateSingleton(dynContext).stringValue(), dynContext); m_compiledParts |= FlagsPrecompiled; } if(m_compiledParts == FlagsAndPattern) applyFlags(m_flags, m_pattern); return me; }
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; }
Expression::Ptr XSLT20CoreFunctions::retrieveExpression(const QXmlName lname, const Expression::List &args, const FunctionSignature::Ptr &sign) const { Q_ASSERT(sign); Expression::Ptr fn; #define testXSLTFN(ln, cname) else if(lname.localName() == StandardLocalNames::ln) fn = Expression::Ptr(new cname()) if(false) /* Dummy for the macro handling. Will be optimized away anyway. */ return Expression::Ptr(); /* Alphabetic order. */ testXSLTFN(current, CurrentFN); testXSLTFN(document, DocumentFN); testXSLTFN(element_available, ElementAvailableFN); testXSLTFN(function_available, FunctionAvailableFN); testXSLTFN(generate_id, GenerateIDFN); testXSLTFN(system_property, SystemPropertyFN); testXSLTFN(type_available, TypeAvailableFN); testXSLTFN(unparsed_entity_public_id, UnparsedEntityPublicIDFN); testXSLTFN(unparsed_entity_uri, UnparsedEntityURIFN); testXSLTFN(unparsed_text_available, UnparsedTextAvailableFN); testXSLTFN(unparsed_text, UnparsedTextFN); #undef testXSLTFN Q_ASSERT(fn); fn->setOperands(args); fn->as<FunctionCall>()->setSignature(sign); return fn; }
void CallTargetDescription::checkCallsiteCircularity(CallTargetDescription::List &signList, const Expression::Ptr expr) { Q_ASSERT(expr); if(expr->is(Expression::IDUserFunctionCallsite)) { CallTargetDescription::List::const_iterator it(signList.constBegin()); const CallTargetDescription::List::const_iterator end(signList.constEnd()); CallSite *const callsite = static_cast<CallSite *>(expr.data()); for(; it != end; ++it) { if(callsite->configureRecursion(*it)) { /* A callsite inside the function body to the function. This user function * is recursive if it's to the same function, in other words. Which it was * if configureRecursion() returned true. */ /* Now we continue and check the arguments of the callsite. That is, the arguments. * This catches for instance local:foo(local:foo(3)). */ checkArgumentsCircularity(signList, expr); return; } } /* Check the body of the function so this callsite isn't "indirectly" a * recursive call to the function we're checking. XQTS test case * default_namespace-011 is an example of this. */ signList.append(callsite->callTargetDescription()); checkCallsiteCircularity(signList, callsite->body()); } checkArgumentsCircularity(signList, expr); /* We're done in this case. */ }
void CCodeGenerator::operator()(Construct* expr) { // Look up the function by name in the current context. String::Ptr id = env_->name("@init"); Class::Ptr clazz = expr->type()->clazz(); Function::Ptr func = clazz->function(id); std::vector<Operand> args; for (Expression::Ptr a = expr->arguments(); a; a = a->next()) { args.push_back(emit(a)); } return_ = alloc_temp(clazz->type()); out_ << func->label() << "("; Formal::Ptr formal = func->formals(); Expression::Ptr arg = expr->arguments(); for (int i = 0; i < args.size(); i++) { if(!formal->is_self() && !formal->type()->equals(arg->type())) { // Cast to the appropriate C-type, since C doesn't know anything // about subtypes, etc.. out_ << "("; operator()(formal->type()); out_ << ")"; } out_ << args[i]; if (i < args.size() - 1) { out_ << ", "; } formal = formal->next(); arg = arg->next(); } out_ << ");\n"; }
void CCodeGenerator::operator()(Assignment* expr) { // Handle all types of assignment, including member assignment Expression::Ptr init = expr->initializer(); if (dynamic_cast<Empty*>(init.pointer())) { return_ = Operand(env_->integer("0")); } else { return_ = emit(init); } String::Ptr id = expr->identifier(); Variable::Ptr var = variable(id); Attribute::Ptr attr = class_ ? class_->attribute(id) : 0; if (var) { // Assignment to a local var that has already been initialized once in // the current scope. Type::Ptr type = var->type(); if (!type->is_value()) { refcount_dec(Operand(var->name())); } line(); out_ << id->string() << " = " << return_ << ";\n"; if (!type->is_value()) { refcount_inc(Operand(var->name())); } } else if (attr) { // Assignment to an attribute within a class /* Type::Ptr type = expr->type(); Variable::Ptr self = variable(env_->name("__self")); Operand addr = Operand::addr(, attr->slot()); Operand old = load(addr); if (!type->is_value() && !attr->is_weak()) { refcount_dec(old); } store(addr, return_); if (!type->is_value() && !attr->is_weak()) { refcount_inc(return_); } */ assert(!"not impl"); } else { // Assignment to a local var that has not yet been initialized in the // current scope. Type::Ptr declared = expr->declared_type(); if (declared->is_top()) { declared = expr->type(); } line(); brace(); operator()(declared); out_ << " " << id->string() << " = " << return_ << "; "; out_ << "(void)" << id->string() << ";\n"; variable(new Variable(id, declared)); if (!declared->is_value()) { refcount_inc(return_); } } }
void CCodeGenerator::operator()(Block* expr) { enter_scope(); for (Expression::Ptr s = expr->children(); s; s = s->next()) { loc(s); s(this); } exit_scope(); }
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; } } }
void TreePrinter::operator()(HashLiteral* expression) { indent_level_++; out_ << "HashLiteral\n"; int i = 0; for (Expression::Ptr e = expression->arguments(); e; e = e->next()) { print_tabs(); out_ << "argument" << i << ": "; e(this); i++; } indent_level_--; }
Expression::Ptr XPath10CoreFunctions::retrieveExpression(const QXmlName name, const Expression::List &args, const FunctionSignature::Ptr &sign) const { Q_ASSERT(sign); /* if(name.namespaceURI() == StandardNamespaces::fn) return Expression::Ptr(); */ Expression::Ptr fn; #define testFN(ln, cname) else if(name.localName() == StandardLocalNames::ln) fn = Expression::Ptr(new cname()) if(false) /* Dummy for the macro handling. Will be optimized away anyway. */ return Expression::Ptr(); /* Alphabetic order. */ testFN(boolean, BooleanFN); testFN(ceiling, CeilingFN); testFN(concat, ConcatFN); testFN(contains, ContainsFN); testFN(count, CountFN); testFN(False, FalseFN); testFN(floor, FloorFN); testFN(id, IdFN); testFN(lang, LangFN); testFN(last, LastFN); testFN(local_name, LocalNameFN); testFN(name, NameFN); testFN(namespace_uri, NamespaceURIFN); testFN(normalize_space, NormalizeSpaceFN); testFN(Not, NotFN); testFN(number, NumberFN); testFN(position, PositionFN); testFN(round, RoundFN); testFN(starts_with, StartsWithFN); testFN(string, StringFN); testFN(string_length, StringLengthFN); testFN(substring, SubstringFN); testFN(substring_after, SubstringAfterFN); testFN(substring_before, SubstringBeforeFN); testFN(sum, SumFN); testFN(translate, TranslateFN); testFN(True, TrueFN); #undef testFN Q_ASSERT(fn); fn->setOperands(args); fn->as<FunctionCall>()->setSignature(sign); return fn; }
void TreePrinter::operator()(Block* statement) { indent_level_++; Expression::Ptr children = statement->children(); out_ << "Block\n"; int i = 0; for (Expression::Ptr c = children; c; c = c->next()) { print_tabs(); out_ << "child" << i << ": "; c(this); i++; } indent_level_--; }
Expression::Ptr IdFN::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType) { if(m_hasCreatedSorter) return FunctionCall::typeCheck(context, reqType); else { const Expression::Ptr newMe(new NodeSortExpression(Expression::Ptr(this))); context->wrapExpressionWith(this, newMe); m_hasCreatedSorter = true; return newMe->typeCheck(context, reqType); } }
void IA_x86Details::findThunkInBlock(Block* curBlock) { const unsigned char* buf = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(curBlock->start())); if( buf == NULL ) { parsing_printf("%s[%d]: failed to get pointer to instruction by offset\n", FILE__, __LINE__); return; } InstructionDecoder dec(buf,curBlock->size() + InstructionDecoder::maxInstructionLength, currentBlock->_isrc->getArch()); IA_IAPI block(dec,curBlock->start(),currentBlock->_obj,currentBlock->_cr, currentBlock->_isrc, curBlock); parsing_printf("\tchecking block at 0x%lx for thunk\n", curBlock->start()); while(block.getAddr() < curBlock->end()) { if(block.getInstruction()->getCategory() == c_CallInsn) { if(handleCall(block)) return; } else if(block.getInstruction()->getOperation().getID() == e_lea) // Look for an AMD64 IP-relative LEA. If we find one, it should point to the start of a { // relative jump table. parsing_printf("\tchecking instruction %s at 0x%lx for IP-relative LEA\n", block.getInstruction()->format().c_str(), block.getAddr()); Expression::Ptr IPRelAddr = block.getInstruction()->getOperand(1).getValue(); IPRelAddr->bind(currentBlock->thePC[currentBlock->_isrc->getArch()].get(), Result(s64, block.getNextAddr())); Result iprel = IPRelAddr->eval(); if(iprel.defined) { thunkInsn.addrFromInsn = iprel.convert<Address>(); parsing_printf("\tsetting thunkOffset to 0x%lx at 0x%lx\n",thunkInsn.addrFromInsn, block.getAddr()); thunkInsn.addrOfInsn = block.getAddr(); thunkInsn.insn = block.getInstruction(); return; } } else if(block.getInstruction()->getOperation().getID() == e_add) { if(handleAdd(block)) { parsing_printf("handleAdd found thunk candidate, addr is 0x%lx\n", block.getAddr()); return; } } block.advance(); } return; }
Expression::Ptr GenericPredicate::create(const Expression::Ptr &sourceExpression, const Expression::Ptr &predicateExpression, const StaticContext::Ptr &context, const QSourceLocation &location) { Q_ASSERT(sourceExpression); Q_ASSERT(predicateExpression); Q_ASSERT(context); const ItemType::Ptr type(predicateExpression->staticType()->itemType()); if(predicateExpression->is(IDIntegerValue) && predicateExpression->as<Literal>()->item().as<Numeric>()->toInteger() == 1) { /* Handle [1] */ return createFirstItem(sourceExpression); } else if(BuiltinTypes::numeric->xdtTypeMatches(type)) { /* A numeric predicate, other than [1]. */ /* TODO at somepoint we'll return a specialized expr here, NumericPredicate or so. * Dependency analysis is a bit tricky, since the contained expression can depend on * some loop component. */ return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression)); } else if(*CommonSequenceTypes::Empty == *type) { return EmptySequence::create(predicateExpression.data(), context); } else if(*BuiltinTypes::item == *type || *BuiltinTypes::xsAnyAtomicType == *type) { /* The type couldn't be narrowed at compile time, so we use * a generic predicate. This check is before the CommonSequenceTypes::EBV check, * because the latter matches these types as well. */ return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression)); } else if(CommonSequenceTypes::EBV->itemType()->xdtTypeMatches(type)) { return Expression::Ptr(new TruthPredicate(sourceExpression, predicateExpression)); } else { context->error(QtXmlPatterns::tr("A value of type %1 cannot be a " "predicate. A predicate must have " "either a numeric type or an " "Effective Boolean Value type.") .arg(formatType(context->namePool(), sourceExpression->staticType())), ReportContext::FORG0006, location); return Expression::Ptr(); /* Silence compiler warning. */ } }
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; }
void TreePrinter::operator()(Match* statement) { indent_level_++; Expression::Ptr guard = statement->guard(); out_ << "Match\n"; print_tabs(); out_ << "guard: "; guard(this); int i = 0; for (Expression::Ptr b = statement->cases(); b; b = b->next()) { print_tabs(); out_ << "case" << i << ": "; b(this); i++; } indent_level_--; }
void TreePrinter::operator()(Construct* expression) { indent_level_++; Expression::Ptr arguments = expression->arguments(); out_ << "Construct\n"; print_tabs(); out_ << "type: "; out_ << expression->type() << "\n"; int i = 0; for (Expression::Ptr a = arguments; a; a = a->next()) { print_tabs(); out_ << "argument" << i << ": "; a(this); i++; } indent_level_--; }
INSTRUCTION_EXPORT std::string Operand::format(Architecture arch, Address addr) const { if(!op_value) return "ERROR: format() called on empty operand!"; if (addr) { Expression::Ptr thePC = Expression::Ptr(new RegisterAST(MachRegister::getPC(arch))); op_value->bind(thePC.get(), Result(u32, addr)); Result res = op_value->eval(); if (res.defined) { stringstream ret; ret << hex << res.convert<unsigned>() << dec; return ret.str(); } } return op_value->format(); }
void TreePrinter::operator()(Call* expression) { indent_level_++; Expression::Ptr arguments = expression->arguments(); Expression::Ptr expr = expression->expression(); out_ << "Call\n"; print_tabs(); out_ << "expression: "; expr(this); int i = 0; for (Expression::Ptr a = arguments; a; a = a->next()) { print_tabs(); out_ << "argument" << i << ": "; a(this); i++; } indent_level_--; }
void TreePrinter::operator()(Let* expression) { indent_level_++; Expression::Ptr block = expression->block(); out_ << "Let\n"; int i = 0; for (Expression::Ptr v = expression->variables(); v; v = v->next()) { print_tabs(); out_ << "variable" << i << ": "; v(this); i++; } print_tabs(); out_ << "block: "; block(this); indent_level_--; }
std::pair<bool, Address> RelocBlock::getJumpTarget() { InstructionAPI::Instruction insn = cfWidget()->insn(); if (!insn.isValid()) return std::make_pair(false, 0); Expression::Ptr cft = insn.getControlFlowTarget(); if (!cft) return std::make_pair(false, 0); Expression::Ptr thePC(new RegisterAST(MachRegister::getPC(insn.getArch()))); cft->bind(thePC.get(), Result(u64, cfWidget()->addr())); Result res = cft->eval(); if (res.defined) { return std::make_pair(true, res.convert<Address>()); } return std::make_pair(false, 0); }
void OrderBy::OrderSpec::prepare(const Expression::Ptr &source, const StaticContext::Ptr &context) { m_expr = source; const ItemType::Ptr t(source->staticType()->itemType()); prepareComparison(fetchComparator(t, t, context)); }
bool BySequenceTypeIdentifier::matches(const Expression::Ptr &expr) const { const SequenceType::Ptr t(expr->staticType()); return m_seqType->itemType()->xdtTypeMatches(t->itemType()) && m_seqType->cardinality().isMatch(t->cardinality()); }