Commit 81ee224e authored by Gaurav Kukreja's avatar Gaurav Kukreja

Map CFG working for ADPCM

Signed-off-by: Gaurav Kukreja's avatarGaurav Kukreja <gaurav@gauravk.in>
parent 0faeaaca
...@@ -27,6 +27,9 @@ class BasicBlock: ...@@ -27,6 +27,9 @@ class BasicBlock:
else: else:
self.listFunctionCalls = listFuncCalls self.listFunctionCalls = listFuncCalls
self.flow = 0.0 self.flow = 0.0
self.mapsTo = []
self.nestingLevel = -1
self.hasConditionalExec = 0
class ControlFlowGraph: class ControlFlowGraph:
...@@ -35,6 +38,19 @@ class ControlFlowGraph: ...@@ -35,6 +38,19 @@ class ControlFlowGraph:
self.listEdges = listEdges self.listEdges = listEdges
self.listBackEdges = [] self.listBackEdges = []
def find(self, blockName=None, lineNum = None):
if blockName:
for block in self.listBlocks:
if block.name == blockName:
return block
return None
if lineNum:
for block in self.listBlocks:
if block.startLine <= lineNum and block.endLine >= lineNum:
return block
return None
def successorBlocks(self, blockIndex): def successorBlocks(self, blockIndex):
listSuccBlockIndices = [] listSuccBlockIndices = []
for edge in self.listEdges: for edge in self.listEdges:
...@@ -86,6 +102,8 @@ class ControlFlowGraph: ...@@ -86,6 +102,8 @@ class ControlFlowGraph:
def dft(self, blockIndex): def dft(self, blockIndex):
self.dft_stack.append(blockIndex) self.dft_stack.append(blockIndex)
for succBlock in self.successorBlocksWOBackEdges(blockIndex): for succBlock in self.successorBlocksWOBackEdges(blockIndex):
if self.listBlocks[succBlock].nestingLevel > self.listBlocks[blockIndex].nestingLevel or self.listBlocks[succBlock].nestingLevel == -1:
self.listBlocks[succBlock].nestingLevel = self.listBlocks[blockIndex].nestingLevel + 1
if succBlock not in self.dft_stack: if succBlock not in self.dft_stack:
self.dft(succBlock) self.dft(succBlock)
else: else:
...@@ -119,6 +137,7 @@ class ControlFlowGraph: ...@@ -119,6 +137,7 @@ class ControlFlowGraph:
Depth First Fashion Depth First Fashion
''' '''
self.dft_stack = [] self.dft_stack = []
self.listBlocks[0].nestingLevel = 0
self.dft(0) self.dft(0)
self.listBackEdges = list(set(self.listBackEdges)) self.listBackEdges = list(set(self.listBackEdges))
return self.listBackEdges return self.listBackEdges
......
...@@ -8,7 +8,7 @@ from cfg import * ...@@ -8,7 +8,7 @@ from cfg import *
re_sectionStart = re.compile('Disassembly of section .(.*):') re_sectionStart = re.compile('Disassembly of section .(.*):')
re_funcDef = re.compile('\s*([0-9a-f]*)\s*<(.*)>:') re_funcDef = re.compile('\s*([0-9a-f]*)\s*<(.*)>:')
re_instruction = re.compile('\s*([0-9a-f]*):\s*[0-9a-f]*\s*(.*)') re_instruction = re.compile('\s*([0-9a-f]*):\s*([0-9a-f]*)\s*(.*)')
re_branchInst = re.compile('\s*(b(?!ic)(?:l|x|lx|xj)?(?:eq|ne|mi|pl|hi|ls|ge|lt|gt|le)?)\s*([0-9a-f]*)\s*<(.*)>') re_branchInst = re.compile('\s*(b(?!ic)(?: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_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_conditionalBranchInst = re.compile('\s*(b(?:l|x|lx|xj)?(?:eq|ne|mi|pl|hi|ls|ge|lt|gt|le))\s*([0-9a-f]*)\s*<(.*)>')
...@@ -53,6 +53,8 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -53,6 +53,8 @@ def parse_binary(fileName, listFunctionNames = []):
listCurrFuncBlockEndLineNum = [] listCurrFuncBlockEndLineNum = []
listCurrFuncBlockStartAddress = [] listCurrFuncBlockStartAddress = []
listCurrFuncBlockEndAddress = [] listCurrFuncBlockEndAddress = []
listCurrFuncConditionalExecInstAtLine = []
lineNumForAddress = {} lineNumForAddress = {}
branchInstAtLine = {} branchInstAtLine = {}
returnInstAtLine = {} returnInstAtLine = {}
...@@ -111,7 +113,8 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -111,7 +113,8 @@ def parse_binary(fileName, listFunctionNames = []):
if m is not None: if m is not None:
address = m.group(1) address = m.group(1)
lineNumForAddress[address] = lineNum; lineNumForAddress[address] = lineNum;
inst = m.group(2) opcode = m.group(2)
inst = m.group(3)
m = re_branchInst.match(inst) m = re_branchInst.match(inst)
if m is not None and m.group(3).startswith(currFuncName): if m is not None and m.group(3).startswith(currFuncName):
...@@ -139,6 +142,12 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -139,6 +142,12 @@ def parse_binary(fileName, listFunctionNames = []):
listCurrFuncBlockEndAddress.append(address) listCurrFuncBlockEndAddress.append(address)
continue continue
# Not a branch or return instruction,
# Check if a conditional execution instruction
if re.match('[0-9a-d]./*', opcode):
listCurrFuncConditionalExecInstAtLine.append(lineNum)
continue
continue continue
else: else:
# inside Function, instruction did not match i.e. end of # inside Function, instruction did not match i.e. end of
...@@ -228,6 +237,12 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -228,6 +237,12 @@ def parse_binary(fileName, listFunctionNames = []):
for block in listBlocks: for block in listBlocks:
if block.startLine <= lNum and block.endLine >= lNum: if block.startLine <= lNum and block.endLine >= lNum:
block.listFunctionCalls.append(calledFuncName) block.listFunctionCalls.append(calledFuncName)
# Indicate which blocks have conditional execution instructions
for lNum in listCurrFuncConditionalExecInstAtLine:
for block in listBlocks:
if block.startLine <= lNum and block.endLine >= lNum:
block.hasConditionalExec = 1
# Add the current function and the CFG to the list of functions # Add the current function and the CFG to the list of functions
listFunctions.append(FunctionDesc(currFuncName, listFunctions.append(FunctionDesc(currFuncName,
...@@ -246,6 +261,7 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -246,6 +261,7 @@ def parse_binary(fileName, listFunctionNames = []):
listCurrFuncBlockEndLineNum = [] listCurrFuncBlockEndLineNum = []
listCurrFuncBlockStartAddress = [] listCurrFuncBlockStartAddress = []
listCurrFuncBlockEndAddress = [] listCurrFuncBlockEndAddress = []
listCurrFuncConditionalExecInstAtLine = []
#lineNumForAddress = {} #lineNumForAddress = {}
branchInstAtLine = {} branchInstAtLine = {}
returnInstAtLine = {} returnInstAtLine = {}
...@@ -255,22 +271,43 @@ def parse_binary(fileName, listFunctionNames = []): ...@@ -255,22 +271,43 @@ def parse_binary(fileName, listFunctionNames = []):
return listFunctions, lineNumForAddress return listFunctions, lineNumForAddress
def print_debug_binary(listFunctions): def print_debug_binary(listFunctions, gdbMapping=None):
for func in listFunctions: if gdbMapping == None:
print("\nFileName : %s" % (func.fileName)) for func in listFunctions:
print("Function : %s" % (func.functionName)) print("\nFileName : %s" % (func.fileName))
i = 0 print("Function : %s" % (func.functionName))
for block in func.cfg.listBlocks: i = 0
print("\t Block %d: line %d - %d, flow = %f" % (i, block.startLine, block.endLine, block.flow)) for block in func.cfg.listBlocks:
for funcCall in block.listFunctionCalls: print("\t Block %d: line %d - %d, flow = %f" % (i, block.startLine, block.endLine, block.flow))
print("\t\t calls %s()" % (funcCall)) for funcCall in block.listFunctionCalls:
if block.isReturning == 1: print("\t\t calls %s()" % (funcCall))
print("\t\t returns") if block.isReturning == 1:
for edge in func.cfg.listEdges: print("\t\t returns")
if edge.fromBlockIndex == i: for edge in func.cfg.listEdges:
print("\t\t Edge to block %d" % (edge.toBlockIndex)) if edge.fromBlockIndex == i:
i = i + 1 print("\t\t Edge to block %d" % (edge.toBlockIndex))
i = i + 1
else:
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 %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))
for lineNum in range(block.startLine, block.endLine):
if lineNum in gdbMapping:
print("\t\t Line %d from %s:%d" % (lineNum,
gdbMapping[lineNum].fileName,
gdbMapping[lineNum].lineNum))
i = i + 1
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) > 1: if len(sys.argv) > 1:
......
...@@ -19,6 +19,8 @@ re_gotoLine = re.compile('\s*goto\s*(\w*bb_[0-9]*);') ...@@ -19,6 +19,8 @@ re_gotoLine = re.compile('\s*goto\s*(\w*bb_[0-9]*);')
re_funcCallLine = re.compile('\s*(\w*)\s*\([,\s\w&\[\]\*]*\);') re_funcCallLine = re.compile('\s*(\w*)\s*\([,\s\w&\[\]\*]*\);')
re_returnLine = re.compile('\s*return\s*.*;') re_returnLine = re.compile('\s*return\s*.*;')
re_funcDefEnd = re.compile('\s*\}') re_funcDefEnd = re.compile('\s*\}')
re_commentStart = re.compile('\s*/\*.*')
re_commentEnd = re.compile('\s*.*\*/')
class BasicBlockTargets: class BasicBlockTargets:
def __init__(self, name, listTargets = None): def __init__(self, name, listTargets = None):
...@@ -49,6 +51,8 @@ def parse_isc(fileName): ...@@ -49,6 +51,8 @@ def parse_isc(fileName):
listCurrBlockFuncCalls = [] listCurrBlockFuncCalls = []
listCurrBasicBlockTargets = [] listCurrBasicBlockTargets = []
inMultiLineComment = 0
lineNum = 0 lineNum = 0
file = open(fileName, 'r') file = open(fileName, 'r')
for line in file: for line in file:
...@@ -75,6 +79,23 @@ def parse_isc(fileName): ...@@ -75,6 +79,23 @@ def parse_isc(fileName):
1. Keep note if current Basic Block Returns. 1. Keep note if current Basic Block Returns.
''' '''
# Comment Handling
m = re_commentStart.match(line)
if m is not None:
if re_commentEnd.match(line) == None:
inMultiLineComment = 1
continue
else:
continue
if inMultiLineComment == 1:
m = re_commentEnd.match(line)
if m is not None:
inMultiLineComment = 0
continue
else:
continue
# 1. Look for function definition # 1. Look for function definition
m = re_funcDef.match(line) m = re_funcDef.match(line)
if m is not None: if m is not None:
......
...@@ -22,11 +22,54 @@ class GDBMapTarget: ...@@ -22,11 +22,54 @@ class GDBMapTarget:
self.fileName = fileName self.fileName = fileName
self.lineNum = lineNum self.lineNum = lineNum
def printDebugMapCFG(listISCFunctions, listObjdumpFunctions, gdbMapping):
for func in listObjdumpFunctions:
print("\nFileName : %s" % (func.fileName))
print("Function : %s" % (func.functionName))
ISCFuncCfg = find(lambda fn: fn.functionName == func.functionName, listISCFunctions).cfg
i = 0
for block in func.cfg.listBlocks:
print("\t Block %d: line %d - %d, flow = %f, nestingLevel = %d" %
(i, block.startLine, block.endLine,
block.flow, block.nestingLevel))
print "\t Maps to ",
block.mapsTo = list(set(block.mapsTo))
for blockIndISC in block.mapsTo:
print ISCFuncCfg.listBlocks[blockIndISC].name+", ",
print ""
for funcCall in block.listFunctionCalls:
print("\t\t calls %s()" % (funcCall))
if block.hasConditionalExec == 1:
print("\t\t Conditional Execution Instruction!")
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))
for lineNum in range(block.startLine, block.endLine):
if lineNum in gdbMapping:
ISCFileName = gdbMapping[lineNum].fileName
ISCLineNum = gdbMapping[lineNum].lineNum
ISCBlock = ISCFuncCfg.find(lineNum = ISCLineNum)
if ISCBlock is not None:
ISCBlockName = ISCFuncCfg.find(lineNum = ISCLineNum).name
else:
ISCBlockName = "%d" % (ISCLineNum)
print("\t\t Line %d from %s:%s" % (lineNum,
gdbMapping[lineNum].fileName,
ISCBlockName))
i = i + 1
def gdbMappingDebug(gdbMapping): def gdbMappingDebug(gdbMapping):
for lineNum in gdbMapping: for lineNum in gdbMapping:
print ("line %d maps to %s:%d" % (lineNum, gdbMapping[lineNum].fileName, gdbMapping[lineNum].lineNum)) print ("line %d maps to %s:%d" % (lineNum, gdbMapping[lineNum].fileName, gdbMapping[lineNum].lineNum))
def find(f, seq):
"""Return first item in sequence where f(item) == True."""
for item in seq:
if f(item):
return item
def getGDBMapping(binFileName, objdumpLineNumForAddress): def getGDBMapping(binFileName, objdumpLineNumForAddress):
gdbMapping = {} gdbMapping = {}
...@@ -60,21 +103,152 @@ def getGDBMapping(binFileName, objdumpLineNumForAddress): ...@@ -60,21 +103,152 @@ def getGDBMapping(binFileName, objdumpLineNumForAddress):
gdbMapping[objdumpLineNum] = GDBMapTarget(targetFileName, targetLineNum) gdbMapping[objdumpLineNum] = GDBMapTarget(targetFileName, targetLineNum)
gdbOutputFile.close() gdbOutputFile.close()
# gdbMappingDebug(gdbMapping) # gdbMappingDebug(gdbMapping)
return gdbMapping return gdbMapping
mappingStackISC = []
mappingStackObj = []
def mapping(cfgISC, blockIndISC, cfgObj, blockIndObj, mergedLevelsISC):
# a = input("Press Enter to continue...")
mappingStackISC.append(blockIndISC)
mappingStackObj.append(blockIndObj)
blockISC = cfgISC.listBlocks[blockIndISC]
blockObj = cfgObj.listBlocks[blockIndObj]
print "\tMapping blocks ISC:%s and OBJ:%d" % (blockISC.name, blockIndObj)
print "\tmergedLevelsISC = %d" % (mergedLevelsISC)
if (blockISC.isReturning == 1 and
blockObj.isReturning == 1):
print "\t\tBoth Blocks return!!!"
blockISC.mapsTo.append(blockIndObj)
blockObj.mapsTo.append(blockIndISC)
mappingStackISC.pop()
mappingStackObj.pop()
return 0
if (blockISC.flow != blockObj.flow or
(blockISC.nestingLevel - mergedLevelsISC) != blockObj.nestingLevel or
blockISC.isReturning != blockObj.isReturning):
print "\t\tFlow, or nesting level did not match or only one of them returns!"
mappingStackISC.pop()
mappingStackObj.pop()
return -1
# if (blockIndISC, blockIndObj) in mappingDict:
# return mappingDict[(blockIndISC, blockIndObj)]
mincost = -1
listSuccISC = cfgISC.successorBlocks(blockIndISC)
listSuccObj = cfgObj.successorBlocks(blockIndObj)
listSuccWOBackEdgeISC = cfgISC.successorBlocksWOBackEdges(blockIndISC)
listSuccWOBackEdgeObj = cfgObj.successorBlocksWOBackEdges(blockIndObj)
if(len(listSuccWOBackEdgeISC) != len(listSuccWOBackEdgeObj)):
if(blockObj.hasConditionalExec == 1 and
len(listSuccWOBackEdgeObj) == len(listSuccWOBackEdgeISC) - 1):
print "\t\t Conditional Execution Found!"
# Conditional Execution!
for succ1BlockISC in listSuccISC:
if succ1BlockISC in mappingStackISC:
continue
for succSucc1BlockISC in cfgISC.successorBlocks(succ1BlockISC):
if succSucc1BlockISC in mappingStackISC:
continue
if succSucc1BlockISC in (set(listSuccISC) - {succ1BlockISC}):
# case 1
print "\t\tcase 1"
for succSuccSucc1BlockISC in cfgISC.successorBlocks(succSucc1BlockISC):
if succSuccSucc1BlockISC in mappingStackISC:
continue
for succBlockObj in listSuccObj:
if succBlockObj in mappingStackObj:
continue
mappingStackISC.append(succ1BlockISC)
mappingStackISC.append(succSucc1BlockISC)
if mapping(cfgISC, succSuccSucc1BlockISC, cfgObj, succBlockObj, mergedLevelsISC+1) == 0:
cfgISC.listBlocks[blockIndISC].mapsTo.append(blockIndObj)
cfgISC.listBlocks[succ1BlockISC].mapsTo.append(blockIndObj)
cfgISC.listBlocks[succSucc1BlockISC].mapsTo.append(blockIndObj)
cfgObj.listBlocks[blockIndObj].mapsTo.append(succSucc1BlockISC)
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackObj.pop()
return 0
else:
mappingStackISC.pop()
mappingStackISC.pop()
for succ2BlockISC in list(set(listSuccISC) - {succ1BlockISC}):
if succ2BlockISC in mappingStackISC:
continue
for succSucc2BlockISC in cfgISC.successorBlocks(succ2BlockISC):
if succSucc2BlockISC in mappingStackISC:
continue
if succSucc1BlockISC == succSucc2BlockISC:
# case 2
print "\t\tcase 2"
for succSuccSucc1BlockISC in cfgISC.successorBlocks(succSucc1BlockISC):
if succSuccSucc1BlockISC in mappingStackISC:
continue
for succBlockObj in listSuccObj:
if succBlockObj in mappingStackObj:
continue
mappingStackISC.append(succ1BlockISC)
mappingStackISC.append(succ2BlockISC)
mappingStackISC.append(succSucc1BlockISC)
if mapping(cfgISC, succSuccSucc1BlockISC, cfgObj, succBlockObj, mergedLevelsISC+2) == 0:
cfgISC.listBlocks[blockIndISC].mapsTo.append(blockIndObj)
cfgISC.listBlocks[succ1BlockISC].mapsTo.append(blockIndObj)
cfgISC.listBlocks[succ2BlockISC].mapsTo.append(blockIndObj)
cfgISC.listBlocks[succSucc1BlockISC].mapsTo.append(blockIndObj)
cfgObj.listBlocks[blockIndObj].mapsTo.append(succSucc1BlockISC)
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackObj.pop()
return 0
else:
mappingStackISC.pop()
mappingStackISC.pop()
mappingStackISC.pop()
else:
print "no. of successors not same, and difference more than one."
print "ISC Block %d; Obj Block %d" % (blockIndISC, blockIndObj)
exit(1)
for succBlockISC in listSuccISC:
if succBlockISC in mappingStackISC:
continue
for succBlockObj in listSuccObj:
if succBlockObj in mappingStackObj:
continue
if mapping(cfgISC, succBlockISC, cfgObj, succBlockObj, mergedLevelsISC) == 0:
blockISC.mapsTo.append(blockIndObj)
blockObj.mapsTo.append(blockIndISC)
else:
continue
mappingStackISC.pop()
mappingStackObj.pop()
print "Here"
return 0
def map_cfg(listISCFileNames, listObjdumpFileNames, listBinaryFileNames): def map_cfg(listISCFileNames, listObjdumpFileNames, listBinaryFileNames):
listISCFunctions = [] listISCFunctions = []
listFunctionNames = [] listFunctionNames = []
listObjdumpFunctions = [] listObjdumpFunctions = []
gdbMapping = []
# Parse the ISC files # Parse the ISC files
for ISCFileName in listISCFileNames: for ISCFileName in listISCFileNames:
listISCFunctions = listISCFunctions + parse_isc(ISCFileName) listISCFunctions = listISCFunctions + parse_isc(ISCFileName)
for function in listISCFunctions: for function in listISCFunctions:
listFunctionNames.append(function.functionName) listFunctionNames.append(function.functionName)
logging.debug("parsed "+ISCFileName) logging.debug("parsed "+ISCFileName)
# Parse the objdump files # Parse the objdump files
for ObjdumpFileName in listObjdumpFileNames: for ObjdumpFileName in listObjdumpFileNames:
...@@ -96,10 +270,25 @@ def map_cfg(listISCFileNames, listObjdumpFileNames, listBinaryFileNames): ...@@ -96,10 +270,25 @@ def map_cfg(listISCFileNames, listObjdumpFileNames, listBinaryFileNames):
function.cfg.computeFlow() function.cfg.computeFlow()
for binaryFileName in listBinaryFileNames: for binaryFileName in listBinaryFileNames:
getGDBMapping(binaryFileName, objdumpLineNumForAddress) gdbMapping = getGDBMapping(binaryFileName, objdumpLineNumForAddress)
print_debug_isc (listISCFunctions) print_debug_isc (listISCFunctions)
print_debug_binary (listObjdumpFunctions) print_debug_binary (listObjdumpFunctions, gdbMapping)
mappingStackISC = []
mappingStackObj = []
for fnISC in listISCFunctions:
cfgISC = fnISC.cfg
fnObj = find(lambda fn: fn.functionName == fnISC.functionName, listObjdumpFunctions)
cfgObj = fnObj.cfg
print "Mapping Function %s" % (fnISC.functionName)
if mapping(cfgISC, 0, cfgObj, 0, 0) == 0:
print "Mapping Found!!!!"
else:
print "Fuck my life!!!"
printDebugMapCFG(listISCFunctions, listObjdumpFunctions, gdbMapping)
if __name__ == "__main__": if __name__ == "__main__":
......
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