# this file contains definitions related to the Linux kernel itself #
# list here the macros that you know are always defined/undefined when including # the kernel headers # import sys, cpp, re, os.path, time from defaults import *
verboseSearch = 0
verboseFind = 0
######################################################################## ######################################################################## ##### ##### ##### H E A D E R S C A N N E R ##### ##### ##### ######################################################################## ########################################################################
class HeaderScanner: """a class used to non-recursively detect which Linux kernel headers are
used by a given set of input source files"""
# to use the HeaderScanner, do the following: # # scanner = HeaderScanner() # for path in <your list of files>: # scanner.parseFile(path) # # # get the set of Linux headers included by your files # headers = scanner.getHeaders() # # # get the set of of input files that do include Linux headers # files = scanner.getFiles() # # note that the result of getHeaders() is a set of strings, each one # corresponding to a non-bracketed path name, e.g.: # # set("linux/types","asm/types.h") #
# the default algorithm is pretty smart and will analyze the input # files with a custom C pre-processor in order to optimize out macros, # get rid of comments, empty lines, etc.. # # this avoids many annoying false positives... !! #
# this regular expression is used to detect include paths that relate to # the kernel, by default, it selects one of: # <linux/*> # <asm/*> # <asm-generic/*> # <mtd/*> #
re_combined_str=\
r"^.*<((%s)/[\d\w_\+\.\-/]*)>.*$" % "|".join(kernel_dirs)
re_combined = re.compile(re_combined_str)
# some kernel files choose to include files with relative paths (x86 32/64 # dispatch for instance)
re_rel_dir = re.compile(r'^.*"([\d\w_\+\.\-/]+)".*$')
def __init__(self,config={}): """initialize a HeaderScanner"""
self.reset()
self.config = config
def reset(self,config={}):
self.files = set() # set of files being parsed for headers
self.headers = {} # maps headers to set of users
self.config = config
def checkInclude(self, line, from_file, kernel_root=None):
relative = False
m = HeaderScanner.re_combined.match(line) if kernel_root andnot m:
m = HeaderScanner.re_rel_dir.match(line)
relative = True ifnot m: return
header = m.group(1) if from_file:
self.files.add(from_file) if kernel_root and relative:
hdr_dir = os.path.realpath(os.path.dirname(from_file))
hdr_dir = hdr_dir.replace("%s/" % os.path.realpath(kernel_root), "") if hdr_dir:
_prefix = "%s/" % hdr_dir else:
_prefix = ""
header = "%s%s" % (_prefix, header)
ifnot header in self.headers:
self.headers[header] = set()
if from_file: if verboseFind:
print("=== %s uses %s" % (from_file, header))
self.headers[header].add(from_file)
def parseFile(self, path, arch=None, kernel_root=None): """parse a given file for Linux headers""" ifnot os.path.exists(path): return
# since tokenizing the file is very slow, we first try a quick grep # to see if this returns any meaningful results. only if this is true # do we do the tokenization""" try:
f = open(path, "rt") except:
print("!!! can't read '%s'" % path) return
hasIncludes = False for line in f: if (HeaderScanner.re_combined.match(line) or
(kernel_root and HeaderScanner.re_rel_dir.match(line))):
hasIncludes = True break
ifnot hasIncludes: if verboseSearch: print("::: " + path) return
if verboseSearch: print("*** " + path)
list = cpp.BlockParser().parseFile(path) if list:
macros = kernel_known_macros.copy() if kernel_root:
macros.update(self.config) if arch and arch in kernel_default_arch_macros:
macros.update(kernel_default_arch_macros[arch])
list.optimizeMacros(macros)
list.optimizeIf01()
includes = list.findIncludes() for inc in includes:
self.checkInclude(inc, path, kernel_root)
def getHeaders(self): """return the set of all needed kernel headers""" return set(self.headers.keys())
def getHeaderUsers(self,header): """return the set of all users for a given header""" return set(self.headers.get(header))
def getAllUsers(self): """return a dictionary mapping heaaders to their user set""" return self.headers.copy()
def getFiles(self): """returns the set of files that do include kernel headers""" return self.files.copy()
########################################################################## ########################################################################## ##### ##### ##### H E A D E R F I N D E R ##### ##### ##### ########################################################################## ##########################################################################
class KernelHeaderFinder: """a class used to scan the kernel headers themselves."""
# this is different # from a HeaderScanner because we need to translate the path returned by # HeaderScanner.getHeaders() into possibly architecture-specific ones. # # for example, <asm/XXXX.h> needs to be translated in <asm-ARCH/XXXX.h> # where ARCH is appropriately chosen
# here's how to use this: # # scanner = HeaderScanner() # for path in <your list of user sources>: # scanner.parseFile(path) # # used_headers = scanner.getHeaders() # finder = KernelHeaderFinder(used_headers, [ "arm", "x86" ], # "<kernel_include_path>") # all_headers = finder.scanForAllArchs() # # not that the result of scanForAllArchs() is a list of relative # header paths that are not bracketed #
def __init__(self,headers,archs,kernel_root,kernel_config): """init a KernelHeaderScanner,
'headers'is a list or set of headers, 'archs'is a list of architectures 'kernel_root'is the path to the 'include' directory
of your original kernel sources """
def scanForArch(self):
fparser = HeaderScanner(config=self.kernel_config)
workqueue = []
needed = {} for h in self.searched:
path = self.pathFromHeader(h) ifnot path in needed:
needed[path] = set()
workqueue.append(path)
i = 0 while i < len(workqueue):
path = workqueue[i]
i += 1
fparser.parseFile(self.kernel_root + path,
arch=self.curr_arch, kernel_root=self.kernel_root) for used in fparser.getHeaders():
path = self.pathFromHeader(used) ifnot path in needed:
needed[path] = set()
workqueue.append(path) for user in fparser.getHeaderUsers(used):
needed[path].add(user)
# now copy the arch-specific headers into the global list for header in needed.keys():
users = needed[header] ifnot header in self.needed:
self.needed[header] = set()
for user in users:
self.needed[header].add(user)
def scanForAllArchs(self): """scan for all architectures and return the set of all needed kernel headers""" for arch in self.archs:
self.setArch(arch)
self.scanForArch()
return set(self.needed.keys())
def getHeaderUsers(self,header): """return the set of all users for a given header""" return set(self.needed[header])
def getArchHeaders(self,arch): """return the set of all <asm/...> headers required by a given architecture""" return set() # XXX: TODO
##################################################################################### ##################################################################################### ##### ##### ##### C O N F I G P A R S E R ##### ##### ##### ##################################################################################### #####################################################################################
class ConfigParser: """a class used to parse the Linux kernel .config file"""
re_CONFIG_ = re.compile(r"^(CONFIG_\w+)=(.*)$")
# skip empty and comment lines if len(line) == 0or line[0] == "#": return
m = ConfigParser.re_CONFIG_.match(line) ifnot m: return
name = m.group(1)
value = m.group(2)
if name in self.items: # aarg, duplicate value
self.duplicates = True
self.items[name] = value
def parseFile(self,path):
f = file(path, "r") for line in f: if len(line) > 0: if line[-1] == "\n":
line = line[:-1] if len(line) > 0and line[-1] == "\r":
line = line[:-1]
self.parseLine(line)
f.close()
def getDefinitions(self): """retrieve a dictionary containing definitions for CONFIG_XXX""" return self.items.copy()
def __repr__(self): return repr(self.items)
def __str__(self): return str(self.items)
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-28)
¤