std::vector<CallExpr *> Utils::callListForChain(CallExpr *lastCallExpr) { if (!lastCallExpr) return {}; const bool isOperator = isa<CXXOperatorCallExpr>(lastCallExpr); vector<CallExpr *> callexprs = { lastCallExpr }; Stmt *s = lastCallExpr; do { const int childCount = std::distance(s->child_begin(), s->child_end()); if (isOperator && childCount > 1) { // for operator case, the chained call childs are in the second child s = *(++s->child_begin()); } else { s = childCount > 0 ? *s->child_begin() : nullptr; } if (s) { CallExpr *callExpr = dyn_cast<CallExpr>(s); if (callExpr && callExpr->getCalleeDecl()) { callexprs.push_back(callExpr); } else if (MemberExpr *memberExpr = dyn_cast<MemberExpr>(s)) { if (isa<FieldDecl>(memberExpr->getMemberDecl())) break; // accessing a public member via . or -> breaks the chain } } } while (s); return callexprs; }
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(); } }
const CXXRecordDecl *Utils::recordForMemberCall(CXXMemberCallExpr *call, string &implicitCallee) { implicitCallee.clear(); Expr *implicitArgument= call->getImplicitObjectArgument(); if (!implicitArgument) { return nullptr; } Stmt *s = implicitArgument; while (s) { if (auto declRef = dyn_cast<DeclRefExpr>(s)) { if (declRef->getDecl()) { implicitCallee = declRef->getDecl()->getNameAsString(); QualType qt = declRef->getDecl()->getType(); return qt->getPointeeCXXRecordDecl(); } else { return nullptr; } } else if (auto thisExpr = dyn_cast<CXXThisExpr>(s)) { implicitCallee = "this"; return thisExpr->getType()->getPointeeCXXRecordDecl(); } else if (auto memberExpr = dyn_cast<MemberExpr>(s)) { auto decl = memberExpr->getMemberDecl(); if (decl) { implicitCallee = decl->getNameAsString(); QualType qt = decl->getType(); return qt->getPointeeCXXRecordDecl(); } else { return nullptr; } } s = s->child_begin() == s->child_end() ? nullptr : *(s->child_begin()); } return nullptr; }
bool RewriteUtils::addLocalVarToFunc(const std::string &VarStr, FunctionDecl *FD) { Stmt *Body = FD->getBody(); TransAssert(Body && "NULL body for a function definition!"); std::string IndentStr; StmtIterator I = Body->child_begin(); if (I == Body->child_end()) IndentStr = DefaultIndentStr; else IndentStr = getStmtIndentString((*I), SrcManager); std::string NewVarStr = "\n" + IndentStr + VarStr; SourceLocation StartLoc = Body->getLocStart(); return !(TheRewriter->InsertTextAfterToken(StartLoc, NewVarStr)); }
// Deal with all the call expr in the transaction. bool VisitCallExpr(CallExpr* TheCall) { if (FunctionDecl* FDecl = TheCall->getDirectCallee()) { std::bitset<32> ArgIndexs; for (FunctionDecl::redecl_iterator RI = FDecl->redecls_begin(), RE = FDecl->redecls_end(); RI != RE; ++RI) { for (specific_attr_iterator<NonNullAttr> I = RI->specific_attr_begin<NonNullAttr>(), E = RI->specific_attr_end<NonNullAttr>(); I != E; ++I) { NonNullAttr *NonNull = *I; // Store all the null attr argument's index into "ArgIndexs". for (NonNullAttr::args_iterator i = NonNull->args_begin(), e = NonNull->args_end(); i != e; ++i) { // Get the argument with the nonnull attribute. const Expr* Arg = TheCall->getArg(*i); // Check whether we can get the argument'value. If the argument is // not null, then ignore this argument and continue to deal with the // next argument with the nonnull attribute.ArgIndexs.set(*i); bool Result; ASTContext& Context = m_Sema->getASTContext(); if (Arg->EvaluateAsBooleanCondition(Result, Context) && Result) { continue; } ArgIndexs.set(*i); } break; } } if (ArgIndexs.any()) { // Get the function decl's name. std::string FName = getMangledName(FDecl); // Store the function decl's name into the vector. m_NonNullDeclNames.push_back(FName); // Store the function decl's name with its null attr args' indexes // into the map. m_NonNullArgIndexs.insert(std::make_pair(FName, ArgIndexs)); } // FIXME: For now we will only work/check on declarations that are not // deserialized. We want to avoid our null deref transaformer to // deserialize all the contents of a PCH/PCM. // We have to think of a better way to find the annotated // declarations, without that to cause too much deserialization. Stmt* S = (FDecl->isFromASTFile()) ? 0 : FDecl->getBody(); if (S) { for (Stmt::child_iterator II = S->child_begin(), EE = S->child_end(); II != EE; ++II) { CallExpr* child = dyn_cast<CallExpr>(*II); if (child && child->getDirectCallee() != FDecl) VisitCallExpr(child); } } } return true; // returning false will abort the in-depth traversal. }
bool VisitFunctionDecl(FunctionDecl *f) { // Only function definitions (with bodies), not declarations. if (f->hasBody()) { Stmt *FuncBody = f->getBody(); // Type name as string QualType QT = f->getReturnType(); std::string TypeStr = QT.getAsString(); // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); // Add comment before std::stringstream SSBefore; SSBefore << "// Begin function " << FuncName << " returning " << TypeStr << "\n"; SourceLocation ST = f->getSourceRange().getBegin(); TheRewriter.InsertText(ST, SSBefore.str(), true, true); // And after std::stringstream SSAfter; SSAfter << "\n// End function " << FuncName; ST = FuncBody->getLocEnd().getLocWithOffset(1); TheRewriter.InsertText(ST, SSAfter.str(), true, true); int forCounter=0; Stmt::child_iterator CI, CE = FuncBody->child_end(); for (CI = FuncBody->child_begin(); CI != CE; ++CI) { if (*CI != 0) { if (isa<ForStmt>(*CI)) { forCounter++; std::stringstream MarkerBefore; std::stringstream MarkerAfter; MarkerBefore<<"\nMCPROF_ZONE_ENTER(" << forCounter << ");\n"; MarkerAfter<<"\nMCPROF_ZONE_EXIT(" << forCounter << ");\n"; ForStmt *For = cast<ForStmt>(*CI); SourceLocation ST = For->getLocStart(); TheRewriter.InsertText(ST, MarkerBefore.str(), true, false); Stmt *ForBody = For->getBody(); SourceLocation END = ForBody->getLocEnd(); int offset = Lexer::MeasureTokenLength(END, TheRewriter.getSourceMgr(), TheRewriter.getLangOpts()) + 1; SourceLocation END1 = END.getLocWithOffset(offset); TheRewriter.InsertText(END1, MarkerAfter.str(), true, false); // llvm::errs() << " Detected for loop number " << forCounter // << " in function " << FuncName << "\n"; // InstrumentStmt(ForBody); // Stmt *ForBody = CI->getBody(); // SourceLocation ST = CI->getLocStart(); // char *b = sourceManager->getCharacterData(_b) // llvm::errs() << ST << " is location \n"; } } } } return true; }
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); }
bool FindGPUMacro::VisitForStmt(ForStmt *fstmt) { Stmt *body = fstmt->getBody(); analyze_data_struct(body); int tx = 1, ty = 1, tz = 1 , bx = 1, by = 1, bz = 1, gpu_time = 0, cpu_time = 0, instanceNum = 0; for (Stmt::child_iterator it = body->child_begin(), eit = body->child_end(); it != eit; it++) { Stmt *s = *it; if (DeclStmt *ds = dyn_cast<DeclStmt>(s)){ if (VarDecl *vd = dyn_cast<VarDecl>(ds->getSingleDecl())){ string className = vd->getTypeSourceInfo()->getType().getBaseTypeIdentifier()->getName(); if (className == "profile_time") { if (CXXConstructExpr *ce = dyn_cast<CXXConstructExpr>(vd->getInit()->IgnoreImpCasts())) { if (MaterializeTemporaryExpr *me = dyn_cast<MaterializeTemporaryExpr>(ce->getArg(0)->IgnoreImpCasts())) { if (CXXTemporaryObjectExpr *co = dyn_cast<CXXTemporaryObjectExpr>(me->GetTemporaryExpr()->IgnoreImpCasts())) { IntegerLiteral *x = dyn_cast<IntegerLiteral>(co->getArg(0)); IntegerLiteral *y = dyn_cast<IntegerLiteral>(co->getArg(1)); IntegerLiteral *z = dyn_cast<IntegerLiteral>(co->getArg(2)); instanceNum = x->getValue().getSExtValue(); gpu_time = y->getValue().getSExtValue(); cpu_time = z->getValue().getSExtValue(); } } } } if (className == "sc_gpu_thread_hierarchy") { if (CXXConstructExpr *ce = dyn_cast<CXXConstructExpr>(vd->getInit()->IgnoreImpCasts())) { if (MaterializeTemporaryExpr *me = dyn_cast<MaterializeTemporaryExpr>(ce->getArg(0)->IgnoreImpCasts())) { if (CXXTemporaryObjectExpr *co = dyn_cast<CXXTemporaryObjectExpr>(me->GetTemporaryExpr()->IgnoreImpCasts())) { IntegerLiteral *x = dyn_cast<IntegerLiteral>(co->getArg(1)); IntegerLiteral *y = dyn_cast<IntegerLiteral>(co->getArg(2)); IntegerLiteral *z = dyn_cast<IntegerLiteral>(co->getArg(3)); IntegerLiteral *w = dyn_cast<IntegerLiteral>(co->getArg(4)); instanceNum = x->getValue().getSExtValue(); tx = x->getValue().getSExtValue(); ty = y->getValue().getSExtValue(); tz = z->getValue().getSExtValue(); } } } } if (className == "sc_gpu_block_hierarchy") { if (CXXConstructExpr *ce = dyn_cast<CXXConstructExpr>(vd->getInit()->IgnoreImpCasts())) { if (MaterializeTemporaryExpr *me = dyn_cast<MaterializeTemporaryExpr>(ce->getArg(0)->IgnoreImpCasts())) { if (CXXTemporaryObjectExpr *co = dyn_cast<CXXTemporaryObjectExpr>(me->GetTemporaryExpr()->IgnoreImpCasts())) { IntegerLiteral *x = dyn_cast<IntegerLiteral>(co->getArg(1)); IntegerLiteral *y = dyn_cast<IntegerLiteral>(co->getArg(2)); IntegerLiteral *z = dyn_cast<IntegerLiteral>(co->getArg(3)); IntegerLiteral *w = dyn_cast<IntegerLiteral>(co->getArg(4)); instanceNum = x->getValue().getSExtValue(); bx = y->getValue().getSExtValue(); by = z->getValue().getSExtValue(); bz = w->getValue().getSExtValue(); } } } } } } //_os <<"\n gpu_time : " <<gpu_time<<" cpu_time : " <<cpu_time<<" instanceNum : " <<_instanceNum<<" " <<instanceNum; if (tx && ty && tz && bx && by && bz && gpu_time && cpu_time && (_instanceNum == instanceNum)) { //_os <<"\n instance num : " <<_instanceNum<<" " <<instanceNum; GPUMacro *gm = new GPUMacro(bx, by, bz, tx, ty, tz, gpu_time, cpu_time); //_os <<"\n for stmt : " <<fstmt; forStmtInstanceIdPairType forStmtInstanceId = make_pair(_instanceNum, fstmt); _forStmtGPUMacroMap.insert(forStmtGPUMacroPairType(forStmtInstanceId, gm)); break; } } return true; }