Exemplo n.º 1
0
        // Entry point
        public static int Main(string[] args, ISimpleLineWriter output)
        {
            var start          = DateTime.Now;
            var slicingOptions = new SlicingOptions(args);

            // we use it to parse the clousot options, and to split the work
            var clousot = new NewCCI2Driver(slicingOptions.remainingArgs.ToArray(), output);

            if (!clousot.CheckOptions())
            {
                return(-1);
            }

            var                   errorCode                      = 0;
            WorkerPool            workerPool                     = null;
            IQueue                queue                          = null;
            IWorkerFactory        localWorkerFactory             = null;
            List <IWorkerFactory> remoteWorkerFactories          = null;
            Func <SliceDefinition, ISliceWorkResult> workOnSlice = null;
            Dictionary <ISliceId, int> failedRegressions         = null;

            var localWorkers  = slicingOptions.LocalWorkers;
            var remoteWorkers = slicingOptions.RemoteWorkers;
            var workers       = localWorkers + remoteWorkers;


            // If we have workers, we create a Worker factory
            if (workers > 0)
            {
                IDB db;
                if (remoteWorkers > 0 || clousot.options.useCache)
                {
                    // Use Clousot Database
                    db = new StdDB(clousot.options);
                }
                else
                {
                    // In-memory database
                    db = new MemorySingletonDB();
                }

                workerPool = new WorkerPool("Worker", canCancel: false);
                queue      = new FIFOQueue(workerPool, db);

                // When a job is done, it choses which jobs to put in the queue (e.g., analyze the dependencies)
                var scheduler =
                    clousot.options.InferObjectInvariantsOnlyForReadonlyFields?
                    new LazySchedulerForObjectInvariants(queue, db) : // use LazySchedulerForObjectInvariants for global fixpoint computation including object invariants
                    new LazyScheduler(queue, db);                     // use LazyScheduler for the global fixpoint computation

                //var scheduler = new NoloopScheduler(queue);

                // Usual cache
                var clousotDB = slicingOptions.useDB ? db : null;

                var argsForWorker = clousot.argsForWorker.ToFList();

                if (localWorkers > 0)
                {
                    if (slicingOptions.cci1)
                    {
                        localWorkerFactory = new Clousot1WorkerFactory(scheduler, argsForWorker, output, clousotDB);
                    }
                    else
                    {
                        localWorkerFactory = new Clousot2WorkerFactory(scheduler, argsForWorker, output, clousotDB);
                    }
                    // TODO: use a lighter version of ClousotMain since options are already checked here
                }
                if (remoteWorkers > 0) // so far 1 factory per remote worker but we can do better
                {
                    // TODO: specifiy, for each address the number of workers

                    // We have a list, because we can have several addresses
                    remoteWorkerFactories = slicingOptions.serviceAddress.Select(addr => new Clousot2SWorkerFactory(scheduler, argsForWorker, output, addr)).ToList <IWorkerFactory>();
                }

                if (clousot.options.IsRegression)
                {
                    failedRegressions = new Dictionary <ISliceId, int>();
                }

                // fail if any work fails
                scheduler.OnWorkDone += (sliceId, returnCode) =>
                {
                    if (errorCode >= 0)
                    {
                        if (returnCode < 0) // special error code, keep only one
                        {
                            errorCode = returnCode;
                        }
                        else
                        {
                            int prevValue;
                            if (clousot.options.IsRegression)
                            {
                                lock (failedRegressions)
                                {
                                    Contract.Assume(failedRegressions != null);
                                    if (failedRegressions.TryGetValue(sliceId, out prevValue))
                                    {
                                        output.WriteLine("[Regression] We already analyzed {0} with outcome {1}. Now we update the outcome to {2}", sliceId.Dll, prevValue, returnCode);
                                    }
                                    failedRegressions[sliceId] = returnCode;
                                }
                            }
                            errorCode += returnCode; // regression error count, additive
                        }
                    }
                };

                // What we do for each slice. Two things:
                // 1. Register the slice in the db
                // 2. Add to the queue (via the scheduler, who decides how to do it)
                workOnSlice = sliceDef =>
                {
                    var sliceId = db.RegisterSlice(sliceDef);
                    scheduler.FeedQueue(new ISliceId[] { sliceId });
                    return(null);
                };
            }

            ISlicerResult slicerResult = null;

            if (slicingOptions.sliceFirst)
            {
                slicerResult = clousot.SplitWork(workOnSlice);
                output.WriteLine("Slicing time: {0}", DateTime.Now - start);
            }

            if (workerPool != null)
            {
                if (localWorkerFactory != null)
                {
                    for (var i = 0; i < localWorkers; i++)
                    {
                        workerPool.CreateWorker(localWorkerFactory);
                    }
                }
                if (remoteWorkerFactories != null)
                {
                    foreach (var factory in remoteWorkerFactories)
                    {
                        workerPool.CreateWorker(factory);
                    }
                }
            }

            if (!slicingOptions.sliceFirst)
            {
                slicerResult = clousot.SplitWork(workOnSlice);
                output.WriteLine("Slicing time and thread creation time : {0}", DateTime.Now - start);
            }

            if (workerPool != null)
            {
                // workerPool != null ==> queue != null
                Contract.Assume(queue != null);
                workerPool.WaitAllAnd(queue.EmptyQueueWaitHandle);
                // Something else can arrive at the queue, so we want to stop all of them
                workerPool.StopAll();
            }

            if (slicerResult != null)
            {
                var errors = slicerResult.GetErrors();
                if (errors.Any())
                {
                    foreach (var errMessage in errors)
                    {
                        output.WriteLine(errMessage);
                    }
                    errorCode = errors.Count();
                }
            }

            output.WriteLine("Total analysis time: {0}", DateTime.Now - start);

            var returnValue = errorCode;

            if (failedRegressions != null && clousot.options.IsRegression && errorCode >= 0)
            {
                returnValue = failedRegressions.Where(pair => pair.Value != 0).Select(pair => Math.Abs(pair.Value)).Sum();
            }

#if DEBUG
            if (clousot.options.IsRegression)
            {
                Console.WriteLine("[Regression] Returned value {0}", returnValue);
            }
#endif
            return(returnValue);
        }
