aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Masters <jcm@jonmasters.org>2009-05-19 04:50:08 -0400
committerJon Masters <jcm@jonmasters.org>2009-05-19 04:50:08 -0400
commitaa6fe1585412d5ad603fc81b7075dffb93a8b8f2 (patch)
tree5df1a6e2aa8aa42518b1cc02d75bd1b4e0662f86
parent243fc689453662f4573f2601a64c5c7f9312906d (diff)
parent686703ef1f9f6b123ef67360a008d1ffe9bdc074 (diff)
downloadmodule-init-tools-aa6fe1585412d5ad603fc81b7075dffb93a8b8f2.tar.gz
Merge branch 'elf_cleanup' of ../module_init_tools_andr345
-rw-r--r--Makefile.am12
-rw-r--r--depmod.c80
-rw-r--r--depmod.h39
-rw-r--r--elf_core.c43
-rw-r--r--elfops.c57
-rw-r--r--elfops.h78
-rw-r--r--elfops_core.c303
-rw-r--r--modinfo.c1
-rw-r--r--modprobe.c1
-rw-r--r--moduleops.c25
-rw-r--r--moduleops.h28
-rw-r--r--moduleops_core.c241
-rw-r--r--tables.c86
-rw-r--r--util.c91
-rw-r--r--util.h17
15 files changed, 618 insertions, 484 deletions
diff --git a/Makefile.am b/Makefile.am
index 424aa8f..be697dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,8 +4,8 @@ insmod_SOURCES = insmod.c testing.h
lsmod_SOURCES = lsmod.c testing.h
modprobe_SOURCES = modprobe.c zlibsupport.c zlibsupport.h testing.h
rmmod_SOURCES = rmmod.c testing.h
-depmod_SOURCES = depmod.c zlibsupport.c moduleops.c tables.c \
- zlibsupport.h moduleops.h tables.h testing.h
+depmod_SOURCES = depmod.c zlibsupport.c tables.c \
+ zlibsupport.h tables.h testing.h
modinfo_SOURCES = modinfo.c zlibsupport.c zlibsupport.h testing.h
modindex_SOURCES = modindex.c zlibsupport.c zlibsupport.h testing.h
@@ -19,14 +19,14 @@ EXTRA_lsmod_SOURCES =
EXTRA_modprobe_SOURCES =
EXTRA_rmmod_SOURCES =
EXTRA_insmod_static_SOURCES =
-EXTRA_depmod_SOURCES = moduleops_core.c
+EXTRA_depmod_SOURCES =
EXTRA_modinfo_SOURCES =
-libmodtools_a_SOURCES = util.c logging.c index.c config_filter.c \
- util.h depmod.h logging.h index.h list.h config_filter.h
+libmodtools_a_SOURCES = util.c logging.c index.c config_filter.c elfops.c \
+ util.h depmod.h logging.h index.h list.h config_filter.h elfops.h
libmodtools_a_CFLAGS = -ffunction-sections
-EXTRA_libmodtools_a_SOURCES = elf_core.c
+EXTRA_libmodtools_a_SOURCES = elf_core.c elfops_core.c
insmod_LDADD = $(LDADD) libmodtools.a
lsmod_LDADD = $(LDADD) libmodtools.a
diff --git a/depmod.c b/depmod.c
index 3544b89..a7bd948 100644
--- a/depmod.c
+++ b/depmod.c
@@ -26,7 +26,7 @@
#include "depmod.h"
#include "logging.h"
#include "index.h"
-#include "moduleops.h"
+#include "elfops.h"
#include "tables.h"
#include "config_filter.h"
@@ -264,6 +264,7 @@ static int ends_in(const char *name, const char *ext)
static struct module *grab_module(const char *dirname, const char *filename)
{
struct module *new;
+ struct elf_file *file;
new = NOFAIL(malloc(sizeof(*new)
+ strlen(dirname?:"") + 1 + strlen(filename) + 1));
@@ -276,19 +277,21 @@ static struct module *grab_module(const char *dirname, const char *filename)
INIT_LIST_HEAD(&new->dep_list);
new->order = INDEX_PRIORITY_MIN;
- new->data = grab_file(new->pathname, &new->len);
- if (!new->data) {
+ file = &new->file;
+
+ file->data = grab_file(new->pathname, &file->len);
+ if (!file->data) {
warn("Can't read module %s: %s\n",
new->pathname, strerror(errno));
goto fail_data;
}
- switch (elf_ident(new->data, new->len, &new->conv)) {
+ switch (elf_ident(file->data, file->len, &file->conv)) {
case ELFCLASS32:
- new->ops = &mod_ops32;
+ file->ops = &mod_ops32;
break;
case ELFCLASS64:
- new->ops = &mod_ops64;
+ file->ops = &mod_ops64;
break;
case -ENOEXEC:
warn("Module %s is not an elf object\n", new->pathname);
@@ -303,7 +306,7 @@ static struct module *grab_module(const char *dirname, const char *filename)
return new;
fail:
- release_file(new->data, new->len);
+ release_file(file->data, new->file.len);
fail_data:
free(new);
return NULL;
@@ -667,17 +670,62 @@ static struct module *sort_modules(const char *dirname, struct module *list)
return tlist;
}
+/* Calculate the dependencies for this module */
+static void calculate_deps(struct module *module)
+{
+ unsigned int i;
+ struct string_table *symnames;
+ struct string_table *symtypes;
+ struct elf_file *file;
+
+ module->num_deps = 0;
+ module->deps = NULL;
+ file = &module->file;
+
+ symnames = file->ops->load_dep_syms(module->pathname, file, &symtypes);
+ if (!symnames || !symtypes)
+ return;
+
+ for (i = 0; i < symnames->cnt; i++) {
+ const char *name;
+ struct module *owner;
+ int weak;
+
+ name = symnames->str[i];
+ weak = (*(symtypes->str[i]) == 'W');
+ owner = find_symbol(name, module->pathname, weak);
+ if (owner) {
+ info("%s needs \"%s\": %s\n",
+ module->pathname, name,
+ owner->pathname);
+ add_dep(module, owner);
+ }
+ }
+
+ free(symnames);
+ free(symtypes);
+}
+
static struct module *parse_modules(struct module *list)
{
struct module *i;
+ struct elf_file *file;
+ struct string_table *syms;
+ int j;
for (i = list; i; i = i->next) {
- i->ops->load_symbols(i);
- i->ops->fetch_tables(i);
+ file = &i->file;
+ syms = file->ops->load_symbols(file);
+ if (syms) {
+ for (j = 0; j < syms->cnt; j++)
+ add_symbol(syms->str[j], i);
+ free(syms);
+ }
+ file->ops->fetch_tables(file, &i->tables);
}
for (i = list; i; i = i->next)
- i->ops->calculate_deps(i);
+ calculate_deps(i);
/* Strip out modules with dependency loops. */
again:
@@ -747,6 +795,7 @@ static void output_symbols_bin(struct module *unused, FILE *out, char *dirname)
static void output_aliases(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
+ struct elf_file *file;
const char *p;
unsigned long size;
@@ -754,16 +803,17 @@ static void output_aliases(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
char modname[strlen(i->pathname)+1];
+ file = &i->file;
filename2modname(modname, i->pathname);
/* Grab from old-style .modalias section. */
- for (p = i->ops->get_aliases(i, &size);
+ for (p = file->ops->get_aliases(file, &size);
p;
p = next_string(p, &size))
fprintf(out, "alias %s %s\n", p, modname);
/* Grab form new-style .modinfo section. */
- for (p = i->ops->get_modinfo(i, &size);
+ for (p = file->ops->get_modinfo(file, &size);
p;
p = next_string(p, &size)) {
if (strstarts(p, "alias="))
@@ -776,6 +826,7 @@ static void output_aliases(struct module *modules, FILE *out, char *dirname)
static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
+ struct elf_file *file;
const char *p;
char *alias;
unsigned long size;
@@ -787,10 +838,11 @@ static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
char modname[strlen(i->pathname)+1];
+ file = &i->file;
filename2modname(modname, i->pathname);
/* Grab from old-style .modalias section. */
- for (p = i->ops->get_aliases(i, &size);
+ for (p = file->ops->get_aliases(file, &size);
p;
p = next_string(p, &size)) {
alias = NOFAIL(strdup(p));
@@ -803,7 +855,7 @@ static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
}
/* Grab from new-style .modinfo section. */
- for (p = i->ops->get_modinfo(i, &size);
+ for (p = file->ops->get_modinfo(file, &size);
p;
p = next_string(p, &size)) {
if (strstarts(p, "alias=")) {
diff --git a/depmod.h b/depmod.h
index 32cab3d..be06b7c 100644
--- a/depmod.h
+++ b/depmod.h
@@ -1,25 +1,15 @@
#ifndef MODINITTOOLS_DEPMOD_H
#define MODINITTOOLS_DEPMOD_H
#include "list.h"
+#include "elfops.h"
struct module;
-/* Functions provided by depmod.c */
-void add_symbol(const char *name, struct module *owner);
-struct module *find_symbol(const char *name, const char *modname, int weak);
-void add_dep(struct module *mod, struct module *depends_on);
-
struct module
{
/* Next module in list of all modules */
struct module *next;
- /* 64 or 32 bit? */
- struct module_ops *ops;
-
- /* Convert endian? */
- int conv;
-
/* Dependencies: filled in by ops->calculate_deps() */
unsigned int num_deps;
struct module **deps;
@@ -31,30 +21,9 @@ struct module
unsigned int order;
/* Tables extracted from module by ops->fetch_tables(). */
- unsigned int pci_size;
- void *pci_table;
- unsigned int usb_size;
- void *usb_table;
- unsigned int ieee1394_size;
- void *ieee1394_table;
- unsigned int ccw_size;
- void *ccw_table;
- unsigned int pnp_size;
- void *pnp_table;
- unsigned int pnp_card_size;
- unsigned int pnp_card_offset;
- void *pnp_card_table;
- unsigned int input_size;
- void *input_table;
- unsigned int input_table_size;
- unsigned int serio_size;
- void *serio_table;
- unsigned int of_size;
- void *of_table;
-
- /* File contents and length. */
- void *data;
- unsigned long len;
+ struct module_tables tables;
+
+ struct elf_file file;
char *basename; /* points into pathname */
char pathname[0];
diff --git a/elf_core.c b/elf_core.c
deleted file mode 100644
index 1525c36..0000000
--- a/elf_core.c
+++ /dev/null
@@ -1,43 +0,0 @@
-void *PERBIT(get_section)(void *file,
- unsigned long fsize,
- const char *secname,
- unsigned long *secsize,
- int conv)
-{
- ElfPERBIT(Ehdr) *hdr;
- ElfPERBIT(Shdr) *sechdrs;
- ElfPERBIT(Off) e_shoff;
- ElfPERBIT(Half) e_shnum, e_shstrndx;
-
- const char *secnames;
- unsigned int i;
-
- if (fsize > 0 && fsize < sizeof(*hdr))
- return NULL;
-
- hdr = file;
- e_shoff = END(hdr->e_shoff, conv);
- e_shnum = END(hdr->e_shnum, conv);
- e_shstrndx = END(hdr->e_shstrndx, conv);
-
- if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0]))
- return NULL;
-
- sechdrs = file + e_shoff;
-
- if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv))
- return NULL;
-
- /* Find section by name, return pointer and size. */
-
- secnames = file + END(sechdrs[e_shstrndx].sh_offset, conv);
- for (i = 1; i < e_shnum; i++) {
- if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) {
- *secsize = END(sechdrs[i].sh_size, conv);
- return file + END(sechdrs[i].sh_offset, conv);
- }
- }
- *secsize = 0;
- return NULL;
-}
-
diff --git a/elfops.c b/elfops.c
new file mode 100644
index 0000000..9ae77ef
--- /dev/null
+++ b/elfops.c
@@ -0,0 +1,57 @@
+/* The nasty work of reading 32 and 64-bit modules is in here. */
+#include <elf.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "depmod.h"
+#include "util.h"
+#include "logging.h"
+#include "elfops.h"
+#include "tables.h"
+
+/* Symbol types, returned by load_dep_syms */
+static const char *weak_sym = "W";
+static const char *undef_sym = "U";
+
+#define ELF32BIT
+#include "elfops_core.c"
+#undef ELF32BIT
+
+#define ELF64BIT
+#include "elfops_core.c"
+#undef ELF64BIT
+
+/*
+ * Check ELF file header.
+ */
+int elf_ident(void *file, unsigned long fsize, int *conv)
+{
+ /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
+ unsigned char *ident = file;
+
+ if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0)
+ return -ENOEXEC; /* Not an ELF object */
+ if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2)
+ return -EINVAL; /* Unknown endianness */
+
+ if (conv != NULL)
+ *conv = native_endianness() != ident[EI_DATA];
+ return ident[EI_CLASS];
+}
+
+void *get_section(void *file, unsigned long filesize,
+ const char *secname, unsigned long *secsize)
+{
+ int conv;
+
+ switch (elf_ident(file, filesize, &conv)) {
+ case ELFCLASS32:
+ return get_section32(file, filesize, secname, secsize, conv);
+ case ELFCLASS64:
+ return get_section64(file, filesize, secname, secsize, conv);
+ default:
+ return NULL;
+ }
+}
diff --git a/elfops.h b/elfops.h
new file mode 100644
index 0000000..dc10c3d
--- /dev/null
+++ b/elfops.h
@@ -0,0 +1,78 @@
+#ifndef MODINITTOOLS_MODULEOPS_H
+#define MODINITTOOLS_MODULEOPS_H
+#include <stdio.h>
+
+/* All the icky stuff to do with manipulating 64 and 32-bit modules
+ belongs here. */
+struct kernel_symbol32 {
+ char value[4];
+ char name[64 - 4];
+};
+
+struct kernel_symbol64 {
+ char value[8];
+ char name[64 - 8];
+};
+
+struct elf_file
+{
+ /* File operations */
+ struct module_ops *ops;
+
+ /* Convert endian? */
+ int conv;
+
+ /* File contents and length. */
+ void *data;
+ unsigned long len;
+};
+
+/* Tables extracted from module by ops->fetch_tables(). */
+struct module_tables
+{
+ unsigned int pci_size;
+ void *pci_table;
+ unsigned int usb_size;
+ void *usb_table;
+ unsigned int ieee1394_size;
+ void *ieee1394_table;
+ unsigned int ccw_size;
+ void *ccw_table;
+ unsigned int pnp_size;
+ void *pnp_table;
+ unsigned int pnp_card_size;
+ unsigned int pnp_card_offset;
+ void *pnp_card_table;
+ unsigned int input_size;
+ void *input_table;
+ unsigned int input_table_size;
+ unsigned int serio_size;
+ void *serio_table;
+ unsigned int of_size;
+ void *of_table;
+};
+
+struct module_ops
+{
+ struct string_table *(*load_strings)(struct elf_file *module,
+ const char *secname, struct string_table *tbl);
+ struct string_table *(*load_symbols)(struct elf_file *module);
+ struct string_table *(*load_dep_syms)(const char *pathname,
+ struct elf_file *module, struct string_table **types);
+ void (*fetch_tables)(struct elf_file *module,
+ struct module_tables *tables);
+ char *(*get_aliases)(struct elf_file *module, unsigned long *size);
+ char *(*get_modinfo)(struct elf_file *module, unsigned long *size);
+};
+
+extern struct module_ops mod_ops32, mod_ops64;
+
+int elf_ident(void *file, unsigned long fsize, int *conv);
+void *get_section(void *file, unsigned long filesize,
+ const char *secname, unsigned long *secsize);
+void *get_section32(void *file, unsigned long filesize,
+ const char *secname, unsigned long *secsize, int conv);
+void *get_section64(void *file, unsigned long filesize,
+ const char *secname, unsigned long *secsize, int conv);
+
+#endif /* MODINITTOOLS_MODULEOPS_H */
diff --git a/elfops_core.c b/elfops_core.c
new file mode 100644
index 0000000..8b7f4de
--- /dev/null
+++ b/elfops_core.c
@@ -0,0 +1,303 @@
+#if defined(ELF32BIT)
+
+#define PERBIT(x) x##32
+#define ElfPERBIT(x) Elf32_##x
+#define ELFPERBIT(x) ELF32_##x
+
+#elif defined(ELF64BIT)
+
+#define PERBIT(x) x##64
+#define ElfPERBIT(x) Elf64_##x
+#define ELFPERBIT(x) ELF64_##x
+
+#else
+# error "Undefined ELF word length"
+#endif
+
+void *PERBIT(get_section)(void *file,
+ unsigned long fsize,
+ const char *secname,
+ unsigned long *secsize,
+ int conv)
+{
+ ElfPERBIT(Ehdr) *hdr;
+ ElfPERBIT(Shdr) *sechdrs;
+ ElfPERBIT(Off) e_shoff;
+ ElfPERBIT(Half) e_shnum, e_shstrndx;
+
+ const char *secnames;
+ unsigned int i;
+
+ if (fsize > 0 && fsize < sizeof(*hdr))
+ return NULL;
+
+ hdr = file;
+ e_shoff = END(hdr->e_shoff, conv);
+ e_shnum = END(hdr->e_shnum, conv);
+ e_shstrndx = END(hdr->e_shstrndx, conv);
+
+ if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0]))
+ return NULL;
+
+ sechdrs = file + e_shoff;
+
+ if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv))
+ return NULL;
+
+ /* Find section by name, return pointer and size. */
+
+ secnames = file + END(sechdrs[e_shstrndx].sh_offset, conv);
+ for (i = 1; i < e_shnum; i++) {
+ if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) {
+ *secsize = END(sechdrs[i].sh_size, conv);
+ return file + END(sechdrs[i].sh_offset, conv);
+ }
+ }
+ *secsize = 0;
+ return NULL;
+}
+
+/* Load the given section: NULL on error. */
+static void *PERBIT(load_section)(struct elf_file *module,
+ const char *secname,
+ unsigned long *secsize)
+{
+ return PERBIT(get_section)(module->data, 0, secname, secsize, module->conv);
+}
+
+static struct string_table *PERBIT(load_strings)(struct elf_file *module,
+ const char *secname,
+ struct string_table *tbl)
+{
+ unsigned long size;
+ const char *strings;
+
+ strings = PERBIT(load_section)(module, secname, &size);
+ if (strings) {
+ /* Skip any zero padding. */
+ while (!strings[0]) {
+ strings++;
+ if (size-- <= 1)
+ return tbl;
+ }
+ for (; strings; strings = next_string(strings, &size))
+ tbl = NOFAIL(strtbl_add(strings, tbl));
+ }
+ return tbl;
+}
+
+static struct string_table *PERBIT(load_symbols)(struct elf_file *module)
+{
+ struct PERBIT(kernel_symbol) *ksyms;
+ struct string_table *symtbl;
+ unsigned long i, size;
+
+ symtbl = NULL;
+
+ /* New-style: strings are in this section. */
+ symtbl = PERBIT(load_strings)(module, "__ksymtab_strings", symtbl);
+ if (symtbl) {
+ /* GPL symbols too */
+ return PERBIT(load_strings)(module, "__ksymtab_strings_gpl",
+ symtbl);
+ }
+
+ /* Old-style. */
+ ksyms = PERBIT(load_section)(module, "__ksymtab", &size);
+ for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
+ symtbl = NOFAIL(strtbl_add(ksyms[i].name, symtbl));
+ ksyms = PERBIT(load_section)(module, "__gpl_ksymtab", &size);
+ for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
+ symtbl = NOFAIL(strtbl_add(ksyms[i].name, symtbl));
+
+ return symtbl;
+}
+
+static char *PERBIT(get_aliases)(struct elf_file *module, unsigned long *size)
+{
+ return PERBIT(load_section)(module, ".modalias", size);
+}
+
+static char *PERBIT(get_modinfo)(struct elf_file *module, unsigned long *size)
+{
+ return PERBIT(load_section)(module, ".modinfo", size);
+}
+
+#ifndef STT_REGISTER
+#define STT_REGISTER 13 /* Global register reserved to app. */
+#endif
+
+static struct string_table *PERBIT(load_dep_syms)(const char *pathname,
+ struct elf_file *module,
+ struct string_table **types)
+{
+ unsigned int i;
+ unsigned long size;
+ char *strings;
+ ElfPERBIT(Sym) *syms;
+ ElfPERBIT(Ehdr) *hdr;
+ int handle_register_symbols;
+ struct string_table *names;
+ int conv;
+
+ names = NULL;
+ *types = NULL;
+
+ strings = PERBIT(load_section)(module, ".strtab", &size);
+ syms = PERBIT(load_section)(module, ".symtab", &size);
+
+ if (!strings || !syms) {
+ warn("Couldn't find symtab and strtab in module %s\n",
+ pathname);
+ return NULL;
+ }
+
+ hdr = module->data;
+ conv = module->conv;
+
+ handle_register_symbols =
+ (END(hdr->e_machine, conv) == EM_SPARC ||
+ END(hdr->e_machine, conv) == EM_SPARCV9);
+
+ for (i = 1; i < size / sizeof(syms[0]); i++) {
+ if (END(syms[i].st_shndx, conv) == SHN_UNDEF) {
+ /* Look for symbol */
+ const char *name;
+ int weak;
+
+ name = strings + END(syms[i].st_name, conv);
+
+ /* Not really undefined: sparc gcc 3.3 creates
+ U references when you have global asm
+ variables, to avoid anyone else misusing
+ them. */
+ if (handle_register_symbols
+ && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info, conv))
+ == STT_REGISTER))
+ continue;
+
+ weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info, conv))
+ == STB_WEAK);
+ names = strtbl_add(name, names);
+ *types = strtbl_add(weak ? weak_sym : undef_sym, *types);
+ }
+ }
+ return names;
+}
+
+static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
+ ElfPERBIT(Shdr) *sechdrs,
+ ElfPERBIT(Sym) *sym,
+ unsigned int *secsize,
+ int conv)
+{
+ /* In BSS? Happens for empty device tables on
+ * recent GCC versions. */
+ if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
+ return NULL;
+
+ if (secsize)
+ *secsize = END(sym->st_size, conv);
+ return (void *)hdr
+ + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
+ + END(sym->st_value, conv);
+}
+
+/* FIXME: Check size, unless we end up using aliases anyway --RR */
+static void PERBIT(fetch_tables)(struct elf_file *module,
+ struct module_tables *tables)
+{
+ unsigned int i;
+ unsigned long size;
+ char *strings;
+ ElfPERBIT(Ehdr) *hdr;
+ ElfPERBIT(Sym) *syms;
+ ElfPERBIT(Shdr) *sechdrs;
+ int conv;
+
+ hdr = module->data;
+ conv = module->conv;
+
+ sechdrs = (void *)hdr + END(hdr->e_shoff, conv);
+ strings = PERBIT(load_section)(module, ".strtab", &size);
+ syms = PERBIT(load_section)(module, ".symtab", &size);
+
+ /* Don't warn again: we already have above */
+ if (!strings || !syms)
+ return;
+
+ tables->pci_table = NULL;
+ tables->usb_table = NULL;
+ tables->ccw_table = NULL;
+ tables->ieee1394_table = NULL;
+ tables->pnp_table = NULL;
+ tables->pnp_card_table = NULL;
+ tables->input_table = NULL;
+ tables->serio_table = NULL;
+ tables->of_table = NULL;
+
+ for (i = 0; i < size / sizeof(syms[0]); i++) {
+ char *name = strings + END(syms[i].st_name, conv);
+
+ if (!tables->pci_table && streq(name, "__mod_pci_device_table")) {
+ tables->pci_size = PERBIT(PCI_DEVICE_SIZE);
+ tables->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->usb_table && streq(name, "__mod_usb_device_table")) {
+ tables->usb_size = PERBIT(USB_DEVICE_SIZE);
+ tables->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->ccw_table && streq(name, "__mod_ccw_device_table")) {
+ tables->ccw_size = PERBIT(CCW_DEVICE_SIZE);
+ tables->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
+ tables->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
+ tables->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->pnp_table && streq(name, "__mod_pnp_device_table")) {
+ tables->pnp_size = PERBIT(PNP_DEVICE_SIZE);
+ tables->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
+ tables->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
+ tables->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ tables->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
+ }
+ else if (!tables->input_table && streq(name, "__mod_input_device_table")) {
+ tables->input_size = PERBIT(INPUT_DEVICE_SIZE);
+ tables->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ &tables->input_table_size,
+ conv);
+ }
+ else if (!tables->serio_table && streq(name, "__mod_serio_device_table")) {
+ tables->serio_size = PERBIT(SERIO_DEVICE_SIZE);
+ tables->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ else if (!tables->of_table && streq(name, "__mod_of_device_table")) {
+ tables->of_size = PERBIT(OF_DEVICE_SIZE);
+ tables->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
+ NULL, conv);
+ }
+ }
+}
+
+struct module_ops PERBIT(mod_ops) = {
+ .load_strings = PERBIT(load_strings),
+ .load_symbols = PERBIT(load_symbols),
+ .load_dep_syms = PERBIT(load_dep_syms),
+ .fetch_tables = PERBIT(fetch_tables),
+ .get_aliases = PERBIT(get_aliases),
+ .get_modinfo = PERBIT(get_modinfo),
+};
+
+#undef PERBIT
+#undef ElfPERBIT
+#undef ELFPERBIT
diff --git a/modinfo.c b/modinfo.c
index 07199c2..4f16c78 100644
--- a/modinfo.c
+++ b/modinfo.c
@@ -14,6 +14,7 @@
#include <sys/mman.h>
#include "util.h"
+#include "elfops.h"
#include "zlibsupport.h"
#include "testing.h"
diff --git a/modprobe.c b/modprobe.c
index c2d0ef6..c0680a7 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -40,6 +40,7 @@
#include <syslog.h>
#include "util.h"
+#include "elfops.h"
#include "zlibsupport.h"
#include "logging.h"
#include "index.h"
diff --git a/moduleops.c b/moduleops.c
deleted file mode 100644
index 1ee52be..0000000
--- a/moduleops.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* The nasty work of reading 32 and 64-bit modules is in here. */
-#include <elf.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include "depmod.h"
-#include "util.h"
-#include "logging.h"
-#include "moduleops.h"
-#include "tables.h"
-
-#define PERBIT(x) x##32
-#define ElfPERBIT(x) Elf32_##x
-#define ELFPERBIT(x) ELF32_##x
-#include "moduleops_core.c"
-
-#undef PERBIT
-#undef ElfPERBIT
-#undef ELFPERBIT
-#define PERBIT(x) x##64
-#define ElfPERBIT(x) Elf64_##x
-#define ELFPERBIT(x) ELF64_##x
-#include "moduleops_core.c"
diff --git a/moduleops.h b/moduleops.h
deleted file mode 100644
index 67c60ca..0000000
--- a/moduleops.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef MODINITTOOLS_MODULEOPS_H
-#define MODINITTOOLS_MODULEOPS_H
-#include <stdio.h>
-
-/* All the icky stuff to do with manipulating 64 and 32-bit modules
- belongs here. */
-struct kernel_symbol32 {
- char value[4];
- char name[64 - 4];
-};
-
-struct kernel_symbol64 {
- char value[8];
- char name[64 - 8];
-};
-
-struct module_ops
-{
- void (*load_symbols)(struct module *module);
- void (*calculate_deps)(struct module *module);
- void (*fetch_tables)(struct module *module);
- char *(*get_aliases)(struct module *module, unsigned long *size);
- char *(*get_modinfo)(struct module *module, unsigned long *size);
-};
-
-extern struct module_ops mod_ops32, mod_ops64;
-
-#endif /* MODINITTOOLS_MODULEOPS_H */
diff --git a/moduleops_core.c b/moduleops_core.c
deleted file mode 100644
index 0313e27..0000000
--- a/moduleops_core.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* Load the given section: NULL on error. */
-static void *PERBIT(load_section)(ElfPERBIT(Ehdr) *hdr,
- const char *secname,
- unsigned long *secsize,
- int conv)
-{
- return PERBIT(get_section)(hdr, 0, secname, secsize, conv);
-}
-
-static void PERBIT(load_symbols)(struct module *module)
-{
- struct PERBIT(kernel_symbol) *ksyms;
- char *ksymstrings;
- unsigned long i, size;
-
- /* New-style: strings are in this section. */
- ksymstrings = PERBIT(load_section)(module->data, "__ksymtab_strings",
- &size, module->conv);
- if (ksymstrings) {
- unsigned int i = 0;
- for (;;) {
- /* Skip any zero padding. */
- while (!ksymstrings[i])
- if (++i >= size)
- return;
- add_symbol(ksymstrings+i, module);
- i += strlen(ksymstrings+i);
- }
- /* GPL symbols too */
- ksymstrings = PERBIT(load_section)(module->data,
- "__ksymtab_strings_gpl",
- &size, module->conv);
- for (;;) {
- /* Skip any zero padding. */
- while (!ksymstrings[i])
- if (++i >= size)
- return;
- add_symbol(ksymstrings+i, module);
- i += strlen(ksymstrings+i);
- }
- return;
- }
-
- /* Old-style. */
- ksyms = PERBIT(load_section)(module->data, "__ksymtab", &size,
- module->conv);
- for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
- add_symbol(ksyms[i].name, module);
- ksyms = PERBIT(load_section)(module->data, "__gpl_ksymtab", &size,
- module->conv);
- for (i = 0; i < size / sizeof(struct PERBIT(kernel_symbol)); i++)
- add_symbol(ksyms[i].name, module);
-}
-
-static char *PERBIT(get_aliases)(struct module *module, unsigned long *size)
-{
- return PERBIT(load_section)(module->data, ".modalias", size,
- module->conv);
-}
-
-static char *PERBIT(get_modinfo)(struct module *module, unsigned long *size)
-{
- return PERBIT(load_section)(module->data, ".modinfo", size,
- module->conv);
-}
-
-#ifndef STT_REGISTER
-#define STT_REGISTER 13 /* Global register reserved to app. */
-#endif
-
-/* Calculate the dependencies for this module */
-static void PERBIT(calculate_deps)(struct module *module)
-{
- unsigned int i;
- unsigned long size;
- char *strings;
- ElfPERBIT(Sym) *syms;
- ElfPERBIT(Ehdr) *hdr;
- int handle_register_symbols;
-
- strings = PERBIT(load_section)(module->data, ".strtab", &size,
- module->conv);
- syms = PERBIT(load_section)(module->data, ".symtab", &size,
- module->conv);
-
- module->num_deps = 0;
- module->deps = NULL;
-
- if (!strings || !syms) {
- warn("Couldn't find symtab and strtab in module %s\n",
- module->pathname);
- return;
- }
-
- hdr = module->data;
- handle_register_symbols = 0;
- if (END(hdr->e_machine, module->conv) == EM_SPARC ||
- END(hdr->e_machine, module->conv) == EM_SPARCV9)
- handle_register_symbols = 1;
-
- for (i = 1; i < size / sizeof(syms[0]); i++) {
- if (END(syms[i].st_shndx, module->conv) == SHN_UNDEF) {
- /* Look for symbol */
- const char *name;
- struct module *owner;
- int weak;
-
- name = strings + END(syms[i].st_name, module->conv);
-
- /* Not really undefined: sparc gcc 3.3 creates
- U references when you have global asm
- variables, to avoid anyone else misusing
- them. */
- if (handle_register_symbols
- && (ELFPERBIT(ST_TYPE)(END(syms[i].st_info,
- module->conv))
- == STT_REGISTER))
- continue;
-
- weak = (ELFPERBIT(ST_BIND)(END(syms[i].st_info,
- module->conv))
- == STB_WEAK);
- owner = find_symbol(name, module->pathname, weak);
- if (owner) {
- info("%s needs \"%s\": %s\n",
- module->pathname, name,
- owner->pathname);
- add_dep(module, owner);
- }
- }
- }
-}
-
-static void *PERBIT(deref_sym)(ElfPERBIT(Ehdr) *hdr,
- ElfPERBIT(Shdr) *sechdrs,
- ElfPERBIT(Sym) *sym,
- unsigned int *secsize,
- int conv)
-{
- /* In BSS? Happens for empty device tables on
- * recent GCC versions. */
- if (END(sechdrs[END(sym->st_shndx, conv)].sh_type,conv) == SHT_NOBITS)
- return NULL;
-
- if (secsize)
- *secsize = END(sym->st_size, conv);
- return (void *)hdr
- + END(sechdrs[END(sym->st_shndx, conv)].sh_offset, conv)
- + END(sym->st_value, conv);
-}
-
-/* FIXME: Check size, unless we end up using aliases anyway --RR */
-static void PERBIT(fetch_tables)(struct module *module)
-{
- unsigned int i;
- unsigned long size;
- char *strings;
- ElfPERBIT(Ehdr) *hdr;
- ElfPERBIT(Sym) *syms;
- ElfPERBIT(Shdr) *sechdrs;
-
- hdr = module->data;
-
- sechdrs = (void *)hdr + END(hdr->e_shoff, module->conv);
- strings = PERBIT(load_section)(hdr, ".strtab", &size, module->conv);
- syms = PERBIT(load_section)(hdr, ".symtab", &size, module->conv);
-
- /* Don't warn again: we already have above */
- if (!strings || !syms)
- return;
-
- module->pci_table = NULL;
- module->usb_table = NULL;
- module->ccw_table = NULL;
- module->ieee1394_table = NULL;
- module->pnp_table = NULL;
- module->pnp_card_table = NULL;
- module->input_table = NULL;
- module->serio_table = NULL;
- module->of_table = NULL;
-
- for (i = 0; i < size / sizeof(syms[0]); i++) {
- char *name = strings + END(syms[i].st_name, module->conv);
-
- if (!module->pci_table && streq(name, "__mod_pci_device_table")) {
- module->pci_size = PERBIT(PCI_DEVICE_SIZE);
- module->pci_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->usb_table && streq(name, "__mod_usb_device_table")) {
- module->usb_size = PERBIT(USB_DEVICE_SIZE);
- module->usb_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->ccw_table && streq(name, "__mod_ccw_device_table")) {
- module->ccw_size = PERBIT(CCW_DEVICE_SIZE);
- module->ccw_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->ieee1394_table && streq(name, "__mod_ieee1394_device_table")) {
- module->ieee1394_size = PERBIT(IEEE1394_DEVICE_SIZE);
- module->ieee1394_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->pnp_table && streq(name, "__mod_pnp_device_table")) {
- module->pnp_size = PERBIT(PNP_DEVICE_SIZE);
- module->pnp_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->pnp_card_table && streq(name, "__mod_pnp_card_device_table")) {
- module->pnp_card_size = PERBIT(PNP_CARD_DEVICE_SIZE);
- module->pnp_card_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- module->pnp_card_offset = PERBIT(PNP_CARD_DEVICE_OFFSET);
- }
- else if (!module->input_table && streq(name, "__mod_input_device_table")) {
- module->input_size = PERBIT(INPUT_DEVICE_SIZE);
- module->input_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- &module->input_table_size,
- module->conv);
- }
- else if (!module->serio_table && streq(name, "__mod_serio_device_table")) {
- module->serio_size = PERBIT(SERIO_DEVICE_SIZE);
- module->serio_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- else if (!module->of_table && streq(name, "__mod_of_device_table")) {
- module->of_size = PERBIT(OF_DEVICE_SIZE);
- module->of_table = PERBIT(deref_sym)(hdr, sechdrs, &syms[i],
- NULL, module->conv);
- }
- }
-}
-
-struct module_ops PERBIT(mod_ops) = {
- .load_symbols = PERBIT(load_symbols),
- .calculate_deps = PERBIT(calculate_deps),
- .fetch_tables = PERBIT(fetch_tables),
- .get_aliases = PERBIT(get_aliases),
- .get_modinfo = PERBIT(get_modinfo),
-};
diff --git a/tables.c b/tables.c
index e3f005f..ecbf030 100644
--- a/tables.c
+++ b/tables.c
@@ -44,13 +44,14 @@ void output_pci_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct pci_device_id *e;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->pci_table)
+ if (!t->pci_table)
continue;
make_shortname(shortname, i->pathname);
- for (e = i->pci_table; e->vendor; e = (void *)e + i->pci_size)
- output_pci_entry(e, shortname, out, i->conv);
+ for (e = t->pci_table; e->vendor; e = (void *)e + t->pci_size)
+ output_pci_entry(e, shortname, out, i->file.conv);
}
}
@@ -92,15 +93,16 @@ void output_usb_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct usb_device_id *e;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->usb_table)
+ if (!t->usb_table)
continue;
make_shortname(shortname, i->pathname);
- for (e = i->usb_table;
+ for (e = t->usb_table;
e->idVendor || e->bDeviceClass || e->bInterfaceClass;
- e = (void *)e + i->usb_size)
- output_usb_entry(e, shortname, out, i->conv);
+ e = (void *)e + t->usb_size)
+ output_usb_entry(e, shortname, out, i->file.conv);
}
}
@@ -126,14 +128,15 @@ void output_ieee1394_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct ieee1394_device_id *fw;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->ieee1394_table)
+ if (!t->ieee1394_table)
continue;
make_shortname(shortname, i->pathname);
- for (fw = i->ieee1394_table; fw->match_flags;
- fw = (void *) fw + i->ieee1394_size)
- output_ieee1394_entry(fw, shortname, out, i->conv);
+ for (fw = t->ieee1394_table; fw->match_flags;
+ fw = (void *) fw + t->ieee1394_size)
+ output_ieee1394_entry(fw, shortname, out, i->file.conv);
}
}
@@ -158,15 +161,16 @@ void output_ccw_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct ccw_device_id *e;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->ccw_table)
+ if (!t->ccw_table)
continue;
make_shortname(shortname, i->pathname);
- for (e = i->ccw_table;
+ for (e = t->ccw_table;
e->cu_type || e->cu_model || e->dev_type || e->dev_model;
- e = (void *) e + i->ccw_size)
- output_ccw_entry(e, shortname, out, i->conv);
+ e = (void *) e + t->ccw_size)
+ output_ccw_entry(e, shortname, out, i->file.conv);
}
}
@@ -197,13 +201,14 @@ void output_isapnp_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (i->pnp_table) {
+ if (t->pnp_table) {
struct pnp_device_id *id;
make_shortname(shortname, i->pathname);
- for (id = i->pnp_table;
+ for (id = t->pnp_table;
id->id[0];
- id = (void *)id + i->pnp_size) {
+ id = (void *)id + t->pnp_size) {
fprintf(out, "%-20s", shortname);
fprintf(out, " 0xffff 0xffff ");
fprintf(out, " 0x00000000 "); /* driver_data */
@@ -211,15 +216,15 @@ void output_isapnp_table(struct module *modules, FILE *out, char *dirname)
fprintf(out, "\n");
}
}
- if (i->pnp_card_table) {
+ if (t->pnp_card_table) {
void *id;
make_shortname(shortname, i->pathname);
- for (id = i->pnp_card_table;
+ for (id = t->pnp_card_table;
((char *)id)[0];
- id += i->pnp_card_size) {
+ id += t->pnp_card_size) {
int idx;
struct pnp_card_devid *devid
- = id + i->pnp_card_offset;
+ = id + t->pnp_card_offset;
fprintf(out, "%-20s", shortname);
put_isapnp_id(out, id);
@@ -419,46 +424,47 @@ void output_input_table(struct module *modules, FILE *out, char *dirname)
void *p;
char shortname[strlen(i->pathname) + 1];
int done = 0;
+ struct module_tables *t = &i->tables;
- if (!i->input_table)
+ if (!t->input_table)
continue;
make_shortname(shortname, i->pathname);
/* Guess what size it really is, based on size of
* whole table. Table changed in 2.6.14. This is a hack. */
- if (i->input_size == sizeof(struct input_device_id_old_64)) {
- if ((i->input_table_size % i->input_size) != 0) {
- i->input_size
+ if (t->input_size == sizeof(struct input_device_id_old_64)) {
+ if ((t->input_table_size % t->input_size) != 0) {
+ t->input_size
= sizeof(struct input_device_id_64);
}
} else {
- if ((i->input_table_size % i->input_size) != 0) {
- i->input_size
+ if ((t->input_table_size % t->input_size) != 0) {
+ t->input_size
= sizeof(struct input_device_id_32);
}
}
- for (p = i->input_table; !done; p += i->input_size) {
- switch (i->input_size) {
+ for (p = t->input_table; !done; p += t->input_size) {
+ switch (t->input_size) {
case sizeof(struct input_device_id_old_64):
done = output_input_entry_64_old(p,
shortname,
out,
- i->conv);
+ i->file.conv);
break;
case sizeof(struct input_device_id_64):
done = output_input_entry_64(p, shortname,
- out, i->conv);
+ out, i->file.conv);
break;
case sizeof(struct input_device_id_old_32):
done = output_input_entry_32_old(p,
shortname,
out,
- i->conv);
+ i->file.conv);
break;
case sizeof(struct input_device_id_32):
done = output_input_entry_32(p, shortname,
- out, i->conv);
+ out, i->file.conv);
break;
}
}
@@ -486,12 +492,13 @@ void output_serio_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct serio_device_id *e;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->serio_table)
+ if (!t->serio_table)
continue;
make_shortname(shortname, i->pathname);
- for (e = i->serio_table; e->type || e->proto; e = (void *)e + i->serio_size)
+ for (e = t->serio_table; e->type || e->proto; e = (void *)e + t->serio_size)
output_serio_entry(e, shortname, out);
}
}
@@ -544,13 +551,14 @@ void output_of_table(struct module *modules, FILE *out, char *dirname)
for (i = modules; i; i = i->next) {
struct of_device_id *e;
char shortname[strlen(i->pathname) + 1];
+ struct module_tables *t = &i->tables;
- if (!i->of_table)
+ if (!t->of_table)
continue;
make_shortname(shortname, i->pathname);
- for (e = i->of_table; e->name[0]|e->type[0]|e->compatible[0];
- e = (void *)e + i->of_size)
+ for (e = t->of_table; e->name[0]|e->type[0]|e->compatible[0];
+ e = (void *)e + t->of_size)
output_of_entry(e, shortname, out);
}
}
diff --git a/util.c b/util.c
index 482363b..3802a02 100644
--- a/util.c
+++ b/util.c
@@ -114,6 +114,52 @@ char *underscores(char *string)
}
/*
+ * strtbl_add - add a string to a string table.
+ *
+ * @str: string to add
+ * @tbl: current string table. NULL = allocate new table
+ *
+ * Allocates an array of pointers to strings.
+ * The strings themselves are not actually kept in the table.
+ *
+ * Returns reallocated and updated string table. NULL = out of memory.
+ *
+ * Implementation note: The string table is designed to be lighter-weight
+ * and faster than a more conventional linked list that stores the strings
+ * in the list elements, as it does far fewer malloc/realloc calls
+ * and avoids copying entirely.
+ */
+struct string_table *strtbl_add(const char *str, struct string_table *tbl)
+{
+ if (tbl == NULL) {
+ const char max = 100;
+ tbl = malloc(sizeof(*tbl) + sizeof(char *) * max);
+ if (!tbl)
+ return NULL;
+ tbl->max = max;
+ tbl->cnt = 0;
+ }
+ if (tbl->cnt >= tbl->max) {
+ tbl->max *= 2;
+ tbl = realloc(tbl, sizeof(*tbl) + sizeof(char *) * tbl->max);
+ if (!tbl)
+ return NULL;
+ }
+ tbl->str[tbl->cnt] = str;
+ tbl->cnt += 1;
+
+ return tbl;
+}
+
+/*
+ * strtbl_destroy - string table destructor
+ */
+void strtbl_free(struct string_table *tbl)
+{
+ free(tbl);
+}
+
+/*
* Get the basename in a pathname.
* Unlike the standard implementation, this does not copy the string.
*/
@@ -157,48 +203,3 @@ int __attribute__ ((pure)) native_endianness()
return (char) *((uint32_t*)("\1\0\0\2"));
}
-/*
- * Check ELF file header.
- */
-int elf_ident(void *file, unsigned long fsize, int *conv)
-{
- /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
- unsigned char *ident = file;
-
- if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0)
- return -ENOEXEC; /* Not an ELF object */
- if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2)
- return -EINVAL; /* Unknown endianness */
-
- if (conv != NULL)
- *conv = native_endianness() != ident[EI_DATA];
- return ident[EI_CLASS];
-}
-
-#define PERBIT(x) x##32
-#define ElfPERBIT(x) Elf32_##x
-#define ELFPERBIT(x) ELF32_##x
-#include "elf_core.c"
-
-#undef PERBIT
-#undef ElfPERBIT
-#undef ELFPERBIT
-#define PERBIT(x) x##64
-#define ElfPERBIT(x) Elf64_##x
-#define ELFPERBIT(x) ELF64_##x
-#include "elf_core.c"
-
-void *get_section(void *file, unsigned long filesize,
- const char *secname, unsigned long *secsize)
-{
- int conv;
-
- switch (elf_ident(file, filesize, &conv)) {
- case ELFCLASS32:
- return get_section32(file, filesize, secname, secsize, conv);
- case ELFCLASS64:
- return get_section64(file, filesize, secname, secsize, conv);
- default:
- return NULL;
- }
-}
diff --git a/util.h b/util.h
index fbda299..d6112b0 100644
--- a/util.h
+++ b/util.h
@@ -3,12 +3,21 @@
#include <stdio.h>
+struct string_table
+{
+ unsigned int cnt;
+ unsigned int max;
+ const char *str[0];
+};
+
char *getline_wrapped(FILE *file, unsigned int *linenum);
void filename2modname(char *modname, const char *filename);
char *underscores(char *string);
char *my_basename(const char *path);
+struct string_table *strtbl_add(const char *str, struct string_table *tbl);
+
const char *next_string(const char *string, unsigned long *secsize);
/*
@@ -31,14 +40,6 @@ static inline void __swap_bytes(const void *src, void *dest, unsigned int size)
int native_endianness(void);
-int elf_ident(void *file, unsigned long fsize, int *conv);
-void *get_section(void *file, unsigned long filesize,
- const char *secname, unsigned long *secsize);
-void *get_section32(void *file, unsigned long filesize,
- const char *secname, unsigned long *secsize, int conv);
-void *get_section64(void *file, unsigned long filesize,
- const char *secname, unsigned long *secsize, int conv);
-
#define streq(a,b) (strcmp((a),(b)) == 0)
#define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0)