Commit 238ffdd7 authored by Gaurav Kukreja's avatar Gaurav Kukreja

Created copy of cfg_generator and named it map_cfg

Signed-off-by: Gaurav Kukreja's avatarGaurav Kukreja <gaurav@gauravk.in>
parent d94fa667
#-----------------------------------------------------------------
# map_cfg.py: Map Control Flow Graphs from Binary and ISC
#-----------------------------------------------------------------
from optparse import OptionParser
from cfg_binary import parse_binary, print_debug_binary
from cfg_isc import parse_isc, print_debug_isc
import logging
from collections import deque
listISCFileNames = []
listObjdumpFileNames = []
def map_cfg(listISCFileNames, listObjdumpFileNames):
listISCFunctions = []
listFunctionNames = []
listObjdumpFunctions = []
# Parse the ISC files
for ISCFileName in listISCFileNames:
listISCFunctions = listISCFunctions + parse_isc(ISCFileName)
for function in listISCFunctions:
listFunctionNames.append(function.functionName)
# Parse the objdump files
for ObjdumpFileName in listObjdumpFileNames:
listObjdumpFunctions = listObjdumpFunctions + parse_binary(ObjdumpFileName,
listFunctionNames)
print_debug_isc (listISCFunctions)
print_debug_binary (listObjdumpFunctions)
# Check that we found all functions in ISC in Objdump
if len(listISCFunctions) != len(listObjdumpFunctions):
raise ParseError("all functions in ISC file not found in Objdump file!")
for function in listISCFunctions:
logging.debug("Computing flow for function %s from file %s" % (function.functionName, function.fileName))
function.cfg.computeFlow()
for function in listObjdumpFunctions:
logging.debug("Computing flow for function %s from file %s" % (function.functionName, function.fileName))
function.cfg.computeFlow()
if __name__ == "__main__":
# listISCFileNames = []
# listObjdumpFileNames = []
logging.basicConfig(level=logging.DEBUG)
optparser = OptionParser()
optparser.add_option("-i", "--isc", action="append", dest="listISCFileNames",
type="string", help="ISC Filenamel. For multiple files, use -i <filename> multiple times.",
metavar="FILE")
optparser.add_option("-o", "--objdump", action="append",
type="string", dest="listObjdumpFileNames",
help="Objdump Filename. For multiple files, use -o <filename> multiple times.",
metavar="FILE")
(options, args) = optparser.parse_args()
if (len(args) > 0):
print "Addtional arguments are being ignored"
listISCFileNames = options.listISCFileNames
listObjdumpFileNames = options.listObjdumpFileNames
map_cfg(listISCFileNames, listObjdumpFileNames)
\ No newline at end of file
import sys
from collections import deque
import logging
class ParseError(Exception):
def __init__(self, str):
self.value = str
def __str__(self):
return repr(self.value)
class BBEdge:
def __init__(self, fromBlockIndex, toBlockIndex):
self.fromBlockIndex = fromBlockIndex;
self.toBlockIndex = toBlockIndex;
class BasicBlock:
def __init__(self, startLine, endLine, isReturning=0, listFuncCalls = None, name = None):
if name is None:
self.name = ""
else:
self.name = name
self.startLine = startLine
self.endLine = endLine
self.isReturning = isReturning
if listFuncCalls is None:
self.listFunctionCalls = []
else:
self.listFunctionCalls = listFuncCalls
self.flow = 0.0
class ControlFlowGraph:
def __init__(self, listBlocks, listEdges):
self.listBlocks = listBlocks
self.listEdges = listEdges
self.listBackEdges = []
def successorBlocks(self, blockIndex):
listSuccBlockIndices = []
for edge in self.listEdges:
if edge.fromBlockIndex == blockIndex:
listSuccBlockIndices.append(edge.toBlockIndex)
#logging.debug("Returns from successorBlocks(blockIndex)")
return listSuccBlockIndices
def successorBlocksWOBackEdges(self, blockIndex):
listSuccBlockIndices = []
edgeIndex = 0
for edge in self.listEdges:
if edge.fromBlockIndex == blockIndex and edgeIndex not in self.listBackEdges:
listSuccBlockIndices.append(edge.toBlockIndex)
edgeIndex = edgeIndex + 1
return listSuccBlockIndices
def successorBlocks(self, blockIndex):
listSuccBlockIndices = []
for edge in self.listEdges:
if edge.fromBlockIndex == blockIndex:
listSuccBlockIndices.append(edge.toBlockIndex)
return listSuccBlockIndices
def predecessorBlocksWOBackEdges(self, blockIndex):
listPredBlockIndices = []
edgeIndex = 0
for edge in self.listEdges:
if edge.toBlockIndex == blockIndex and edgeIndex not in self.listBackEdges:
listPredBlockIndices.append(edge.toBlockIndex)
edgeIndex = edgeIndex + 1
logging.debug("returns from predecessorBlocksWOBackEdges(blockIndex)")
return listPredBlockIndices
def findEdgeIndex(self, fromBlockIndex, toBlockIndex):
'''
Returns index of edge in listEdges with given starting and ending blocks
Return -1 if edge not found
'''
index = -1
for edge in self.listEdges:
index = index + 1
if edge.fromBlockIndex == fromBlockIndex and edge.toBlockIndex == toBlockIndex:
break
return index
# TODO Use a better name for this
def dft(self, blockIndex):
self.dft_stack.append(blockIndex)
for succBlock in self.successorBlocksWOBackEdges(blockIndex):
if succBlock not in self.dft_stack:
self.dft(succBlock)
else:
self.listBackEdges.append(self.findEdgeIndex(blockIndex, succBlock))
self.dft_stack.pop()
def findBackEdges(self):
'''
Populate the list of Back Edges in the graph by traversing in
Depth First Fashion
'''
self.dft_stack = []
self.dft(0)
self.listBackEdges = list(set(self.listBackEdges))
for edgeIndex in self.listBackEdges:
print self.listEdges[edgeIndex].fromBlockIndex, self.listEdges[edgeIndex].toBlockIndex
return self.listBackEdges
def computeFlow(self):
'''
Compute the flow value of each block in CFG of each function
'''
currBlockPredNotVisited = 0
queuePending = deque([])
self.findBackEdges()
self.listBlocks[0].flow = 1.0
for blockIndex in self.successorBlocksWOBackEdges(0):
queuePending.append(blockIndex)
while queuePending:
currBlockIndex = queuePending.popleft()
currBlockFlow = 0.0
for predBlockIndex in self.predecessorBlocksWOBackEdges(currBlockIndex):
if self.listBlocks[predBlockIndex].flow == 0:
# predecessor block still not visited
# add the current block back into queue, set flag and break from loop.
queuePending.append(currBlockIndex)
currBlockPredNotVisited = 1
break
else:
currBlockFlow = currBlockFlow + (self.listBlocks[predBlockIndex].flow / len(self.successorBlocksWOBackEdges(predBlockIndex)))
if currBlockPredNotVisited == 1:
currBlockPredNotVisited = 0
continue
else:
if currBlockFlow > 1.0:
raise ParseError("Flow in graph greater than 1!!")
exit(1)
else:
self.listBlocks[currBlockIndex].flow = currBlockFlow
class FunctionDesc:
def __init__(self, functionName, fileName, startLine, endLine, cfg):
self.functionName = functionName
self.fileName = fileName
self.startLine = startLine
self.endLine = endLine
self.cfg = cfg
\ No newline at end of file
File added
#-----------------------------------------------------------------
# cfg_binary.py: Construct Control Flow Graph for Binary
#-----------------------------------------------------------------
import sys
import re
from cfg import *
re_sectionStart = re.compile('Disassembly of section .(.*):')
re_funcDef = re.compile('\s*([0-9a-f]*)\s*<(.*)>:')
re_instruction = re.compile('\s*([0-9a-f]*):\s*[0-9a-f]*\s*(.*)')
re_branchInst = re.compile('\s*(b(?:l|x|lx|xj)?(?:eq|ne|mi|pl|hi|ls|ge|lt|gt|le)?)\s*([0-9a-f]*)\s*<(.*)>')
re_unconditionalBranchInst = re.compile('\s*(b(?:l|x|lx|xj)?)\s*([0-9a-f]*)\s*<(.*)>')
re_conditionalBranchInst = re.compile('\s*(b(?:l|x|lx|xj)?(?:eq|ne|mi|pl|hi|ls|ge|lt|gt|le))\s*([0-9a-f]*)\s*<(.*)>')
re_returnInst = re.compile('\s*(bx)\s*(lr)')
listFunctionsIgnore = ['__cs3_interrupt_vector',
'__cs3_reset',
'__cs3_start_asm_sim',
'__cs3_heap_start_ptr',
'__cs3_start_c',
'__do_global_dtors_aux',
'frame_dummy',
'atexit',
'exit',
'__register_exitproc',
'__call_exitprocs',
'register_fini',
'__libc_fini_array',
'__cs3_premain',
'_exit',
'__cs3_isr_interrupt',
'__libc_init_array']
def print_usage():
print("Usage:")
print("\t %s <objdump_fileName>\n" % (sys.argv[0]))
def parse_binary(fileName, listFunctionNames = []):
'''
Returns a list of all the functions defined in the objdump, along with the
control flow graph of each of the function.
'''
# State Management Variables
inTextSection = 0 # is 1, when inside Text Section
inFuncBody = 0 # is 1, when inside Function Body
currFuncName = ""
currFuncFileName = ""
currFuncStartLine = 0
listCurrFuncBlockStartLineNum = []
listCurrFuncBlockEndLineNum = []
listCurrFuncBlockStartAddress = []
listCurrFuncBlockEndAddress = []
lineNumForAddress = {}
branchInstAtLine = {}
returnInstAtLine = {}
functionCallAtLine = {}
# list of functions that will be returned
listFunctions = []
file = open(fileName, 'r')
lineNum = 0
for line in file:
'''
Main loop that parses the objdump file line by line.
Algorithm:
1. We only care for the .text section. Ignore lines in other sections.
2. Inside text section, look for start of function definition.
3. Inside Function, look for branch instruction. At each branch inst.
a. End of block at branch instruction.
b. Start of block at target of branch instruction.
c. End of block at inst. before target of branch inst.
d. Start of block at inst. after branch inst.
4. Inside Function, also look for return instruction.
a. End of block at return instruction.
'''
lineNum = lineNum + 1;
# 1. Ignore sections other than .text sections
m = re_sectionStart.match(line);
if m == None and inTextSection == 0:
continue
elif (m != None and m.group(1) != "text"):
if(inTextSection == 1):
# was in text section, and text section ended
break
elif (m != None and m.group(1) == "text"):
inTextSection = 1
continue
elif m == None and inTextSection == 1:
# inside text section
# 2. Look for start of function definition.
m = re_funcDef.match(line)
# if listFunctionNames provided, check if function name is in list
# if not, check that function name is not in listFunctionsIgnore
if m is not None and ((len(listFunctionNames) > 0 and
m.group(2) in listFunctionNames) or
(len(listFunctionNames) == 0 and
m.group(2) not in listFunctionsIgnore)):
inFuncBody = 1
currFuncName = m.group(2)
currFuncFileName = fileName
currFuncStartLine = lineNum + 1
listCurrFuncBlockStartLineNum.append(currFuncStartLine)
continue
if(inFuncBody == 1):
m = re_instruction.match(line)
if m is not None:
address = m.group(1)
lineNumForAddress[address] = lineNum;
inst = m.group(2)
m = re_branchInst.match(inst)
if m is not None and m.group(3).startswith(currFuncName):
# Branch Instruction
branchInstAtLine[lineNum] = inst
# 3.a End Block at Branch Inst.
listCurrFuncBlockEndAddress.append(address)
# 3.b Start Block at Target Address
targetAdd = m.group(2);
listCurrFuncBlockStartAddress.append(targetAdd)
# 3.c End Block before Target Address
listCurrFuncBlockEndAddress.append("%x" % (int(targetAdd, 16) - 4))
# 3.d Start Block after Branch Inst.
listCurrFuncBlockStartAddress.append("%x" % (int(address, 16) + 4))
continue
elif m is not None and not m.group(3).startswith(currFuncName):
# Function call
functionCallAtLine[lineNum] = inst
continue
m = re_returnInst.match(inst)
if m is not None:
# Return Instruction
returnInstAtLine[lineNum] = inst
listCurrFuncBlockEndAddress.append(address)
continue
continue
else:
# inside Function, instruction did not match i.e. end of
# function body.
# TODO: Explicitly check for a blank line
inFuncBody = 0
currFuncEndLine = lineNum - 1
# Construct the CFG here.
# Create list of line numbers
for add in listCurrFuncBlockStartAddress:
listCurrFuncBlockStartLineNum.append(lineNumForAddress[add])
for add in listCurrFuncBlockEndAddress:
listCurrFuncBlockEndLineNum.append(lineNumForAddress[add])
# Remove duplicates from the lists
listCurrFuncBlockStartLineNum = list(set(listCurrFuncBlockStartLineNum))
listCurrFuncBlockEndLineNum = list(set(listCurrFuncBlockEndLineNum))
# Sort the lists
listCurrFuncBlockStartLineNum.sort()
listCurrFuncBlockEndLineNum.sort()
# Ensure length of lists is equal
if len(listCurrFuncBlockStartLineNum) != len(listCurrFuncBlockEndLineNum):
raise ParseError("Length of lists of block start and end line numbers do not match for function %s" % (currFuncName))
# Create List of Blocks
listBlocks = []
for i in range(len(listCurrFuncBlockStartLineNum)):
listBlocks.append(BasicBlock(listCurrFuncBlockStartLineNum[i],
listCurrFuncBlockEndLineNum[i]))
# Create list of Edges
listEdges = []
for lNum in branchInstAtLine:
edgeStartBlockIndex = -1;
edgeEndBlockIndex = -1;
for i in range(len(listBlocks)):
if listBlocks[i].endLine == lNum:
edgeStartBlockIndex = i;
inst = branchInstAtLine[lNum]
m = re_branchInst.match(inst)
targetAdd = m.group(2)
targetLine = lineNumForAddress[targetAdd]
for i in range(len(listBlocks)):
if listBlocks[i].startLine == targetLine:
edgeEndBlockIndex = i;
if (edgeStartBlockIndex == -1 or edgeEndBlockIndex == -1):
raise ParseError("Matching edge for branch inst. could not be created in function %s" % (currFuncName))
listEdges.append(BBEdge(edgeStartBlockIndex,
edgeEndBlockIndex))
# For Conditional Branches, add an edge to next block
m = re_conditionalBranchInst.match(inst)
if m is not None:
listEdges.append(BBEdge(edgeStartBlockIndex,
edgeStartBlockIndex + 1))
# For Block End Line, which are not branch instructions,
# add edge to next block
for i in range(len(listBlocks)):
blockEndLine = listBlocks[i].endLine;
if blockEndLine not in branchInstAtLine and blockEndLine not in returnInstAtLine:
listEdges.append(BBEdge(i, i + 1))
# Mark the returning blocks
for lNum in returnInstAtLine:
for block in listBlocks:
if block.endLine == lNum:
block.isReturning = 1
# Add list of functions called in each block
for lNum in functionCallAtLine:
inst = functionCallAtLine[lNum]
m = re_branchInst.match(inst)
calledFuncName = m.group(3)
for block in listBlocks:
if block.startLine <= lNum and block.endLine >= lNum:
block.listFunctionCalls.append(calledFuncName)
# Add the current function and the CFG to the list of functions
listFunctions.append(FunctionDesc(currFuncName,
currFuncFileName,
currFuncStartLine,
currFuncEndLine,
ControlFlowGraph(listBlocks,
listEdges)))
# reset the state management variables
currFuncName = ""
currFuncFileName = ""
currFuncStartLine = 0
currFuncEndLine = 0
listCurrFuncBlockStartLineNum = []
listCurrFuncBlockEndLineNum = []
listCurrFuncBlockStartAddress = []
listCurrFuncBlockEndAddress = []
lineNumForAddress = {}
branchInstAtLine = {}
returnInstAtLine = {}
functionCallAtLine = {}
return listFunctions
def print_debug_binary(listFunctions):
for func in listFunctions:
print("\nlFileName : %s" % (func.fileName))
print("Function : %s" % (func.functionName))
i = 0
for block in func.cfg.listBlocks:
print("\t Block %d: line %d - %d, flow = %f" % (i, block.startLine, block.endLine, block.flow))
for funcCall in block.listFunctionCalls:
print("\t\t calls %s()" % (funcCall))
if block.isReturning == 1:
print("\t\t returns")
for edge in func.cfg.listEdges:
if edge.fromBlockIndex == i:
print("\t\t Edge to block %d" % (edge.toBlockIndex))
i = i + 1
if __name__ == "__main__":
if len(sys.argv) > 1:
fileName = sys.argv[1]
else:
print_usage()
exit(1)
listFunctions = parse_binary(fileName)
print_debug_binary(listFunctions)
\ No newline at end of file
#-----------------------------------------------------------------
# cfg_isc.py: Construct Control Flow Graph for Intermediate Source Code
#-----------------------------------------------------------------
import sys
import re
from cfg import *
# RE for function definition
# group(1) is function Name
# if group(2) == "){", single line definition
# elif group(2) == $, multi line definition
re_funcDef = re.compile('(?:\w*\s+)*\**(\w+)\s*\([\w\s,*]*($|\)\s*\{)')
re_funcDefArgLine = re.compile('[\w\s,]*($|\)\s*\{)')
re_basicBlockLabel = re.compile('\s*(\w*bb_[0-9]*):')
re_basicBlockStart = re.compile('\s*//\s*#\s*PRED:./*')
re_basicBlockEnd = re.compile('\s*//\s*#\s*SUCC:./*')
re_gotoLine = re.compile('\s*goto\s*(\w*bb_[0-9]*);')
re_funcCallLine = re.compile('\s*(\w*)\s*\([\w\s,]*\);')
re_returnLine = re.compile('\s*return\s*.*;')
re_funcDefEnd = re.compile('\s*\}')
class BasicBlockTargets:
def __init__(self, name, listTargets = None):
self.name = name
if listTargets == None:
self.listTargets = []
else:
self.listTargets = listTargets
def parse_isc(fileName):
listFunctions = []
# State Management
inFunctionBody = 0 # is 1, when inside Function Body
inFuncDefArgMultiLine = 0 # is 1, when inside multiline argument list for func Def.
currFuncName = ""
currFuncStartLine = 0
currFuncEndLine = 0
listCurrFuncBasicBlocks = []
listCurrFuncBasicBlockTargets = []
listCurrFuncBBEdges = []
inBasicBlock = 0
currBasicBlockName = ""
currBasicBlockStartLine = 0
currBasicBlockEndLine = 0
isCurrBasicBlockReturning = 0
listCurrBlockFuncCalls = []
listCurrBasicBlockTargets = []
lineNum = 0
file = open(fileName, 'r')
for line in file:
lineNum = lineNum + 1
'''
Loop to parse each line in the code.
Algorithm:
1. We only care about the code inside functions. Look for function
definitions.
a. Single Line Definition
b. Multiple Line Parameters
2. Inside the function body, we want to look for basic block labels,
function calls, goto instructions and return instructions.
a. Labels:
1. Record the name of the basic block.
2. Basic Block starts at next line with "// # PRED..."
3. Basic Block ends at line with "// # SUCC..."
b. Goto:
1. Keep list of targets of current basic block.
2. Keep a list of all basic blocks with list of their targets.
c. Function Calls:
1. Keep list of functions called by current block.
d. Return Instructions
1. Keep note if current Basic Block Returns.
'''
# 1. Look for function definition
m = re_funcDef.match(line)
if m is not None:
if m.group(2) == "":
# 1.b. Multi Line Function Arguments
inFuncDefArgMultiLine = 1
currFuncName = m.group(1)
continue
else:
# 1.a. Single Line Definition
inFunctionBody = 1
currFuncName = m.group(1)
currFuncStartLine = lineNum + 1
continue
if inFuncDefArgMultiLine == 1:
# 1.b. Multi Line Function Arguments
m = re_funcDefArgLine.match(line)
if m is not None:
if m.group(1) == "":
# Next line is still argument list
continue
else:
# End of Argument List. Start of function body in next line.
inFuncDefArgMultiLine = 0
inFunctionBody = 1
currFuncStartLine = lineNum + 1
continue
else:
raise ParseError("Not found the expected Multi Line Argument List at %s:%d." & (fileName, lineNum))
exit(1)
# 2. Inside Function Body
if inFunctionBody == 1:
# 2.a Look for labels
m = re_basicBlockLabel.match(line)
if m is not None:
# 2.a.1 Record name of Basic Block
currBasicBlockName = m.group(1)
continue
# 2.a.2. Look for start of Basic Block
m = re_basicBlockStart.match(line)
if m is not None:
inBasicBlock = 1
currBasicBlockStartLine = lineNum + 1
continue;
if inBasicBlock == 1:
# 2.a.3. Look for end of basic block
m = re_basicBlockEnd.match(line)
if m is not None:
inBasicBlock = 0
currBasicBlockEndLine = lineNum - 1
listCurrFuncBasicBlocks.append(BasicBlock(currBasicBlockStartLine,
currBasicBlockEndLine,
isCurrBasicBlockReturning,
listCurrBlockFuncCalls,
currBasicBlockName))
# 2.b.2. List of Basic Blocks with list of their targets
listCurrFuncBasicBlockTargets.append(BasicBlockTargets(currBasicBlockName,
listCurrBasicBlockTargets))
# Resetting state variabless
currBasicBlockName = ""
currBasicBlockStartLine = 0
currBasicBlockEndLine = 0
isCurrBasicBlockReturning = 0
listCurrBlockFuncCalls = []
listCurrBasicBlockTargets = []
continue;
# 2.b. look for goto instructions
m = re_gotoLine.match(line)
if m is not None:
# 2.b.1. List of targets of current basic block
targetBlock = m.group(1)
listCurrBasicBlockTargets.append(targetBlock)
continue
# 2.c. look for function calls
m = re_funcCallLine.match(line)
if m is not None:
# 2.c.1. List of functions called by current block
funcCallName = m.group(1)
listCurrBlockFuncCalls.append(funcCallName)
continue
# 2.d. look for return instructions
m = re_returnLine.match(line)
if m is not None:
# Flag to say current basic block returns
isCurrBasicBlockReturning = 1
continue
# look for end of function definition
m = re_funcDefEnd.match(line)
if m is not None:
currFuncEndLine = lineNum - 1
for blockTarget in listCurrFuncBasicBlockTargets:
startBlockIndex = -1
index = 0
for block in listCurrFuncBasicBlocks:
if block.name == blockTarget.name:
startBlockIndex = index
break
index = index + 1
if startBlockIndex == -1:
raise ParseError("Block %s with entry in listCurrFuncBasicBlockTargets not found in listCurrFuncBasicBlocks" % (blockTarget.name))
exit(1)
for target in blockTarget.listTargets:
endBlockIndex = -1
index = 0
for block in listCurrFuncBasicBlocks:
if block.name == target:
endBlockIndex = index
break
index = index + 1
if endBlockIndex == -1:
raise ParseError("Block %s, a target of block %s with entry in listCurrFuncBasicBlockTargets not found in listCurrFuncBasicBlocks" % (target, blockTarget.name))
exit(1)
listCurrFuncBBEdges.append(BBEdge(startBlockIndex,
endBlockIndex))
if not blockTarget.listTargets and listCurrFuncBasicBlocks[startBlockIndex].isReturning == 0:
# if current block had no targets, edge to next block
listCurrFuncBBEdges.append(BBEdge(startBlockIndex,
startBlockIndex + 1))
listFunctions.append(FunctionDesc(currFuncName,
fileName,
currFuncStartLine,
currFuncEndLine,
ControlFlowGraph(listCurrFuncBasicBlocks,
listCurrFuncBBEdges)))
# Resetting State Variables
inFunctionBody = 0
inFuncDefArgMultiLine = 0
currFuncName = ""
currFuncStartLine = 0
currFuncEndLine = 0
listCurrFuncBasicBlocks = []
listCurrFuncBasicBlockTargets = []
listCurrFuncBBEdges = []
continue
return listFunctions
def print_debug_isc(listFunctions):
for func in listFunctions:
print("\nFileName : %s" % (func.fileName))
print("Function : %s" % (func.functionName))
i = 0
for block in func.cfg.listBlocks:
print("\t Block %s: line %d - %d, flow = %f" % (block.name, block.startLine, block.endLine, block.flow))
for funcCall in block.listFunctionCalls:
print("\t\t calls %s()" % (funcCall))
if block.isReturning == 1:
print("\t\t returns")
for edge in func.cfg.listEdges:
if edge.fromBlockIndex == i:
print("\t\t Edge to block %s" % (func.cfg.listBlocks[edge.toBlockIndex].name))
i = i + 1
if __name__ == "__main__":
if len(sys.argv) > 1:
listFileNames = sys.argv[1:]
else:
print_usage()
exit(1)
listFunctions = []
for fileName in listFileNames:
listFunctions = listFunctions + parse_isc(fileName)
print_debug_isc(listFunctions)
\ No newline at end of file
/***********************************************************
Intermediate representation of
sieve/app_dir/erat_sieve_no_print.c
Converted by ir2c v0.1
***********************************************************/
#include <limits.h>
#include <stdint.h>
#include "ir2c.h"
#include <stdio.h>
#define N 500000
unsigned int results[N];
struct test {
unsigned int v;
unsigned int k;
} m = { 1, 1 };
void sieve() {
uintptr_t ivtmp_84;
int j_82;
int i_81;
uintptr_t ivtmp_77;
uintptr_t D_2271;
uintptr_t ivtmp_67;
uintptr_t D_2260;
uintptr_t ivtmp_58;
uintptr_t D_2248;
uintptr_t ivtmp_45;
int j;
int i;
unsigned int sieve[500000];
sievebb_2:
// # PRED: ENTRY [100.0%] (fallthru,exec)
ivtmp_77 = 0;
// # SUCC: 3 [100.0%] (fallthru,exec)
sievebb_3:
// # PRED: 3 [99.0%] (dfs_back,true,exec) 2 [100.0%] (fallthru,exec)
*(unsigned int*)((uintptr_t)&results + (uintptr_t)ivtmp_77) = 0;
*(unsigned int*)((uintptr_t)&sieve + (uintptr_t)ivtmp_77) = 1;
ivtmp_77 = ivtmp_77 + 4;
if (ivtmp_77 != 2000000)
goto sievebb_3;
else
goto sievebb_15;
// # SUCC: 3 [99.0%] (dfs_back,true,exec) 15 [1.0%] (false,exec)
sievebb_15:
// # PRED: 3 [1.0%] (false,exec)
ivtmp_84 = 6;
ivtmp_67 = 4;
i_81 = 2;
// # SUCC: 4 [100.0%] (fallthru)
sievebb_4:
// # PRED: 15 [100.0%] (fallthru) 7 [99.0%] (dfs_back,true,exec)
D_2271 = (unsigned int) i_81;
if (*(unsigned int*)((uintptr_t)&sieve + (uintptr_t)D_2271 * 4) != 0)
goto sievebb_5;
else
goto sievebb_7;
// # SUCC: 5 [50.0%] (true,exec) 7 [50.0%] (false,exec)
sievebb_5:
// # PRED: 4 [50.0%] (true,exec)
j_82 = (int) ivtmp_67;
if (j_82 <= 499999)
goto sievebb_16;
else
goto sievebb_7;
// # SUCC: 16 [91.0%] (true,exec) 7 [9.0%] (false,exec)
sievebb_16:
// # PRED: 5 [91.0%] (true,exec)
ivtmp_58 = ivtmp_84;
// # SUCC: 6 [100.0%] (fallthru)
sievebb_6:
// # PRED: 6 [91.0%] (dfs_back,true,exec) 16 [100.0%] (fallthru)
sieve[j_82] = 0;
D_2260 = (unsigned int) j_82 + D_2271;
j_82 = (int) D_2260;
ivtmp_58 = ivtmp_58 + D_2271;
if ((int) (ivtmp_58 - D_2271) <= 499999)
goto sievebb_6;
else
goto sievebb_7;
// # SUCC: 6 [91.0%] (dfs_back,true,exec) 7 [9.0%] (false,exec)
sievebb_7:
// # PRED: 4 [50.0%] (false,exec) 6 [9.0%] (false,exec) 5 [9.0%] (false,exec)
i_81 = i_81 + 1;
ivtmp_67 = ivtmp_67 + 2;
ivtmp_84 = ivtmp_84 + 3;
if (i_81 * i_81 <= 499999)
goto sievebb_4;
else
goto sievebb_8;
// # SUCC: 4 [99.0%] (dfs_back,true,exec) 8 [1.0%] (false,exec)
sievebb_8:
// # PRED: 7 [1.0%] (false,exec)
j = 2;
i = 0;
// # SUCC: 9 [100.0%] (fallthru,exec)
sievebb_9:
// # PRED: 11 [99.0%] (dfs_back,true,exec) 8 [100.0%] (fallthru,exec)
D_2248 = (unsigned int) j;
if (*(unsigned int*)((uintptr_t)&sieve + (uintptr_t)D_2248 * 4) != 0)
goto sievebb_10;
else
goto sievebb_11;
// # SUCC: 10 [50.0%] (true,exec) 11 [50.0%] (false,exec)
sievebb_10:
// # PRED: 9 [50.0%] (true,exec)
results[i] = D_2248;
i = i + 1;
// # SUCC: 11 [100.0%] (fallthru,exec)
sievebb_11:
// # PRED: 9 [50.0%] (false,exec) 10 [100.0%] (fallthru,exec)
j = j + 1;
if (j != 500000)
goto sievebb_9;
else
goto sievebb_17;
// # SUCC: 9 [99.0%] (dfs_back,true,exec) 17 [1.0%] (false,exec)
sievebb_17:
// # PRED: 11 [1.0%] (false,exec)
ivtmp_45 = 0;
// # SUCC: 12 [100.0%] (fallthru)
sievebb_12:
// # PRED: 17 [100.0%] (fallthru) 13 [98.9%] (dfs_back,true,exec)
if (*(unsigned int*)((uintptr_t)&results + (uintptr_t)ivtmp_45) == 0)
goto sievebb_14;
else
goto sievebb_13;
// # SUCC: 14 [4.5%] (true,exec) 13 [95.5%] (false,exec)
sievebb_13:
// # PRED: 12 [95.5%] (false,exec)
ivtmp_45 = ivtmp_45 + 4;
if (ivtmp_45 != 2000000)
goto sievebb_12;
else
goto sievebb_14;
// # SUCC: 12 [98.9%] (dfs_back,true,exec) 14 [1.1%] (false,exec)
sievebb_14:
// # PRED: 12 [4.5%] (true,exec) 13 [1.1%] (false,exec)
m.v = 0;
return;
// # SUCC: EXIT [100.0%]
}
int main(void) {
mainbb_2:
// # PRED: ENTRY [100.0%] (fallthru,exec)
sieve ();
return 0;
// # SUCC: EXIT [100.0%]
}
/***********************************************************
Intermediate representation of
simple/app_dir/simple.c
Converted by ir2c v0.1
***********************************************************/
#include <limits.h>
#include <stdint.h>
#include "ir2c.h"
#define FIB_MAX_NUM 15
int a=0, b=1;
int i;
int main(int argc, char* argv) {
int prephitmp_52;
int prephitmp_51;
int prephitmp_50;
uintptr_t ivtmp_43;
int prephitmp_28;
mainbb_2:
// # PRED: ENTRY [100.0%] (fallthru,exec)
prephitmp_51 = b;
prephitmp_50 = a;
ivtmp_43 = 0;
// # SUCC: 3 [100.0%] (fallthru,exec)
mainbb_3:
// # PRED: 5 [100.0%] (fallthru) 2 [100.0%] (fallthru,exec)
prephitmp_28 = prephitmp_50 + prephitmp_51;
ivtmp_43 = ivtmp_43 + 1;
if (ivtmp_43 != 98)
goto mainbb_5;
else
goto mainbb_6;
// # SUCC: 5 [91.0%] (dfs_back,true,exec) 6 [9.0%] (false,exec)
mainbb_5:
// # PRED: 3 [91.0%] (dfs_back,true,exec)
prephitmp_50 = prephitmp_51;
prephitmp_51 = prephitmp_28;
goto mainbb_3;
// # SUCC: 3 [100.0%] (fallthru)
mainbb_6:
// # PRED: 3 [9.0%] (false,exec)
prephitmp_52 = prephitmp_28;
// # SUCC: 4 [100.0%] (fallthru)
mainbb_4:
// # PRED: 6 [100.0%] (fallthru)
b = prephitmp_28;
a = prephitmp_51;
i = 101;
return prephitmp_52;
// # SUCC: EXIT [100.0%]
}
#-----------------------------------------------------------------
# map_cfg.py: Map Control Flow Graphs from Binary and ISC
#-----------------------------------------------------------------
from optparse import OptionParser
from cfg_binary import parse_binary, print_debug_binary
from cfg_isc import parse_isc, print_debug_isc
import logging
from collections import deque
listISCFileNames = []
listObjdumpFileNames = []
def map_cfg(listISCFileNames, listObjdumpFileNames):
listISCFunctions = []
listFunctionNames = []
listObjdumpFunctions = []
# Parse the ISC files
for ISCFileName in listISCFileNames:
listISCFunctions = listISCFunctions + parse_isc(ISCFileName)
for function in listISCFunctions:
listFunctionNames.append(function.functionName)
# Parse the objdump files
for ObjdumpFileName in listObjdumpFileNames:
listObjdumpFunctions = listObjdumpFunctions + parse_binary(ObjdumpFileName,
listFunctionNames)
print_debug_isc (listISCFunctions)
print_debug_binary (listObjdumpFunctions)
# Check that we found all functions in ISC in Objdump
if len(listISCFunctions) != len(listObjdumpFunctions):
raise ParseError("all functions in ISC file not found in Objdump file!")
for function in listISCFunctions:
logging.debug("Computing flow for function %s from file %s" % (function.functionName, function.fileName))
function.cfg.computeFlow()
for function in listObjdumpFunctions:
logging.debug("Computing flow for function %s from file %s" % (function.functionName, function.fileName))
function.cfg.computeFlow()
if __name__ == "__main__":
# listISCFileNames = []
# listObjdumpFileNames = []
logging.basicConfig(level=logging.DEBUG)
optparser = OptionParser()
optparser.add_option("-i", "--isc", action="append", dest="listISCFileNames",
type="string", help="ISC Filenamel. For multiple files, use -i <filename> multiple times.",
metavar="FILE")
optparser.add_option("-o", "--objdump", action="append",
type="string", dest="listObjdumpFileNames",
help="Objdump Filename. For multiple files, use -o <filename> multiple times.",
metavar="FILE")
(options, args) = optparser.parse_args()
if (len(args) > 0):
print "Addtional arguments are being ignored"
listISCFileNames = options.listISCFileNames
listObjdumpFileNames = options.listObjdumpFileNames
map_cfg(listISCFileNames, listObjdumpFileNames)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment