Skip to content

Commit

Permalink
remove old cfg
Browse files Browse the repository at this point in the history
  • Loading branch information
ailrst committed Aug 9, 2024
1 parent 091002f commit f713fae
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 1,127 deletions.
829 changes: 0 additions & 829 deletions src/main/scala/analysis/Cfg.scala

This file was deleted.

20 changes: 0 additions & 20 deletions src/main/scala/analysis/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,6 @@ trait Dependencies[N]:
*/
def indep(n: N): Set[N]

trait InterproceduralForwardDependencies extends Dependencies[CfgNode] {
override def outdep(n: CfgNode): Set[CfgNode] = n.succInter.toSet
override def indep(n: CfgNode): Set[CfgNode] = n.predInter.toSet
}

trait IntraproceduralForwardDependencies extends Dependencies[CfgNode] {
override def outdep(n: CfgNode): Set[CfgNode] = n.succIntra.toSet
override def indep(n: CfgNode): Set[CfgNode] = n.predIntra.toSet
}

trait InterproceduralBackwardDependencies extends Dependencies[CfgNode] {
override def outdep(n: CfgNode): Set[CfgNode] = n.predInter.toSet
override def indep(n: CfgNode): Set[CfgNode] = n.succInter.toSet
}

trait IntraproceduralBackwardDependencies extends Dependencies[CfgNode] {
override def outdep(n: CfgNode): Set[CfgNode] = n.predIntra.toSet
override def indep(n: CfgNode): Set[CfgNode] = n.succIntra.toSet
}

trait IRInterproceduralForwardDependencies extends Dependencies[CFGPosition] {
override def outdep(n: CFGPosition): Set[CFGPosition] = InterProcIRCursor.succ(n)
override def indep(n: CFGPosition): Set[CFGPosition] = InterProcIRCursor.pred(n)
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/analysis/InterprocSteensgaardAnalysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ case class RegisterWrapperEqualSets(variable: Variable, assigns: Set[Assign]) {
class InterprocSteensgaardAnalysis(
program: Program,
constantProp: Map[CFGPosition, Map[RegisterWrapperEqualSets, Set[BitVecLiteral]]],
regionAccesses: Map[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]]],
regionAccesses: Map[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]]],
mmm: MemoryModelMap,
reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])],
globalOffsets: Map[BigInt, BigInt]) extends Analysis[Any] {
Expand Down Expand Up @@ -431,4 +431,4 @@ object Fresh {
n += 1
n
}
}
}
6 changes: 3 additions & 3 deletions src/main/scala/analysis/MemoryRegionAnalysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ trait MemoryRegionAnalysis(val program: Program,
val constantProp: Map[CFGPosition, Map[Variable, FlatElement[BitVecLiteral]]],
val ANRResult: Map[CFGPosition, Set[Variable]],
val RNAResult: Map[CFGPosition, Set[Variable]],
val regionAccesses: Map[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]]],
val regionAccesses: Map[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]]],
reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])]) {

var mallocCount: Int = 0
Expand Down Expand Up @@ -234,7 +234,7 @@ class MemoryRegionAnalysisSolver(
constantProp: Map[CFGPosition, Map[Variable, FlatElement[BitVecLiteral]]],
ANRResult: Map[CFGPosition, Set[Variable]],
RNAResult: Map[CFGPosition, Set[Variable]],
regionAccesses: Map[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]]],
regionAccesses: Map[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]]],
reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])]
) extends MemoryRegionAnalysis(program, globals, globalOffsets, subroutines, constantProp, ANRResult, RNAResult, regionAccesses, reachingDefs)
with IRIntraproceduralForwardDependencies
Expand All @@ -249,4 +249,4 @@ class MemoryRegionAnalysisSolver(
case _ => super.funsub(n, x)
}
}
}
}
38 changes: 19 additions & 19 deletions src/main/scala/analysis/RegToMemAnalysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,29 @@ import scala.collection.immutable
*
* Both in which constant propagation mark as TOP which is not useful.
*/
trait RegionAccessesAnalysis(cfg: ProgramCfg, constantProp: Map[CFGPosition, Map[Variable, FlatElement[BitVecLiteral]]], reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])]) {
trait RegionAccessesAnalysis(program: Program, constantProp: Map[CFGPosition, Map[Variable, FlatElement[BitVecLiteral]]], reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])]) {

val mapLattice: MapLattice[RegisterVariableWrapper, FlatElement[Expr], FlatLattice[Expr]] = MapLattice(FlatLattice[_root_.ir.Expr]())

val lattice: MapLattice[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]], MapLattice[RegisterVariableWrapper, FlatElement[Expr], FlatLattice[Expr]]] = MapLattice(mapLattice)
val lattice: MapLattice[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]], MapLattice[RegisterVariableWrapper, FlatElement[Expr], FlatLattice[Expr]]] = MapLattice(mapLattice)

