VarDecl *SwitchStmt::getConditionVariable() const { if (!SubExprs[VAR]) return 0; DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); }
VarDecl *WhileStmt::getConditionVariable() const { if (!SubExprs[VAR]) return nullptr; DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); return cast<VarDecl>(DS->getSingleDecl()); }
VarDecl *varDeclFromInitStmt(Stmt *initStmt) { DeclStmt *declStmt = dyn_cast_or_null<DeclStmt>(initStmt); if (declStmt && declStmt->isSingleDecl()) { return dyn_cast_or_null<VarDecl>(declStmt->getSingleDecl()); } return nullptr; }
NamedDecl* RedundantLocalVariableRule::extractFromDeclStmt(Stmt *stmt) { CompoundStmt *compoundStmt = dyn_cast<CompoundStmt>(stmt); if (compoundStmt && compoundStmt->size() >= 2) { Stmt *lastSecondStmt = (Stmt *)*(compoundStmt->body_end() - 2); DeclStmt *declStmt = dyn_cast<DeclStmt>(lastSecondStmt); if (declStmt && declStmt->isSingleDecl()) { return dyn_cast<NamedDecl>(declStmt->getSingleDecl()); } } return NULL; }
void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { // As long as debug info is modeled with instructions, we have to ensure we // have a place to insert here and write the stop point here. if (getDebugInfo()) { EnsureInsertPoint(); EmitStopPoint(&S); } for (DeclStmt::const_decl_iterator I = S.decl_begin(), E = S.decl_end(); I != E; ++I) EmitDecl(**I); }
void handleDeclStmt(Stmt *initStmt) { DeclStmt *declStmt = dyn_cast_or_null<DeclStmt>(initStmt); if (!declStmt) { return; } if (declStmt->isSingleDecl()) { handleVarDecl(dyn_cast_or_null<VarDecl>(declStmt->getSingleDecl())); } else { for (DeclStmt::reverse_decl_iterator it = declStmt->decl_rbegin(), itEnd = declStmt->decl_rend(); it != itEnd; it++) { handleVarDecl(dyn_cast_or_null<VarDecl>(*it)); } } }
void NetworkDriverRewriteVisitor::InstrumentEntryPoints(FunctionDecl* funcDecl, string fdFile) { if (funcDecl->getStorageClass() == SC_Static) RW.RemoveText(funcDecl->getInnerLocStart(), 7); if (DI->getInstance().GetInitFunction() == funcDecl->getNameInfo().getName().getAsString()) return; if (funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct device *" && funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct pci_dev *") return; SourceRange sr = funcDecl->getParamDecl(0)->getSourceRange(); RW.InsertTextBefore(sr.getBegin(), "struct net_device *dev, "); Stmt *body = funcDecl->getBody(); list<DeclStmt*> stmtsToRewrite; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (!isa<DeclStmt>(*i)) continue; DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *var = cast<VarDecl>(declStmt->getSingleDecl()); if (!var->hasInit()) continue; Expr *expr = var->getInit(); if (!isa<ImplicitCastExpr>(expr)) continue; ImplicitCastExpr *implicit = cast<ImplicitCastExpr>(expr); if (!isa<CallExpr>(implicit->getSubExpr())) continue; CallExpr *call = cast<CallExpr>(implicit->getSubExpr()); DeclRefExpr *callee = cast<DeclRefExpr>(cast<ImplicitCastExpr>(call->getCallee())->getSubExpr()); if (callee->getNameInfo().getName().getAsString() == "to_pci_dev" || callee->getNameInfo().getName().getAsString() == "pci_get_drvdata") { stmtsToRewrite.push_back(declStmt); } } while (!stmtsToRewrite.empty()) { DeclStmt *stmt = stmtsToRewrite.back(); RW.RemoveText(stmt->getSourceRange()); stmtsToRewrite.pop_back(); } }
Expr *CXXForRangeStmt::getRangeInit() { DeclStmt *RangeStmt = getRangeStmt(); VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl()); assert(RangeDecl &&& "for-range should have a single var decl"); return RangeDecl->getInit(); }
bool DeclExtractor::ExtractDecl(FunctionDecl* FD) { llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (isa<UsingDirectiveDecl>(*J)) continue; // FIXME: Here we should be more elegant. if (ND) { if (Stmts.size()) { // We need to emit a new custom wrapper wrapping the stmts EnforceInitOrder(Stmts); assert(!Stmts.size() && "Stmt list must be flushed."); } // We know the transaction is closed, but it is safe. getTransaction()->forceAppend(ND); DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition ND->getLexicalDeclContext()->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); if (utils::Analyze::isOnScopeChains(ND, *m_Sema)) m_Sema->IdResolver.RemoveDecl(ND); } // For variable definitions causing var/function ambiguity such as: // MyClass my();, C++ standard says it shall be resolved as a function // // In the particular context this definition is inside a function // already, but clang thinks it as a lambda, so we need to ignore the // check decl context vs lexical decl context. if (ND->getDeclContext() == ND->getLexicalDeclContext() || isa<FunctionDecl>(ND)) ND->setLexicalDeclContext(DC); else assert(0 && "Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); } clearLinkage(ND); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { // We should skip the checks for annonymous decls and we should not // register them in the lookup. if (!TouchedDecls[i]->getDeclName()) continue; m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // The order matters, because when we extract decls from the wrapper we // append them to the transaction. If the transaction gets unloaded it will // introduce a fake dependency, so put the move last. Transaction* T = getTransaction(); for (Transaction::iterator I = T->decls_begin(), E = T->decls_end(); I != E; ++I) if (!I->m_DGR.isNull() && I->m_DGR.isSingleDecl() && I->m_DGR.getSingleDecl() == T->getWrapperFD()) { T->erase(I); break; } T->forceAppend(FD); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; }
/// BuildScopeInformation - The statements from CI to CE are known to form a /// coherent VLA scope with a specified parent node. Walk through the /// statements, adding any labels or gotos to LabelAndGotoScopes and recursively /// walking the AST as needed. void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) { // If this is a statement, rather than an expression, scopes within it don't // propagate out into the enclosing scope. Otherwise we have to worry // about block literals, which have the lifetime of their enclosing statement. unsigned independentParentScope = origParentScope; unsigned &ParentScope = ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope : independentParentScope); unsigned StmtsToSkip = 0u; // If we found a label, remember that it is in ParentScope scope. switch (S->getStmtClass()) { case Stmt::AddrLabelExprClass: IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); break; case Stmt::ObjCForCollectionStmtClass: { auto *CS = cast<ObjCForCollectionStmt>(S); unsigned Diag = diag::note_protected_by_objc_fast_enumeration; unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart())); BuildScopeInformation(CS->getBody(), NewParentScope); return; } case Stmt::IndirectGotoStmtClass: // "goto *&&lbl;" is a special case which we treat as equivalent // to a normal goto. In addition, we don't calculate scope in the // operand (to avoid recording the address-of-label use), which // works only because of the restricted set of expressions which // we detect as constant targets. if (cast<IndirectGotoStmt>(S)->getConstantTarget()) { LabelAndGotoScopes[S] = ParentScope; Jumps.push_back(S); return; } LabelAndGotoScopes[S] = ParentScope; IndirectJumps.push_back(cast<IndirectGotoStmt>(S)); break; case Stmt::SwitchStmtClass: // Evaluate the C++17 init stmt and condition variable // before entering the scope of the switch statement. if (Stmt *Init = cast<SwitchStmt>(S)->getInit()) { BuildScopeInformation(Init, ParentScope); ++StmtsToSkip; } if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) { BuildScopeInformation(Var, ParentScope); ++StmtsToSkip; } LLVM_FALLTHROUGH; case Stmt::GotoStmtClass: // Remember both what scope a goto is in as well as the fact that we have // it. This makes the second scan not have to walk the AST again. LabelAndGotoScopes[S] = ParentScope; Jumps.push_back(S); break; case Stmt::IfStmtClass: { IfStmt *IS = cast<IfStmt>(S); if (!(IS->isConstexpr() || IS->isObjCAvailabilityCheck())) break; unsigned Diag = IS->isConstexpr() ? diag::note_protected_by_constexpr_if : diag::note_protected_by_if_available; if (VarDecl *Var = IS->getConditionVariable()) BuildScopeInformation(Var, ParentScope); // Cannot jump into the middle of the condition. unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); BuildScopeInformation(IS->getCond(), NewParentScope); // Jumps into either arm of an 'if constexpr' are not allowed. NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); BuildScopeInformation(IS->getThen(), NewParentScope); if (Stmt *Else = IS->getElse()) { NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart())); BuildScopeInformation(Else, NewParentScope); } return; } case Stmt::CXXTryStmtClass: { CXXTryStmt *TS = cast<CXXTryStmt>(S); { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_cxx_try, diag::note_exits_cxx_try, TS->getSourceRange().getBegin())); if (Stmt *TryBlock = TS->getTryBlock()) BuildScopeInformation(TryBlock, NewParentScope); } // Jump from the catch into the try is not allowed either. for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { CXXCatchStmt *CS = TS->getHandler(I); unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_cxx_catch, diag::note_exits_cxx_catch, CS->getSourceRange().getBegin())); BuildScopeInformation(CS->getHandlerBlock(), NewParentScope); } return; } case Stmt::SEHTryStmtClass: { SEHTryStmt *TS = cast<SEHTryStmt>(S); { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_seh_try, diag::note_exits_seh_try, TS->getSourceRange().getBegin())); if (Stmt *TryBlock = TS->getTryBlock()) BuildScopeInformation(TryBlock, NewParentScope); } // Jump from __except or __finally into the __try are not allowed either. if (SEHExceptStmt *Except = TS->getExceptHandler()) { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_seh_except, diag::note_exits_seh_except, Except->getSourceRange().getBegin())); BuildScopeInformation(Except->getBlock(), NewParentScope); } else if (SEHFinallyStmt *Finally = TS->getFinallyHandler()) { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_seh_finally, diag::note_exits_seh_finally, Finally->getSourceRange().getBegin())); BuildScopeInformation(Finally->getBlock(), NewParentScope); } return; } case Stmt::DeclStmtClass: { // If this is a declstmt with a VLA definition, it defines a scope from here // to the end of the containing context. DeclStmt *DS = cast<DeclStmt>(S); // The decl statement creates a scope if any of the decls in it are VLAs // or have the cleanup attribute. for (auto *I : DS->decls()) BuildScopeInformation(I, origParentScope); return; } case Stmt::ObjCAtTryStmtClass: { // Disallow jumps into any part of an @try statement by pushing a scope and // walking all sub-stmts in that scope. ObjCAtTryStmt *AT = cast<ObjCAtTryStmt>(S); // Recursively walk the AST for the @try part. { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_try, diag::note_exits_objc_try, AT->getAtTryLoc())); if (Stmt *TryPart = AT->getTryBody()) BuildScopeInformation(TryPart, NewParentScope); } // Jump from the catch to the finally or try is not valid. for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) { ObjCAtCatchStmt *AC = AT->getCatchStmt(I); unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_catch, diag::note_exits_objc_catch, AC->getAtCatchLoc())); // @catches are nested and it isn't BuildScopeInformation(AC->getCatchBody(), NewParentScope); } // Jump from the finally to the try or catch is not valid. if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) { unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_finally, diag::note_exits_objc_finally, AF->getAtFinallyLoc())); BuildScopeInformation(AF, NewParentScope); } return; } case Stmt::ObjCAtSynchronizedStmtClass: { // Disallow jumps into the protected statement of an @synchronized, but // allow jumps into the object expression it protects. ObjCAtSynchronizedStmt *AS = cast<ObjCAtSynchronizedStmt>(S); // Recursively walk the AST for the @synchronized object expr, it is // evaluated in the normal scope. BuildScopeInformation(AS->getSynchExpr(), ParentScope); // Recursively walk the AST for the @synchronized part, protected by a new // scope. unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_synchronized, diag::note_exits_objc_synchronized, AS->getAtSynchronizedLoc())); BuildScopeInformation(AS->getSynchBody(), NewParentScope); return; } case Stmt::ObjCAutoreleasePoolStmtClass: { // Disallow jumps into the protected statement of an @autoreleasepool. ObjCAutoreleasePoolStmt *AS = cast<ObjCAutoreleasePoolStmt>(S); // Recursively walk the AST for the @autoreleasepool part, protected by a // new scope. unsigned NewParentScope = Scopes.size(); Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_autoreleasepool, diag::note_exits_objc_autoreleasepool, AS->getAtLoc())); BuildScopeInformation(AS->getSubStmt(), NewParentScope); return; } case Stmt::ExprWithCleanupsClass: { // Disallow jumps past full-expressions that use blocks with // non-trivial cleanups of their captures. This is theoretically // implementable but a lot of work which we haven't felt up to doing. ExprWithCleanups *EWC = cast<ExprWithCleanups>(S); for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) { const BlockDecl *BDecl = EWC->getObject(i); for (const auto &CI : BDecl->captures()) { VarDecl *variable = CI.getVariable(); BuildScopeInformation(variable, BDecl, origParentScope); } } break; } case Stmt::MaterializeTemporaryExprClass: { // Disallow jumps out of scopes containing temporaries lifetime-extended to // automatic storage duration. MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(S); if (MTE->getStorageDuration() == SD_Automatic) { SmallVector<const Expr *, 4> CommaLHS; SmallVector<SubobjectAdjustment, 4> Adjustments; const Expr *ExtendedObject = MTE->GetTemporaryExpr()->skipRValueSubobjectAdjustments( CommaLHS, Adjustments); if (ExtendedObject->getType().isDestructedType()) { Scopes.push_back(GotoScope(ParentScope, 0, diag::note_exits_temporary_dtor, ExtendedObject->getExprLoc())); origParentScope = Scopes.size()-1; } } break; } case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: case Stmt::LabelStmtClass: LabelAndGotoScopes[S] = ParentScope; break; default: break; } for (Stmt *SubStmt : S->children()) { if (!SubStmt) continue; if (StmtsToSkip) { --StmtsToSkip; continue; } // Cases, labels, and defaults aren't "scope parents". It's also // important to handle these iteratively instead of recursively in // order to avoid blowing out the stack. while (true) { Stmt *Next; if (SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt)) Next = SC->getSubStmt(); else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt)) Next = LS->getSubStmt(); else break; LabelAndGotoScopes[SubStmt] = ParentScope; SubStmt = Next; } // Recursively walk the AST. BuildScopeInformation(SubStmt, ParentScope); } }
void NetworkDriverRewriteVisitor::CreateCheckerFunction(FunctionDecl* funcDecl, string fdFile) { string device_str; Stmt *body = funcDecl->getBody(); for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (!isa<DeclStmt>(*i)) continue; DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *varDecl = cast<VarDecl>(declStmt->getSingleDecl()); if (!isa<ValueDecl>(varDecl)) continue; ValueDecl *value = cast<ValueDecl>(varDecl); if (value->getType().getAsString(Context->getPrintingPolicy()) != "struct net_device *") continue; if (!isa<NamedDecl>(varDecl)) continue; NamedDecl *named = cast<NamedDecl>(varDecl); device_str = named->getNameAsString(); break; } if (device_str.empty()) return; string shared_struct_str = GetSharedStructStrInFunctionBody(body, true); if (shared_struct_str.empty()) return; FileID fileId = Context->getSourceManager().getFileID(funcDecl->getLocation()); SourceLocation loc = Context->getSourceManager().getLocForEndOfFile(fileId); RW.InsertText(loc, "\n", true, true); RW.InsertText(loc, "void whoop$checker(", true, true); map<string, string> func_params; for (auto i = funcDecl->param_begin(), e = funcDecl->param_end(); i != e; ++i) { ValueDecl *paramVal = cast<ValueDecl>(*i); NamedDecl *paramNam = cast<NamedDecl>(*i); string paramType = paramVal->getType().getAsString(Context->getPrintingPolicy()); string paramName = paramNam->getNameAsString(); func_params[paramType] = paramName; if (i == funcDecl->param_begin()) RW.InsertText(loc, paramType + " " + paramName + ", ", true, true); else RW.InsertText(loc, paramType + " " + paramName, true, true); } RW.InsertText(loc, ")\n", true, true); RW.InsertText(loc, "{\n", true, true); RW.InsertText(loc, "\tstruct net_device *dev;\n", true, true); RW.InsertText(loc, "\t" + shared_struct_str + "shared;\n", true, true); RW.InsertText(loc, "\tdev = alloc_etherdev(sizeof(*shared));\n\n", true, true); RW.InsertText(loc, "\tstruct sk_buff *whoop_skb = (struct sk_buff *) malloc(sizeof(struct sk_buff));\n", true, true); RW.InsertText(loc, "\tstruct ethtool_wolinfo *whoop_wolinfo = (struct ethtool_wolinfo *) malloc(sizeof(struct ethtool_wolinfo));\n", true, true); RW.InsertText(loc, "\tstruct ethtool_cmd *whoop_ecmd = (struct ethtool_cmd *) malloc(sizeof(struct ethtool_cmd));\n", true, true); RW.InsertText(loc, "\tstruct ifreq *whoop_ifreq = (struct ifreq *) malloc(sizeof(struct ifreq));\n", true, true); RW.InsertText(loc, "\tstruct rtnl_link_stats64 *whoop_rtnlsts64 = (struct rtnl_link_stats64 *) malloc(sizeof(struct rtnl_link_stats64));\n", true, true); RW.InsertText(loc, "\tstruct ethtool_regs *whoop_ethtoolregs = (struct ethtool_regs *) malloc(sizeof(struct ethtool_regs));\n", true, true); RW.InsertText(loc, "\tstruct ethtool_stats *whoop_ethtoolsts = (struct ethtool_stats *) malloc(sizeof(struct ethtool_stats));\n", true, true); RW.InsertText(loc, "\tstruct ethtool_drvinfo *whoop_ethtooldrvinfo = (struct ethtool_drvinfo *) malloc(sizeof(struct ethtool_drvinfo));\n", true, true); RW.InsertText(loc, "\tnetdev_features_t whoop_netdevfeat = NETIF_F_RXCSUM;\n\n", true, true); RW.InsertText(loc, "\tint whoop_int = __SMACK_nondet();\n", true, true); RW.InsertText(loc, "\t__SMACK_code(\"assume @ >= @;\", whoop_int, 0);\n\n", true, true); auto entry_points = DI->getInstance().GetEntryPoints(); for(auto i = entry_points.rbegin(); i != entry_points.rend(); i++) { string entry_point_call; entry_point_call = "" + i->first + "("; if (find(i->second.begin(), i->second.end(), "struct net_device *") == i->second.end()) entry_point_call += device_str + ", "; for(auto j = i->second.begin(); j != i->second.end(); j++) { if (*j == "struct net_device *") entry_point_call += device_str + ", "; else if (*j == "struct pci_dev *") entry_point_call += func_params["struct pci_dev *"] + ", "; else if (*j == "struct device *") entry_point_call += "&" + func_params["struct pci_dev *"] + "->dev, "; else if (*j == "void *") entry_point_call += "NULL, "; else if (*j == "u64 *") entry_point_call += "NULL, "; else if (*j == "u8 *") entry_point_call += "NULL, "; else if (*j == "struct sk_buff *") entry_point_call += "whoop_skb, "; else if (*j == "struct ethtool_wolinfo *") entry_point_call += "whoop_wolinfo, "; else if (*j == "struct ethtool_cmd *") entry_point_call += "whoop_ecmd, "; else if (*j == "struct ifreq *") entry_point_call += "whoop_ifreq, "; else if (*j == "struct rtnl_link_stats64 *") entry_point_call += "whoop_rtnlsts64, "; else if (*j == "struct ethtool_regs *") entry_point_call += "whoop_ethtoolregs, "; else if (*j == "struct ethtool_stats *") entry_point_call += "whoop_ethtoolsts, "; else if (*j == "struct ethtool_drvinfo *") entry_point_call += "whoop_ethtooldrvinfo, "; else if (*j == "netdev_features_t") entry_point_call += "whoop_netdevfeat, "; else if (*j == "int") entry_point_call += "whoop_int, "; else if (*j == "u32") entry_point_call += "whoop_int, "; else entry_point_call += *j + ", "; } entry_point_call.resize(entry_point_call.size() - 2); RW.InsertText(loc, "\t" + entry_point_call + ");\n", true, true); } RW.InsertText(loc, "}", true, true); }
string NetworkDriverRewriteVisitor::GetSharedStructStrInFunctionBody(Stmt *body, bool doLog) { string shared_struct_str = ""; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (isa<DeclStmt>(*i)) { DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *varDecl = cast<VarDecl>(declStmt->getSingleDecl()); if (!isa<ValueDecl>(varDecl)) continue; ValueDecl *value = cast<ValueDecl>(varDecl); if (value->getType().getAsString(Context->getPrintingPolicy()) != "struct net_device *") continue; if (!isa<NamedDecl>(varDecl)) continue; if (varDecl->getInit() == 0 || !isa<CallExpr>(varDecl->getInit())) continue; CallExpr *callExpr = cast<CallExpr>(varDecl->getInit()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } else if (isa<BinaryOperator>(*i)) { BinaryOperator *binOp = cast<BinaryOperator>(*i); if (!isa<CallExpr>(binOp->getRHS())) continue; CallExpr *callExpr = cast<CallExpr>(binOp->getRHS()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } } return shared_struct_str; }
bool DeclExtractor::ExtractDecl(Decl* D) { FunctionDecl* FD = dyn_cast<FunctionDecl>(D); if (FD) { if (FD->getNameAsString().find("__cling_Un1Qu3")) return true; llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (ND) { DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition OldDC->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); m_Sema->IdResolver.RemoveDecl(ND); } if (ND->getDeclContext() == ND->getLexicalDeclContext()) ND->setLexicalDeclContext(DC); else assert("Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); VD->setStorageClassAsWritten(SC_None); // if we want to print the result of the initializer of int i = 5 // or the default initializer int i if (I+1 == EI || !isa<NullStmt>(*(I+1))) { QualType VDTy = VD->getType().getNonReferenceType(); Expr* DRE = m_Sema->BuildDeclRefExpr(VD, VDTy,VK_LValue, SourceLocation() ).take(); Stmts.push_back(DRE); } } // force recalc of the linkage (to external) ND->ClearLinkageCache(); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } // Append the new top level decl to the current transaction. getTransaction()->appendUnique(DeclGroupRef(TouchedDecls[i])); } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; } return true; }