Replace own modpost with a dispatcher and four version of the original one.

* src/mod/Makefile: Build all modpost variants.
* src/mod/Makefile.real, src/mod/elfconfig.h, src/mod/modpost.c,
  src/mod/real-lsb-32/elfconfig.h, src/mod/real-lsb-64/elfconfig.h,
  src/mod/real-msb-32/elfconfig.h, src/mod/real-msb-64/elfconfig.h: Add.
* src/mod/real-lsb-32, src/mod/real-lsb-64, src/mod/real-msb-32,
  src/mod/real-msb-64: New directory.
* src/mod/elf.cpp, src/mod/elf.hpp, src/mod/endian.hpp, src/mod/modpost.cpp,
  src/mod/module.cpp, src/mod/module.hpp, src/mod/module_devicetable.cpp,
  src/mod/module_devicetable.hpp, src/mod/module_devicetable.tpp,
  src/mod/module_devicetable_impl_2_6_16.cpp,
  src/mod/module_devicetable_impl_2_6_16.hpp: Remove.

svn path=/dists/trunk/linux-kbuild-2.6/; revision=7045
This commit is contained in:
Bastian Blank 2006-07-19 22:56:40 +00:00
parent d525b055b2
commit c3687a0f8c
19 changed files with 114 additions and 2521 deletions

View File

@ -1,13 +1,20 @@
PROGS = modpost
PROGS = \
modpost \
modpost.real-lsb-32 \
modpost.real-lsb-64 \
modpost.real-msb-32 \
modpost.real-msb-64
OUTDIR = mod
modpost: elf.o modpost.o module.o module_devicetable.o module_devicetable_impl_2_6_16.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^
modpost.real-%:
$(MAKE) -f Makefile.real TYPE=$* SOURCEDIR=$(top_srcdir)/scripts/mod
%.o: %.cpp %.hpp endian.hpp
%: %.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
include ../Makefile.inc
clean:
rm $(PROGS) *.o
include ../Makefile.inc

10
src/mod/Makefile.real Normal file
View File

@ -0,0 +1,10 @@
PROGS = modpost.real-$(TYPE)
include ../Makefile.inc
modpost.real-$(TYPE): file2alias.real-$(TYPE).o modpost.real-$(TYPE).o sumversion.real-$(TYPE).o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
%.real-$(TYPE).o: $(SOURCEDIR)/%.c
$(CC) -I real-$(TYPE) $(CFLAGS) -c -o $@ $^

View File