Exemplo n.º 2
0
    // Entry point
    public static int Main(string[] args, ISimpleLineWriter output)
    {
      var start = DateTime.Now;
      var slicingOptions = new SlicingOptions(args);

      // we use it to parse the clousot options, and to split the work
      var clousot = new NewCCI2Driver(slicingOptions.remainingArgs.ToArray(), output);

      if (!clousot.CheckOptions())
      {
        return -1;
      }

      var errorCode = 0;
      WorkerPool workerPool = null;
      IQueue queue = null;
      IWorkerFactory localWorkerFactory = null;
      List<IWorkerFactory> remoteWorkerFactories = null;
      Func<SliceDefinition, ISliceWorkResult> workOnSlice = null;
      Dictionary<ISliceId, int> failedRegressions = null;

      var localWorkers = slicingOptions.LocalWorkers;
      var remoteWorkers = slicingOptions.RemoteWorkers;
      var workers = localWorkers + remoteWorkers;


      // If we have workers, we create a Worker factory
      if (workers > 0)
      {
        IDB db;
        if (remoteWorkers > 0 || clousot.options.useCache)
        {
          // Use Clousot Database 
          db = new StdDB(clousot.options);
        }
        else
        {
          // In-memory database
          db = new MemorySingletonDB();
        }

        workerPool = new WorkerPool("Worker", canCancel: false);
        queue = new FIFOQueue(workerPool, db);

        // When a job is done, it choses which jobs to put in the queue (e.g., analyze the dependencies)
        var scheduler = 
          clousot.options.InferObjectInvariantsOnlyForReadonlyFields? 
          new LazySchedulerForObjectInvariants(queue, db) : // use LazySchedulerForObjectInvariants for global fixpoint computation including object invariants
          new LazyScheduler(queue, db); // use LazyScheduler for the global fixpoint computation

        //var scheduler = new NoloopScheduler(queue);
        
        // Usual cache
        var clousotDB = slicingOptions.useDB ? db : null;

        var argsForWorker = clousot.argsForWorker.ToFList();

        if (localWorkers > 0)
        {
          if (slicingOptions.cci1)
            localWorkerFactory = new Clousot1WorkerFactory(scheduler, argsForWorker, output, clousotDB);
          else
            localWorkerFactory = new Clousot2WorkerFactory(scheduler, argsForWorker, output, clousotDB);
          // TODO: use a lighter version of ClousotMain since options are already checked here
        }
        if (remoteWorkers > 0) // so far 1 factory per remote worker but we can do better
        {
          // TODO: specifiy, for each address the number of workers

          // We have a list, because we can have several addresses
          remoteWorkerFactories = slicingOptions.serviceAddress.Select(addr => new Clousot2SWorkerFactory(scheduler, argsForWorker, output, addr)).ToList<IWorkerFactory>();
        }

        if (clousot.options.IsRegression)
        {
           failedRegressions = new Dictionary<ISliceId, int>();
        }

        // fail if any work fails
        scheduler.OnWorkDone += (sliceId, returnCode) =>
          {
            if (errorCode >= 0)
            {
              if (returnCode < 0) // special error code, keep only one
              {
                errorCode = returnCode;
              }
              else
              {
                int prevValue;
                if (clousot.options.IsRegression)
                {
                  lock (failedRegressions)
                  {
                    Contract.Assume(failedRegressions != null);
                    if (failedRegressions.TryGetValue(sliceId, out prevValue))
                    {
                      output.WriteLine("[Regression] We already analyzed {0} with outcome {1}. Now we update the outcome to {2}", sliceId.Dll, prevValue, returnCode);
                    }
                    failedRegressions[sliceId] = returnCode;
                  }
                }
                errorCode += returnCode; // regression error count, additive
              }
            }
          };

        // What we do for each slice. Two things:
        // 1. Register the slice in the db
        // 2. Add to the queue (via the scheduler, who decides how to do it)
        workOnSlice = sliceDef =>
        {
          var sliceId = db.RegisterSlice(sliceDef);
          scheduler.FeedQueue(new ISliceId[] { sliceId });
          return null;
        };
      }

      ISlicerResult slicerResult = null;

      if (slicingOptions.sliceFirst)
      {
        slicerResult = clousot.SplitWork(workOnSlice);
        output.WriteLine("Slicing time: {0}", DateTime.Now - start);
      }

      if (workerPool != null)
      {
        if (localWorkerFactory != null)
          for (var i = 0; i < localWorkers; i++)
            workerPool.CreateWorker(localWorkerFactory);
        if (remoteWorkerFactories != null)
          foreach (var factory in remoteWorkerFactories)
            workerPool.CreateWorker(factory);
      }

      if (!slicingOptions.sliceFirst)
      {
        slicerResult = clousot.SplitWork(workOnSlice);
        output.WriteLine("Slicing time and thread creation time : {0}", DateTime.Now - start);
      }

      if (workerPool != null)
      {
        // workerPool != null ==> queue != null
        Contract.Assume(queue != null);
        workerPool.WaitAllAnd(queue.EmptyQueueWaitHandle);
        // Something else can arrive at the queue, so we want to stop all of them
        workerPool.StopAll();
      }

      if (slicerResult != null)
      {
        var errors = slicerResult.GetErrors();
        if (errors.Any())
        {
          foreach (var errMessage in errors)
            output.WriteLine(errMessage);
          errorCode = errors.Count();
        }
      }

      output.WriteLine("Total analysis time: {0}", DateTime.Now - start);

      var returnValue = errorCode;

      if (failedRegressions != null && clousot.options.IsRegression && errorCode >= 0)
      {
        returnValue = failedRegressions.Where(pair => pair.Value != 0).Select(pair => Math.Abs(pair.Value)).Sum();
      }

#if DEBUG
      if (clousot.options.IsRegression)
      {
        Console.WriteLine("[Regression] Returned value {0}", returnValue);
      }
#endif      
      return returnValue;
    }