1# 2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6 7# parsing code for objdump files. used on a symtab dump to build a python 8# symbol table and on a disassembly of the .rodata section to build a 9# summary of the read-only data 10 11import re 12 13def build_syms (symtab): 14 syms = {} 15 for line in symtab: 16 bits = line.split () 17 try: 18 addr = int (bits[0], 16) 19 size = int (bits[-2], 16) 20 section = bits[-3] 21 syms[bits[-1]] = (addr, size, section) 22 except ValueError: 23 pass 24 except IndexError: 25 pass 26 27 sections = {} 28 for (addr, size, section) in syms.itervalues (): 29 if not size: 30 continue 31 (start, end) = sections.get (section, (addr, addr)) 32 start = min (addr, start) 33 end = max (addr + size - 1, end) 34 sections[section] = (start, end) 35 36 return (syms, sections) 37 38def install_syms (symtab): 39 (syms, sects) = build_syms (symtab) 40 import target_objects 41 target_objects.symbols.update (syms) 42 target_objects.sections.update (sects) 43 44is_rodata_line = re.compile('^\s*[0-9a-fA-F]+:\s+[0-9a-fA-F]+\s+') 45 46def build_rodata (rodata_stream, rodata_ranges = [('Section', '.rodata')]): 47 from syntax import structs, fresh_name, Struct, mk_word32 48 import syntax 49 from target_objects import symbols, sections, trace 50 51 act_rodata_ranges = [] 52 for (kind, nm) in rodata_ranges: 53 if kind == 'Symbol': 54 (addr, size, _) = symbols[nm] 55 act_rodata_ranges.append ((addr, addr + size - 1)) 56 elif kind == 'Section': 57 if nm in sections: 58 act_rodata_ranges.append (sections[nm]) 59 else: 60 # it's reasonable to supply .rodata as the 61 # expected section only for it to be missing 62 trace ('No %r section in objdump.' % nm) 63 else: 64 assert kind in ['Symbol', 'Section'], rodata_ranges 65 66 comb_ranges = [] 67 for (start, end) in sorted (act_rodata_ranges): 68 if comb_ranges and comb_ranges[-1][1] + 1 == start: 69 (start, _) = comb_ranges[-1] 70 comb_ranges[-1] = (start, end) 71 else: 72 comb_ranges.append ((start, end)) 73 74 rodata = {} 75 for line in rodata_stream: 76 if not is_rodata_line.match (line): 77 continue 78 bits = line.split () 79 (addr, v) = (int (bits[0][:-1], 16), int (bits[1], 16)) 80 if [1 for (start, end) in comb_ranges 81 if start <= addr and addr <= end]: 82 assert addr % 4 == 0, addr 83 rodata[addr] = v 84 85 if len (comb_ranges) == 1: 86 rodata_names = ['rodata_struct'] 87 else: 88 rodata_names = ['rodata_struct_%d' % (i + 1) 89 for (i, _) in enumerate (comb_ranges)] 90 91 rodata_ptrs = [] 92 for ((start, end), name) in zip (comb_ranges, rodata_names): 93 struct_name = fresh_name (name, structs) 94 struct = Struct (struct_name, (end - start) + 1, 1) 95 structs[struct_name] = struct 96 typ = syntax.get_global_wrapper (struct.typ) 97 rodata_ptrs.append ((mk_word32 (start), typ)) 98 99 return (rodata, comb_ranges, rodata_ptrs) 100 101def install_rodata (rodata_stream, rodata_ranges = [('Section', '.rodata')]): 102 import target_objects 103 rodata = build_rodata (rodata_stream, rodata_ranges) 104 target_objects.rodata[:] = rodata 105 106# the prunes file isn't really an objdump file, but this seems the best place 107 108non_var_re = re.compile('[(),\s\[\]]+') 109 110def parse_prunes (prune_stream): 111 prunes = {} 112 for l in prune_stream: 113 [lname, rhs] = l.split ('from [') 114 bits = lname.split () 115 assert bits[:3] == ['Pruned', 'inputs', 'of'] 116 name = bits[3] 117 [lvars, rvars] = rhs.split ('] to [') 118 lvars = [v for v in non_var_re.split (lvars) if v] 119 rvars = [v for v in non_var_re.split (rvars) if v] 120 if not (lvars[-2:] == ['dm', 'm'] 121 and rvars[-2:] == ['dm', 'm']): 122 continue 123 lvars = lvars[:-2] 124 rvars = rvars[:-2] 125 prunes['DecompiledFuns.' + name + '_step'] = (lvars, rvars) 126 return prunes 127 128# likewise the signatures produced by the c-parser 129 130def parse_sigs (sig_stream): 131 sigs = {} 132 for l in sig_stream: 133 bits = l.split () 134 if not bits: 135 continue 136 ret = int (bits[0]) 137 nm = bits[1] 138 args = [int(bit) for bit in bits[2:]] 139 sigs[nm] = (args, ret) 140 return sigs 141 142