/dists/trunk/linux-kbuild-2.6: Add.

svn path=/dists/trunk/linux-kbuild-2.6/; revision=6325
This commit is contained in:
Bastian Blank 2006-03-28 21:46:39 +00:00
commit 4b9ae46e44
28 changed files with 3115 additions and 0 deletions

153
debian/bin/gencontrol.py vendored Executable file
View File

@ -0,0 +1,153 @@
#!/usr/bin/env python2.4
import sys
sys.path.append("debian/lib/python")
import warnings
from debian_linux.debian import *
from debian_linux.utils import *
class packages_list(sorted_dict):
def append(self, package):
self[package['Package']] = package
def extend(self, packages):
for package in packages:
self[package['Package']] = package
class gencontrol(object):
makefile_targets = ('binary-arch', 'build')
def __init__(self, underlay = None):
self.changelog = read_changelog()
self.templates = templates()
self.version, self.changelog_vars = self.process_changelog({})
def __call__(self):
packages = packages_list()
makefile = []
self.do_source(packages)
self.do_main(packages, makefile)
self.write_control(packages.itervalues())
self.write_makefile(makefile)
def do_source(self, packages):
source = self.templates["control.source"]
packages['source'] = self.process_package(source[0], self.changelog_vars)
def do_main(self, packages, makefile):
makeflags = {
'VERSION': self.version['version'],
'SOURCE_UPSTREAM': self.version['source_upstream'],
'SOURCEVERSION': self.version['source'],
'UPSTREAMVERSION': self.version['upstream'],
}
vars = self.changelog_vars.copy()
self.do_main_setup(vars, makeflags)
self.do_main_packages(packages)
self.do_main_makefile(makefile, makeflags)
def do_main_setup(self, vars, makeflags):
pass
def do_main_makefile(self, makefile, makeflags):
makeflags_string = ' '.join(["%s='%s'" % i for i in makeflags.iteritems()])
for i in self.makefile_targets:
makefile.append(("%s:" % i, ("$(MAKE) -f debian/rules.real %s %s" % (i, makeflags_string))))
def do_main_packages(self, packages):
vars = self.changelog_vars
main = self.templates["control.main"]
packages.extend(self.process_packages(main, vars))
def process_changelog(self, in_vars):
ret = [None, None]
ret[0] = version = self.changelog[0]['Version']
vars = in_vars.copy()
vars['upstreamversion'] = version['upstream']
vars['version'] = version['version']
vars['source_upstream'] = version['source_upstream']
vars['major'] = version['major']
ret[1] = vars
return ret
def process_relation(self, key, e, in_e, vars):
in_dep = in_e[key]
dep = package_relation_list()
for in_groups in in_dep:
groups = package_relation_group()
for in_item in in_groups:
item = package_relation()
item.name = self.substitute(in_item.name, vars)
if in_item.version is not None:
item.version = self.substitute(in_item.version, vars)
item.arches = in_item.arches
groups.append(item)
dep.append(groups)
e[key] = dep
def process_description(self, e, in_e, vars):
in_desc = in_e['Description']
desc = in_desc.__class__()
desc.short = self.substitute(in_desc.short, vars)
for i in in_desc.long:
desc.long.append(self.substitute(i, vars))
e['Description'] = desc
def process_package(self, in_entry, vars):
e = package()
for key, value in in_entry.iteritems():
if isinstance(value, package_relation_list):
self.process_relation(key, e, in_entry, vars)
elif key == 'Description':
self.process_description(e, in_entry, vars)
elif key[:2] == 'X-':
pass
else:
e[key] = self.substitute(value, vars)
return e
def process_packages(self, in_entries, vars):
entries = []
for i in in_entries:
entries.append(self.process_package(i, vars))
return entries
def substitute(self, s, vars):
if isinstance(s, (list, tuple)):
for i in xrange(len(s)):
s[i] = self.substitute(s[i], vars)
return s
def subst(match):
return vars[match.group(1)]
return re.sub(r'@([a-z_]+)@', subst, s)
def write_control(self, list):
self.write_rfc822(file("debian/control", 'w'), list)
def write_makefile(self, out_list):
out = file("debian/rules.gen", 'w')
for item in out_list:
if isinstance(item, (list, tuple)):
out.write("%s\n" % item[0])
cmd_list = item[1]
if isinstance(cmd_list, basestring):
cmd_list = cmd_list.split('\n')
for j in cmd_list:
out.write("\t%s\n" % j)
else:
out.write("%s\n" % item)
def write_rfc822(self, f, list):
for entry in list:
for key, value in entry.iteritems():
f.write("%s: %s\n" % (key, value))
f.write('\n')
if __name__ == '__main__':
gencontrol()()

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
linux-kbuild-2.6 (2.6.16-1) UNRELEASED; urgency=low
* Initial release.
-- Bastian Blank <waldi@debian.org> Mon, 27 Mar 2006 19:06:30 +0200

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
4

View File

@ -0,0 +1,3 @@
from debian import *
from utils import *

231
debian/lib/python/debian_linux/debian.py vendored Normal file
View File

@ -0,0 +1,231 @@
import itertools, os.path, re, utils
def read_changelog(dir = ''):
r = re.compile(r"""
^
(
(?P<header>
(?P<header_source>
\w[-+0-9a-z.]+
)
\
\(
(?P<header_version>
[^\(\)\ \t]+
)
\)
\s+
(?P<header_distribution>
[-0-9a-zA-Z]+
)
\;
)
)
""", re.VERBOSE)
f = file(os.path.join(dir, "debian/changelog"))
entries = []
act_upstream = None
while True:
line = f.readline()
if not line:
break
line = line.strip('\n')
match = r.match(line)
if not match:
continue
if match.group('header'):
e = {}
e['Distribution'] = match.group('header_distribution')
e['Source'] = match.group('header_source')
version = parse_version(match.group('header_version'))
e['Version'] = version
if act_upstream is None:
act_upstream = version['upstream']
elif version['upstream'] != act_upstream:
break
entries.append(e)
return entries
def parse_version(version):
version_re = ur"""
^
(?P<source>
(?P<parent>
\d+\.\d+\.\d+\+
)?
(?P<upstream>
(?P<version>
(?P<major>\d+\.\d+)
\.
\d+
)
(?:
-
(?P<modifier>
.+?
)
)?
)
-
(?P<debian>[^-]+)
)
$
"""
match = re.match(version_re, version, re.X)
if match is None:
raise ValueError
ret = match.groupdict()
if ret['parent'] is not None:
ret['source_upstream'] = ret['parent'] + ret['upstream']
else:
ret['source_upstream'] = ret['upstream']
return ret
class package_description(object):
__slots__ = "short", "long"
def __init__(self, value = None):
if value is not None:
self.short, long = value.split ("\n", 1)
self.long = long.split ("\n.\n")
else:
self.short = None
self.long = []
def __str__(self):
ret = self.short + '\n'
w = utils.wrap(width = 74, fix_sentence_endings = True)
pars = []
for i in self.long:
pars.append('\n '.join(w.wrap(i)))
return self.short + '\n ' + '\n .\n '.join(pars)
class package_relation(object):
__slots__ = "name", "version", "arches"
_re = re.compile(r'^(\S+)(?: \(([^)]+)\))?(?: \[([^]]+)\])?$')
def __init__(self, value = None):
if value is not None:
match = self._re.match(value)
if match is None:
raise RuntimeError, "Can't parse dependency %s" % value
match = match.groups()
self.name = match[0]
self.version = match[1]
if match[2] is not None:
self.arches = re.split('\s+', match[2])
else:
self.arches = []
else:
self.name = None
self.version = None
self.arches = []
def __str__(self):
ret = [self.name]
if self.version is not None:
ret.extend([' (', self.version, ')'])
if self.arches:
ret.extend([' [', ' '.join(self.arches), ']'])
return ''.join(ret)
class package_relation_list(list):
def __init__(self, value = None):
if isinstance(value, (list, tuple)):
self.extend(value)
elif value is not None:
self.extend(value)
def __str__(self):
return ', '.join([str(i) for i in self])
def _match(self, value):
for i in self:
if i._match(value):
return i
return None
def extend(self, value):
if isinstance(value, basestring):
value = [package_relation_group(j.strip()) for j in re.split(',', value.strip())]
for i in value:
if isinstance(i, basestring):
i = package_relation_group(i)
j = self._match(i)
if j:
j._update_arches(i)
else:
self.append(i)
class package_relation_group(list):
def __init__(self, value = None):
if isinstance(value, package_relation_list):
self.extend(value)
elif value is not None:
self._extend(value)
def __str__(self):
return ' | '.join([str(i) for i in self])
def _extend(self, value):
self.extend([package_relation(j.strip()) for j in re.split('\|', value.strip())])
def _match(self, value):
for i, j in itertools.izip(self, value):
if i.name != j.name or i.version != j.version:
return None
return self
def _update_arches(self, value):
for i, j in itertools.izip(self, value):
if i.arches:
for arch in j.arches:
if arch not in i.arches:
i.arches.append(arch)
class package(dict):
_fields = utils.sorted_dict((
('Package', str),
('Source', str),
('Architecture', utils.field_list),
('Section', str),
('Priority', str),
('Maintainer', str),
('Uploaders', str),
('Standards-Version', str),
('Build-Depends', package_relation_list),
('Build-Depends-Indep', package_relation_list),
('Provides', package_relation_list),
('Depends', package_relation_list),
('Recommends', package_relation_list),
('Suggests', package_relation_list),
('Replaces', package_relation_list),
('Conflicts', package_relation_list),
('Reverse-Depends', package_relation_list), # Some sort of hack
('Description', package_description),
))
def __setitem__(self, key, value):
try:
cls = self._fields[key]
if not isinstance(value, cls):
value = cls(value)
except KeyError: pass
super(package, self).__setitem__(key, value)
def iterkeys(self):
for i in self._fields.iterkeys():
if self.has_key(i) and self[i]:
yield i
def iteritems(self):
for i in self._fields.iterkeys():
if self.has_key(i) and self[i]:
yield (i, self[i])
def itervalues(self):
for i in self._fields.iterkeys():
if self.has_key(i) and self[i]:
yield self[i]

136
debian/lib/python/debian_linux/utils.py vendored Normal file
View File

