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