示例#1
0
VarDecl *SwitchStmt::getConditionVariable() const {
  if (!SubExprs[VAR])
    return 0;

  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
  return cast<VarDecl>(DS->getSingleDecl());
}
示例#2
0
VarDecl *WhileStmt::getConditionVariable() const {
  if (!SubExprs[VAR])
    return nullptr;

  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
  return cast<VarDecl>(DS->getSingleDecl());
}
示例#3
0
 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;
}
示例#5
0
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);
}
示例#6
0
 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();
    }
  }
示例#8
0
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();
}
示例#9
0
  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;
  }
示例#10
0
/// 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;
  }
示例#13
0
  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;
  }