@ -0,0 +1,136 @@
import debian, re, textwrap
class sorted_dict(dict):
__slots__ = '_list',
def __init__(self, entries = None):
super(sorted_dict, self).__init__()
self._list = []
if entries is not None:
for key, value in entries:
self[key] = value
def __delitem__(self, key):
super(sorted_dict, self).__delitem__(key)
self._list.remove(key)
def __setitem__(self, key, value):
super(sorted_dict, self).__setitem__(key, value)
if key not in self._list:
self._list.append(key)
def iterkeys(self):
for i in iter(self._list):
yield i
def iteritems(self):
for i in iter(self._list):
yield (i, self[i])
def itervalues(self):
for i in iter(self._list):
yield self[i]
class field_list(list):
TYPE_WHITESPACE = object()
TYPE_COMMATA = object()
def __init__(self, value = None, type = TYPE_WHITESPACE):
self.type = type
if isinstance(value, field_list):
self.type = value.type
self.extend(value)
elif isinstance(value, (list, tuple)):
self.extend(value)
else:
self._extend(value)
def __str__(self):
if self.type is self.TYPE_WHITESPACE:
type = ' '
elif self.type is self.TYPE_COMMATA:
type = ', '
return type.join(self)
def _extend(self, value):
if self.type is self.TYPE_WHITESPACE:
type = '\s'
elif self.type is self.TYPE_COMMATA:
type = ','
if value is not None:
self.extend([j.strip() for j in re.split(type, value.strip())])
def extend(self, value):
if isinstance(value, str):
self._extend(value)
else:
super(field_list, self).extend(value)
class field_list_commata(field_list):
def __init__(self, value = None):
super(field_list_commata, self).__init__(value, field_list.TYPE_COMMATA)
class field_string(str):
def __str__(self):
return '\n '.join(self.split('\n'))
class templates(dict):
def __init__(self, dir = None):
if dir is None:
self.dir = "debian/templates"
else:
self.dir = dir
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError: pass
ret = self._read(key)
dict.__setitem__(self, key, ret)
return ret
def __setitem__(self, key, value):
raise NotImplemented()
def _read(self, filename):
entries = []
f = file("%s/%s.in" % (self.dir, filename))
while True:
e = debian.package()
last = None
lines = []
while True:
line = f.readline()
if not line:
break
line = line.strip('\n')
if not line:
break
if line[0] in ' \t':
if not last:
raise ValueError('Continuation line seen before first header')
lines.append(line.lstrip())
continue
if last:
e[last] = '\n'.join(lines)
i = line.find(':')
if i < 0:
raise ValueError("Not a header, not a continuation: ``%s''" % line)
last = line[:i]
lines = [line[i+1:].lstrip()]
if last:
e[last] = '\n'.join(lines)
if not e:
break
entries.append(e)
return entries
class wrap(textwrap.TextWrapper):
wordsep_re = re.compile(
r'(\s+|' # any whitespace
r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash

73
debian/rules vendored Executable file
View File

@ -0,0 +1,73 @@
#!/usr/bin/make -f
SHELL := sh -e
DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH)
DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH)
srcver := $(shell dpkg-parsechangelog | awk '/^Version:/ {print $$2}')
VERSION := $(shell echo $(srcver) | sed -e 's,-[^-]*$$,,')
MAJOR := $(word 1,$(subst ., ,$(VERSION))).$(word 2,$(subst ., ,$(VERSION)))
include debian/rules.defs
build: debian/control $(STAMPS_DIR)/build-base
$(STAMPS_DIR)/build-base: $(BUILD_DIR) $(STAMPS_DIR)
dh_testdir
$(MAKE) -f debian/rules.gen build
touch $@
$(BUILD_DIR) $(STAMPS_DIR):
@[ -d $@ ] || mkdir $@
orig: ../orig/linux-kbuild-$(MAJOR)-$(VERSION)
rsync --delete --exclude debian --exclude .svn --link-dest=$^/ -av $^/ .
../orig/linux-kbuild-$(MAJOR)-$(VERSION):
if [ -f "../linux-kbuild-$(MAJOR)_$(VERSION).orig.tar.gz" ]; then \
mkdir -p ../orig; \
tar -C ../orig -xzf ../linux-kbuild-$(MAJOR)_$(VERSION).orig.tar.gz; \
else \
echo "Can't find orig tarball." >&2; \
exit 1; \
fi
maintainerclean:
-rm debian/control debian/control.md5sum debian/rules.gen
-rm -rf scripts
clean: debian/control
dh_testdir
rm -rf $(BUILD_DIR) $(STAMPS_DIR) debian/lib/python/debian_linux/*.pyc
dh_clean
binary-indep:
dh_testdir
$(MAKE) -f debian/rules.gen binary-indep
binary-arch:
dh_testdir
$(MAKE) -f debian/rules.gen binary-arch
binary: binary-indep binary-arch
CONTROL_FILES = debian/changelog $(wildcard debian/templates/control.*)
debian/control debian/rules.gen: debian/bin/gencontrol.py $(CONTROL_FILES)
if [ -f debian/control.md5sum ]; then \
if md5sum $^ | diff - debian/control.md5sum > /dev/null; then true; else \
$(MAKE) -f debian/rules debian/control-real; \
fi \
else \
$(MAKE) -f debian/rules debian/control-real; \
fi
debian/control-real: debian/bin/gencontrol.py $(CONTROL_FILES)
chmod +x $<
$<
md5sum $^ > debian/control.md5sum
@echo
@echo This target is made to fail intentionally, to make sure
@echo that it is NEVER run during the automated build. Please
@echo ignore the following error, the debian/control file has
@echo been generated SUCCESSFULLY.
@echo
exit 1
.PHONY: clean build setup binary-indep binary-arch binary

4
debian/rules.defs vendored Normal file
View File

@ -0,0 +1,4 @@
BUILD_DIR = debian/build
STAMPS_DIR = debian/stamps
TEMPLATES_DIR = debian/templates

37
debian/rules.real vendored Normal file
View File

@ -0,0 +1,37 @@
export DH_OPTIONS
include debian/rules.defs
binary-arch: install-kbuild
build: $(STAMPS_DIR)/build
$(STAMPS_DIR)/build: DIR=$(BUILD_DIR)/build
$(STAMPS_DIR)/build:
rm -rf '$(DIR)'
mkdir -p '$(DIR)'
cp -al src/* '$(DIR)'
make -C $(DIR) top_srcdir=$(CURDIR)
touch '$@'
install-kbuild: PACKAGE_NAME = linux-kbuild-$(VERSION)
install-kbuild: DH_OPTIONS = -p$(PACKAGE_NAME)
install-kbuild: BASE_DIR = /usr/src/$(PACKAGE_NAME)
install-kbuild: SOURCE_DIR = $(BUILD_DIR)/build
install-kbuild: DIR = $(CURDIR)/debian/$(PACKAGE_NAME)/$(BASE_DIR)
install-kbuild: $(STAMPS_DIR)/build
dh_testdir
dh_testroot
dh_clean -k -d
make -C $(SOURCE_DIR) install prefix=$(DIR) top_srcdir=$(CURDIR)
dh_installchangelogs
dh_installdocs
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb

7
debian/templates/control.main.in vendored Normal file
View File

@ -0,0 +1,7 @@
Package: linux-kbuild-@version@
Architecture: any
Section: devel
Priority: optional
Provides: linux-kbuild, linux-kbuild-@major@
Description: Linux kernel
Kbuild

7
debian/templates/control.source.in vendored Normal file
View File

@ -0,0 +1,7 @@
Source: linux-kbuild-@major@
Section: devel
Priority: optional
Maintainer: Debian Kernel Team <debian-kernel@lists.debian.org>
Uploaders: Bastian Blank <waldi@debian.org>
Standards-Version: 3.6.2.0
Build-Depends: debhelper (>= 4.1.0)

56
src/Makefile Normal file
View File

@ -0,0 +1,56 @@
include Makefile.inc
PROGS = \
bin2c \
conmakehash \
kallsyms \
pnmtologo
SCRIPTS = \
checkconfig.pl \
checkincludes.pl \
checkstack.pl \
checkversion.pl \
gcc-version.sh \
gen_initramfs_list.sh \
Kbuild.include \
kernel-doc \
Lindent \
Makefile.build \
Makefile.clean \
Makefile.host \
Makefile.lib \
Makefile.modinst \
Makefile.modpost \
makelst \
mksysmap \
mkuboot.sh \
mkversion \
namespace.pl \
patch-kernel \
reference_discarded.pl \
reference_init.pl \
setlocalversion \
show_delta \
ver_linux
SUBDIRS = \
basic \
genksyms \
kconfig \
mod
VPATH = $(top_srcdir)/scripts
all-local: $(PROGS)
install-local: $(PROGS)
@list='$(PROGS)'; for p in $$list; do \
echo " install -D '$$p' '$(prefix)/scripts/$$p'"; \
install -D "$$p" "$(prefix)/scripts/$$p"; \
done
@list='$(SCRIPTS)'; for p in $$list; do \
echo " install -D '$(top_srcdir)/scripts/$$p' '$(prefix)/scripts/$$p'"; \
install -D "$(top_srcdir)/scripts/$$p" "$(prefix)/scripts/$$p"; \
done

17
src/Makefile.inc Normal file
View File

@ -0,0 +1,17 @@
CC = gcc
CXX = g++
CFLAGS = -Wall -W -O2
CXXFLAGS = $(CFLAGS)
all: all-local all-recursive
install: install-local install-recursive
all-recursive install-recursive:
@target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
$(MAKE) -C $$subdir $$target \
|| exit 1; \
done

17
src/basic/Makefile Normal file
View File

@ -0,0 +1,17 @@
include ../Makefile.inc
PROGS = \
docproc \
fixdep \
split-include
VPATH = $(top_srcdir)/scripts/basic
all-local: $(PROGS)
install-local: $(PROGS)
@list='$(PROGS)'; for p in $$list; do \
echo " install -D '$$p' '$(prefix)/scripts/basic/$$p'"; \
install -D "$$p" "$(prefix)/scripts/basic/$$p"; \
done

25
src/genksyms/Makefile Normal file
View File

@ -0,0 +1,25 @@
include ../Makefile.inc
PROGS = genksyms
VPATH = $(top_srcdir)/scripts/genksyms
CFLAGS += -I$(top_srcdir)/scripts/genksyms
all-local: $(PROGS)
install-local: $(PROGS)
@list='$(PROGS)'; for p in $$list; do \
echo " install -D '$$p' '$(prefix)/scripts/genksyms/$$p'"; \
install -D "$$p" "$(prefix)/scripts/genksyms/$$p"; \
done
genksyms: genksyms.o parse.o lex.o
lex.o: keywords.c parse.h
%.c: %.c_shipped
ln -s $< $@
%.h: %.h_shipped
ln -s $< $@

25
src/kconfig/Makefile Normal file
View File

@ -0,0 +1,25 @@
include ../Makefile.inc
PROGS = conf
VPATH = $(top_srcdir)/scripts/kconfig
CFLAGS += -I$(top_srcdir)/scripts/kconfig
all-local: $(PROGS)
install-local: $(PROGS)
@list='$(PROGS)'; for p in $$list; do \
echo " install -D '$$p' '$(prefix)/scripts/kconfig/$$p'"; \
install -D "$$p" "$(prefix)/scripts/kconfig/$$p"; \
done
conf: conf.o zconf.tab.o
zconf.tab.c: zconf.hash.c lex.zconf.c
%.c: %.c_shipped
ln -s $< $@
%.h: %.h_shipped
ln -s $< $@

17
src/mod/Makefile Normal file
View File

@ -0,0 +1,17 @@
include ../Makefile.inc
PROGS = modpost
all-local: $(PROGS)
install-local: $(PROGS)
@list='$(PROGS)'; for p in $$list; do \
echo " install -D '$$p' '$(prefix)/scripts/mod/$$p'"; \
install -D "$$p" "$(prefix)/scripts/mod/$$p"; \
done
modpost: elf.o modpost.o module.o module_devicetable.o module_devicetable_impl_2_6_16.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
%.o: %.cpp %.hpp endian.hpp

243
src/mod/elf.cpp Normal file
View File

@ -0,0 +1,243 @@
/*
* elf.cpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "elf.hpp"
#include "endian.hpp"
#include <stdexcept>
#include <fcntl.h>
#include <elf.h>
#include <sys/mman.h>
#include <sys/stat.h>
using namespace Elf;
namespace
{
template <typename _class>
struct _elfdef
{ };
template <>
struct _elfdef<file_class_32>
{
typedef Elf32_Ehdr Ehdr;
typedef Elf32_Shdr Shdr;
typedef Elf32_Sym Sym;
static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF32_ST_BIND (st_info); }
static inline uint8_t st_type (uint8_t st_info) throw () { return ELF32_ST_TYPE (st_info); }
};
template <>
struct _elfdef<file_class_64>
{
typedef Elf64_Ehdr Ehdr;
typedef Elf64_Shdr Shdr;
typedef Elf64_Sym Sym;
static inline uint8_t st_bind (uint8_t st_info) throw () { return ELF64_ST_BIND (st_info); }
static inline uint8_t st_type (uint8_t st_info) throw () { return ELF64_ST_TYPE (st_info); }
};
}
file::file (const char *filename, void *mem, size_t len) throw (std::bad_alloc)
: filename (std::string (filename)), mem (mem), len (len)
{ }
file::~file () throw ()
{
::munmap (mem, len);
for (std::vector<section *>::iterator it = sections.begin (); it != sections.end (); ++it)
delete *it;
}
file *file::open (const char *filename) throw (std::bad_alloc, std::runtime_error)
{
struct stat buf;
int fd;
void *mem;
size_t len;
if ((fd = ::open (filename, O_RDONLY)) == -1)
throw std::runtime_error ("mapping failed");
try
{
if (::fstat (fd, &buf) == -1)
throw std::runtime_error ("mapping failed");
len = buf.st_size;
if ((mem = ::mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
throw std::runtime_error ("mapping failed");
const uint8_t *buf = static_cast <uint8_t *> (mem);
switch (buf[EI_CLASS])
{
case ELFCLASS32:
return open_class<file_class_32> (filename, buf, mem, len);
case ELFCLASS64:
return open_class<file_class_64> (filename, buf, mem, len);
default:
throw std::runtime_error ("Invalid file class");
}
}
catch (...)
{
::close (fd);
throw;
}
}
template<typename _class>
file *file::open_class (const char *filename, const uint8_t *buf, void * mem, size_t len) throw (std::bad_alloc, std::runtime_error)
{
switch (buf[EI_DATA])
{
case ELFDATA2LSB:
return new file_data<_class, file_data_2LSB> (filename, mem, len);
case ELFDATA2MSB:
return new file_data<_class, file_data_2MSB> (filename, mem, len);
default:
throw std::runtime_error ("Invalid file data");
}
}
template <typename _class, typename _data>
file_data<_class, _data>::file_data (const char *filename) throw (std::bad_alloc, std::runtime_error)
: file (filename)
{
construct ();
}
template <typename _class, typename _data>
file_data<_class, _data>::file_data (const char *filename, void *mem, size_t len) throw (std::bad_alloc, std::runtime_error)
: file (filename, mem, len)
{
construct ();
}
template <typename _class, typename _data>
void file_data<_class, _data>::construct () throw (std::bad_alloc, std::runtime_error)
{
uint8_t *buf = static_cast <uint8_t *> (this->mem);
if (buf[EI_CLASS] != _class::id)
throw std::runtime_error ("Wrong file class");
if (buf[EI_DATA] != _data::id)
throw std::runtime_error ("Wrong data encoding");
typedef typename _elfdef<_class>::Ehdr Ehdr;
Ehdr *ehdr = static_cast <Ehdr *> (this->mem);
this->type = convert<_data, typeof (ehdr->e_type )> () (ehdr->e_type );
this->machine = convert<_data, typeof (ehdr->e_machine )> () (ehdr->e_machine );
this->shoff = convert<_data, typeof (ehdr->e_shoff )> () (ehdr->e_shoff );
this->shnum = convert<_data, typeof (ehdr->e_shnum )> () (ehdr->e_shnum );
this->shstrndx = convert<_data, typeof (ehdr->e_shstrndx)> () (ehdr->e_shstrndx);
typedef typename _elfdef<_class>::Shdr Shdr;
Shdr *shdrs = static_cast <Shdr *> (static_cast <void *> (static_cast <char *> (this->mem) + this->shoff));
this->sections.reserve (this->shnum);
for (unsigned int i = 0; i < this->shnum; i++)
{
section *temp;
switch (convert<_data, typeof (shdrs[i].sh_type)> () (shdrs[i].sh_type))
{
case section_type_SYMTAB::id:
temp = new section_real<_class, _data, section_type_SYMTAB> (&shdrs[i], this->mem);
break;
default:
temp = new section_real<_class, _data, section_type_UNDEFINED> (&shdrs[i], this->mem);
break;
}
this->sections.push_back (temp);
}
for (unsigned int i = 0; i < this->shnum; i++)
this->sections[i]->update_string_table (this);
}
void section::update_string_table (file *file) throw (std::bad_alloc)
{
const section *section = file->get_section (file->get_shstrndx ());
this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
}
template <typename _class, typename _data>
section_data<_class, _data>::section_data (void *header, void *mem) throw ()
{
typedef typename _elfdef<_class>::Shdr Shdr;
Shdr *shdr = static_cast <Shdr *> (header);
this->name = convert<_data, typeof (shdr->sh_name )> () (shdr->sh_name );
this->type = convert<_data, typeof (shdr->sh_type )> () (shdr->sh_type );
this->offset = convert<_data, typeof (shdr->sh_offset)> () (shdr->sh_offset);
this->size = convert<_data, typeof (shdr->sh_size )> () (shdr->sh_size );
this->link = convert<_data, typeof (shdr->sh_link )> () (shdr->sh_link );
this->mem = static_cast <void *> (static_cast <char *> (mem) + this->offset);
}
section_type<section_type_SYMTAB>::~section_type () throw ()
{
for (std::vector<symbol *>::iterator it = symbols.begin (); it != symbols.end (); ++it)
delete *it;
}
void section_type<section_type_SYMTAB>::update_string_table (file *file) throw (std::bad_alloc)
{
section::update_string_table (file);
for (unsigned int i = 0; i < symbols.size (); i++)
this->symbols[i]->update_string_table (file, link);
}
template <typename _class, typename _data>
section_real<_class, _data, section_type_SYMTAB>::section_real (void *header, void *mem) throw (std::bad_alloc)
: section_data<_class, _data> (header, mem)
{
if (this->type != SHT_SYMTAB)
throw std::logic_error ("Wrong section type");
typedef typename _elfdef<_class>::Sym Sym;
Sym *syms = static_cast <Sym *> (this->mem);
unsigned int max = this->size / sizeof (Sym);
this->symbols.reserve (max);
for (unsigned int i = 0; i < max; i++)
this->symbols.push_back (new symbol_data<_class, _data> (&syms[i]));
}
template <typename _class, typename _data>
symbol_data<_class, _data>::symbol_data (void *mem) throw ()
{
typedef typename _elfdef<_class>::Sym Sym;
Sym *sym = static_cast <Sym *> (mem);
this->name = convert<_data, typeof (sym->st_name )> () (sym->st_name);
this->info = convert<_data, typeof (sym->st_info )> () (sym->st_info);
this->shndx = convert<_data, typeof (sym->st_shndx)> () (sym->st_shndx);
this->value = convert<_data, typeof (sym->st_value)> () (sym->st_value);
this->size = convert<_data, typeof (sym->st_size )> () (sym->st_size);
this->bind = _elfdef<_class>::st_bind (this->info);
this->type = _elfdef<_class>::st_type (this->info);
}
template <typename _class, typename _data>
void symbol_data<_class, _data>::update_string_table (file *file, uint16_t s) throw (std::bad_alloc)
{
const section *section = file->get_section (s);
this->name_string = std::string (static_cast <const char *> (section->_mem ()) + this->name);
}

219
src/mod/elf.hpp Normal file
View File

@ -0,0 +1,219 @@
/*
* elf.hpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ELF_HPP
#define ELF_HPP
#include "endian.hpp"
#include <stdexcept>
#include <string>
#include <vector>
#include <stdint.h>
namespace Elf
{
class file_class_32 { public: static const unsigned int id = 1; };
class file_class_64 { public: static const unsigned int id = 2; };
class file_data_2LSB { public: static const unsigned int id = 1; };
class file_data_2MSB { public: static const unsigned int id = 2; };
class section_type_UNDEFINED { };
class section_type_SYMTAB { public: static const unsigned int id = 2; };
class section;
class file
{
public:
virtual ~file () throw ();
virtual const uint8_t get_class () const throw () = 0;
virtual const uint8_t get_data () const throw () = 0;
const uint16_t get_type () const throw () { return type; }
const uint16_t get_machine () const throw () { return machine; }
const uint16_t get_shstrndx () const throw () { return shstrndx; }
const std::vector <section *> get_sections () const throw () { return sections; };
const section *get_section (unsigned int i) const throw (std::out_of_range) { return sections.at(i); };
const void *const _mem () const throw () { return mem; }
static file *open (const char *filename) throw (std::bad_alloc, std::runtime_error);
protected:
file (const char *, void *, size_t len) throw (std::bad_alloc);
template<typename _class>
static file *open_class (const char *, const uint8_t *, void *, size_t) throw (std::bad_alloc, std::runtime_error);
uint16_t type;
uint16_t machine;
uint64_t shoff;
uint16_t shnum;
uint16_t shstrndx;
std::vector <section *> sections;
const std::string filename;
void *mem;
size_t len;
};
template <typename _class, typename _data>
class file_data : public file
{
public:
file_data (const char *) throw (std::bad_alloc, std::runtime_error);
file_data (const char *, void *, size_t len) throw (std::bad_alloc, std::runtime_error);
const uint8_t get_class () const throw () { return _class::id; }
const uint8_t get_data () const throw () { return _data::id; }
private:
void construct () throw (std::bad_alloc, std::runtime_error);
};
class section
{
public:
virtual ~section () throw () {}
uint32_t get_type () const throw () { return type; }
uint64_t get_size () const throw () { return size; }
const std::string &get_name_string () const throw () { return name_string; }
const void *const _mem () const throw () { return mem; }
virtual void update_string_table (file *) throw (std::bad_alloc);
protected:
uint32_t name;
uint32_t type;
uint64_t offset;
uint64_t size;
uint32_t link;
std::string name_string;
void *mem;
};
template <typename _class, typename _data>
class section_data : public virtual section
{
public:
section_data (void *, void *) throw ();
};
template <typename _type>
class section_type : public virtual section
{
};
class symbol;
template <>
class section_type<section_type_SYMTAB> : public virtual section
{
public:
~section_type () throw ();
const std::vector<symbol *> &get_symbols () throw () { return symbols; }
void update_string_table (file *) throw (std::bad_alloc);
protected:
std::vector<symbol *> symbols;
};
template <typename _class, typename _data, typename _type>
class section_real : public section_data<_class, _data>, public section_type<_type>
{
public:
section_real (void *, void *) throw ();
};
template <typename _class, typename _data>
class section_real<_class, _data, section_type_UNDEFINED> : public section_data<_class, _data>, public section_type<section_type_UNDEFINED>
{
public:
section_real (void *a, void *b) throw () : section_data<_class, _data> (a, b) { }
};
template <typename _class, typename _data>
class section_real<_class, _data, section_type_SYMTAB> : public section_data<_class, _data>, public section_type<section_type_SYMTAB>
{
public:
section_real (void *, void *) throw (std::bad_alloc);
};
class symbol
{
public:
virtual ~symbol () throw () {}
uint8_t get_info () const throw () { return info; }
uint16_t get_shndx () const throw () { return shndx; }
uint64_t get_value () const throw () { return value; }
uint64_t get_size () const throw () { return size; }
uint8_t get_bind () const throw () { return bind; }
uint8_t get_type () const throw () { return type; }
const std::string &get_name_string () const throw () { return name_string; }
virtual void update_string_table (file *, uint16_t) throw (std::bad_alloc) = 0;
protected:
uint32_t name;
uint8_t info;
uint16_t shndx;
uint64_t value;
uint64_t size;
uint8_t bind;
uint8_t type;
std::string name_string;
};
template <typename _class, typename _data>
class symbol_data : public symbol
{
public:
symbol_data (void *) throw ();
void update_string_table (file *, uint16_t) throw (std::bad_alloc);
protected:
};
template <typename from, typename type>
struct convert
{ };
template <typename type>
struct convert<file_data_2LSB, type> : public endian::convert<endian::little_endian, type>
{ };
template <typename type>
struct convert<file_data_2MSB, type> : public endian::convert<endian::big_endian, type>
{ };
}
#endif

138
src/mod/endian.hpp Normal file
View File

@ -0,0 +1,138 @@
/*
* endian.hpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef ENDIAN_HPP
#define ENDIAN_HPP
#include <endian.h>
#include <stdint.h>
namespace endian
{
class little_endian
{ };
class big_endian
{ };
#if __BYTE_ORDER == __LITTLE_ENDIAN
typedef little_endian host_endian;
#elif __BYTE_ORDER == __BIG_ENDIAN
typedef big_endian host_endian;
#endif
template <typename type>
struct convert_nop
{
inline type operator () (const type &in) const throw () { return in; }
};
template <typename type>
struct convert_simple
{ };
template <>
struct convert_simple<uint8_t> : public convert_nop<uint8_t>
{ };
template <>
struct convert_simple<uint16_t>
{
inline uint16_t operator () (const uint16_t &in) const throw ()
{
return (in & 0x00ffU) << 8 |
(in & 0xff00U) >> 8;
}
};
template <>
struct convert_simple<uint32_t>
{
inline uint32_t operator () (const uint32_t &in) const throw ()
{
return (in & 0x000000ffU) << 24 |
(in & 0xff000000U) >> 24 |
(in & 0x0000ff00U) << 8 |
(in & 0x00ff0000U) >> 8;
}
};
template <>
struct convert_simple<uint64_t>
{
inline uint64_t operator () (const uint64_t &in) const throw ()
{
return (in & 0x00000000000000ffULL) << 56 |
(in & 0xff00000000000000ULL) >> 56 |
(in & 0x000000000000ff00ULL) << 40 |
(in & 0x00ff000000000000ULL) >> 40 |
(in & 0x0000000000ff0000ULL) << 24 |
(in & 0x0000ff0000000000ULL) >> 24 |
(in & 0x00000000ff000000ULL) << 8 |
(in & 0x000000ff00000000ULL) >> 8;
}
};
template <>
struct convert_simple<const uint8_t> : public convert_simple<uint8_t>
{ };
template <>
struct convert_simple<const uint16_t> : public convert_simple<uint16_t>
{ };
template <>
struct convert_simple<const uint32_t> : public convert_simple<uint32_t>
{ };
template <typename from, typename to, typename type>
struct convert_complete
{ };
template <typename type>
struct convert_complete<little_endian, little_endian, type> : public convert_nop<type>
{ };
template <typename type>
struct convert_complete<little_endian, big_endian, type> : public convert_simple<type>
{ };
template <typename type>
struct convert_complete<big_endian, big_endian, type> : public convert_nop<type>
{ };
template <typename type>
struct convert_complete<big_endian, little_endian, type> : public convert_simple<type>
{ };
template <typename from, typename type>
struct convert
{ };
template <typename type>
struct convert<little_endian, type> : public convert_complete<little_endian, host_endian, type>
{ };
template <typename type>
struct convert<big_endian, type> : public convert_complete<big_endian, host_endian, type>
{ };
}
#endif

84
src/mod/modpost.cpp Normal file
View File

@ -0,0 +1,84 @@
/*
* modpost.cpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "elf.hpp"
#include "module.hpp"
#include <iostream>
#include <getopt.h>
using namespace linuxkernel;
modulelist modules;
int main (int argc, char *const argv[])
{
int ret = EXIT_SUCCESS;
int opt;
const char *dump_read = 0, *dump_write = 0;
bool all_versions = false, modversions = false;;
while ((opt = getopt (argc, argv, "ai:mo:")) != -1)
{
switch(opt) {
case 'a':
all_versions = true;
std::clog << "*** Warning: CONFIG_MODULE_SRCVERSION_ALL is not supported!" << std::endl;
return EXIT_FAILURE;
break;
case 'i':
dump_read = optarg;
break;
case 'm':
modversions = true;
break;
case 'o':
dump_write = optarg;
break;
default:
exit(1);
}
}
if (dump_read)
modules.dump_read (dump_read);
for (int i = optind; i < argc; i++)
{
std::string filename (argv[i]);
try
{
modules.insert (filename);
}
catch (std::runtime_error &e)
{
std::clog << "*** Warning: \"" << filename << "\" failed to load: " << e.what () << std::endl;
ret = EXIT_FAILURE;
continue;
}
}
modules.write (modversions);
if (dump_write)
modules.dump_write (dump_write);
return ret;
}

469
src/mod/module.cpp Normal file
View File

@ -0,0 +1,469 @@
/*
* module.cpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "module.hpp"
#include <fstream>
#include <iostream>
#include <sstream>
#include <set>
#include <elf.h>
using namespace linuxkernel;
const std::string module_real::symbol_name_cleanup ("cleanup_module");
const std::string module_real::symbol_name_init ("init_module");
const std::string module_real::symbol_prefix_crc ("__crc_");
const std::string module_real::symbol_prefix_ksymtab ("__ksymtab_");
module::module (const std::string &name) throw ()
: name (name)
{
std::string::size_type t1 = name.find_last_of ('/');
if (t1 == std::string::npos)
t1 = 0;
else
t1++;
name_short = name.substr (t1, std::string::npos);
if (name == "vmlinux")
is_vmlinux = true;
}
module::module (const std::string &filename, bool) throw ()
{
std::string::size_type t1 = filename.find_last_of ('/');
std::string::size_type t2 = filename.find_last_of ('.');
if (t1 == std::string::npos)
t1 = 0;
else
t1++;
name = filename.substr (0, t2);
if (t2 != std::string::npos)
t2 -= t1;
name_short = filename.substr (t1, t2);
if (name == "vmlinux")
is_vmlinux = true;
}
module_real::module_real (const std::string &filename, Elf::file *file) throw (std::runtime_error)
: module (filename, false), has_init (false), has_cleanup (false), file (file)
{
const std::vector <Elf::section *> &sections = file->get_sections ();
Elf::section *modinfo = 0;
symtab = 0;
for (std::vector <Elf::section *>::const_iterator it = sections.begin (); it != sections.end (); ++it)
{
const std::string &name = (*it)->get_name_string ();
uint32_t type = (*it)->get_type ();
if (name == ".modinfo")
modinfo = *it;
if (type == Elf::section_type_SYMTAB::id)
symtab = dynamic_cast <Elf::section_type<Elf::section_type_SYMTAB> *> (*it);
}
if (!is_vmlinux && !modinfo)
throw std::runtime_error ("Not a kernel module, lacks modinfo section");
if (!symtab)
throw std::runtime_error ("Not a kernel module, lacks symbol table");
if (!is_vmlinux)
{
read_modinfo (modinfo);
symbols_undefined.insert (std::pair<std::string, symbol_undefined> ("struct_module", symbol_undefined ("struct_module", 0)));
}
read_symtab (symtab);
}
const Elf::symbol *module_real::_get_symbol (const std::string &name) const throw ()
{
for (std::vector<Elf::symbol *>::const_iterator it = symtab->get_symbols ().begin (); it != symtab->get_symbols ().end (); ++it)
{
Elf::symbol *symbol = *it;
std::string symname = symbol->get_name_string ();
if (symname == name)
return symbol;
}
return 0;
}
void module_real::write (const modulelist &list, bool modversions)
{
std::string filename = name + ".mod.c";
std::ofstream out (filename.c_str ());
write_header (out);
if (modversions)
write_versions (out, list);
write_depends (out, list);
write_moddevtable (out);
}
module_real *module_real::open (const std::string &filename) throw (std::bad_alloc, std::runtime_error)
{
Elf::file *file = Elf::file::open (filename.c_str ());
switch (file->get_class ())
{
case Elf::file_class_32::id:
return open_class<Elf::file_class_32> (filename, file);
case Elf::file_class_64::id:
return open_class<Elf::file_class_64> (filename, file);
default:
throw std::runtime_error ("Unsupported file class");
}
}
template<typename Elf_class>
module_real *module_real::open_class (const std::string &filename, Elf::file *file) throw (std::bad_alloc, std::runtime_error)
{
switch (file->get_data ())
{
case Elf::file_data_2LSB::id:
return new module_data<Elf_class, Elf::file_data_2LSB> (filename, file);
case Elf::file_data_2MSB::id:
return new module_data<Elf_class, Elf::file_data_2MSB> (filename, file);
default:
throw std::runtime_error ("Unsupported data encoding");
}
}
void module_real::read_modinfo (Elf::section *section) throw (std::runtime_error)
{
const char *act, *end, *temp1, *temp2;
act = static_cast <const char *> (section->_mem ());
end = act + section->get_size ();
while (act <= end)
{
temp1 = act;
for (; *act && *act != '=' && act <= end; act++);
if (act > end)
break;
temp2 = ++act;
for (; *act && act <= end; act++);
if (act > end)
break;
modinfo.insert (std::pair<std::string, std::string> (std::string (temp1, temp2 - temp1 - 1), std::string (temp2, act - temp2)));
for (; !*act && act <= end; act++);
}
}
void module_real::read_symtab (Elf::section_type<Elf::section_type_SYMTAB> *section) throw (std::runtime_error)
{
for (std::vector<Elf::symbol *>::const_iterator it = section->get_symbols ().begin (); it != section->get_symbols ().end (); ++it)
{
Elf::symbol *symbol = *it;
std::string symname = symbol->get_name_string ();
switch (symbol->get_shndx ())
{
case SHN_COMMON:
std::clog << "*** Warning: \"" << symname << "\" [" << name << "] is COMMON symbol" << std::endl;
break;
case SHN_ABS:
if (symname.compare (0, symbol_prefix_crc.size (), symbol_prefix_crc) == 0)
{
std::string symname_real (symname.substr (symbol_prefix_crc.size ()));
std::map<std::string, symbol_exported>::iterator it = symbols_exported.find (symname_real);
if (it == symbols_exported.end ())
symbols_exported.insert (std::pair<std::string, symbol_exported> (symname_real, symbol_exported (symname_real, symbol->get_value ())));
else
it->second.set_crc (symbol->get_value ());
}
break;
case SHN_UNDEF:
if (symbol->get_bind () != STB_GLOBAL &&
symbol->get_bind () != STB_WEAK)
break;
//FIXME: if (symbol->get_type () == STT_REGISTER)
// break;
/* ignore global offset table */
if (symname == "_GLOBAL_OFFSET_TABLE_")
break;
/* ignore __this_module, it will be resolved shortly */
if (symname == "__this_module")
break;
symbols_undefined.insert (std::pair<std::string, symbol_undefined> (symname, symbol_undefined (symname, symbol->get_bind () == STB_WEAK)));
break;
default:
if (symname.compare (0, symbol_prefix_ksymtab.size (), symbol_prefix_ksymtab) == 0)
{
std::string symname_real (symname.substr (symbol_prefix_ksymtab.size ()));
std::map<std::string, symbol_exported>::iterator it = symbols_exported.find (symname_real);
if (it == symbols_exported.end ())
symbols_exported.insert (std::pair<std::string, symbol_exported> (symname_real, symbol_exported (symname_real)));
}
else if (symname == symbol_name_cleanup)
has_cleanup = true;
else if (symname == symbol_name_init)
has_init = true;
break;
};
}
}
void module_real::write_depends (std::ostream &out, const modulelist &list)
{
std::set<std::string> depends;
for (std::map<std::string, symbol_undefined>::const_iterator it = symbols_undefined.begin (); it != symbols_undefined.end (); ++it)
{
try
{
const std::string &mod (list.get_module_name_short_for_symbol (it->first));
if (mod != "vmlinux")
depends.insert (mod);
}
catch (std::out_of_range &)
{ }
}
out <<
"static const char __module_depends[]\n"
"__attribute_used__\n"
"__attribute__((section(\".modinfo\"))) =\n"
"\"depends=";
if (depends.begin () != depends.end ())
{
std::set<std::string>::const_iterator it = depends.begin ();
out << *it;
for (++it; it != depends.end (); ++it)
out << ',' << *it;
}
out << "\";\n\n";
}
void module_real::write_header (std::ostream &out)
{
out <<
"#include <linux/module.h>\n"
"#include <linux/vermagic.h>\n"
"#include <linux/compiler.h>\n"
"\n"
"MODULE_INFO(vermagic, VERMAGIC_STRING);\n"
"\n"
"struct module __this_module\n"
"__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"
" .name = KBUILD_MODNAME,\n";
if (has_init)
out << " .init = init_module,\n";
if (has_cleanup)
out <<
"#ifdef CONFIG_MODULE_UNLOAD\n"
" .exit = cleanup_module,\n"
"#endif\n";
out << "};\n\n";
}
void module_real::write_moddevtable (std::ostream &out)
{
for (std::list<module_devicetable::table_base *>::iterator it = devicetables.begin (); it != devicetables.end (); ++it)
{
module_devicetable::table_base *ent = *it;
if (ent)
ent->write (out);
}
}
void module_real::write_versions (std::ostream &out, const modulelist &list)
{
out <<
"static const struct modversion_info ____versions[]\n"
"__attribute_used__\n"
"__attribute__((section(\"__versions\"))) = {\n";
for (_symbols_undefined::const_iterator it = symbols_undefined.begin (); it != symbols_undefined.end (); ++it)
{
try
{
const symbol_exported &sym (list.get_symbol (it->first));
if (sym.get_crc_valid ())
out << "\t{ 0x" << std::hex << sym.get_crc () << std::dec << ", \"" << it->first << "\" },\n";
else
std::clog << "*** Warning: \"" << sym.get_name () << "\" [" << name << "] has no CRC!" << std::endl;
}
catch (std::out_of_range &)
{
if (list.report_symbols_missing)
std::clog << "*** Warning: \"" << it->first << "\" is undefined!" << std::endl;
}
}
out << "};\n\n";
}
template <typename Elf_class, typename Elf_data>
module_data<Elf_class, Elf_data>::module_data (const std::string &filename, Elf::file *file) throw (std::runtime_error)
: module_real (filename, file)
{
module_devicetable::table_create<Elf_class, Elf_data> (devicetables, this, file);
}
modulelist::modulelist () throw ()
: report_symbols_missing (false)
{ }
modulelist::~modulelist () throw ()
{
for (_modules_real::iterator it = modules_real.begin (); it != modules_real.end (); ++it)
delete it->second;
for (_modules_shadow::iterator it = modules_shadow.begin (); it != modules_shadow.end (); ++it)
delete it->second;
}
void modulelist::dump_read (const std::string &filename) throw (std::runtime_error)
{
std::ifstream in (filename.c_str ());
while (in.good ())
{
char buf[512];
in.getline (buf, sizeof (buf));
std::stringstream str (buf);
uint32_t crc;
std::string symbol, module_name;
str >> std::hex >> crc >> std::dec >> symbol >> module_name;
_modules_shadow::const_iterator it = modules_shadow.find (module_name);
module *mod;
if (it == modules_shadow.end ())
{
mod = new module (module_name);
modules_shadow.insert (_modules_shadow_pair (module_name, mod));
}
else
mod = it->second;
mod->symbols_exported.insert (std::pair<std::string, symbol_exported> (symbol, symbol_exported (symbol, crc)));
symbols_exported.insert (std::pair<std::string, std::string> (symbol, module_name));
if (mod->get_is_vmlinux ())
report_symbols_missing = true;
}
}
void modulelist::dump_write (const std::string &filename) const throw (std::runtime_error)
{
char buf[128];
std::ofstream out (filename.c_str (), std::ios::trunc);
for (_symbols::const_iterator it = symbols_exported.begin (); it != symbols_exported.end (); ++it)
{
const module *mod = get_module (it->second);
const symbol_exported &sym = get_symbol (it->first);
snprintf (buf, sizeof (buf), "0x%08x\t%s\t%s\n", sym.get_crc (), it->first.c_str (), mod->get_name ().c_str ());
out << buf;
}
}
const module *modulelist::get_module (const std::string &name) const throw (std::out_of_range)
{
_modules_real::const_iterator it1 = modules_real.find (name);
if (it1 != modules_real.end ())
return it1->second;
_modules_shadow::const_iterator it2 = modules_shadow.find (name);
if (it2 != modules_shadow.end ())
return it2->second;
throw std::out_of_range ("Don't find module");
}
const module *modulelist::get_module_for_symbol (const symbolname &name) const throw (std::out_of_range)
{
_symbols::const_iterator it = symbols_exported.find (name);
if (it == symbols_exported.end ())
throw std::out_of_range ("symbol is undefined");
return get_module (it->second);
}
const std::string &modulelist::get_module_name_short_for_symbol (const symbolname &name) const throw (std::out_of_range)
{
const module *mod = get_module_for_symbol (name);
return mod->get_name_short ();
}
const symbol_exported &modulelist::get_symbol (const symbolname &name) const throw (std::out_of_range)
{
const module *mod = get_module_for_symbol (name);
std::map<std::string, symbol_exported>::const_iterator it = mod->get_symbols_exported ().find (name);
if (it == mod->get_symbols_exported ().end ())
throw std::logic_error ("Don't find symbol");
return it->second;
}
void modulelist::insert (module_real *mod) throw (std::runtime_error)
{
bool overwrite = false;
if (mod->get_is_vmlinux ())
{
if (!modules_shadow.insert (_modules_shadow_pair (mod->get_name (), mod)).second)
overwrite = true;
report_symbols_missing = true;
}
else
{
if (!modules_real.insert (_modules_real_pair (mod->get_name (), mod)).second)
throw std::runtime_error ("Already know a module with this name");
}
for (std::map<std::string, symbol_exported>::const_iterator it = mod->get_symbols_exported ().begin ();
it != mod->get_symbols_exported ().end (); ++it)
if (!symbols_exported.insert (std::pair<std::string, std::string> (it->second.get_name (), mod->get_name ())).second)
if (!overwrite)
std::clog << "*** Warning: \"" << it->second.get_name () << "\" [" << mod->get_name () << "] duplicated symbol!" << std::endl;
}
void modulelist::insert (const std::string &filename) throw (std::runtime_error)
{
module_real *mod = module_real::open (filename);
try
{
insert (mod);
}
catch (...)
{
delete mod;
throw;
}
}
void modulelist::write (bool modversions)
{
for (_modules_real::iterator it = modules_real.begin (); it != modules_real.end (); ++it)
it->second->write (*this, modversions);
}
symbol::symbol (const symbolname &name) throw ()
: name (name)
{ }
symbol_exported::symbol_exported (const symbolname &name) throw ()
: symbol (name), crc_valid (false)
{ }
symbol_exported::symbol_exported (const symbolname &name, uint32_t crc) throw ()
: symbol (name), crc (crc), crc_valid (true)
{ }
void symbol_exported::set_crc (uint32_t _crc) throw ()
{
crc = _crc;
crc_valid = true;
}
symbol_undefined::symbol_undefined (const symbolname &name, bool weak) throw ()
: symbol (name), weak (weak)
{ }