val domain: Set[CfgNode] = cfg.nodes.toSet
val domain: Set[CFGPosition] = program.toSet

val first: Set[CfgNode] = Set(cfg.startNode)
val first: Set[CFGPosition] = program.procedures.toSet

/** Default implementation of eval.
*/
def eval(cmd: CfgCommandNode, constants: Map[Variable, FlatElement[BitVecLiteral]], s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = {
cmd.data match {
def eval(cmd: Statement, constants: Map[Variable, FlatElement[BitVecLiteral]], s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = {
cmd match {
case assign: Assign =>
assign.rhs match {
case memoryLoad: MemoryLoad =>
s + (RegisterVariableWrapper(assign.lhs, getDefinition(assign.lhs, cmd.data, reachingDefs)) -> FlatEl(memoryLoad))
s + (RegisterVariableWrapper(assign.lhs, getDefinition(assign.lhs, cmd, reachingDefs)) -> FlatEl(memoryLoad))
case binaryExpr: BinaryExpr =>
if (evaluateExpression(binaryExpr.arg1, constants).isEmpty) { // approximates Base + Offset
Logger.debug(s"Approximating $assign in $binaryExpr")
Logger.debug(s"Reaching defs: ${reachingDefs(cmd.data)}")
s + (RegisterVariableWrapper(assign.lhs, getDefinition(assign.lhs, cmd.data, reachingDefs)) -> FlatEl(binaryExpr))
Logger.debug(s"Reaching defs: ${reachingDefs(cmd)}")
s + (RegisterVariableWrapper(assign.lhs, getDefinition(assign.lhs, cmd, reachingDefs)) -> FlatEl(binaryExpr))
} else {
s
}
Expand All @@ -50,23 +50,23 @@ trait RegionAccessesAnalysis(cfg: ProgramCfg, constantProp: Map[CFGPosition, Map

/** Transfer function for state lattice elements.
*/
def localTransfer(n: CfgNode, s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = n match {
case cmd: CfgCommandNode =>
eval(cmd, constantProp(cmd.data), s)
def localTransfer(n: CFGPosition, s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = n match {
case cmd: Statement =>
eval(cmd, constantProp(cmd), s)
case _ => s // ignore other kinds of nodes
}

/** Transfer function for state lattice elements.
*/
def transfer(n: CfgNode, s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = localTransfer(n, s)
def transfer(n: CFGPosition, s: Map[RegisterVariableWrapper, FlatElement[Expr]]): Map[RegisterVariableWrapper, FlatElement[Expr]] = localTransfer(n, s)
}

class RegionAccessesAnalysisSolver(
cfg: ProgramCfg,
program: Program,
constantProp: Map[CFGPosition, Map[Variable, FlatElement[BitVecLiteral]]],
reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])],
) extends RegionAccessesAnalysis(cfg, constantProp, reachingDefs)
with InterproceduralForwardDependencies
with Analysis[Map[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]]]]
with SimpleWorklistFixpointSolver[CfgNode, Map[RegisterVariableWrapper, FlatElement[Expr]], MapLattice[RegisterVariableWrapper, FlatElement[Expr], FlatLattice[Expr]]] {
}
) extends RegionAccessesAnalysis(program, constantProp, reachingDefs)
with IRInterproceduralForwardDependencies
with Analysis[Map[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]]]]
with SimpleWorklistFixpointSolver[CFGPosition, Map[RegisterVariableWrapper, FlatElement[Expr]], MapLattice[RegisterVariableWrapper, FlatElement[Expr], FlatLattice[Expr]]] {
}
6 changes: 4 additions & 2 deletions src/main/scala/analysis/solvers/IDESolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,14 @@ abstract class BackwardIDESolver[D, T, L <: Lattice[T]](program: Program)

protected def isCall(call: CFGPosition): Boolean =
call match
case c : Command => isAfterCall(c) && IRWalk.prevCommandInBlock(c).map(_.isInstanceOf[DirectCall]).getOrElse(false)
case c : Command => isAfterCall(c)
&& c.parent.parent.returnBlock.isDefined
&& IRWalk.prevCommandInBlock(c).map(c => (!IRWalk.nextCommandInBlock(c).get.isInstanceOf[Halt]) && c.isInstanceOf[DirectCall]).getOrElse(false)
case _ => false

protected def isExit(exit: CFGPosition): Boolean =
exit match
case procedure: Procedure => true
case procedure: Procedure => procedure.blocks.nonEmpty
case _ => false

protected def getAfterCalls(exit: Procedure): Set[DirectCall] = exit.incomingCalls().toSet
Expand Down
37 changes: 0 additions & 37 deletions src/main/scala/cfg_visualiser/Output.scala

This file was deleted.

130 changes: 63 additions & 67 deletions src/main/scala/ir/transforms/IndirectCallResolution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import ir.*
import translating.*
import util.Logger
import util.intrusive_list.IntrusiveList
import analysis.CfgCommandNode
import scala.collection.mutable
import cilvisitor._

Expand Down Expand Up @@ -154,22 +153,23 @@ def resolveIndirectCalls(
*/

def resolveIndirectCallsUsingPointsTo(
cfg: ProgramCfg,
pointsTos: Map[RegisterVariableWrapper, Set[RegisterVariableWrapper | MemoryRegion]],
regionContents: Map[MemoryRegion, Set[BitVecLiteral | MemoryRegion]],
reachingDefs: Map[CFGPosition, (Map[Variable, Set[Assign]], Map[Variable, Set[Assign]])],
IRProgram: Program
): Boolean = {
var modified: Boolean = false
val worklist = ListBuffer[CfgNode]()
cfg.startNode.succIntra.union(cfg.startNode.succInter).foreach(node => worklist.addOne(node))
val worklist = ListBuffer[CFGPosition]()

val visited = mutable.Set[CfgNode]()
worklist.addAll(IRProgram)

val visited = mutable.Set[CFGPosition]()
while (worklist.nonEmpty) {
val node = worklist.remove(0)
if (!visited.contains(node)) {
// add to worklist before we delete the node and can no longer find its successors
InterProcIRCursor.succ(node).foreach(node => worklist.addOne(node))
process(node)
node.succIntra.union(node.succInter).foreach(node => worklist.addOne(node))
visited.add(node)
}
}
Expand Down Expand Up @@ -225,69 +225,65 @@ def resolveIndirectCallsUsingPointsTo(
}
}

def process(n: CfgNode): Unit = n match {
case c: CfgJumpNode =>
val block = c.block
c.data match
// don't try to resolve returns
case indirectCall: IndirectCall if indirectCall.target != Register("R30", 64) =>
if (!indirectCall.hasParent) {
// We only replace the calls with DirectCalls in the IR, and don't replace the CommandNode.data
// Hence if we have already processed this CFG node there will be no corresponding IndirectCall in the IR
// to replace.
// We want to replace all possible indirect calls based on this CFG, before regenerating it from the IR
return
def process(n: CFGPosition): Unit = n match {
case indirectCall: IndirectCall if indirectCall.target != Register("R30", 64) =>
if (!indirectCall.hasParent) {
// We only replace the calls with DirectCalls in the IR, and don't replace the CommandNode.data
// Hence if we have already processed this CFG node there will be no corresponding IndirectCall in the IR
// to replace.
// We want to replace all possible indirect calls based on this CFG, before regenerating it from the IR
return
}
assert(indirectCall.parent.statements.lastOption.contains(indirectCall))

val block = indirectCall.parent
val procedure = block.parent

val targetNames = resolveAddresses(indirectCall.target, indirectCall)
Logger.debug(s"Points-To approximated call ${indirectCall.target} with $targetNames")
Logger.debug(IRProgram.procedures)
val targets: mutable.Set[Procedure] = targetNames.map(name => IRProgram.procedures.find(_.name == name).getOrElse(addFakeProcedure(name)))

if (targets.size > 1) {
Logger.info(s"Resolved indirect call $indirectCall")
}

if (targets.size == 1) {
modified = true

// indirectCall.parent.parent.removeBlocks(indirectCall.returnTarget)
val newCall = DirectCall(targets.head, indirectCall.label)
block.statements.replace(indirectCall, newCall)
} else if (targets.size > 1) {

val oft = indirectCall.parent.jump

modified = true
val newBlocks = ArrayBuffer[Block]()
// indirectCall.parent.parent.removeBlocks(indirectCall.returnTarget)
for (t <- targets) {
Logger.debug(targets)
val address = t.address.match {
case Some(a) => a
case None => throw Exception(s"resolved indirect call $indirectCall to procedure which does not have address: $t")
}
assert(indirectCall.parent.statements.lastOption.contains(indirectCall))

val targetNames = resolveAddresses(indirectCall.target, indirectCall)
Logger.debug(s"Points-To approximated call ${indirectCall.target} with $targetNames")
Logger.debug(IRProgram.procedures)
val targets: mutable.Set[Procedure] = targetNames.map(name => IRProgram.procedures.find(_.name == name).getOrElse(addFakeProcedure(name)))

if (targets.size > 1) {
Logger.info(s"Resolved indirect call $indirectCall")
val assume = Assume(BinaryExpr(BVEQ, indirectCall.target, BitVecLiteral(address, 64)))
val newLabel: String = block.label + t.name
val directCall = DirectCall(t)

/* copy the goto node resulting */
val fallthrough = oft match {
case g: GoTo => GoTo(g.targets, g.label)
case h: Halt => Halt()
case r: Return => Return()
}


if (targets.size == 1) {
modified = true

// indirectCall.parent.parent.removeBlocks(indirectCall.returnTarget)
val newCall = DirectCall(targets.head, indirectCall.label)
block.statements.replace(indirectCall, newCall)
} else if (targets.size > 1) {

val oft = indirectCall.parent.jump

modified = true
val procedure = c.parent.data
val newBlocks = ArrayBuffer[Block]()
// indirectCall.parent.parent.removeBlocks(indirectCall.returnTarget)
for (t <- targets) {
Logger.debug(targets)
val address = t.address.match {
case Some(a) => a
case None => throw Exception(s"resolved indirect call $indirectCall to procedure which does not have address: $t")
}
val assume = Assume(BinaryExpr(BVEQ, indirectCall.target, BitVecLiteral(address, 64)))
val newLabel: String = block.label + t.name
val directCall = DirectCall(t)

/* copy the goto node resulting */
val fallthrough = oft match {
case g: GoTo => GoTo(g.targets, g.label)
case h: Halt => Halt()
case r: Return => Return()
}
newBlocks.append(Block(newLabel, None, ArrayBuffer(assume, directCall), fallthrough))
}
block.statements.remove(indirectCall)
procedure.addBlocks(newBlocks)
val newCall = GoTo(newBlocks, indirectCall.label)
block.replaceJump(newCall)
}
case _ =>
newBlocks.append(Block(newLabel, None, ArrayBuffer(assume, directCall), fallthrough))
}
block.statements.remove(indirectCall)
procedure.addBlocks(newBlocks)
val newCall = GoTo(newBlocks, indirectCall.label)
block.replaceJump(newCall)
}
case _ =>
}

Expand Down
1 change: 0 additions & 1 deletion src/main/scala/ir/transforms/ReplaceReturn.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def addReturnBlocks(p: Program, toAll: Boolean = false) = {
p.procedures.foreach(p => {
val containsReturn = p.blocks.map(_.jump).find(_.isInstanceOf[Return]).isDefined
if (toAll && p.blocks.isEmpty && p.entryBlock.isEmpty && p.returnBlock.isEmpty) {
Logger.info(s"proc ${p.name} ${p.entryBlock}, ${p.returnBlock}")
p.returnBlock = (Block(label=p.name + "_basil_return",jump=Return()))
p.entryBlock = (Block(label=p.name + "_basil_entry",jump=GoTo(p.returnBlock.get)))
} else if (p.returnBlock.isEmpty && (toAll || containsReturn)) {
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/ir/transforms/SplitThreads.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import util.Logger
import java.util.Base64
import spray.json.DefaultJsonProtocol.*
import util.intrusive_list.IntrusiveList
import analysis.CfgCommandNode
import scala.collection.mutable
import cilvisitor._

Expand Down
Loading

0 comments on commit f713fae

Please sign in to comment.