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