1*8d67ca89SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*8d67ca89SAndroid Build Coastguard Worker 3*8d67ca89SAndroid Build Coastguard Worker#------------------------------------------------------------------------------ 4*8d67ca89SAndroid Build Coastguard Worker# Description of the header clean process 5*8d67ca89SAndroid Build Coastguard Worker#------------------------------------------------------------------------------ 6*8d67ca89SAndroid Build Coastguard Worker# Here is the list of actions performed by this script to clean the original 7*8d67ca89SAndroid Build Coastguard Worker# kernel headers. 8*8d67ca89SAndroid Build Coastguard Worker# 9*8d67ca89SAndroid Build Coastguard Worker# 1. Optimize well-known macros (e.g. __KERNEL__, __KERNEL_STRICT_NAMES) 10*8d67ca89SAndroid Build Coastguard Worker# 11*8d67ca89SAndroid Build Coastguard Worker# This pass gets rid of everything that is guarded by a well-known macro 12*8d67ca89SAndroid Build Coastguard Worker# definition. This means that a block like: 13*8d67ca89SAndroid Build Coastguard Worker# 14*8d67ca89SAndroid Build Coastguard Worker# #ifdef __KERNEL__ 15*8d67ca89SAndroid Build Coastguard Worker# .... 16*8d67ca89SAndroid Build Coastguard Worker# #endif 17*8d67ca89SAndroid Build Coastguard Worker# 18*8d67ca89SAndroid Build Coastguard Worker# Will be totally omitted from the output. The optimizer is smart enough to 19*8d67ca89SAndroid Build Coastguard Worker# handle all complex C-preprocessor conditional expression appropriately. 20*8d67ca89SAndroid Build Coastguard Worker# This means that, for example: 21*8d67ca89SAndroid Build Coastguard Worker# 22*8d67ca89SAndroid Build Coastguard Worker# #if defined(__KERNEL__) || defined(FOO) 23*8d67ca89SAndroid Build Coastguard Worker# ... 24*8d67ca89SAndroid Build Coastguard Worker# #endif 25*8d67ca89SAndroid Build Coastguard Worker# 26*8d67ca89SAndroid Build Coastguard Worker# Will be transformed into: 27*8d67ca89SAndroid Build Coastguard Worker# 28*8d67ca89SAndroid Build Coastguard Worker# #ifdef FOO 29*8d67ca89SAndroid Build Coastguard Worker# ... 30*8d67ca89SAndroid Build Coastguard Worker# #endif 31*8d67ca89SAndroid Build Coastguard Worker# 32*8d67ca89SAndroid Build Coastguard Worker# See tools/defaults.py for the list of well-known macros used in this pass, 33*8d67ca89SAndroid Build Coastguard Worker# in case you need to update it in the future. 34*8d67ca89SAndroid Build Coastguard Worker# 35*8d67ca89SAndroid Build Coastguard Worker# Note that this also removes any reference to a kernel-specific 36*8d67ca89SAndroid Build Coastguard Worker# configuration macro like CONFIG_FOO from the clean headers. 37*8d67ca89SAndroid Build Coastguard Worker# 38*8d67ca89SAndroid Build Coastguard Worker# 39*8d67ca89SAndroid Build Coastguard Worker# 2. Remove variable and function declarations: 40*8d67ca89SAndroid Build Coastguard Worker# 41*8d67ca89SAndroid Build Coastguard Worker# This pass scans non-directive text and only keeps things that look like a 42*8d67ca89SAndroid Build Coastguard Worker# typedef/struct/union/enum declaration. This allows us to get rid of any 43*8d67ca89SAndroid Build Coastguard Worker# variables or function declarations that should only be used within the 44*8d67ca89SAndroid Build Coastguard Worker# kernel anyway (and which normally *should* be guarded by an #ifdef 45*8d67ca89SAndroid Build Coastguard Worker# __KERNEL__ ... #endif block, if the kernel writers were not so messy). 46*8d67ca89SAndroid Build Coastguard Worker# 47*8d67ca89SAndroid Build Coastguard Worker# There are, however, a few exceptions: it is seldom useful to keep the 48*8d67ca89SAndroid Build Coastguard Worker# definition of some static inline functions performing very simple 49*8d67ca89SAndroid Build Coastguard Worker# operations. A good example is the optimized 32-bit byte-swap function 50*8d67ca89SAndroid Build Coastguard Worker# found in: 51*8d67ca89SAndroid Build Coastguard Worker# 52*8d67ca89SAndroid Build Coastguard Worker# arch-arm/asm/byteorder.h 53*8d67ca89SAndroid Build Coastguard Worker# 54*8d67ca89SAndroid Build Coastguard Worker# The list of exceptions is in tools/defaults.py in case you need to update 55*8d67ca89SAndroid Build Coastguard Worker# it in the future. 56*8d67ca89SAndroid Build Coastguard Worker# 57*8d67ca89SAndroid Build Coastguard Worker# Note that we do *not* remove macro definitions, including these macro that 58*8d67ca89SAndroid Build Coastguard Worker# perform a call to one of these kernel-header functions, or even define other 59*8d67ca89SAndroid Build Coastguard Worker# functions. We consider it safe since userland applications have no business 60*8d67ca89SAndroid Build Coastguard Worker# using them anyway. 61*8d67ca89SAndroid Build Coastguard Worker# 62*8d67ca89SAndroid Build Coastguard Worker# 63*8d67ca89SAndroid Build Coastguard Worker# 3. Add a standard disclaimer: 64*8d67ca89SAndroid Build Coastguard Worker# 65*8d67ca89SAndroid Build Coastguard Worker# The message: 66*8d67ca89SAndroid Build Coastguard Worker# 67*8d67ca89SAndroid Build Coastguard Worker# /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ 68*8d67ca89SAndroid Build Coastguard Worker# 69*8d67ca89SAndroid Build Coastguard Worker# Is prepended to each generated header. 70*8d67ca89SAndroid Build Coastguard Worker#------------------------------------------------------------------------------ 71*8d67ca89SAndroid Build Coastguard Worker 72*8d67ca89SAndroid Build Coastguard Workerimport sys, cpp, kernel, glob, os, re, getopt, textwrap 73*8d67ca89SAndroid Build Coastguard Workerfrom defaults import * 74*8d67ca89SAndroid Build Coastguard Workerfrom utils import * 75*8d67ca89SAndroid Build Coastguard Worker 76*8d67ca89SAndroid Build Coastguard Workerdef print_error(no_update, msg): 77*8d67ca89SAndroid Build Coastguard Worker if no_update: 78*8d67ca89SAndroid Build Coastguard Worker panic(msg) 79*8d67ca89SAndroid Build Coastguard Worker sys.stderr.write("warning: " + msg) 80*8d67ca89SAndroid Build Coastguard Worker 81*8d67ca89SAndroid Build Coastguard Worker 82*8d67ca89SAndroid Build Coastguard Workerdef cleanupFile(dst_file, src_file, rel_path, no_update = True): 83*8d67ca89SAndroid Build Coastguard Worker """reads an original header and perform the cleanup operation on it 84*8d67ca89SAndroid Build Coastguard Worker this functions returns the destination path and the clean header 85*8d67ca89SAndroid Build Coastguard Worker as a single string""" 86*8d67ca89SAndroid Build Coastguard Worker # Check the header path 87*8d67ca89SAndroid Build Coastguard Worker if not os.path.exists(src_file): 88*8d67ca89SAndroid Build Coastguard Worker print_error(no_update, "'%s' does not exist\n" % src_file) 89*8d67ca89SAndroid Build Coastguard Worker return None 90*8d67ca89SAndroid Build Coastguard Worker 91*8d67ca89SAndroid Build Coastguard Worker if not os.path.isfile(src_file): 92*8d67ca89SAndroid Build Coastguard Worker print_error(no_update, "'%s' is not a file\n" % src_file) 93*8d67ca89SAndroid Build Coastguard Worker return None 94*8d67ca89SAndroid Build Coastguard Worker 95*8d67ca89SAndroid Build Coastguard Worker # Extract the architecture if found. 96*8d67ca89SAndroid Build Coastguard Worker arch = None 97*8d67ca89SAndroid Build Coastguard Worker m = re.search(r"(^|/)asm-([\w\d_\+\.\-]+)/.*", rel_path) 98*8d67ca89SAndroid Build Coastguard Worker if m and m.group(2) != 'generic': 99*8d67ca89SAndroid Build Coastguard Worker arch = m.group(2) 100*8d67ca89SAndroid Build Coastguard Worker 101*8d67ca89SAndroid Build Coastguard Worker # Now, let's parse the file. 102*8d67ca89SAndroid Build Coastguard Worker parser = cpp.BlockParser() 103*8d67ca89SAndroid Build Coastguard Worker blocks = parser.parseFile(src_file) 104*8d67ca89SAndroid Build Coastguard Worker if not parser.parsed: 105*8d67ca89SAndroid Build Coastguard Worker print_error(no_update, "Can't parse '%s'" % src_file) 106*8d67ca89SAndroid Build Coastguard Worker return None 107*8d67ca89SAndroid Build Coastguard Worker 108*8d67ca89SAndroid Build Coastguard Worker macros = kernel_known_macros.copy() 109*8d67ca89SAndroid Build Coastguard Worker if arch and arch in kernel_default_arch_macros: 110*8d67ca89SAndroid Build Coastguard Worker macros.update(kernel_default_arch_macros[arch]) 111*8d67ca89SAndroid Build Coastguard Worker 112*8d67ca89SAndroid Build Coastguard Worker blocks.removeStructs(kernel_structs_to_remove) 113*8d67ca89SAndroid Build Coastguard Worker blocks.optimizeMacros(macros) 114*8d67ca89SAndroid Build Coastguard Worker blocks.optimizeIf01() 115*8d67ca89SAndroid Build Coastguard Worker blocks.removeVarsAndFuncs(kernel_known_generic_statics) 116*8d67ca89SAndroid Build Coastguard Worker blocks.replaceTokens(kernel_token_replacements) 117*8d67ca89SAndroid Build Coastguard Worker 118*8d67ca89SAndroid Build Coastguard Worker out = StringOutput() 119*8d67ca89SAndroid Build Coastguard Worker out.write(textwrap.dedent("""\ 120*8d67ca89SAndroid Build Coastguard Worker /* 121*8d67ca89SAndroid Build Coastguard Worker * This file is auto-generated. Modifications will be lost. 122*8d67ca89SAndroid Build Coastguard Worker * 123*8d67ca89SAndroid Build Coastguard Worker * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/ 124*8d67ca89SAndroid Build Coastguard Worker * for more information. 125*8d67ca89SAndroid Build Coastguard Worker */ 126*8d67ca89SAndroid Build Coastguard Worker """)) 127*8d67ca89SAndroid Build Coastguard Worker blocks.write(out) 128*8d67ca89SAndroid Build Coastguard Worker return out.get() 129*8d67ca89SAndroid Build Coastguard Worker 130*8d67ca89SAndroid Build Coastguard Worker 131*8d67ca89SAndroid Build Coastguard Workerif __name__ == "__main__": 132*8d67ca89SAndroid Build Coastguard Worker 133*8d67ca89SAndroid Build Coastguard Worker def usage(): 134*8d67ca89SAndroid Build Coastguard Worker print("""\ 135*8d67ca89SAndroid Build Coastguard Worker usage: %s [options] <header_path> 136*8d67ca89SAndroid Build Coastguard Worker 137*8d67ca89SAndroid Build Coastguard Worker options: 138*8d67ca89SAndroid Build Coastguard Worker -v enable verbose mode 139*8d67ca89SAndroid Build Coastguard Worker 140*8d67ca89SAndroid Build Coastguard Worker -u enabled update mode 141*8d67ca89SAndroid Build Coastguard Worker this will try to update the corresponding 'clean header' 142*8d67ca89SAndroid Build Coastguard Worker if the content has changed. with this, you can pass more 143*8d67ca89SAndroid Build Coastguard Worker than one file on the command-line 144*8d67ca89SAndroid Build Coastguard Worker 145*8d67ca89SAndroid Build Coastguard Worker -k<path> specify path of original kernel headers 146*8d67ca89SAndroid Build Coastguard Worker -d<path> specify path of cleaned kernel headers 147*8d67ca89SAndroid Build Coastguard Worker 148*8d67ca89SAndroid Build Coastguard Worker <header_path> must be in a subdirectory of 'original' 149*8d67ca89SAndroid Build Coastguard Worker """ % os.path.basename(sys.argv[0])) 150*8d67ca89SAndroid Build Coastguard Worker sys.exit(1) 151*8d67ca89SAndroid Build Coastguard Worker 152*8d67ca89SAndroid Build Coastguard Worker try: 153*8d67ca89SAndroid Build Coastguard Worker optlist, args = getopt.getopt(sys.argv[1:], 'uvk:d:') 154*8d67ca89SAndroid Build Coastguard Worker except: 155*8d67ca89SAndroid Build Coastguard Worker # unrecognized option 156*8d67ca89SAndroid Build Coastguard Worker sys.stderr.write("error: unrecognized option\n") 157*8d67ca89SAndroid Build Coastguard Worker usage() 158*8d67ca89SAndroid Build Coastguard Worker 159*8d67ca89SAndroid Build Coastguard Worker no_update = True 160*8d67ca89SAndroid Build Coastguard Worker dst_dir = None 161*8d67ca89SAndroid Build Coastguard Worker src_dir = None 162*8d67ca89SAndroid Build Coastguard Worker for opt, arg in optlist: 163*8d67ca89SAndroid Build Coastguard Worker if opt == '-u': 164*8d67ca89SAndroid Build Coastguard Worker no_update = False 165*8d67ca89SAndroid Build Coastguard Worker elif opt == '-v': 166*8d67ca89SAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG) 167*8d67ca89SAndroid Build Coastguard Worker elif opt == '-k': 168*8d67ca89SAndroid Build Coastguard Worker src_dir = arg 169*8d67ca89SAndroid Build Coastguard Worker elif opt == '-d': 170*8d67ca89SAndroid Build Coastguard Worker dst_dir = arg 171*8d67ca89SAndroid Build Coastguard Worker # get_kernel_dir() and get_kernel_headers_original_dir() require the current 172*8d67ca89SAndroid Build Coastguard Worker # working directory to be a direct or indirect subdirectory of 173*8d67ca89SAndroid Build Coastguard Worker # ANDROID_BUILD_TOP. Otherwise, these functions print an error message and 174*8d67ca89SAndroid Build Coastguard Worker # exit. Let's allow the user to run this program from an unrelated 175*8d67ca89SAndroid Build Coastguard Worker # directory, if they specify src_dir and dst_dir on the command line. 176*8d67ca89SAndroid Build Coastguard Worker if dst_dir is None: 177*8d67ca89SAndroid Build Coastguard Worker dst_dir = get_kernel_dir() 178*8d67ca89SAndroid Build Coastguard Worker if src_dir is None: 179*8d67ca89SAndroid Build Coastguard Worker src_dir = get_kernel_headers_original_dir() 180*8d67ca89SAndroid Build Coastguard Worker 181*8d67ca89SAndroid Build Coastguard Worker if len(args) == 0: 182*8d67ca89SAndroid Build Coastguard Worker usage() 183*8d67ca89SAndroid Build Coastguard Worker 184*8d67ca89SAndroid Build Coastguard Worker if no_update: 185*8d67ca89SAndroid Build Coastguard Worker for path in args: 186*8d67ca89SAndroid Build Coastguard Worker dst_file = os.path.join(dst_dir, path) 187*8d67ca89SAndroid Build Coastguard Worker src_file = os.path.join(src_dir, path) 188*8d67ca89SAndroid Build Coastguard Worker new_data = cleanupFile(dst_file, src_file, path) 189*8d67ca89SAndroid Build Coastguard Worker # Use sys.stdout.write instead of a simple print statement to avoid 190*8d67ca89SAndroid Build Coastguard Worker # sending an extra new line character to stdout. Running this 191*8d67ca89SAndroid Build Coastguard Worker # program in non-update mode and redirecting stdout to a file should 192*8d67ca89SAndroid Build Coastguard Worker # yield the same result as using update mode, where new_data is 193*8d67ca89SAndroid Build Coastguard Worker # written directly to a file. 194*8d67ca89SAndroid Build Coastguard Worker sys.stdout.write(new_data) 195*8d67ca89SAndroid Build Coastguard Worker 196*8d67ca89SAndroid Build Coastguard Worker sys.exit(0) 197*8d67ca89SAndroid Build Coastguard Worker 198*8d67ca89SAndroid Build Coastguard Worker # Now let's update our files. 199*8d67ca89SAndroid Build Coastguard Worker 200*8d67ca89SAndroid Build Coastguard Worker b = BatchFileUpdater() 201*8d67ca89SAndroid Build Coastguard Worker 202*8d67ca89SAndroid Build Coastguard Worker for path in args: 203*8d67ca89SAndroid Build Coastguard Worker dst_file = os.path.join(dst_dir, path) 204*8d67ca89SAndroid Build Coastguard Worker src_file = os.path.join(src_dir, path) 205*8d67ca89SAndroid Build Coastguard Worker new_data = cleanupFile(dst_file, src_file, path, no_update) 206*8d67ca89SAndroid Build Coastguard Worker if not new_data: 207*8d67ca89SAndroid Build Coastguard Worker continue 208*8d67ca89SAndroid Build Coastguard Worker 209*8d67ca89SAndroid Build Coastguard Worker b.readFile(dst_file) 210*8d67ca89SAndroid Build Coastguard Worker r = b.editFile(dst_file, new_data) 211*8d67ca89SAndroid Build Coastguard Worker if r == 0: 212*8d67ca89SAndroid Build Coastguard Worker r = "unchanged" 213*8d67ca89SAndroid Build Coastguard Worker elif r == 1: 214*8d67ca89SAndroid Build Coastguard Worker r = "edited" 215*8d67ca89SAndroid Build Coastguard Worker else: 216*8d67ca89SAndroid Build Coastguard Worker r = "added" 217*8d67ca89SAndroid Build Coastguard Worker 218*8d67ca89SAndroid Build Coastguard Worker print("cleaning: %-*s -> %-*s (%s)" % (35, path, 35, path, r)) 219*8d67ca89SAndroid Build Coastguard Worker 220*8d67ca89SAndroid Build Coastguard Worker b.updateFiles() 221*8d67ca89SAndroid Build Coastguard Worker 222*8d67ca89SAndroid Build Coastguard Worker sys.exit(0) 223