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 InstrumentSourceLocationInfo(InstrumentationRegion region) { foreach (var b in region.Blocks()) { for (int idx = 0; idx < b.Cmds.Count; idx++) { if (!(b.Cmds[idx] is CallCmd)) { continue; } CallCmd call = b.Cmds[idx] as CallCmd; AssumeCmd assume = null; for (int i = idx; i >= 0; i--) { if (b.Cmds[i] is AssumeCmd) { assume = b.Cmds[i] as AssumeCmd; break; } } if (assume == null) { for (int i = idx; i < b.Cmds.Count; i++) { if (b.Cmds[i] is AssumeCmd) { assume = b.Cmds[i] as AssumeCmd; break; } } } if (call.callee.Contains("_UPDATE_CLS")) { call.Attributes = this.GetSourceLocationAttributes( assume.Attributes, call.Attributes); } else if (call.callee.Contains("_WRITE_LS_")) { call.Attributes = this.GetSourceLocationAttributes( assume.Attributes, call.Attributes); } else if (call.callee.Contains("_READ_LS_")) { call.Attributes = this.GetSourceLocationAttributes( assume.Attributes, call.Attributes); } } } }
private void AbstractReadAccesses(InstrumentationRegion region) { foreach (var b in region.Blocks()) { for (int k = 0; k < b.Cmds.Count; k++) { if (!(b.Cmds[k] is AssignCmd)) { continue; } foreach (var rhs in (b.Cmds[k] as AssignCmd).Rhss.OfType <NAryExpr>()) { if (!(rhs.Fun is MapSelect) || rhs.Args.Count != 2 || !((rhs.Args[0] as IdentifierExpr).Name.StartsWith("$M."))) { continue; } Variable v = (b.Cmds[k] as AssignCmd).Lhss[0].DeepAssignedVariable; HavocCmd havoc = new HavocCmd(Token.NoToken, new List <IdentifierExpr> { new IdentifierExpr(v.tok, v) }); b.Cmds[k] = havoc; } if (!(b.Cmds[k] is AssignCmd)) { continue; } foreach (var rhs in (b.Cmds[k] as AssignCmd).Rhss.OfType <IdentifierExpr>()) { if (!(rhs.Name.StartsWith("$M."))) { continue; } Variable v = (b.Cmds[k] as AssignCmd).Lhss[0].DeepAssignedVariable; HavocCmd havoc = new HavocCmd(Token.NoToken, new List <IdentifierExpr> { new IdentifierExpr(v.tok, v) }); b.Cmds[k] = havoc; } } } }
private void FindUseOfFunctionPointers(InstrumentationRegion region) { 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 idxConst = new Dictionary <int, IdentifierExpr>(); for (int i = 0; i < call.Ins.Count; i++) { if (!(call.Ins[i] is IdentifierExpr)) { continue; } if (!this.AC.TopLevelDeclarations.OfType <Constant>().Any(val => val.Name.Equals((call.Ins[i] as IdentifierExpr).Name))) { continue; } idxConst.Add(i, call.Ins[i] as IdentifierExpr); } if (idxConst.Count == 0) { continue; } foreach (var ic in idxConst) { var alreadyFound = new HashSet <InstrumentationRegion>(); this.FindUseOfFunctionPointers(calleeRegion, ic.Key, ic.Value, alreadyFound); } } } }
private void AbstractWriteAccesses(InstrumentationRegion region) { foreach (var b in region.Blocks()) { List <Cmd> cmdsToRemove = new List <Cmd>(); for (int k = 0; k < b.Cmds.Count; k++) { if (!(b.Cmds[k] is AssignCmd)) { continue; } foreach (var lhs in (b.Cmds[k] as AssignCmd).Lhss.OfType <MapAssignLhs>()) { if (!(lhs.DeepAssignedIdentifier.Name.StartsWith("$M.")) || !(lhs.Map is SimpleAssignLhs) || lhs.Indexes.Count != 1) { continue; } cmdsToRemove.Add(b.Cmds[k]); } foreach (var lhs in (b.Cmds[k] as AssignCmd).Lhss.OfType <SimpleAssignLhs>()) { if (!(lhs.DeepAssignedIdentifier.Name.StartsWith("$M."))) { continue; } cmdsToRemove.Add(b.Cmds[k]); } } foreach (var c in cmdsToRemove) { b.Cmds.Remove(c); } } }
private void AnalyseBlocksForDeviceRegisterRegion(InstrumentationRegion hotRegion, bool type, HashSet <InstrumentationRegion> predecessorCallees, HashSet <InstrumentationRegion> successorCallees) { bool foundCall = false; foreach (var block in hotRegion.Blocks()) { foreach (var call in block.Cmds.OfType <CallCmd>()) { if (type && !foundCall && call.callee.StartsWith("_REGISTER_DEVICE_")) { foundCall = true; } else if (!type && !foundCall && call.callee.StartsWith("_UNREGISTER_DEVICE_")) { 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); } } } }
private void AnalyseLocksetFuncForwardsUsage(string type) { if (type.Equals("tx") && this.TransmitLockHolder == null) { return; } InstrumentationRegion lockHolder = null; if (type.Equals("tx")) { lockHolder = this.TransmitLockHolder; } var predecessorCallees = new HashSet <InstrumentationRegion>(); var successorCallees = new HashSet <InstrumentationRegion>(); bool foundCall = false; foreach (var block in lockHolder.Blocks()) { foreach (var call in block.Cmds.OfType <CallCmd>()) { if (!foundCall && call.callee.StartsWith("_UPDATE_CLS_") && call.Ins[0].ToString().Equals("lock$" + type)) { 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); } } } var predecessors = this.EP.CallGraph.NestedPredecessors(lockHolder); predecessorCallees.UnionWith(predecessors); var predSuccs = new HashSet <InstrumentationRegion>(); foreach (var pred in predecessorCallees) { var succs = this.EP.CallGraph.NestedSuccessors(pred, lockHolder); predSuccs.UnionWith(succs); } predecessorCallees.UnionWith(predSuccs); var successors = this.EP.CallGraph.NestedSuccessors(lockHolder); successorCallees.UnionWith(successors); successorCallees.RemoveWhere(val => predecessorCallees.Contains(val)); foreach (var succ in successorCallees) { if (type.Equals("tx")) { succ.IsHoldingTxLock = true; } } }
private void InstrumentImplementation(InstrumentationRegion region) { foreach (var block in region.Blocks()) { for (int idx = 0; idx < block.Cmds.Count; idx++) { if (!(block.Cmds[idx] is AssignCmd)) { continue; } var assign = block.Cmds[idx] as AssignCmd; var lhssMap = assign.Lhss.OfType <MapAssignLhs>(); var lhss = assign.Lhss.OfType <SimpleAssignLhs>(); var rhssMap = assign.Rhss.OfType <NAryExpr>(); var rhss = assign.Rhss.OfType <IdentifierExpr>(); CallCmd call = null; if (lhssMap.Count() == 1) { var lhs = lhssMap.First(); if (lhs.DeepAssignedIdentifier.Name.StartsWith("$M.") && lhs.Map is SimpleAssignLhs && lhs.Indexes.Count == 1) { if (SharedStateAnalyser.GetMemoryRegions(this.EP).Any(val => val.Name.Equals(lhs.DeepAssignedIdentifier.Name))) { var ind = lhs.Indexes[0]; call = new CallCmd(Token.NoToken, this.MakeAccessFuncName(AccessType.WRITE, lhs.DeepAssignedIdentifier.Name), new List <Expr> { ind }, new List <IdentifierExpr>()); if (rhssMap.Count() == 0 && assign.Rhss.Count == 1 && assign.Rhss[0].ToString().StartsWith("$p")) { call.Attributes = new QKeyValue(Token.NoToken, "rhs", new List <object>() { assign.Rhss[0] }, call.Attributes); } if (!region.HasWriteAccess.ContainsKey(lhs.DeepAssignedIdentifier.Name)) { region.HasWriteAccess.Add(lhs.DeepAssignedIdentifier.Name, 0); } region.HasWriteAccess[lhs.DeepAssignedIdentifier.Name] = region.HasWriteAccess[lhs.DeepAssignedIdentifier.Name] + 1; } else { call = new CallCmd(Token.NoToken, "_NO_OP_$" + this.EP.Name, new List <Expr>(), new List <IdentifierExpr>()); } } } else if (lhss.Count() == 1) { var lhs = lhss.First(); if (lhs.DeepAssignedIdentifier.Name.StartsWith("$M.")) { if (SharedStateAnalyser.GetMemoryRegions(this.EP).Any(val => val.Name.Equals(lhs.DeepAssignedIdentifier.Name))) { call = new CallCmd(Token.NoToken, this.MakeAccessFuncName(AccessType.WRITE, lhs.DeepAssignedIdentifier.Name), new List <Expr>(), new List <IdentifierExpr>()); if (rhssMap.Count() == 0 && assign.Rhss.Count == 1 && assign.Rhss[0].ToString().StartsWith("$p")) { call.Attributes = new QKeyValue(Token.NoToken, "rhs", new List <object>() { assign.Rhss[0] }, call.Attributes); } if (!region.HasWriteAccess.ContainsKey(lhs.DeepAssignedIdentifier.Name)) { region.HasWriteAccess.Add(lhs.DeepAssignedIdentifier.Name, 0); } region.HasWriteAccess[lhs.DeepAssignedIdentifier.Name] = region.HasWriteAccess[lhs.DeepAssignedIdentifier.Name] + 1; } else { call = new CallCmd(Token.NoToken, "_NO_OP_$" + this.EP.Name, new List <Expr>(), new List <IdentifierExpr>()); } } } if (rhssMap.Count() == 1) { var rhs = rhssMap.First(); if (rhs.Fun is MapSelect && rhs.Args.Count == 2 && (rhs.Args[0] as IdentifierExpr).Name.StartsWith("$M.")) { if (SharedStateAnalyser.GetMemoryRegions(this.EP).Any(val => val.Name.Equals((rhs.Args[0] as IdentifierExpr).Name))) { call = new CallCmd(Token.NoToken, this.MakeAccessFuncName(AccessType.READ, (rhs.Args[0] as IdentifierExpr).Name), new List <Expr> { rhs.Args[1] }, new List <IdentifierExpr>()); if (!region.HasReadAccess.ContainsKey((rhs.Args[0] as IdentifierExpr).Name)) { region.HasReadAccess.Add((rhs.Args[0] as IdentifierExpr).Name, 0); } region.HasReadAccess[(rhs.Args[0] as IdentifierExpr).Name] = region.HasReadAccess[(rhs.Args[0] as IdentifierExpr).Name] + 1; } else { call = new CallCmd(Token.NoToken, "_NO_OP_$" + this.EP.Name, new List <Expr>(), new List <IdentifierExpr>()); } } } else if (rhss.Count() == 1) { var rhs = rhss.First(); if (rhs.Name.StartsWith("$M.")) { if (SharedStateAnalyser.GetMemoryRegions(this.EP).Any(val => val.Name.Equals(rhs.Name))) { call = new CallCmd(Token.NoToken, this.MakeAccessFuncName(AccessType.READ, rhs.Name), new List <Expr>(), new List <IdentifierExpr>()); if (!region.HasReadAccess.ContainsKey(rhs.Name)) { region.HasReadAccess.Add(rhs.Name, 0); } region.HasReadAccess[rhs.Name] = region.HasReadAccess[rhs.Name] + 1; } else { call = new CallCmd(Token.NoToken, "_NO_OP_$" + this.EP.Name, new List <Expr>(), new List <IdentifierExpr>()); } } } if (call != null) { block.Cmds.Insert(idx + 1, call); } } } foreach (var write in region.HasWriteAccess) { if (!this.EP.HasWriteAccess.ContainsKey(write.Key)) { this.EP.HasWriteAccess.Add(write.Key, 0); } this.EP.HasWriteAccess[write.Key] = this.EP.HasWriteAccess[write.Key] + write.Value; } foreach (var read in region.HasReadAccess) { if (!this.EP.HasReadAccess.ContainsKey(read.Key)) { this.EP.HasReadAccess.Add(read.Key, 0); } this.EP.HasReadAccess[read.Key] = this.EP.HasReadAccess[read.Key] + read.Value; } }
private void InstrumentImplementation(InstrumentationRegion region) { 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("register_netdev") || call.callee.Equals("misc_register") || call.callee.Equals("nfc_register_device")) { call.callee = "_REGISTER_DEVICE_$" + this.EP.Name; call.Ins.Clear(); if (this.DeviceRegisterRegion == null) { this.DeviceRegisterRegion = region; } region.IsChangingDeviceRegistration = true; this.EP.IsEnablingDevice = true; } else if (call.callee.Equals("unregister_netdev") || call.callee.Equals("misc_deregister") || call.callee.Equals("nfc_free_device")) { call.callee = "_UNREGISTER_DEVICE_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); if (this.DeviceUnregisterRegion == null) { this.DeviceUnregisterRegion = region; } region.IsChangingDeviceRegistration = true; this.EP.IsDisablingDevice = true; } else if (call.callee.Equals("netif_device_attach")) { if (!this.EP.IsNetLocked) { call.callee = "_ENABLE_NETWORK_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); if (this.NetworkEnableRegion == null) { this.NetworkEnableRegion = region; } region.IsChangingNetAvailability = true; } else { call.callee = "_NO_OP_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); } } else if (call.callee.Equals("netif_device_detach")) { if (!this.EP.IsNetLocked) { call.callee = "_DISABLE_NETWORK_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); region.IsChangingNetAvailability = true; } else { call.callee = "_NO_OP_$" + this.EP.Name; call.Ins.Clear(); call.Outs.Clear(); } } else if (call.callee.Equals("alloc_etherdev") || call.callee.Equals("alloc_testdev")) { List <AssignLhs> newLhss = new List <AssignLhs>(); List <Expr> newRhss = new List <Expr>(); newLhss.Add(new SimpleAssignLhs(call.Outs[0].tok, call.Outs[0])); newRhss.Add(new IdentifierExpr(this.AC.DeviceStruct.tok, this.AC.DeviceStruct)); var assign = new AssignCmd(Token.NoToken, newLhss, newRhss); block.Cmds[idx] = assign; } } } }
private void InstrumentDeadlockCheckingCaptureStates(InstrumentationRegion region) { 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("_CHECK_ALL_LOCKS_HAVE_BEEN_RELEASED") || call.callee.Contains("_UPDATE_CLS"))) { newCmds.Add(call); continue; } AssumeCmd assume = new AssumeCmd(Token.NoToken, Expr.True); if (call.callee.Contains("_UPDATE_CLS")) { 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); } assume.Attributes = new QKeyValue(Token.NoToken, "entrypoint", new List <object>() { this.EP.Name }, assume.Attributes); if (call.callee.Contains("_UPDATE_CLS")) { assume.Attributes = new QKeyValue(Token.NoToken, "captureState", new List <object>() { "update_cls_state_" + this.UpdateCounter++ }, assume.Attributes); newCmds.Add(call); newCmds.Add(assume); } else { assume.Attributes = new QKeyValue(Token.NoToken, "captureState", new List <object>() { "check_deadlock_state" }, assume.Attributes); newCmds.Add(assume); newCmds.Add(call); } } b.Cmds = newCmds; } }
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; } }