1*58b9f456SAndroid Build Coastguard Worker#!/usr/bin/env python 2*58b9f456SAndroid Build Coastguard Worker 3*58b9f456SAndroid Build Coastguard Worker""" 4*58b9f456SAndroid Build Coastguard Workerstrip_asm.py - Cleanup ASM output for the specified file 5*58b9f456SAndroid Build Coastguard Worker""" 6*58b9f456SAndroid Build Coastguard Worker 7*58b9f456SAndroid Build Coastguard Workerfrom argparse import ArgumentParser 8*58b9f456SAndroid Build Coastguard Workerimport sys 9*58b9f456SAndroid Build Coastguard Workerimport os 10*58b9f456SAndroid Build Coastguard Workerimport re 11*58b9f456SAndroid Build Coastguard Worker 12*58b9f456SAndroid Build Coastguard Workerdef find_used_labels(asm): 13*58b9f456SAndroid Build Coastguard Worker found = set() 14*58b9f456SAndroid Build Coastguard Worker label_re = re.compile("\s*j[a-z]+\s+\.L([a-zA-Z0-9][a-zA-Z0-9_]*)") 15*58b9f456SAndroid Build Coastguard Worker for l in asm.splitlines(): 16*58b9f456SAndroid Build Coastguard Worker m = label_re.match(l) 17*58b9f456SAndroid Build Coastguard Worker if m: 18*58b9f456SAndroid Build Coastguard Worker found.add('.L%s' % m.group(1)) 19*58b9f456SAndroid Build Coastguard Worker return found 20*58b9f456SAndroid Build Coastguard Worker 21*58b9f456SAndroid Build Coastguard Worker 22*58b9f456SAndroid Build Coastguard Workerdef normalize_labels(asm): 23*58b9f456SAndroid Build Coastguard Worker decls = set() 24*58b9f456SAndroid Build Coastguard Worker label_decl = re.compile("^[.]{0,1}L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)") 25*58b9f456SAndroid Build Coastguard Worker for l in asm.splitlines(): 26*58b9f456SAndroid Build Coastguard Worker m = label_decl.match(l) 27*58b9f456SAndroid Build Coastguard Worker if m: 28*58b9f456SAndroid Build Coastguard Worker decls.add(m.group(0)) 29*58b9f456SAndroid Build Coastguard Worker if len(decls) == 0: 30*58b9f456SAndroid Build Coastguard Worker return asm 31*58b9f456SAndroid Build Coastguard Worker needs_dot = next(iter(decls))[0] != '.' 32*58b9f456SAndroid Build Coastguard Worker if not needs_dot: 33*58b9f456SAndroid Build Coastguard Worker return asm 34*58b9f456SAndroid Build Coastguard Worker for ld in decls: 35*58b9f456SAndroid Build Coastguard Worker asm = re.sub("(^|\s+)" + ld + "(?=:|\s)", '\\1.' + ld, asm) 36*58b9f456SAndroid Build Coastguard Worker return asm 37*58b9f456SAndroid Build Coastguard Worker 38*58b9f456SAndroid Build Coastguard Worker 39*58b9f456SAndroid Build Coastguard Workerdef transform_labels(asm): 40*58b9f456SAndroid Build Coastguard Worker asm = normalize_labels(asm) 41*58b9f456SAndroid Build Coastguard Worker used_decls = find_used_labels(asm) 42*58b9f456SAndroid Build Coastguard Worker new_asm = '' 43*58b9f456SAndroid Build Coastguard Worker label_decl = re.compile("^\.L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)") 44*58b9f456SAndroid Build Coastguard Worker for l in asm.splitlines(): 45*58b9f456SAndroid Build Coastguard Worker m = label_decl.match(l) 46*58b9f456SAndroid Build Coastguard Worker if not m or m.group(0) in used_decls: 47*58b9f456SAndroid Build Coastguard Worker new_asm += l 48*58b9f456SAndroid Build Coastguard Worker new_asm += '\n' 49*58b9f456SAndroid Build Coastguard Worker return new_asm 50*58b9f456SAndroid Build Coastguard Worker 51*58b9f456SAndroid Build Coastguard Worker 52*58b9f456SAndroid Build Coastguard Workerdef is_identifier(tk): 53*58b9f456SAndroid Build Coastguard Worker if len(tk) == 0: 54*58b9f456SAndroid Build Coastguard Worker return False 55*58b9f456SAndroid Build Coastguard Worker first = tk[0] 56*58b9f456SAndroid Build Coastguard Worker if not first.isalpha() and first != '_': 57*58b9f456SAndroid Build Coastguard Worker return False 58*58b9f456SAndroid Build Coastguard Worker for i in range(1, len(tk)): 59*58b9f456SAndroid Build Coastguard Worker c = tk[i] 60*58b9f456SAndroid Build Coastguard Worker if not c.isalnum() and c != '_': 61*58b9f456SAndroid Build Coastguard Worker return False 62*58b9f456SAndroid Build Coastguard Worker return True 63*58b9f456SAndroid Build Coastguard Worker 64*58b9f456SAndroid Build Coastguard Workerdef process_identifiers(l): 65*58b9f456SAndroid Build Coastguard Worker """ 66*58b9f456SAndroid Build Coastguard Worker process_identifiers - process all identifiers and modify them to have 67*58b9f456SAndroid Build Coastguard Worker consistent names across all platforms; specifically across ELF and MachO. 68*58b9f456SAndroid Build Coastguard Worker For example, MachO inserts an additional understore at the beginning of 69*58b9f456SAndroid Build Coastguard Worker names. This function removes that. 70*58b9f456SAndroid Build Coastguard Worker """ 71*58b9f456SAndroid Build Coastguard Worker parts = re.split(r'([a-zA-Z0-9_]+)', l) 72*58b9f456SAndroid Build Coastguard Worker new_line = '' 73*58b9f456SAndroid Build Coastguard Worker for tk in parts: 74*58b9f456SAndroid Build Coastguard Worker if is_identifier(tk): 75*58b9f456SAndroid Build Coastguard Worker if tk.startswith('__Z'): 76*58b9f456SAndroid Build Coastguard Worker tk = tk[1:] 77*58b9f456SAndroid Build Coastguard Worker elif tk.startswith('_') and len(tk) > 1 and \ 78*58b9f456SAndroid Build Coastguard Worker tk[1].isalpha() and tk[1] != 'Z': 79*58b9f456SAndroid Build Coastguard Worker tk = tk[1:] 80*58b9f456SAndroid Build Coastguard Worker new_line += tk 81*58b9f456SAndroid Build Coastguard Worker return new_line 82*58b9f456SAndroid Build Coastguard Worker 83*58b9f456SAndroid Build Coastguard Worker 84*58b9f456SAndroid Build Coastguard Workerdef process_asm(asm): 85*58b9f456SAndroid Build Coastguard Worker """ 86*58b9f456SAndroid Build Coastguard Worker Strip the ASM of unwanted directives and lines 87*58b9f456SAndroid Build Coastguard Worker """ 88*58b9f456SAndroid Build Coastguard Worker new_contents = '' 89*58b9f456SAndroid Build Coastguard Worker asm = transform_labels(asm) 90*58b9f456SAndroid Build Coastguard Worker 91*58b9f456SAndroid Build Coastguard Worker # TODO: Add more things we want to remove 92*58b9f456SAndroid Build Coastguard Worker discard_regexes = [ 93*58b9f456SAndroid Build Coastguard Worker re.compile("\s+\..*$"), # directive 94*58b9f456SAndroid Build Coastguard Worker re.compile("\s*#(NO_APP|APP)$"), #inline ASM 95*58b9f456SAndroid Build Coastguard Worker re.compile("\s*#.*$"), # comment line 96*58b9f456SAndroid Build Coastguard Worker re.compile("\s*\.globa?l\s*([.a-zA-Z_][a-zA-Z0-9$_.]*)"), #global directive 97*58b9f456SAndroid Build Coastguard Worker re.compile("\s*\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)"), 98*58b9f456SAndroid Build Coastguard Worker ] 99*58b9f456SAndroid Build Coastguard Worker keep_regexes = [ 100*58b9f456SAndroid Build Coastguard Worker 101*58b9f456SAndroid Build Coastguard Worker ] 102*58b9f456SAndroid Build Coastguard Worker fn_label_def = re.compile("^[a-zA-Z_][a-zA-Z0-9_.]*:") 103*58b9f456SAndroid Build Coastguard Worker for l in asm.splitlines(): 104*58b9f456SAndroid Build Coastguard Worker # Remove Mach-O attribute 105*58b9f456SAndroid Build Coastguard Worker l = l.replace('@GOTPCREL', '') 106*58b9f456SAndroid Build Coastguard Worker add_line = True 107*58b9f456SAndroid Build Coastguard Worker for reg in discard_regexes: 108*58b9f456SAndroid Build Coastguard Worker if reg.match(l) is not None: 109*58b9f456SAndroid Build Coastguard Worker add_line = False 110*58b9f456SAndroid Build Coastguard Worker break 111*58b9f456SAndroid Build Coastguard Worker for reg in keep_regexes: 112*58b9f456SAndroid Build Coastguard Worker if reg.match(l) is not None: 113*58b9f456SAndroid Build Coastguard Worker add_line = True 114*58b9f456SAndroid Build Coastguard Worker break 115*58b9f456SAndroid Build Coastguard Worker if add_line: 116*58b9f456SAndroid Build Coastguard Worker if fn_label_def.match(l) and len(new_contents) != 0: 117*58b9f456SAndroid Build Coastguard Worker new_contents += '\n' 118*58b9f456SAndroid Build Coastguard Worker l = process_identifiers(l) 119*58b9f456SAndroid Build Coastguard Worker new_contents += l 120*58b9f456SAndroid Build Coastguard Worker new_contents += '\n' 121*58b9f456SAndroid Build Coastguard Worker return new_contents 122*58b9f456SAndroid Build Coastguard Worker 123*58b9f456SAndroid Build Coastguard Workerdef main(): 124*58b9f456SAndroid Build Coastguard Worker parser = ArgumentParser( 125*58b9f456SAndroid Build Coastguard Worker description='generate a stripped assembly file') 126*58b9f456SAndroid Build Coastguard Worker parser.add_argument( 127*58b9f456SAndroid Build Coastguard Worker 'input', metavar='input', type=str, nargs=1, 128*58b9f456SAndroid Build Coastguard Worker help='An input assembly file') 129*58b9f456SAndroid Build Coastguard Worker parser.add_argument( 130*58b9f456SAndroid Build Coastguard Worker 'out', metavar='output', type=str, nargs=1, 131*58b9f456SAndroid Build Coastguard Worker help='The output file') 132*58b9f456SAndroid Build Coastguard Worker args, unknown_args = parser.parse_known_args() 133*58b9f456SAndroid Build Coastguard Worker input = args.input[0] 134*58b9f456SAndroid Build Coastguard Worker output = args.out[0] 135*58b9f456SAndroid Build Coastguard Worker if not os.path.isfile(input): 136*58b9f456SAndroid Build Coastguard Worker print(("ERROR: input file '%s' does not exist") % input) 137*58b9f456SAndroid Build Coastguard Worker sys.exit(1) 138*58b9f456SAndroid Build Coastguard Worker contents = None 139*58b9f456SAndroid Build Coastguard Worker with open(input, 'r') as f: 140*58b9f456SAndroid Build Coastguard Worker contents = f.read() 141*58b9f456SAndroid Build Coastguard Worker new_contents = process_asm(contents) 142*58b9f456SAndroid Build Coastguard Worker with open(output, 'w') as f: 143*58b9f456SAndroid Build Coastguard Worker f.write(new_contents) 144*58b9f456SAndroid Build Coastguard Worker 145*58b9f456SAndroid Build Coastguard Worker 146*58b9f456SAndroid Build Coastguard Workerif __name__ == '__main__': 147*58b9f456SAndroid Build Coastguard Worker main() 148*58b9f456SAndroid Build Coastguard Worker 149*58b9f456SAndroid Build Coastguard Worker# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 150*58b9f456SAndroid Build Coastguard Worker# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off; 151*58b9f456SAndroid Build Coastguard Worker# kate: indent-mode python; remove-trailing-spaces modified; 152