204
src/mod/module.hpp Normal file
View File

@ -0,0 +1,204 @@
/*
* module.hpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MODULE_HPP
#define MODULE_HPP
#define DISABLE_TEMPLATES
#include "elf.hpp"
#include "module_devicetable.hpp"
#include <list>
#include <map>
#include <ostream>
namespace linuxkernel
{
class modulelist;
class symbolname;
class symbol_exported;
class symbol_undefined;
class module
{
public:
typedef std::map<std::string, symbol_exported> _symbols_exported;
module (const std::string &name) throw ();
bool get_is_vmlinux () const throw () { return is_vmlinux; }
const std::string &get_name () const throw () { return name; }
const std::string &get_name_short () const throw () { return name_short; }
const _symbols_exported &get_symbols_exported () const throw () { return symbols_exported; }
protected:
module (const std::string &filename, bool) throw ();
std::string name, name_short;
bool is_vmlinux;
_symbols_exported symbols_exported;
friend class modulelist;
};
class module_real : public module
{
public:
typedef std::map<std::string, symbol_undefined> _symbols_undefined;
module_real (const std::string &filename, Elf::file *file) throw (std::runtime_error);
const Elf::symbol *_get_symbol (const std::string &name) const throw ();
void write (const modulelist &, bool modversions);
static module_real *open (const std::string &filename) throw (std::bad_alloc, std::runtime_error);
const static std::string symbol_name_cleanup;
const static std::string symbol_name_init;
const static std::string symbol_prefix_crc;
const static std::string symbol_prefix_ksymtab;
protected:
template<typename Elf_class>
static module_real *open_class (const std::string &filename, Elf::file *) throw (std::bad_alloc, std::runtime_error);
void read_modinfo (Elf::section *) throw (std::runtime_error);
void read_symtab (Elf::section_type<Elf::section_type_SYMTAB> *) throw (std::runtime_error);
void write_depends (std::ostream &, const modulelist &);
void write_header (std::ostream &);
void write_moddevtable (std::ostream &);
void write_versions (std::ostream &, const modulelist &);
std::map<std::string, std::string> modinfo;
_symbols_undefined symbols_undefined;
bool has_init;
bool has_cleanup;
Elf::section_type<Elf::section_type_SYMTAB> *symtab;
std::list<module_devicetable::table_base *> devicetables;
Elf::file *file;
};
template <typename Elf_class, typename Elf_data>
class module_data : public module_real
{
public:
module_data (const std::string &filename, Elf::file *file) throw (std::runtime_error);
};
class modulelist
{
public:
typedef std::map<std::string, module_real *> _modules_real;
typedef std::pair<std::string, module_real *> _modules_real_pair;
typedef std::map<std::string, module *> _modules_shadow;
typedef std::pair<std::string, module *> _modules_shadow_pair;
typedef std::map<std::string, std::string> _symbols;
modulelist () throw ();
~modulelist () throw ();
void dump_read (const std::string &filename) throw (std::runtime_error);
void dump_write (const std::string &filename) const throw (std::runtime_error);
const _modules_real &get_modules_real () const throw () { return modules_real; }
const _modules_shadow &get_modules_shadow () const throw () { return modules_shadow; }
const module *get_module (const std::string &name) const throw (std::out_of_range);
const module *get_module_for_symbol (const symbolname &name) const throw (std::out_of_range);
const std::string &get_module_name_short_for_symbol (const symbolname &name) const throw (std::out_of_range);
const symbol_exported &get_symbol (const symbolname &name) const throw (std::out_of_range);
const _symbols &get_symbols_exported () const throw () { return symbols_exported; }
void insert (module_real *) throw (std::runtime_error);
void insert (const std::string &filename) throw (std::runtime_error);
void write (bool modversions);
bool report_symbols_missing;
protected:
_modules_real modules_real;
_modules_shadow modules_shadow;
_symbols symbols_exported;
};
class symbolname : public std::string
{
public:
symbolname () throw () {}
symbolname (const std::string &name) throw ()
: std::string (name)
{
if (size () && at (0) == '.')
erase (0, 1);
}
symbolname (const char *name) throw ()
: std::string (name)
{
if (size () && at (0) == '.')
erase (0, 1);
}
};
class symbol
{
public:
symbol () throw () {}
symbol (const symbolname &name) throw ();
const symbolname &get_name () const throw () { return name; }
protected:
symbolname name;
};
class symbol_exported : public symbol
{
public:
symbol_exported () throw () {}
symbol_exported (const symbolname &name) throw ();
symbol_exported (const symbolname &name, uint32_t) throw ();
uint32_t get_crc () const throw () { return crc; }
bool get_crc_valid () const throw () { return crc_valid; }
void set_crc (uint32_t) throw ();
protected:
uint32_t crc;
bool crc_valid;
};
class symbol_undefined : public symbol
{
public:
symbol_undefined () throw () {}
symbol_undefined (const symbolname &name, bool weak) throw ();
protected:
bool weak;
};
}
#include "module_devicetable.tpp"
#undef DISABLE_TEMPLATES
#endif

View File

@ -0,0 +1,54 @@
/*
* module_devicetable.cpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "module.hpp"
#include "module_devicetable.hpp"
namespace linuxkernel
{
namespace module_devicetable
{
namespace internal
{
const std::string def<device_ccw>::symbol = "__mod_ccw_device_table";
const std::string def<device_i2c>::symbol = "__mod_i2c_device_table";
const std::string def<device_ieee1394>::symbol = "__mod_ieee1394_device_table";
const std::string def<device_input>::symbol = "__mod_input_device_table";
const std::string def<device_of>::symbol = "__mod_of_device_table";
const std::string def<device_pci>::symbol = "__mod_pci_device_table";
const std::string def<device_pcmcia>::symbol = "__mod_pcmcia_device_table";
const std::string def<device_pnp>::symbol = "__mod_pnp_device_table";
const std::string def<device_pnp_card>::symbol = "__mod_pnp_card_device_table";
const std::string def<device_serio>::symbol = "__mod_serio_device_table";
const std::string def<device_usb>::symbol = "__mod_usb_device_table";
const std::string def<device_vio>::symbol = "__mod_vio_device_table";
}
void table_base::write (std::ostream &out) const throw (std::runtime_error)
{
for (std::list<table_entry *>::const_iterator it = entries.begin (); it != entries.end (); ++it)
{
out << "MODULE_ALIAS(\"";
(*it)->write (out);
out << "\");\n";
}
}
}
}

View File

@ -0,0 +1,126 @@
/*
* module_devicetable.hpp
*
* Copyright (C) 2005, 2006 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MODULE_DEVICETABLE_HPP
#define MODULE_DEVICETABLE_HPP
#include "elf.hpp"
#include <list>
#include <ostream>
#include <stdexcept>
namespace linuxkernel
{
class module_real;
namespace module_devicetable
{
class device_ccw { };
class device_i2c { };
class device_ieee1394 { };
class device_input { };
class device_of { };
class device_pci { };
class device_pcmcia { };
class device_pnp { };
class device_pnp_card { };
class device_serio { };
class device_usb { };
class device_vio { };
class version_2_6_16 { };
namespace internal
{
template<typename device>
struct def {};
template<> struct def<device_ccw> { static const std::string symbol; };
template<> struct def<device_i2c> { static const std::string symbol; };
template<> struct def<device_ieee1394> { static const std::string symbol; };
template<> struct def<device_input> { static const std::string symbol; };
template<> struct def<device_of> { static const std::string symbol; };
template<> struct def<device_pci> { static const std::string symbol; };
template<> struct def<device_pcmcia> { static const std::string symbol; };
template<> struct def<device_pnp> { static const std::string symbol; };
template<> struct def<device_pnp_card> { static const std::string symbol; };
template<> struct def<device_serio> { static const std::string symbol; };
template<> struct def<device_usb> { static const std::string symbol; };
template<> struct def<device_vio> { static const std::string symbol; };
}
class table_entry
{
public:
virtual ~table_entry () {};
virtual void write (std::ostream &) const throw (std::runtime_error) = 0;
};
template<typename device, typename version>
class table_entry_version : public table_entry
{
};
template<typename device, typename version, typename Elf_class, typename Elf_data>
class table_entry_data : public table_entry_version<device, version>
{
};
class table_base
{
public:
virtual ~table_base () throw () {};
void write (std::ostream &out) const throw (std::runtime_error);
protected:
table_base () throw () {};
std::list<table_entry *> entries;
};
template<typename Elf_class, typename Elf_data>
void table_create (std::list<table_base *> &, const module_real *m, const Elf::file *f) throw (std::runtime_error);
template<typename device, typename Elf_class, typename Elf_data>
class table : public table_base
{
public:
static table_base *create (const module_real *m, const Elf::file *f) throw (std::runtime_error);
protected:
table () {};
};
template<typename device, typename version, typename Elf_class, typename Elf_data>
class table_data : public table<device, Elf_class, Elf_data>
{
public:
table_data (const void *, size_t) throw (std::runtime_error);
};
}
}
#ifndef DISABLE_TEMPLATES
#include "module_devicetable.tpp"
#endif
#endif

View File

@ -0,0 +1,60 @@
/*
* module_devicetable.tpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MODULE_DEVICETABLE_TPP
#define MODULE_DEVICETABLE_TPP
#include "module.hpp"
namespace linuxkernel
{
namespace module_devicetable
{
template<typename Elf_class, typename Elf_data>
void table_create (std::list<table_base *> &list, const module_real *m, const Elf::file *file) throw (std::runtime_error)
{
list.push_back (table<module_devicetable::device_ccw, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_i2c, Elf_class, Elf_data>::create (m, file));
list.push_back (table<module_devicetable::device_ieee1394, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_input, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_of, Elf_class, Elf_data>::create (m, file));
list.push_back (table<module_devicetable::device_pci, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_pcmcia, Elf_class, Elf_data>::create (m, file));
list.push_back (table<module_devicetable::device_pnp, Elf_class, Elf_data>::create (m, file));
list.push_back (table<module_devicetable::device_pnp_card, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_serio, Elf_class, Elf_data>::create (m, file));
list.push_back (table<module_devicetable::device_usb, Elf_class, Elf_data>::create (m, file));
// list.push_back (table<module_devicetable::device_vio, Elf_class, Elf_data>::create (m, file));
}
template<typename device, typename Elf_class, typename Elf_data>
table_base *table<device, Elf_class, Elf_data>::create (const module_real *m, const Elf::file *f) throw (std::runtime_error)
{
const Elf::symbol *sym = m->_get_symbol (internal::def<device>::symbol);
if (!sym)
return 0;
const Elf::section *sec = f->get_section (sym->get_shndx ());
const char *mem = static_cast <const char *> (sec->_mem ());
return new table_data<device, version_2_6_16, Elf_class, Elf_data> (mem + sym->get_value (), sym->get_size ());
}
}
}
#endif

View File

@ -0,0 +1,313 @@
/*
* module_devicetable_impl_2_6_16.cpp
*
* Copyright (C) 2005 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "module_devicetable_impl_2_6_16.hpp"
#include <cstdio>
#include <stdint.h>
#include <sstream>
using namespace linuxkernel::module_devicetable;
std::ostream &operator << (std::ostream &out, const identifier_value<uint8_t> &id) throw ()
{
char buf[4];
snprintf (buf, sizeof (buf), "%02X", id.value);
out << buf;
return out;
}
std::ostream &operator << (std::ostream &out, const identifier_value<uint16_t> &id) throw ()
{
char buf[8];
snprintf (buf, sizeof (buf), "%04X", id.value);
out << buf;
return out;
}
std::ostream &operator << (std::ostream &out, const identifier_value<uint32_t> &id) throw ()
{
char buf[12];
snprintf (buf, sizeof (buf), "%08X", id.value);
out << buf;
return out;
}
table_entry_version<device_ccw, version_2_6_16>::table_entry_version () throw () :
cu_type ("t"),
dev_type ("m"),
cu_model ("dt"),
dev_model ("dm")
{ }
void table_entry_version<device_ccw, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "ccw:";
cu_type.write (out, match_flags & CCW_DEVICE_ID_MATCH_CU_TYPE);
cu_model.write (out, match_flags & CCW_DEVICE_ID_MATCH_CU_MODEL);
dev_type.write (out, match_flags & CCW_DEVICE_ID_MATCH_DEVICE_TYPE);
dev_model.write (out, match_flags & CCW_DEVICE_ID_MATCH_DEVICE_TYPE);
}
table_entry_version<device_ieee1394, version_2_6_16>::table_entry_version () throw () :
vendor_id ("ven"),
model_id ("mo"),
specifier_id ("sp"),
version ("ver")
{ }
void table_entry_version<device_ieee1394, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "ieee1394:";
vendor_id.write (out, match_flags & IEEE1394_MATCH_VENDOR_ID);
model_id.write (out, match_flags & IEEE1394_MATCH_MODEL_ID);
specifier_id.write (out, match_flags & IEEE1394_MATCH_SPECIFIER_ID);
version.write (out, match_flags & IEEE1394_MATCH_VERSION, true);
}
table_entry_version<device_pci, version_2_6_16>::table_entry_version () throw () :
vendor ("v"),
device ("d"),
subvendor ("sv"),
subdevice ("sd")
{ }
void table_entry_version<device_pci, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "pci:";
vendor.write (out, vendor != PCI_ANY_ID);
device.write (out, device != PCI_ANY_ID);
subvendor.write (out, subvendor != PCI_ANY_ID);
subdevice.write (out, subdevice != PCI_ANY_ID);
identifier<uint8_t> baseclass ("bc", class_id >> 16);
identifier_value<uint8_t> baseclass_mask (class_mask >> 16);
identifier<uint8_t> subclass ("sc", class_id >> 8);
identifier_value<uint8_t> subclass_mask (class_mask >> 8);
identifier<uint8_t> interface ("i", class_id);
identifier_value<uint8_t> interface_mask (class_mask);
if ((baseclass_mask != 0 && baseclass_mask != 0xFF) ||
(subclass_mask != 0 && subclass_mask != 0xFF) ||
(interface_mask != 0 && interface_mask != 0xFF))
throw std::runtime_error ("Can't handle masks");
baseclass.write (out, baseclass_mask == 0xFF);
subclass.write (out, subclass_mask == 0xFF);
interface.write (out, interface_mask == 0xFF, true);
}
void table_entry_version<device_pnp, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "pnp:" << str << '*';
}
void table_entry_version<device_pnp_card, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "pnp:" << str << '*';
}
table_entry_version<device_usb, version_2_6_16>::table_entry_version () throw () :
idVendor ("v"),
idProduct ("p"),
bDeviceClass ("dc"),
bDeviceSubClass ("dsc"),
bDeviceProtocol ("dp"),
bInterfaceClass ("ic"),
bInterfaceSubClass ("isc"),
bInterfaceProtocol ("ip")
{ }
void table_entry_version<device_usb, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
if (!idVendor && !bDeviceClass && !bInterfaceClass)
return;
out << "usb:";
idVendor.write (out, match_flags & USB_DEVICE_ID_MATCH_VENDOR);
idProduct.write (out, match_flags & USB_DEVICE_ID_MATCH_PRODUCT);
out << 'd';
if (bcdDevice_initial_digits)
{
char buf[12];
snprintf (buf, sizeof (buf), "%0*X", bcdDevice_initial_digits, bcdDevice_initial);
out << buf;
}
if (range_lo == range_hi)
out << static_cast<int> (range_lo);
else if (range_lo > 0 || range_hi < 9)
out << '[' << static_cast<int> (range_lo) << '-' << static_cast<int> (range_hi) << ']';
if (bcdDevice_initial_digits < 3)
out << '*';
bDeviceClass.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS);
bDeviceSubClass.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS);
bDeviceProtocol.write (out, match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL);
bInterfaceClass.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_CLASS);
bInterfaceSubClass.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS);
bInterfaceProtocol.write (out, match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL, true);
}
#define _do_convert(name) name = Elf::convert<Elf_data, typeof (id.name)> () (id.name)
template<typename Elf_class, typename Elf_data>
table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_ccw, Elf_class> &id) throw ()
{
_do_convert (match_flags);
_do_convert (cu_type);
_do_convert (dev_type);
_do_convert (cu_model);
_do_convert (dev_model);
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_ieee1394, Elf_class> &id) throw ()
{
_do_convert (match_flags);
_do_convert (vendor_id);
_do_convert (model_id);
_do_convert (specifier_id);
_do_convert (version);
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pci, Elf_class> &id) throw ()
{
_do_convert (vendor);
_do_convert (device);
_do_convert (subvendor);
_do_convert (subdevice);
_do_convert (class_id);
_do_convert (class_mask);
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pnp, Elf_class> &id) throw ()
{
std::stringstream s;
s << 'd';
s << static_cast <const char *> (static_cast <const void *> (id.id));
str = s.str ();
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pnp_card, Elf_class> &id) throw ()
{
std::stringstream s;
s << 'c';
s << static_cast <const char *> (static_cast <const void *> (id.id));
for (int i = 0; i < PNP_MAX_DEVICES; i++)
{
if (! *id.devs[i].id)
break;
s << 'd';
s << static_cast <const char *> (static_cast <const void *> (id.devs[i].id));
}
str = s.str ();
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_usb, Elf_class> &id, uint16_t _bcdDevice_initial, int _bcdDevice_initial_digits, unsigned char _range_lo, unsigned char _range_hi) throw ()
{
_do_convert (match_flags);
_do_convert (idVendor);
_do_convert (idProduct);
_do_convert (bDeviceClass);
_do_convert (bDeviceSubClass);
_do_convert (bDeviceProtocol);
_do_convert (bInterfaceClass);
_do_convert (bInterfaceSubClass);
_do_convert (bInterfaceProtocol);
bcdDevice_initial = _bcdDevice_initial;
bcdDevice_initial_digits = _bcdDevice_initial_digits;
range_lo = _range_lo;
range_hi = _range_hi;
}
template<typename Elf_class, typename Elf_data>
void table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data>::add (const device_id<device_usb, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
uint16_t match_flags;
uint16_t idVendor;
uint16_t bcdDevice_lo = 0;
uint16_t bcdDevice_hi = ~0;
uint8_t bDeviceClass;
uint8_t bInterfaceClass;
_do_convert (match_flags);
_do_convert (idVendor);
if (match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
_do_convert (bcdDevice_lo);
if (match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
_do_convert (bcdDevice_hi);
_do_convert (bDeviceClass);
_do_convert (bInterfaceClass);
if (!(idVendor | bDeviceClass | bInterfaceClass))
return;
for (int ndigits = 3; bcdDevice_lo <= bcdDevice_hi; ndigits--)
{
unsigned char clo = bcdDevice_lo & 0xf;
unsigned char chi = bcdDevice_hi & 0xf;
if (chi > 9) /* it's bcd not hex */
chi = 9;
bcdDevice_lo >>= 4;
bcdDevice_hi >>= 4;
if (bcdDevice_lo == bcdDevice_hi || !ndigits)
{
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_lo, ndigits, clo, chi));
return;
}
if (clo > 0)
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_lo++, ndigits, clo, 9));
if (chi < 9)
table.push_back (new table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> (id, bcdDevice_hi--, ndigits, 0, chi));
}
}
template<typename device, typename Elf_class, typename Elf_data>
table_data<device, version_2_6_16, Elf_class, Elf_data>::table_data (const void *mem, size_t size) throw (std::runtime_error)
{
if (size % sizeof (devin))
throw std::runtime_error ("Bad size");
size_t len = size / sizeof (devin);
// Remove the terminator.
len--;
const devin *e = static_cast <const devin *> (mem);
for (size_t i = 0; i < len; ++i)
table_entry_data<device, version_2_6_16, Elf_class, Elf_data>::add (e[i], this->entries);
}
#define make_templates(name) \
template class table_data<name, version_2_6_16, Elf::file_class_32, Elf::file_data_2LSB>; \
template class table_data<name, version_2_6_16, Elf::file_class_32, Elf::file_data_2MSB>; \
template class table_data<name, version_2_6_16, Elf::file_class_64, Elf::file_data_2LSB>; \
template class table_data<name, version_2_6_16, Elf::file_class_64, Elf::file_data_2MSB>
make_templates(device_ccw);
make_templates(device_ieee1394);
make_templates(device_pci);
make_templates(device_pnp);
make_templates(device_pnp_card);
make_templates(device_usb);

