File kabitool of Package kernel
#!/usr/bin/python
#
# kabitool - Red Hat kABI extraction tool
#
# We use this script to generate collections (groups) of kABI symbols and also
# optionally output kABI dependencies for use by the RPM.
#
# Author: Jon Masters <jcm@redhat.com>
# Copyright (C) 2006 Red Hat, Inc.
#
# This software may be freely redistributed under the terms of the GNU
# General Public License (GPL).
__author__ = "Jon Masters <jcm@redhat.com>"
__version__ = "$Revisions: 1.2 $"
__date__ = "$Date: 2006/07/25 14:34:58 $"
__copyright__ = "Copyright (C) 2006 Red Hat, Inc"
__license__ = "GPL"
import getopt
import os
import re
import sha
import string
import sys
true = 1
false = 0
def load_kabilist(symsets,filename):
"""Load a list of kABI symbols to generate symsets for from a file."""
kabi_file = open(filename,"r")
while true:
in_line = kabi_file.readline()
if in_line == "":
break
if in_line == "\n":
continue
string.split(in_line)
if in_line[0] == '[':
group=in_line[1:-2]
continue
symbol=in_line[1:-1]
if symsets.has_key(group):
symsets[group].append({"symbol":symbol})
else:
symsets[group] = [{"symbol":symbol}]
kabi_file.close()
def load_symvers(symsets,filename):
"""Load the kernel exported symbols from Module.symvers."""
ksyms_file = open(filename,"r")
while true:
in_line = ksyms_file.readline()
if in_line == "":
break;
if in_line == "\n":
continue
checksum,symbol,source,export_type = string.split(in_line)
for i in symsets:
for j in range(0,len(symsets[i])):
if symsets[i][j]["symbol"] == symbol:
symsets[i][j]["checksum"] = checksum
symsets[i][j]["source"] = source
symsets[i][j]["export_type"] = export_type
def make_hashes(symsets,symhashes):
for i in symsets:
hash_tmp = sha.new()
for j in range(0,len(symsets[i])):
hash_tmp.update(symsets[i][j]["checksum"])
symhashes[i] = hash_tmp.hexdigest()
def save_hashes(symsets,symhashes,kernel,bootdir):
symdir = "symsets-"+kernel
if not os.path.isdir(symdir):
os.mkdir(symdir)
else:
print "symsets already exist for this kernel!"
sys.exit(1)
for i in symhashes:
sym_file = open(symdir+"/"+i+"."+symhashes[i], "w")
for j in range(0,len(symsets[i])):
tmp = symsets[i][j]["checksum"] + "\t" + \
symsets[i][j]["symbol"] + "\t" + \
symsets[i][j]["source"] + "\n"
sym_file.write(tmp)
sym_file.close()
os.system("tar cfz " + bootdir + "/symsets-" + kernel + ".tar.gz " + \
"symsets-" + kernel)
def find_builtin(symsets):
pbuiltins = os.popen("find -name built-in.o -printf '%P\n'")
while true:
file = pbuiltins.readline()
if file == "":
break
file = file[:-1]
pnm = os.popen("nm --extern-only --defined-only " + file)
while true:
in_line = pnm.readline()
if in_line == "":
break
in_line[:-1]
address, type, symbol = string.split(in_line)
for i in symsets:
for j in range(0,len(symsets[i])):
if symsets[i][j]["symbol"] == symbol:
symsets[i][j]["source"] = file
pnm.close()
pbuiltins.close()
def output_deps(symhashes,depsfile):
deps_file = open(depsfile,"w")
for i in symhashes:
deps_file.write("kernel("+i+") = " + symhashes[i] + "\n")
def make_kabilist(product,update,filename_modulesymvers,filename_kabilist):
"""Make a kabilist stub file for the current kernel source tree"""
ksyms_file = open(filename_modulesymvers,"r")
kabi_file = open(filename_kabilist,"w")
kabisyms = {}
while true:
in_line = ksyms_file.readline()
if in_line == "":
break;
if in_line == "\n":
continue
checksum,symbol,source,export_type = string.split(in_line)
kabisyms[symbol] = {}
kabisyms[symbol]["checksum"] = checksum
kabisyms[symbol]["source"] = source
kabisyms[symbol]["export_type"] = export_type
pbuiltins = os.popen("find -name built-in.o -printf '%P\n'")
while true:
file = pbuiltins.readline()
if file == "":
break
file = file[:-1]
pnm = os.popen("nm --extern-only --defined-only " + file)
while true:
in_line = pnm.readline()
if in_line == "":
break
in_line[:-1]
address, type, symbol = string.split(in_line)
if kabisyms.has_key(symbol):
kabisyms[symbol]["source"] = file
pnm.close()
pbuiltins.close()
symsets = {}
for i in kabisyms:
group_name = re.sub("/[^/]*$","",kabisyms[i]["source"])
group_name = re.sub("/","_",group_name)
group_name = re.sub("-","_",group_name)
group_name = re.sub("_built-in.o","",group_name)
if symsets.has_key(group_name):
symsets[group_name].append({"symbol":i, \
"checksum":kabisyms[i]["checksum"], \
"source":kabisyms[i]["source"], \
"export_type":kabisyms[i]["export_type"]})
else:
symsets[group_name] = [{"symbol":i, \
"checksum":kabisyms[i]["checksum"], \
"source":kabisyms[i]["source"], \
"export_type":kabisyms[i]["export_type"]}]
for i in symsets:
if product == "":
kabi_file.write("["+i+"]\n")
elif update == "":
kabi_file.write("["+product+"_"+i+"]\n")
else:
kabi_file.write("["+product+"_"+i+"_"+update+"]\n")
for j in range(0,len(symsets[i])):
kabi_file.write("\t" + symsets[i][j]["symbol"] + "\n")
kabi_file.write("\n")
def debug_output(symsets):
for i in symsets:
for j in range(0,len(symsets[i])):
print "======================"
print "group: " + i
print "checksum: " + symsets[i][j]["checksum"]
print "symbol: " + symsets[i][j]["symbol"]
print "source: " + symsets[i][j]["source"]
print "export: " + symsets[i][j]["export_type"]
print "======================"
def usage():
print """
kabitool: process Module.symvers into useful exported kABI dependencies
kabitool [-b bootdir] [-d] [-k kernel] [-l] [-p product] [-u update]
-b Boot dir to use for output files
-d Output RPM style kernel dependencies
-k The kernel to generate symbol sets against
-l Make a list of kernel kABI symbols
-p Product name (FC/RHEL)
-u Update Number
-w Whitelist
"""
if __name__ == "__main__":
kernel = ""
deps = ""
list = ""
product = ""
update = ""
bootdir = "."
whitelist = ""
opts, args = getopt.getopt(sys.argv[1:], 'b:d:hk:l:p:u:w:')
for o, v in opts:
if o == "-k":
kernel = v
if o == "-d":
deps = v
if o == "-l":
list = v
if o == "-p":
product = v
if o == "-u":
update = v
if o == "-h":
usage()
sys.exit(0)
if o == "-b":
bootdir = v
if o == "-w":
whitelist = v
if (kernel == "") and (list == ""):
usage()
sys.exit(1)
if (whitelist == ""):
whitelist = "kabilist"
symsets={}
symhashes={}
if not (list == ""):
make_kabilist(product,update,"Module.symvers",list)
sys.exit(0)
if not (os.path.isfile(whitelist)):
make_kabilist(product,update,"Module.symvers",whitelist)
load_kabilist(symsets,whitelist)
load_symvers(symsets,"Module.symvers")
find_builtin(symsets)
make_hashes(symsets,symhashes)
save_hashes(symsets,symhashes,kernel,bootdir)
#os.system("gzip -c9 < Module.symvers > " + bootdir +
#"/symvers-" + kernel + ".tar.gz")
if not deps == "":
output_deps(symhashes,deps)