private bool TryComputeNAryExprs(IdentifierExpr id) { var toRemove = new HashSet <Expr>(); foreach (var expr in this.ExpressionMap[id].Keys.ToList()) { if (!(expr is NAryExpr)) { continue; } int ixs = 0; if (((expr as NAryExpr).Args[0] is IdentifierExpr) && ((expr as NAryExpr).Args[0] as IdentifierExpr).Name.StartsWith("$M.")) { toRemove.Add(expr); continue; } if (PointerAnalysis.ShouldSkipFromAnalysis(expr as NAryExpr)) { toRemove.Add(expr); continue; } if (PointerAnalysis.IsArithmeticExpression(expr as NAryExpr)) { toRemove.Add(expr); continue; } Expr p = (expr as NAryExpr).Args[0]; Expr i = (expr as NAryExpr).Args[1]; Expr s = (expr as NAryExpr).Args[2]; if (!(i is LiteralExpr && s is LiteralExpr)) { toRemove.Add(expr); continue; } ixs = (i as LiteralExpr).asBigNum.ToInt * (s as LiteralExpr).asBigNum.ToInt; this.ExpressionMap[id].Add(p, this.ExpressionMap[id][expr] + ixs); toRemove.Add(expr); } foreach (var expr in toRemove) { this.ExpressionMap[id].Remove(expr); } if (this.ExpressionMap[id].Any(val => val.Key is NAryExpr)) { return(false); } return(true); }
/// <summary> /// Performs an analysis to identify lock creation. /// </summary> /// <param name="parent">Thread</param> /// <param name="child">Thread</param> /// <param name="impl">Implementation</param> /// <param name="ins">Optional list of expressions</param> private void IdentifyLockCreationInImplementation(Thread parent, Implementation impl, List <Expr> inPtrs = null) { if (this.AlreadyAnalyzedImplementations.Contains(impl)) { return; } this.AlreadyAnalyzedImplementations.Add(impl); foreach (var block in impl.Blocks) { foreach (var cmd in block.Cmds) { if (cmd is CallCmd) { CallCmd call = cmd as CallCmd; if (call.callee.Equals("pthread_mutex_init")) { var exprs = new HashSet <Expr>(); var result = new PointerAnalysis(this.AC, impl).GetPointerOrigins(call.Ins[0], out exprs); var lockExpr = exprs.FirstOrDefault(); if (result != PointerAnalysis.ResultType.Allocated && result != PointerAnalysis.ResultType.Shared && inPtrs != null) { lockExpr = new PointerAnalysis(this.AC, impl).RecomputeExprFromInParams(lockExpr, inPtrs); } this.AbstractInitializedLock(parent, lockExpr, call); } if (!Utilities.ShouldSkipFromAnalysis(call.callee) || call.callee.StartsWith("pthread_create$")) { List <Expr> computedRootPointers = new List <Expr>(); foreach (var inParam in call.Ins) { if (inParam is NAryExpr) { computedRootPointers.Add(inParam); } else { var exprs = new HashSet <Expr>(); new PointerAnalysis(this.AC, impl).GetPointerOrigins(inParam, out exprs); var ptrExpr = exprs.FirstOrDefault(); computedRootPointers.Add(ptrExpr); } } this.IdentifyLockCreationInCall(parent, call, computedRootPointers); } } } } }
/// <summary> /// Performs an analysis to identify lock usage. /// </summary> /// <param name="parent">Thread</param> /// <param name="impl">Implementation</param> /// <param name="ins">Optional list of expressions</param> private void IdentifyLockUsageInImplementation(Thread parent, Implementation impl, List <Expr> inPtrs = null) { if (this.AlreadyAnalyzedImplementations.Contains(impl)) { return; } this.AlreadyAnalyzedImplementations.Add(impl); foreach (var block in impl.Blocks) { foreach (var cmd in block.Cmds) { if (cmd is CallCmd) { CallCmd call = cmd as CallCmd; if (call.callee.Equals("pthread_mutex_lock") || call.callee.Equals("pthread_mutex_unlock")) { var exprs = new HashSet <Expr>(); var result = new PointerAnalysis(this.AC, impl).GetPointerOrigins(call.Ins[0], out exprs); var lockExpr = exprs.FirstOrDefault(); if (result != PointerAnalysis.ResultType.Allocated && result != PointerAnalysis.ResultType.Shared && inPtrs != null) { lockExpr = new PointerAnalysis(this.AC, impl).RecomputeExprFromInParams(lockExpr, inPtrs); } bool matched = false; foreach (var l in this.AC.Locks) { if (l.IsEqual(this.AC, impl, lockExpr)) { if (ToolCommandLineOptions.Get().SuperVerboseMode) { Output.PrintLine("..... {0} uses lock '{1}'", parent, l.Name); } if (Output.Debugging) { Output.PrintLine("....... replacing lock '{0}' in call '{1}', line {2}", call.Ins[0], call.callee, call.Line); } call.Ins[0] = new IdentifierExpr(l.Id.tok, l.Id); matched = true; break; } } if (!matched && this.AC.Locks.Count == 1) { var l = this.AC.Locks[0]; if (ToolCommandLineOptions.Get().SuperVerboseMode) { Output.PrintLine("..... {0} uses lock '{1}'", parent, l.Name); } if (Output.Debugging) { Output.PrintLine("....... replacing lock '{0}' in call '{1}', line {2}", call.Ins[0], call.callee, call.Line); } call.Ins[0] = new IdentifierExpr(l.Id.tok, l.Id); } else if (!matched) { this.AbstractUsedLock(parent, lockExpr, call); } } if (!Utilities.ShouldSkipFromAnalysis(call.callee) || call.callee.StartsWith("pthread_create$") || call.callee.StartsWith("__call_wrapper$")) { List <Expr> computedRootPointers = new List <Expr>(); foreach (var inParam in call.Ins) { if (inParam is NAryExpr) { computedRootPointers.Add(inParam); } else { var exprs = new HashSet <Expr>(); new PointerAnalysis(this.AC, impl).GetPointerOrigins(inParam, out exprs); var ptrExpr = exprs.FirstOrDefault(); computedRootPointers.Add(ptrExpr); } } Thread child = null; if (call.callee.StartsWith("pthread_create$")) { var tid = computedRootPointers[0] as IdentifierExpr; child = this.AC.Threads.First(val => !val.IsMain && val.Id.IsEqual(tid)); parent = child; } this.IdentifyLockUsageInCall(parent, call, computedRootPointers); } } } } }
/// <summary> /// Performs an analysis to identify thread usage. /// </summary> /// <param name="parent">Thread</param> /// <param name="parent">child</param> /// <param name="impl">Implementation</param> /// <param name="ins">Optional list of expressions</param> private void IdentifyThreadUsageInImplementation(Thread parent, Thread child, Implementation impl, List <Expr> inPtrs = null) { if (this.AlreadyAnalyzedImplementations.Contains(impl)) { return; } this.AlreadyAnalyzedImplementations.Add(impl); if (child != null && impl.Name.Equals(child.Name)) { parent = child; } foreach (var block in impl.Blocks) { foreach (var cmd in block.Cmds) { if (cmd is CallCmd) { CallCmd call = cmd as CallCmd; Thread spawned = null; if (call.callee.Equals("pthread_create")) { var exprs = new HashSet <Expr>(); var result = new PointerAnalysis(this.AC, impl).GetPointerOrigins(call.Ins[0], out exprs); var tidExpr = exprs.FirstOrDefault(); if (result != PointerAnalysis.ResultType.Allocated && result != PointerAnalysis.ResultType.Shared && inPtrs != null) { tidExpr = new PointerAnalysis(this.AC, impl).RecomputeExprFromInParams(tidExpr, inPtrs); } spawned = this.GetAbstractSpawnedThread(parent, impl, tidExpr, call); } else if (call.callee.Equals("pthread_join")) { var exprs = new HashSet <Expr>(); var result = new PointerAnalysis(this.AC, impl).GetPointerOrigins(call.Ins[0], out exprs); var tidExpr = exprs.FirstOrDefault(); if (result != PointerAnalysis.ResultType.Allocated && result != PointerAnalysis.ResultType.Shared && inPtrs != null) { tidExpr = new PointerAnalysis(this.AC, impl).RecomputeExprFromInParams(tidExpr, inPtrs); } bool matched = false; foreach (var tid in this.AC.ThreadIds) { if (tid.IsEqual(this.AC, impl, tidExpr)) { var thread = parent.Children.FirstOrDefault(val => val.Id.Equals(tid)); if (thread == null) { continue; } call.Ins[0] = new IdentifierExpr(tid.Id.tok, tid.Id); thread.Joiner = new Tuple <Implementation, Block, CallCmd>(impl, block, call); if (ToolCommandLineOptions.Get().SuperVerboseMode) { Output.PrintLine("..... {0} blocks {1}", parent, thread); } matched = true; break; } } if (!matched) { this.AbstractBlockedThread(parent, impl, tidExpr, call); } } if (!Utilities.ShouldSkipFromAnalysis(call.callee) || call.callee.Equals("pthread_create") || call.callee.Equals("__call_wrapper")) { List <Expr> computedRootPointers = new List <Expr>(); foreach (var inParam in call.Ins) { if (inParam is NAryExpr) { computedRootPointers.Add(inParam); } else { var exprs = new HashSet <Expr>(); new PointerAnalysis(this.AC, impl).GetPointerOrigins(inParam, out exprs); var ptrExpr = exprs.FirstOrDefault(); computedRootPointers.Add(ptrExpr); } } this.IdentifyThreadUsageInCall(parent, spawned, call, computedRootPointers); } } } } }