@ -1,243 +0,0 @@
/*
* 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);
}

View File

@ -1,219 +0,0 @@
/*
* 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

7
src/mod/elfconfig.h Normal file
View File

@ -0,0 +1,7 @@
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define HOST_ELFDATA ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define HOST_ELFDATA ELFDATA2MSB
#endif

View File

@ -1,138 +0,0 @@
/*
* 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

69
src/mod/modpost.c Normal file
View File

@ -0,0 +1,69 @@
#include <elf.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
char const *data, *class;
char prog[1024];
unsigned char ei[EI_NIDENT];
int opt;
FILE *file;
while ((opt = getopt (argc, argv, "ai:I:mo:")) != -1)
{
switch(opt)
{
case 'a':
case 'i':
case 'I':
case 'm':
case 'o':
break;
default:
return 1;
}
}
if (!(file = fopen (argv[optind], "r")))
{
fprintf (stderr, "Can't open file\n");
return 1;
}
if (fread (ei, 1, EI_NIDENT, file) != EI_NIDENT)
{
fprintf (stderr, "Error: input truncated\n");
return 1;
}
if (memcmp (ei, ELFMAG, SELFMAG) != 0)
{
fprintf (stderr, "Error: not ELF\n");
return 1;
}
switch (ei[EI_DATA]) {
case ELFDATA2LSB:
data = "lsb";
break;
case ELFDATA2MSB:
data = "msb";
break;
default:
return 1;
}
switch (ei[EI_CLASS]) {
case ELFCLASS32:
class = "32";
break;
case ELFCLASS64:
class = "64";
break;
default:
return 1;
}
snprintf (prog, sizeof prog, "%s.real-%s-%s", argv[0], data, class);
return execv (prog, argv);
}

View File

@ -1,89 +0,0 @@
/*
* 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_kernel = 0, *dump_read_module = 0, *dump_write = 0;
bool all_versions = false, modversions = false;;
while ((opt = getopt (argc, argv, "ai:I: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_kernel = optarg;
break;
case 'I':
dump_read_module = optarg;
break;
case 'm':
modversions = true;
break;
case 'o':
dump_write = optarg;
break;
default:
exit(1);
}
}
if (dump_read_kernel)
modules.dump_read (dump_read_kernel, true);
if (dump_read_module)
modules.dump_read (dump_read_module, false);
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, dump_read_module ? false : true);
return ret;
}

View File

@ -1,455 +0,0 @@
/*
* 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 &filename, bool kernel) throw ()
: kernel (kernel), is_vmlinux (false)
{
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 (!symtab)
throw std::runtime_error ("Not a kernel module, lacks symbol table");
if (modinfo)
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, bool kernel) 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, kernel);
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, bool kernel) 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);
if (!kernel && mod->get_kernel ())
continue;
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)
{ }

View File

@ -1,204 +0,0 @@
/*
* 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, bool kernel) throw ();
bool get_kernel () const throw () { return kernel; }
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:
std::string name, name_short;
bool kernel;
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, bool kernel) throw (std::runtime_error);
void dump_write (const std::string &filename, bool kernel) 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

@ -1,54 +0,0 @@
/*
* 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

@ -1,126 +0,0 @@
/*
* 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

@ -1,60 +0,0 @@
/*
* 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

@ -1,403 +0,0 @@
/*
* 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_i2c, version_2_6_16>::table_entry_version () throw ()
{
}
void table_entry_version<device_i2c, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
{
}
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_input, version_2_6_16>::table_entry_version () throw ()
{
}
void table_entry_version<device_input, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
{
}
table_entry_version<device_of, version_2_6_16>::table_entry_version () throw ()
{
}
void table_entry_version<device_of, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
{
}
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);
}
table_entry_version<device_pcmcia, version_2_6_16>::table_entry_version () throw ()
{
}
void table_entry_version<device_pcmcia, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
{
}
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_serio, version_2_6_16>::table_entry_version () throw ()
{
}
void table_entry_version<device_serio, version_2_6_16>::write (std::ostream &out __attribute__ ((unused))) const throw (std::runtime_error)
{
}
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);
}
void table_entry_version<device_vio, version_2_6_16>::write (std::ostream &out) const throw (std::runtime_error)
{
out << "vio:" << str << '*';
}
#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_i2c, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_i2c, Elf_class> &id __attribute__ ((unused))) throw ()
{
throw std::runtime_error ("Not implemented: I2C");
}
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_input, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_input, Elf_class> &id __attribute__ ((unused))) throw ()
{
throw std::runtime_error ("Not implemented: INPUT");
}
template<typename Elf_class, typename Elf_data>
table_entry_data<device_of, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_of, Elf_class> &id __attribute__ ((unused))) throw ()
{
throw std::runtime_error ("Not implemented: OF");
}
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_pcmcia, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_pcmcia, Elf_class> &id __attribute__ ((unused))) throw ()
{
throw std::runtime_error ("Not implemented: PCMCIA");
}
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_serio, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_serio, Elf_class> &id __attribute__((unused))) throw ()
{
throw std::runtime_error ("Not implemented: SERIO");
}
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 Elf_class, typename Elf_data>
table_entry_data<device_vio, version_2_6_16, Elf_class, Elf_data>::table_entry_data (const device_id<device_vio, Elf_class> &id) throw ()
{
std::stringstream s;
s << 'T' << (id.type[0] ? id.type : "*");
s << 'S' << (id.compat[0] ? id.compat : "*");
str = s.str ();
}
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_i2c);
make_templates(device_ieee1394);
make_templates(device_input);
make_templates(device_of);
make_templates(device_pci);
make_templates(device_pcmcia);
make_templates(device_pnp);
make_templates(device_pnp_card);
make_templates(device_serio);
make_templates(device_usb);
make_templates(device_vio);

View File

@ -1,525 +0,0 @@
/*
* 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 Elf_class>
struct device_id<device_vio, Elf_class>
{
char type[32];
char compat[32];
};
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_i2c, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_i2c, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_i2c, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_i2c, Elf_class> &) throw ();
public:
static void add (const device_id<device_i2c, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_i2c, 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_input, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_input, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_input, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_input, Elf_class> &) throw ();
public:
static void add (const device_id<device_input, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_input, version_2_6_16, Elf_class, Elf_data> (id));
}
};
template<>
class table_entry_version<device_of, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_of, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_of, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_of, Elf_class> &) throw ();
public:
static void add (const device_id<device_of, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_of, 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_pcmcia, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_pcmcia, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_pcmcia, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_pcmcia, Elf_class> &) throw ();
public:
static void add (const device_id<device_pcmcia, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_pcmcia, 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_serio, version_2_6_16> : public table_entry
{
public:
table_entry_version () throw ();
void write (std::ostream &) const throw (std::runtime_error);
};
template<typename Elf_class, typename Elf_data>
class table_entry_data<device_serio, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_serio, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_serio, Elf_class> &) throw ();
public:
static void add (const device_id<device_serio, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_serio, 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<>
class table_entry_version<device_vio, 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_vio, version_2_6_16, Elf_class, Elf_data> : public table_entry_version<device_vio, version_2_6_16>
{
protected:
table_entry_data (const device_id<device_vio, Elf_class> &) throw ();
public:
static void add (const device_id<device_vio, Elf_class> &id, std::list<table_entry *> &table) throw ()
{
table.push_back (new table_entry_data<device_vio, version_2_6_16, Elf_class, Elf_data> (id));
}
};
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

View File

@ -0,0 +1,4 @@
#define KERNEL_ELFCLASS ELFCLASS32
#define KERNEL_ELFDATA ELFDATA2LSB
#define MODULE_SYMBOL_PREFIX ""
#include "../elfconfig.h"

View File

@ -0,0 +1,4 @@
#define KERNEL_ELFCLASS ELFCLASS64
#define KERNEL_ELFDATA ELFDATA2LSB
#define MODULE_SYMBOL_PREFIX ""
#include "../elfconfig.h"

View File

@ -0,0 +1,4 @@
#define KERNEL_ELFCLASS ELFCLASS32
#define KERNEL_ELFDATA ELFDATA2MSB
#define MODULE_SYMBOL_PREFIX ""
#include "../elfconfig.h"

View File

@ -0,0 +1,4 @@
#define KERNEL_ELFCLASS ELFCLASS64
#define KERNEL_ELFDATA ELFDATA2MSB
#define MODULE_SYMBOL_PREFIX ""
#include "../elfconfig.h"