private void FindUseOfFunctionPointers(InstrumentationRegion region, int regionIndex, IdentifierExpr constant, HashSet <InstrumentationRegion> alreadyFound) { if (alreadyFound.Contains(region)) { return; } alreadyFound.Add(region); var id = region.Implementation().InParams[regionIndex]; if (region.FunctionPointers.Contains(id)) { return; } region.FunctionPointers.Add(id); foreach (var block in region.Blocks()) { for (int idx = 0; idx < block.Cmds.Count; idx++) { if (!(block.Cmds[idx] is CallCmd)) { continue; } var call = block.Cmds[idx] as CallCmd; var calleeRegion = this.AC.InstrumentationRegions.Find(val => val.Implementation().Name.Equals(call.callee)); if (calleeRegion == null) { continue; } var indexes = new HashSet <int>(); for (int i = 0; i < call.Ins.Count; i++) { if (!(call.Ins[i] is IdentifierExpr)) { continue; } if (id.Name.Equals((call.Ins[i] as IdentifierExpr).Name)) { indexes.Add(i); } } if (indexes.Count == 0) { continue; } foreach (var index in indexes) { this.FindUseOfFunctionPointers(calleeRegion, index, constant, alreadyFound); } } } }
private void CleanUpRegion(InstrumentationRegion region) { region.Implementation().Proc.Modifies.RemoveAll(val => val.Name.Contains("_in_LS_$M.") || val.Name.StartsWith("WRITTEN_$M.") || val.Name.StartsWith("READ_$M.")); }
protected void SliceRegion(InstrumentationRegion region) { foreach (var write in region.HasWriteAccess) { if (!this.EP.HasWriteAccess.ContainsKey(write.Key)) { continue; } this.EP.HasWriteAccess[write.Key] = this.EP.HasWriteAccess[write.Key] - write.Value; if (this.EP.HasWriteAccess[write.Key] <= 0) { this.EP.HasWriteAccess.Remove(write.Key); } } foreach (var read in region.HasReadAccess) { if (!this.EP.HasReadAccess.ContainsKey(read.Key)) { continue; } this.EP.HasReadAccess[read.Key] = this.EP.HasReadAccess[read.Key] - read.Value; if (this.EP.HasReadAccess[read.Key] <= 0) { this.EP.HasReadAccess.Remove(read.Key); } } this.AC.TopLevelDeclarations.RemoveAll(val => (val is Procedure && (val as Procedure).Name.Equals(region.Implementation().Name)) || (val is Implementation && (val as Implementation).Name.Equals(region.Implementation().Name)) || (val is Constant && (val as Constant).Name.Equals(region.Implementation().Name))); this.AC.InstrumentationRegions.Remove(region); this.EP.CallGraph.Remove(region); }
private void CleanUpReadInRegion(InstrumentationRegion region) { region.Implementation().Proc.Modifies.RemoveAll(val => val.Name.StartsWith("READ_$M.")); }
private void CleanUpWriteInRegion(InstrumentationRegion region) { region.Implementation().Proc.Modifies.RemoveAll(val => val.Name.StartsWith("WRITTEN_$M.")); }
private bool IdentifyCallAccessesInRegion(InstrumentationRegion region) { int numberOfCalls = 0; int numberOfNonCheckedCalls = 0; foreach (var block in region.Implementation().Blocks) { for (int idx = 0; idx < block.Cmds.Count; idx++) { if (!(block.Cmds[idx] is CallCmd)) { continue; } var call = block.Cmds[idx] as CallCmd; bool isInstrumentedCall = false; if (idx + 1 < block.Cmds.Count && block.Cmds[idx + 1] is AssumeCmd) { isInstrumentedCall = QKeyValue.FindStringAttribute((block.Cmds[idx + 1] as AssumeCmd).Attributes, "captureState") != null; } if (!isInstrumentedCall) { numberOfCalls++; var calleeRegion = this.AC.InstrumentationRegions.Find(val => val.Implementation().Name.Equals(call.callee)); if (calleeRegion == null) { numberOfNonCheckedCalls++; continue; } if (calleeRegion.GetResourceAccesses().Count == 0 && calleeRegion.IsNotAccessingResources) { numberOfNonCheckedCalls++; continue; } if (!region.CallInformation.ContainsKey(call)) { region.CallInformation.Add(call, new Dictionary <int, Tuple <Expr, Expr> >()); region.ExternallyReceivedAccesses.Add(call, new Dictionary <string, HashSet <Expr> >()); for (int i = 0; i < call.Ins.Count; i++) { var id = calleeRegion.Implementation().InParams[i]; HashSet <Expr> ptrExprs = null; this.PtrAnalysisCache[region].TryComputeRootPointers(call.Ins[i], out ptrExprs); foreach (var ptrExpr in ptrExprs) { region.CallInformation[call].Add(i, new Tuple <Expr, Expr>(ptrExpr, new IdentifierExpr(id.tok, id))); break; } } } } } } if (numberOfCalls == numberOfNonCheckedCalls && region.HasWriteAccess.Count == 0 && this.EP.ForceWriteResource.Count == 0) { this.CleanUpWriteInRegion(region); region.IsNotWriteAccessingResources = true; } if (numberOfCalls == numberOfNonCheckedCalls && region.HasReadAccess.Count == 0 && this.EP.ForceReadResource.Count == 0) { this.CleanUpReadInRegion(region); region.IsNotReadAccessingResources = true; } if (numberOfCalls == numberOfNonCheckedCalls && region.GetResourceAccesses().Count == 0 && this.EP.ForceWriteResource.Count == 0 && this.EP.ForceReadResource.Count == 0) { this.CleanUpRegion(region); region.IsNotAccessingResources = true; return(false); } return(true); }
private void AnalyseLocalAccessesInRegion(InstrumentationRegion region) { foreach (var block in region.Implementation().Blocks) { for (int idx = 0; idx < block.Cmds.Count; idx++) { if (!(block.Cmds[idx] is CallCmd)) { continue; } var call = block.Cmds[idx] as CallCmd; bool isInstrumentedCall = false; string resource = null; string accessType = null; if (idx + 1 < block.Cmds.Count && block.Cmds[idx + 1] is AssumeCmd) { isInstrumentedCall = QKeyValue.FindStringAttribute((block.Cmds[idx + 1] as AssumeCmd).Attributes, "captureState") != null; resource = QKeyValue.FindStringAttribute((block.Cmds[idx + 1] as AssumeCmd).Attributes, "resource"); accessType = QKeyValue.FindStringAttribute((block.Cmds[idx + 1] as AssumeCmd).Attributes, "access"); } if (isInstrumentedCall && resource != null && accessType != null) { if ((this.EP.ForceWriteResource.Contains(resource) && accessType.Equals("write")) || (this.EP.ForceReadResource.Contains(resource) && accessType.Equals("read"))) { continue; } if (call.Ins.Count == 0) { region.TryAddLocalResourceAccess(resource, new LiteralExpr(Token.NoToken, BigNum.FromInt(0))); continue; } HashSet <Expr> ptrExprs = null; var result = this.PtrAnalysisCache[region].TryComputeRootPointers(call.Ins[0], out ptrExprs); foreach (var ptrExpr in ptrExprs) { var id = this.PtrAnalysisCache[region].GetIdentifier(ptrExpr); if (result == PointerArithmeticAnalyser.ResultType.Const) { region.TryAddLocalResourceAccess(resource, ptrExpr); } else if (!WhoopCommandLineOptions.Get().CheckInParamAliasing&& region.FunctionPointers.Any(val => val.Name.Equals(id.Name))) { call.callee = "_NO_OP_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); } else if (this.PtrAnalysisCache[region].IsAxiom(id)) { if (!this.AC.AxiomAccessesMap.ContainsKey(resource)) { this.AC.AxiomAccessesMap.Add(resource, new HashSet <Expr>()); } if (!this.AC.AxiomAccessesMap[resource].Any(val => val.ToString().Equals(ptrExpr.ToString()))) { this.AC.AxiomAccessesMap[resource].Add(ptrExpr); } region.TryAddLocalResourceAccess(resource, ptrExpr); } else { region.TryAddLocalResourceAccess(resource, ptrExpr); } } if (ptrExprs.Count == 0 && accessType.Equals("write")) { this.EP.ForceWriteResource.Add(resource); } else if (ptrExprs.Count == 0 && accessType.Equals("read")) { this.EP.ForceReadResource.Add(resource); } } } } }
private void AnalyseDomainSpecificEnableUsage(string type) { if ((type.Equals("register_netdev") || type.Equals("misc_register") || type.Equals("nfc_register_device")) && this.DeviceRegisterRegion == null) { return; } if (type.Equals("network") && this.NetworkEnableRegion == null) { return; } InstrumentationRegion hotRegion = null; if (type.Equals("register_netdev") || type.Equals("misc_register") || type.Equals("nfc_register_device")) { hotRegion = this.DeviceRegisterRegion; } if (type.Equals("network")) { hotRegion = this.NetworkEnableRegion; } var predecessorCallees = new HashSet <InstrumentationRegion>(); var successorCallees = new HashSet <InstrumentationRegion>(); if (type.Equals("register_netdev") || type.Equals("misc_register") || type.Equals("nfc_register_device")) { this.AnalyseBlocksForDeviceRegisterRegion(hotRegion, true, predecessorCallees, successorCallees); } var checkedPredecessors = new HashSet <InstrumentationRegion>(); bool foundCall = false; var predecessors = this.EP.CallGraph.Predecessors(hotRegion); while (predecessors.Count > 0) { var newPredecessors = new HashSet <InstrumentationRegion>(); foreach (var pred in predecessors) { if (checkedPredecessors.Contains(pred)) { continue; } checkedPredecessors.Add(pred); foreach (var block in pred.Blocks()) { foreach (var call in block.Cmds.OfType <CallCmd>()) { if (!foundCall && call.callee.Equals(hotRegion.Implementation().Name)) { foundCall = true; } var region = this.AC.InstrumentationRegions.Find(val => val.Name().Equals(call.callee + "$instrumented")); if (region == null) { continue; } if (foundCall && !predecessorCallees.Contains(region)) { successorCallees.Add(region); } else { predecessorCallees.Add(region); } } } foreach (var nestedPred in this.EP.CallGraph.Predecessors(pred)) { if (!checkedPredecessors.Contains(nestedPred)) { newPredecessors.Add(nestedPred); } } foundCall = false; } predecessors.Clear(); predecessors = checkedPredecessors; } var successors = this.EP.CallGraph.NestedSuccessors(hotRegion); successorCallees.UnionWith(successors); predecessorCallees.RemoveWhere(val => successorCallees.Contains(val)); foreach (var pred in predecessorCallees.ToList()) { var succs = this.EP.CallGraph.NestedSuccessors(pred); succs.RemoveWhere(val => successorCallees.Contains(val)); predecessorCallees.UnionWith(succs); } foreach (var pred in predecessorCallees) { if (pred.Equals(hotRegion)) { continue; } if (type.Equals("register_netdev") || type.Equals("misc_register") || type.Equals("nfc_register_device")) { pred.IsDeviceRegistered = false; } if (type.Equals("network")) { pred.IsDisablingNetwork = true; } } foreach (var succ in successorCallees) { if (succ.Equals(hotRegion)) { continue; } if (type.Equals("network")) { succ.IsEnablingNetwork = true; } } }
private void InstrumentRaceCheckingCaptureStates(InstrumentationRegion region) { if (region.Implementation().Name.Equals(this.EP.Name)) { AssumeCmd assumeLogHead = new AssumeCmd(Token.NoToken, Expr.True); assumeLogHead.Attributes = new QKeyValue(Token.NoToken, "captureState", new List <object>() { this.EP.Name + "_header_state" }, assumeLogHead.Attributes); region.Header().Cmds.Add(assumeLogHead); } foreach (var b in region.Blocks()) { List <Cmd> newCmds = new List <Cmd>(); foreach (var c in b.Cmds) { if (!(c is CallCmd)) { newCmds.Add(c); continue; } CallCmd call = c as CallCmd; if (!(call.callee.Contains("_WRITE_LS_") || call.callee.Contains("_READ_LS_"))) { newCmds.Add(call); continue; } AssumeCmd assume = new AssumeCmd(Token.NoToken, Expr.True); assume.Attributes = new QKeyValue(Token.NoToken, "column", new List <object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(QKeyValue.FindIntAttribute(call.Attributes, "column", -1))) }, null); assume.Attributes = new QKeyValue(Token.NoToken, "line", new List <object>() { new LiteralExpr(Token.NoToken, BigNum.FromInt(QKeyValue.FindIntAttribute(call.Attributes, "line", -1))) }, assume.Attributes); if (call.callee.Contains("WRITE")) { assume.Attributes = new QKeyValue(Token.NoToken, "access", new List <object>() { "write" }, assume.Attributes); } else if (call.callee.Contains("READ")) { assume.Attributes = new QKeyValue(Token.NoToken, "access", new List <object>() { "read" }, assume.Attributes); } assume.Attributes = new QKeyValue(Token.NoToken, "entrypoint", new List <object>() { this.EP.Name }, assume.Attributes); assume.Attributes = new QKeyValue(Token.NoToken, "captureState", new List <object>() { "access_state_" + this.LogCounter++ }, assume.Attributes); assume.Attributes = new QKeyValue(Token.NoToken, "resource", new List <object>() { "$" + call.callee.Split(new char[] { '$', '_' })[4] }, assume.Attributes); newCmds.Add(call); newCmds.Add(assume); } b.Cmds = newCmds; } }
private bool InstrumentAssumes(InstrumentationRegion checkRegion, IdentifierExpr id1, IdentifierExpr id2, LiteralExpr num1, LiteralExpr num2) { foreach (var region in this.AC.InstrumentationRegions) { if (region.IsNotAccessingResources) { continue; } if (!region.CallInformation.Any(val => val.Key.callee.Equals(checkRegion.Implementation().Name))) { continue; } foreach (var block in region.Blocks()) { for (int idx = 0; idx < block.Cmds.Count; idx++) { if (!(block.Cmds[idx] is CallCmd)) { continue; } var call = block.Cmds[idx] as CallCmd; if (!call.callee.Equals(checkRegion.Implementation().Name)) { continue; } IdentifierExpr callId1 = null; IdentifierExpr callId2 = null; for (int i = 0; i < call.Ins.Count; i++) { if (!(call.Ins[i] is IdentifierExpr)) { continue; } if (checkRegion.Implementation().InParams[i].Name.Equals(id1.Name)) { callId1 = call.Ins[i] as IdentifierExpr; } else if (checkRegion.Implementation().InParams[i].Name.Equals(id2.Name)) { callId2 = call.Ins[i] as IdentifierExpr; } } if (callId1 == null || callId2 == null) { continue; } if (callId1 != null && !this.AC.TopLevelDeclarations.OfType <Constant>().Any(val => val.Name.Equals(callId1.Name)) && !region.Implementation().InParams.Exists(val => val.Name.Equals(callId1.Name))) { HashSet <Expr> ptrExprs = null; this.PtrAnalysisCache[region].TryComputeRootPointers(callId1, out ptrExprs); if (ptrExprs.Count == 0) { return(false); } } if (callId2 != null && !this.AC.TopLevelDeclarations.OfType <Constant>().Any(val => val.Name.Equals(callId2.Name)) && !region.Implementation().InParams.Exists(val => val.Name.Equals(callId2.Name))) { HashSet <Expr> ptrExprs = null; this.PtrAnalysisCache[region].TryComputeRootPointers(callId2, out ptrExprs); if (ptrExprs.Count == 0) { return(false); } } Expr lexpr = Expr.Lt(new NAryExpr(Token.NoToken, new BinaryOperator(Token.NoToken, BinaryOperator.Opcode.Add), new List <Expr> { callId1, num1 }), callId2); Expr rexpr = Expr.Lt(new NAryExpr(Token.NoToken, new BinaryOperator(Token.NoToken, BinaryOperator.Opcode.Add), new List <Expr> { callId2, num2 }), callId1); var assume = new AssumeCmd(Token.NoToken, Expr.Or(lexpr, rexpr)); if (!this.AssumesMap.ContainsKey(region)) { this.AssumesMap.Add(region, new Dictionary <Block, HashSet <Tuple <AssumeCmd, int> > >()); } if (!this.AssumesMap[region].ContainsKey(block)) { this.AssumesMap[region].Add(block, new HashSet <Tuple <AssumeCmd, int> >()); } this.AssumesMap[region][block].Add(new Tuple <AssumeCmd, int>(assume, idx)); } } } return(true); }