1# * Copyright 2016, NICTA 2# * 3# * This software may be distributed and modified according to the terms 4# of 5# * the BSD 2-Clause license. Note that NO WARRANTY is provided. 6# * See "LICENSE_BSD2.txt" for details. 7# * 8# * @TAG(NICTA_BSD) 9import re 10from graph_refine.target_objects import functions, functions_by_tag 11import graph_refine.problem as problem 12from borg import Borg 13 14#hardcoded list of function(s) that should never be called given correctness 15deadend_funcs = ['halt'] 16 17class elfFunc: 18 def __init__ (self,f_name,f_addr,g_f): 19 self.name = f_name 20 self.addr = int(f_addr,16) 21 # a mapping from addr to line text 22 self.lines = {} 23 self.g_f = g_f 24 def __repr__ (self): 25 return ("%s start addr %d %s %d instructions" % (self.name, self.addr,hex(self.addr),len(self.lines) )) 26 def append (self,addr, line): 27 self.lines[int(addr,16)] = line 28 29 30class elfSym: 31 def __init__ (self,addr,flags,section,ali_size): 32 self.addr = addr 33 self.ali_size = ali_size 34 self.flags = flags 35 self.section = section 36 37 38class elfFile (Borg): 39 def __init__ (self,dir_name=None,ignore_funs=None,elf_only=False): 40 Borg.__init__(self) 41 if not (dir_name): 42 return 43 try: 44 self.f_text = open('%s/kernel.elf.txt' %dir_name) 45 self.f_symtab = open('%s/kernel.elf.symtab' %dir_name) 46 except : 47 print "kernel.elf.* can't be opened at directory %s" %dir_name 48 assert 0 49 self.elf_only = elf_only 50 if not elf_only: 51 self.asm_fs = dict ([(x,functions[x]) for x in functions_by_tag['ASM']]) 52 asm_fs = self.asm_fs 53 self.tcg = None 54 #from original name to the cloned name 55 self.to_clone_name = {} 56 self.un_clone_name = {} 57 for f in asm_fs: 58 if 'clone' in f: 59 match = re.search('(.*)(_clone).*',f) 60 f_name = match.groups()[0] 61 self.to_clone_name[f_name] = f 62 self.un_clone_name[f] = f_name 63 #print 'to_clone_name: %s' % self.to_clone_name 64 #print 'un_clone_name: %s' % self.un_clone_name 65 66 #self.insts = {} 67 #funcs is a dict of func names to elfFunc objs 68 self.funcs = {} 69 #dict of sym names to sym objects 70 self.syms = {} 71 #dict of addresses to data 72 self.literals = {} 73 #addr -> line text 74 self.lines = {} 75 self.deadend_funcs = deadend_funcs 76 self.dir_name = dir_name 77 #maps addrs to fun name containing it 78 self.addrs_to_f = {} 79 #handle the clone subfixes 80 def gFunName(self, f): 81 asm_fs = self.asm_fs 82 if f in asm_fs: 83 return f 84 elif f in self.to_clone_name: 85 return self.to_clone_name[f] 86 else: 87 return f 88 def gUnCloneName(self,f): 89 if f in self.un_clone_name: 90 return self.un_clone_name[f] 91 return f 92 93 def addSymbol(self,name,addr,flags,section,ali_size): 94 self.syms[name] = elfSym(addr,flags,section,ali_size) 95 96#for instructions, return (text, rawValue) 97#for literals, return (size, rawValue) 98def rawVals(addr,inst_only=False): 99 #return text,rawValue 100 assert addr % 4 == 0 101 ef = elfFile() 102 if addr in ef.lines: 103 inst = ef.lines[addr] 104 else: 105 if inst_only: 106 return None 107 if addr in ef.literals: 108 #print 'addr %s is a literal' % addr 109 return ef.literals[addr] 110 return None 111 #we take everything after the addr and the raw instruction 112 match = re.search(r'^.*:\s+(?P<raw>[a-f0-9]+)\s*(?P<text>.*)$',inst) 113 return ( match.group('text'), int(match.group('raw'),16)) 114 115def isSpecIns(fun_name): 116 return fun_name.startswith("instruction'") or \ 117 fun_name.startswith("asm_instruction'") or \ 118 fun_name.startswith("impl'") 119 120