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