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