View File

@ -0,0 +1,391 @@
/*
* module_devicetable_impl_2_6_16.hpp
*
* Copyright (C) 2005, 2006 Bastian Blank <waldi@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef MODULE_DEVICETABLE_IMPL_2_6_16_HPP
#define MODULE_DEVICETABLE_IMPL_2_6_16_HPP
#include "module_devicetable.hpp"
#include "elf.hpp"
namespace
{
using namespace linuxkernel::module_devicetable;
template<typename _class>
struct _elfdef
{ };
template<>
struct _elfdef<Elf::file_class_32>
{
typedef uint32_t pointer;
};
template<>
struct _elfdef<Elf::file_class_64>
{
typedef uint64_t pointer;
};
template<typename device, typename Elf_class>
struct device_id
{ };
template<typename Elf_class>
struct device_id<device_ccw, Elf_class>
{
uint16_t match_flags;
uint16_t cu_type;
uint16_t dev_type;
uint8_t cu_model;
uint8_t dev_model;
typename _elfdef<Elf_class>::pointer driver_info;
};
enum
{
CCW_DEVICE_ID_MATCH_CU_TYPE = 0x01,
CCW_DEVICE_ID_MATCH_CU_MODEL = 0x02,
CCW_DEVICE_ID_MATCH_DEVICE_TYPE = 0x04,
CCW_DEVICE_ID_MATCH_DEVICE_MODEL = 0x08,
};
template<typename Elf_class>
struct device_id<device_i2c, Elf_class>
{
uint16_t id;
};
template<typename Elf_class>
struct device_id<device_ieee1394, Elf_class>
{
uint32_t match_flags;
uint32_t vendor_id;
uint32_t model_id;
uint32_t specifier_id;
uint32_t version;
typename _elfdef<Elf_class>::pointer driver_info;
};
enum
{
IEEE1394_MATCH_VENDOR_ID = 0x0001,
IEEE1394_MATCH_MODEL_ID = 0x0002,
IEEE1394_MATCH_SPECIFIER_ID = 0x0004,
IEEE1394_MATCH_VERSION = 0x0008,
};
template<typename Elf_class>
struct device_id<device_pci, Elf_class>
{
uint32_t vendor, device;
uint32_t subvendor, subdevice;
uint32_t class_id, class_mask;
typename _elfdef<Elf_class>::pointer driver_info;
};
const unsigned int PCI_ANY_ID = ~0U;
const int PNP_ID_LEN = 8;
const int PNP_MAX_DEVICES = 8;
template <typename Elf_class>
struct device_id<device_pnp, Elf_class>
{
uint8_t id[PNP_ID_LEN];
typename _elfdef<Elf_class>::pointer driver_info;
};
template <typename Elf_class>
struct device_id<device_pnp_card, Elf_class>
{
uint8_t id[PNP_ID_LEN];
typename _elfdef<Elf_class>::pointer driver_info;
struct
{
uint8_t id[PNP_ID_LEN];
}
devs[PNP_MAX_DEVICES];
};
template <typename Elf_class>
struct device_id<device_serio, Elf_class>
{
uint8_t type;
uint8_t extra;
uint8_t id;
uint8_t proto;
};
enum
{
SERIO_DEVICE_ID_ANY = 0xff,
};
template <typename Elf_class>
struct device_id<device_usb, Elf_class>
{
uint16_t match_flags;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice_lo;
uint16_t bcdDevice_hi;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
typename _elfdef<Elf_class>::pointer driver_info;
};
enum
{
USB_DEVICE_ID_MATCH_VENDOR = 0x0001,
USB_DEVICE_ID_MATCH_PRODUCT = 0x0002,
USB_DEVICE_ID_MATCH_DEV_LO = 0x0004,
USB_DEVICE_ID_MATCH_DEV_HI = 0x0008,
USB_DEVICE_ID_MATCH_DEV_CLASS = 0x0010,
USB_DEVICE_ID_MATCH_DEV_SUBCLASS = 0x0020,
USB_DEVICE_ID_MATCH_DEV_PROTOCOL = 0x0040,
USB_DEVICE_ID_MATCH_INT_CLASS = 0x0080,
USB_DEVICE_ID_MATCH_INT_SUBCLASS = 0x0100,
USB_DEVICE_ID_MATCH_INT_PROTOCOL = 0x0200,
};
template<typename type>
class identifier_value
{
public:
type value;
identifier_value () : value (0) { }
identifier_value (const type &value) : value (value) { }
const type &operator = (const type &_value) { value = _value; return value; }
bool operator ! () const { return !value; }
operator type () const { return value; }
template<typename Elf_data>
void set (const type _value)
{ value = Elf::convert<Elf_data, type> () (_value); }
};
template<typename type>
class identifier
{
public:
identifier_value<type> value;
std::string sep;
identifier (const std::string &sep) : sep (sep) { }
identifier (const std::string &sep, const type &value) : value (value), sep (sep) { }
const type &operator = (const type &_value) { value = _value; return value.value; }
bool operator ! () const { return !value; }
operator type () const { return value; }
void write (std::ostream &out, bool enable, bool last = false) const
{
out << sep;
if (enable)
{
out << value;
if (last)
out << '*';
}
else
out << '*';
}
};
}
std::ostream &operator << (std::ostream &out, const identifier_value<uint8_t> &id) throw ();
std::ostream &operator << (std::ostream &out, const identifier_value<uint16_t> &id) throw ();
std::ostream &operator << (std::ostream &out, const identifier_value<uint32_t> &id) throw ();
namespace linuxkernel
{
namespace module_devicetable
{
template<>
class table_entry_version<device_ccw, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
identifier_value<uint16_t> match_flags;
identifier<uint16_t> cu_type;
identifier<uint16_t> dev_type;
identifier<uint8_t> cu_model;
identifier<uint8_t> dev_model;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_ccw, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_ccw, Elf_class> &) throw ();
public:
static void add (const device_id<device_ccw, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_ccw, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_ieee1394, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
identifier_value<uint32_t> match_flags;
identifier<uint32_t> vendor_id;
identifier<uint32_t> model_id;
identifier<uint32_t> specifier_id;
identifier<uint32_t> version;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_ieee1394, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_ieee1394, Elf_class> &) throw ();
public:
static void add (const device_id<device_ieee1394, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_ieee1394, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_pci, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
identifier<uint32_t> vendor, device;
identifier<uint32_t> subvendor, subdevice;
identifier_value<uint32_t> class_id, class_mask;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pci, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_pci, Elf_class> &) throw ();
public:
static void add (const device_id<device_pci, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_pci, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_pnp, version_2_6_16> : public table_entry
{
public:
void write (std::ostream &) const throw (std::runtime_error);
std::string str;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pnp, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_pnp, Elf_class> &) throw ();
public:
static void add (const device_id<device_pnp, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_pnp, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_pnp_card, version_2_6_16> : public table_entry
{
public:
void write (std::ostream &) const throw (std::runtime_error);
std::string str;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pnp_card, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_pnp_card, Elf_class> &) throw ();
public:
static void add (const device_id<device_pnp_card, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_pnp_card, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_usb, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
identifier_value<uint16_t> match_flags;
identifier<uint16_t> idVendor;
identifier<uint16_t> idProduct;
unsigned int bcdDevice_initial;
int bcdDevice_initial_digits;
unsigned char range_lo;
unsigned char range_hi;
identifier<uint8_t> bDeviceClass;
identifier<uint8_t> bDeviceSubClass;
identifier<uint8_t> bDeviceProtocol;
identifier<uint8_t> bInterfaceClass;
identifier<uint8_t> bInterfaceSubClass;
identifier<uint8_t> bInterfaceProtocol;
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_usb, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_usb, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_usb, Elf_class> &, uint16_t bcdDevice_initial, int bcdDevice_initial_digits, unsigned char range_lo, unsigned char range_hi) throw ();
public:
static void add (const device_id<device_usb, Elf_class> &, std::list<table_entry *> &table) throw ();
};
template<typename device, typename Elf_class, typename Elf_data>
class table_data<device, version_2_6_16, Elf_class, Elf_data> : public table<device, Elf_class, Elf_data>
{
protected:
typedef device_id<device, Elf_class> devin;
public:
table_data (const void *mem, size_t size) throw (std::runtime_error);
};
}
}
#endif