Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 31

kernel-2.6.18-238.el5.src.rpm

#!/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).

# Changelog:
# 
# 2006/12/11 - Add better error handling to catch unresolved symbols.

__author__ = "Jon Masters <jcm@redhat.com>"
__version__ = "$Revisions: 1.3 $"
__date__ = "$Date: 2007/11/26 18:21:15 $"
__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])):
			if symsets[i][j].has_key("checksum"):
				hash_tmp.update(symsets[i][j]["checksum"])
			else:
				print "kabitool: cannot find checksum for symbol",symsets[i][j]["symbol"],"in group",i
				sys.exit(1)
		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])):
                        if symsets[i][j].has_key("checksum"):
				tmp = symsets[i][j]["checksum"] + "\t" + \
				      symsets[i][j]["symbol"] + "\t" + \
				      symsets[i][j]["source"] + "\n"
				sym_file.write(tmp)
                        else:
                                print "kabitool: cannot find checksum for symbol",symsets[i][j]["symbol"],"in group",i
				sys.exit(1)

		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)