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