1
+ package analysis .data_structure_analysis
2
+
3
+ import ir .{CFGPosition , Call , DirectCall , Expr , IndirectCall , IntraProcIRCursor , LocalVar , MemoryLoad , MemoryStore , Procedure , Statement , Variable , computeDomain }
4
+ import util .ConstGenLogger
5
+
6
+ sealed trait Constraint {
7
+ def source : CFGPosition
8
+ val label : String
9
+ def eval (evaluator : Expr => Any = identity): String
10
+ }
11
+
12
+ def content (value : Any ): String = s " [| ${value.toString}|]} "
13
+
14
+ case class ConstraintArg (value : Expr , contents : Boolean = false ) {
15
+ override def toString : String = eval()
16
+ def ignoreContents : ConstraintArg = ConstraintArg (value)
17
+ def eval (evaluator : Expr => Any = identity): String = {
18
+ val evaluated = evaluator(value)
19
+ if contents then content(evaluated) else evaluated.toString
20
+ }
21
+ }
22
+
23
+ sealed trait BinaryConstraint extends Constraint {
24
+ val arg1 : ConstraintArg
25
+ val arg2 : ConstraintArg
26
+
27
+ private def name = this .getClass.getSimpleName
28
+ override def toString : String = eval()
29
+ override def eval (evaluator : Expr => Any = identity): String = s " ( ${arg1.eval(evaluator)} <==> ${arg2.eval(evaluator)}"
30
+ }
31
+
32
+ case class AssignmentConstraint (pos : CFGPosition , ar1 : Expr , ar2 : Expr ) extends BinaryConstraint {
33
+ override def source : CFGPosition = pos
34
+ override val label : String = labelToPC(Some (pos.toString))
35
+ override val arg1 : ConstraintArg = ConstraintArg (ar1)
36
+ override val arg2 : ConstraintArg = ConstraintArg (ar2)
37
+ }
38
+
39
+ sealed trait MemoryAccessConstraint [T <: MemoryStore | MemoryLoad ](pos : T , index : Expr , value : Expr , val size : Int )
40
+ extends BinaryConstraint {
41
+ val label : String = labelToPC(pos.label)
42
+ override def source : T = pos
43
+
44
+ override val arg1 : ConstraintArg = ConstraintArg (index, true )
45
+ override val arg2 : ConstraintArg = ConstraintArg (value)
46
+
47
+ override def toString : String = eval()
48
+
49
+ override def eval (evaluator : Expr => Any = identity): String =
50
+ s " ${this .getClass.getSimpleName}( $label, size: $size): " + super .eval(evaluator)
51
+ }
52
+
53
+ case class MemoryReadConstraint (pos : MemoryLoad )
54
+ extends MemoryAccessConstraint [MemoryLoad ](pos, pos.index, pos.lhs, pos.size/ 8 )
55
+
56
+ case class MemoryWriteConstraint (pos : MemoryStore )
57
+ extends MemoryAccessConstraint [MemoryStore ](pos, pos.index, pos.value, pos.size/ 8 )
58
+
59
+ sealed trait CallConstraint [T <: Call , V <: Procedure | Variable ](call : T )
60
+ extends Constraint {
61
+ val label : String = labelToPC(call.label)
62
+ def caller : Procedure = call.parent.parent
63
+ def target : V
64
+ val inParams : Map [LocalVar , Expr ]
65
+ val outParmas : Map [LocalVar , LocalVar ]
66
+ def inConstraints : Set [AssignmentConstraint ] = inParams.map(pair => AssignmentConstraint (call, pair._1, pair._2)).toSet
67
+ def outConstraints : Set [AssignmentConstraint ] = outParmas.map(pair => AssignmentConstraint (call, pair._1, pair._2)).toSet
68
+ override def source : T = call
69
+ override def toString : String = eval()
70
+
71
+ override def eval (evaluator : Expr => Any = identity): String = {
72
+ s " ${this .getClass.getSimpleName}( $label, Proc ${caller.name} calls $target" ++ s " \n In Param Constraints: ${inConstraints.map(_.eval(evaluator))}"
73
+ ++ s " \n Out Param Constraints: ${outConstraints.map(_.eval(evaluator))}"
74
+ }
75
+ }
76
+
77
+ case class DirectCallConstraint (call : DirectCall )
78
+ extends CallConstraint [DirectCall , Procedure ] (call) {
79
+ override def target : Procedure = call.target
80
+
81
+ override val inParams : Map [LocalVar , Expr ] = call.actualParams
82
+ override val outParmas : Map [LocalVar , LocalVar ] = call.outParams.view.mapValues(_.asInstanceOf [LocalVar ]).toMap
83
+ }
84
+
85
+ case class IndirectCallConstraint (call : IndirectCall )
86
+ extends CallConstraint [IndirectCall , Variable ](call)
87
+ {
88
+
89
+ override def target : Variable = call.target
90
+
91
+ override val inParams : Map [LocalVar , Expr ] = Map .empty
92
+ override val outParmas : Map [LocalVar , LocalVar ] = Map .empty
93
+ }
94
+
95
+ def generateConstraints (proc : Procedure ): Set [Constraint ] = {
96
+ ConstGenLogger .info(s " Generating Constraints for ${proc.name}" )
97
+ val domain = computeDomain(IntraProcIRCursor , Set (proc))
98
+ var constraints : Set [Constraint ] = Set .empty
99
+
100
+ domain.foreach {
101
+ case load : MemoryLoad =>
102
+ constraints += MemoryReadConstraint (load)
103
+ case write : MemoryStore =>
104
+ constraints += MemoryWriteConstraint (write)
105
+ case call : DirectCall =>
106
+ constraints += DirectCallConstraint (call)
107
+ case indirectCall : IndirectCall => constraints += IndirectCallConstraint (indirectCall)
108
+ case _ =>
109
+ }
110
+
111
+ constraints
112
+ }
113
+
114
+ case class SVAConstraints (sva : SymbolicValues , constraints : Set [Constraint ]) {
115
+ def this (proc : Procedure ) = {
116
+ this (getSymbolicValues(proc), generateConstraints(proc))
117
+ }
118
+ def exprToSymVal (expr : Expr ): SymValueSet = sva.exprToSymValSet(expr)
119
+ }
120
+ object SVAConstraints {
121
+ def apply (proc : Procedure ) = new SVAConstraints (proc)
122
+ }
0 commit comments