diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2008-11-25 08:23:15 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2008-11-25 08:23:15 +0000 |
commit | adac189d8f791809898e770aa7ad329bbc0c8d2a (patch) | |
tree | bdb2ca453106cc6a8d7eb2ca78dd67887d7e14d2 /core/busybox | |
parent | 36b7d352a71fcb43221c3c834ba94383d4f989b1 (diff) | |
download | aports-adac189d8f791809898e770aa7ad329bbc0c8d2a.tar.bz2 aports-adac189d8f791809898e770aa7ad329bbc0c8d2a.tar.xz |
core/busybox: upgrade to 1.13.0
Diffstat (limited to 'core/busybox')
-rw-r--r-- | core/busybox/APKBUILD | 60 | ||||
-rw-r--r-- | core/busybox/bb-modprobe-v9.diff | 10876 | ||||
-rw-r--r-- | core/busybox/busybox-1.12.0-mdev-exec.patch | 11 | ||||
-rw-r--r-- | core/busybox/busybox-1.12.1-grep.patch | 27 | ||||
-rw-r--r-- | core/busybox/busybox-1.12.1-iproute-metric.patch | 36 | ||||
-rw-r--r-- | core/busybox/busybox-1.12.1-r1 | 851 | ||||
-rw-r--r-- | core/busybox/busybox-devmem.patch | 128 | ||||
-rw-r--r-- | core/busybox/busyboxconfig | 141 |
8 files changed, 106 insertions, 12024 deletions
diff --git a/core/busybox/APKBUILD b/core/busybox/APKBUILD index 74a0459b..6d50aa69 100644 --- a/core/busybox/APKBUILD +++ b/core/busybox/APKBUILD @@ -1,40 +1,34 @@ pkgname=busybox -pkgver=1.12.1 -pkgrel=6 +pkgver=1.13.0 +pkgrel=0 pkgdesc="Size optimized toolbox of many common UNIX utilities" url=http://busybox.net license=GPL-2 depends=uclibc -source="http://busybox.net/downloads/busybox-1.12.1.tar.bz2 - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-basename.patch - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-grep.patch - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-lineedit.patch - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-login.patch - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-standalone.patch - http://busybox.net/downloads/fixes-1.12.1/busybox-1.12.1-vi.patch - bb-modprobe-v9.diff +source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2 + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-ash.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-getopt.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-id.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-inotify.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-klogd.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-lineedit.patch + http://busybox.net/downloads/fixes-$pkgver/$pkgname-$pkgver-modprobe.patch $pkgname-1.12.1-vi-path.patch $pkgname-1.11.1-bb.patch - $pkgname-1.12.0-mdev-exec.patch - $pkgname-1.12.1-iproute-metric.patch busyboxconfig" build() { cd $srcdir/$pkgname-$pkgver #patches - patch -p1 -i ../$pkgname-1.12.1-basename.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-grep.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-lineedit.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-login.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-standalone.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-vi.patch || return 1 - patch -p1 -i ../$pkgname-1.12.1-vi-path.patch || return 1 - patch -p1 -i ../$pkgname-1.11.1-bb.patch || return 1 - patch -p0 -i ../$pkgname-1.12.0-mdev-exec.patch || return 1 - patch -p0 -i ../$pkgname-1.12.1-iproute-metric.patch || return 1 - patch -p0 -i ../bb-modprobe-v9.diff || return 1 + for i in ../*.patch; do + msg "Applying $i" + if ! patch -p1 -i $i; then + error "$i failed" + return 1 + fi + done cp ../busyboxconfig .config make silentoldconfig || return 1 @@ -42,16 +36,14 @@ build() { make install DESTDIR=$pkgdir } -md5sums="dc2e5e00d6fee8229ae92884c68733a7 busybox-1.12.1.tar.bz2 -70fedd0f03d92bceae053904bca11c1d busybox-1.12.1-basename.patch -76273f1580295a12270dcca0cdeb9a27 busybox-1.12.1-grep.patch -62efeac9a6da03154cfb677935e84c34 busybox-1.12.1-lineedit.patch -9c5d79a7426cfc2b4d7d1f0474d59b75 busybox-1.12.1-login.patch -291c8564e3a25447bbcbfcc6865391cb busybox-1.12.1-standalone.patch -724e2613f9c9308f24a9c2de504de9a0 busybox-1.12.1-vi.patch -a8aff3962d4481e8b402e739703fbe38 bb-modprobe-v9.diff +md5sums="c9159004d24ea7b9f6a816048c5cd1e6 busybox-1.13.0.tar.bz2 +4d92a48bc78034d8d7db87034f27ab27 busybox-1.13.0-ash.patch +c559acc16820d7351510ad9a71a463fd busybox-1.13.0-getopt.patch +93952435bdf3fc81217127f127a4233f busybox-1.13.0-id.patch +de12cfa77e5fa6923eac11fe5d8305c5 busybox-1.13.0-inotify.patch +38a2101d0e01a736864ee0d3fb657571 busybox-1.13.0-klogd.patch +c6ed3d86e147e0691fdd00bce335d901 busybox-1.13.0-lineedit.patch +209bd64eba39e1ecfd119bf865aaa1d6 busybox-1.13.0-modprobe.patch f5a8ae3145aa249868c1a1abc319c228 busybox-1.12.1-vi-path.patch 4c0f3b486eaa0674961b7ddcd0c60a9b busybox-1.11.1-bb.patch -b4ce6235028c2c20fa367375534c3a18 busybox-1.12.0-mdev-exec.patch -54de0abe27e0ad362973be7fa81c487e busybox-1.12.1-iproute-metric.patch -a0c5e5edabf0a6cc73a2c3ce0ba60d74 busyboxconfig" +0a32b03209b82e37e085f0bd06985518 busyboxconfig" diff --git a/core/busybox/bb-modprobe-v9.diff b/core/busybox/bb-modprobe-v9.diff deleted file mode 100644 index b3885988..00000000 --- a/core/busybox/bb-modprobe-v9.diff +++ /dev/null @@ -1,10876 +0,0 @@ -Index: modutils/lsmod.c -=================================================================== ---- modutils/lsmod.c (revision 23360) -+++ modutils/lsmod.c (working copy) -@@ -3,192 +3,77 @@ - * Mini lsmod implementation for busybox - * - * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> -+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com> - * -- * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and -- * Nicolas Ferre <nicolas.ferre@alcove.fr> to support pre 2.1 kernels -- * (which lack the query_module() interface). -- * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - - #include "libbb.h" -+#include "modutils.h" - -+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -+enum { -+ TAINT_PROPRIETORY_MODULE = (1<<0), -+ TAINT_FORCED_MODULE = (1<<1), -+ TAINT_UNSAFE_SMP = (1<<2), -+}; - --#if !ENABLE_FEATURE_CHECK_TAINTED_MODULE --static void check_tainted(void) { bb_putchar('\n'); } --#else --#define TAINT_FILENAME "/proc/sys/kernel/tainted" --#define TAINT_PROPRIETORY_MODULE (1<<0) --#define TAINT_FORCED_MODULE (1<<1) --#define TAINT_UNSAFE_SMP (1<<2) -- - static void check_tainted(void) - { -- int tainted; -- FILE *f; -- -- tainted = 0; -- f = fopen_for_read(TAINT_FILENAME); -- if (f) { -- fscanf(f, "%d", &tainted); -- fclose(f); -+ int tainted = 0; -+ char *buf = xmalloc_open_read_close("/proc/sys/kernel/tainted", NULL); -+ if (buf) { -+ tainted = atoi(buf); -+ if (ENABLE_FEATURE_CLEAN_UP) -+ free(buf); - } -+ - if (tainted) { - printf(" Tainted: %c%c%c\n", - tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G', - tainted & TAINT_FORCED_MODULE ? 'F' : ' ', - tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); - } else { -- printf(" Not tainted\n"); -+ puts(" Not tainted"); - } - } -+#else -+static void check_tainted(void) { putchar('\n'); } - #endif - --#if ENABLE_FEATURE_QUERY_MODULE_INTERFACE -- --struct module_info --{ -- unsigned long addr; -- unsigned long size; -- unsigned long flags; -- long usecount; --}; -- -- --int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); -- --enum { --/* Values for query_module's which. */ -- QM_MODULES = 1, -- QM_DEPS = 2, -- QM_REFS = 3, -- QM_SYMBOLS = 4, -- QM_INFO = 5, -- --/* Bits of module.flags. */ -- NEW_MOD_RUNNING = 1, -- NEW_MOD_DELETED = 2, -- NEW_MOD_AUTOCLEAN = 4, -- NEW_MOD_VISITED = 8, -- NEW_MOD_USED_ONCE = 16, -- NEW_MOD_INITIALIZING = 64 --}; -- - int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) - { -- struct module_info info; -- char *module_names, *mn, *deps, *dn; -- size_t bufsize, depsize, nmod, count, i, j; -- -- module_names = deps = NULL; -- bufsize = depsize = 0; -- while (query_module(NULL, QM_MODULES, module_names, bufsize, &nmod)) { -- if (errno != ENOSPC) bb_perror_msg_and_die("QM_MODULES"); -- module_names = xmalloc(bufsize = nmod); -- } -- -- deps = xmalloc(depsize = 256); -- printf("Module\t\t\tSize Used by"); -+#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT -+ char *token[4]; -+ parser_t *parser = config_open("/proc/modules"); -+ printf("Module Size Used by"); - check_tainted(); - -- for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { -- if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { -- if (errno == ENOENT) { -- /* The module was removed out from underneath us. */ -- continue; -- } -- /* else choke */ -- bb_perror_msg_and_die("module %s: QM_INFO", mn); -+ if (ENABLE_FEATURE_2_4_MODULES && -+ get_linux_version_code() < KERNEL_VERSION(2,6,0)) { -+ while (config_read(parser, token, 4, 3, "# \t", PARSE_NORMAL)) { -+ if (token[3] != NULL && token[3][0] == '[') { -+ token[3]++; -+ token[3][strlen(token[3])-1] = '\0'; -+ } else -+ token[3] = (char *) ""; -+ printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]); - } -- while (query_module(mn, QM_REFS, deps, depsize, &count)) { -- if (errno == ENOENT) { -- /* The module was removed out from underneath us. */ -- continue; -- } else if (errno != ENOSPC) -- bb_perror_msg_and_die("module %s: QM_REFS", mn); -- deps = xrealloc(deps, count); -+ } else { -+ while (config_read(parser, token, 4, 4, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) { -+ // N.B. token[3] is either '-' (module is not used by others) -+ // or comma-separated list ended by comma -+ // so trimming the trailing char is just what we need! -+ token[3][strlen(token[3])-1] = '\0'; -+ printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]); - } -- printf("%-20s%8lu%4ld", mn, info.size, info.usecount); -- if (info.flags & NEW_MOD_DELETED) -- printf(" (deleted)"); -- else if (info.flags & NEW_MOD_INITIALIZING) -- printf(" (initializing)"); -- else if (!(info.flags & NEW_MOD_RUNNING)) -- printf(" (uninitialized)"); -- else { -- if (info.flags & NEW_MOD_AUTOCLEAN) -- printf(" (autoclean) "); -- if (!(info.flags & NEW_MOD_USED_ONCE)) -- printf(" (unused)"); -- } -- if (count) -- printf(" ["); -- for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) { -- printf("%s%s", dn, (j==count-1)? "":" "); -- } -- if (count) -- bb_putchar(']'); -- -- bb_putchar('\n'); - } -- --#if ENABLE_FEATURE_CLEAN_UP -- free(module_names); --#endif -- -- return 0; --} -- --#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */ -- --int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; --int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) --{ -- FILE *file = xfopen_for_read("/proc/modules"); -- -- printf("Module Size Used by"); -- check_tainted(); --#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT -- { -- char *line; -- while ((line = xmalloc_fgets(file)) != NULL) { -- char *tok; -- -- tok = strtok(line, " \t"); -- printf("%-19s", tok); -- tok = strtok(NULL, " \t\n"); -- printf(" %8s", tok); -- tok = strtok(NULL, " \t\n"); -- /* Null if no module unloading support. */ -- if (tok) { -- printf(" %s", tok); -- tok = strtok(NULL, "\n"); -- if (!tok) -- tok = (char*)""; -- /* New-style has commas, or -. If so, -- truncate (other fields might follow). */ -- else if (strchr(tok, ',')) { -- tok = strtok(tok, "\t "); -- /* Strip trailing comma. */ -- if (tok[strlen(tok)-1] == ',') -- tok[strlen(tok)-1] = '\0'; -- } else if (tok[0] == '-' -- && (tok[1] == '\0' || isspace(tok[1])) -- ) { -- tok = (char*)""; -- } -- printf(" %s", tok); -- } -- bb_putchar('\n'); -- free(line); -- } -- fclose(file); -- } -+ if (ENABLE_FEATURE_CLEAN_UP) -+ config_close(parser); - #else -- xprint_and_close_file(file); --#endif /* CONFIG_FEATURE_2_6_MODULES */ -+ check_tainted(); -+ xprint_and_close_file(xfopen_for_read("/proc/modules")); -+#endif - return EXIT_SUCCESS; - } -- --#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */ -Index: modutils/rmmod.c -=================================================================== ---- modutils/rmmod.c (revision 23360) -+++ modutils/rmmod.c (working copy) -@@ -3,98 +3,46 @@ - * Mini rmmod implementation for busybox - * - * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> -+ * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi> - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - - #include "libbb.h" -+#include "modutils.h" - --#ifdef __UCLIBC__ --extern int delete_module(const char *module, unsigned int flags); --#else --# include <sys/syscall.h> --# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) --#endif -- --#if ENABLE_FEATURE_2_6_MODULES --static void filename2modname(char *modname, const char *afterslash) --{ -- unsigned int i; -- int kr_chk = 1; -- -- if (ENABLE_FEATURE_2_4_MODULES -- && get_linux_version_code() <= KERNEL_VERSION(2,6,0)) -- kr_chk = 0; -- -- /* Convert to underscores, stop at first . */ -- for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) { -- if (kr_chk && (afterslash[i] == '-')) -- modname[i] = '_'; -- else -- modname[i] = afterslash[i]; -- } -- modname[i] = '\0'; --} --#else --void filename2modname(char *modname, const char *afterslash); --#endif -- --// There really should be a header file for this... -- --int query_module(const char *name, int which, void *buf, -- size_t bufsize, size_t *ret); -- - int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; --int rmmod_main(int argc, char **argv) -+int rmmod_main(int argc UNUSED_PARAM, char **argv) - { -- int n, ret = EXIT_SUCCESS; -+ int n; - unsigned int flags = O_NONBLOCK|O_EXCL; -+ char modname[MODULE_NAME_LEN]; - --#define misc_buf bb_common_bufsiz1 -- - /* Parse command line. */ -- n = getopt32(argv, "wfa"); -+ n = getopt32(argv, "wfas"); // -s ignored -+ argv += optind; -+ - if (n & 1) // --wait - flags &= ~O_NONBLOCK; - if (n & 2) // --force - flags |= O_TRUNC; - if (n & 4) { - /* Unload _all_ unused modules via NULL delete_module() call */ -- /* until the number of modules does not change */ -- size_t nmod = 0; /* number of modules */ -- size_t pnmod = -1; /* previous number of modules */ -- -- while (nmod != pnmod) { -- if (delete_module(NULL, flags) != 0) { -- if (errno == EFAULT) -- return ret; -- bb_perror_msg_and_die("rmmod"); -- } -- pnmod = nmod; -- // the 1 here is QM_MODULES. -- if (ENABLE_FEATURE_QUERY_MODULE_INTERFACE && query_module(NULL, -- 1, misc_buf, sizeof(misc_buf), -- &nmod)) -- { -- bb_perror_msg_and_die("QM_MODULES"); -- } -- } -+ if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT) -+ bb_perror_msg_and_die("rmmod"); - return EXIT_SUCCESS; - } - -- if (optind == argc) -+ if (!*argv) - bb_show_usage(); - -- for (n = optind; n < argc; n++) { -- if (ENABLE_FEATURE_2_6_MODULES) { -- filename2modname(misc_buf, bb_basename(argv[n])); -- } -+ while (*argv) { -+ filename2modname(bb_basename(*argv++), modname); - -- if (delete_module(ENABLE_FEATURE_2_6_MODULES ? misc_buf : argv[n], flags)) { -- bb_simple_perror_msg(argv[n]); -- ret = EXIT_FAILURE; -- } -+ if (bb_delete_module(modname, flags)) -+ bb_error_msg_and_die("cannot unload '%s': %s", -+ modname, moderror(errno)); - } - -- return ret; -+ return EXIT_SUCCESS; - } -Index: modutils/modutils.c -=================================================================== ---- modutils/modutils.c (revision 0) -+++ modutils/modutils.c (revision 0) -@@ -0,0 +1,111 @@ -+/* -+ * Common modutils related functions for busybox -+ * -+ * Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi> -+ * -+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. -+ */ -+ -+#include "modutils.h" -+ -+#ifdef __UCLIBC__ -+extern int init_module(void *module, unsigned long len, const char *options); -+extern int delete_module(const char *module, unsigned int flags); -+#else -+# include <sys/syscall.h> -+# define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) -+# define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) -+#endif -+ -+USE_FEATURE_2_4_MODULES(char *insmod_outputname); -+ -+int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) -+{ -+ char *tok; -+ int len = 0; -+ -+ while ((tok = strsep(&string, delim)) != NULL) { -+ if (tok[0] == '\0') -+ continue; -+ llist_add_to_end(llist, xstrdup(tok)); -+ len += strlen(tok); -+ } -+ return len; -+} -+ -+char * FAST_FUNC filename2modname(const char *filename, char *modname) -+{ -+ int i; -+ char *from; -+ -+ if (filename == NULL) -+ return NULL; -+ if (modname == NULL) -+ modname = xmalloc(MODULE_NAME_LEN); -+ from = bb_get_last_path_component_nostrip(filename); -+ for (i = 0; i < MODULE_NAME_LEN && from[i] != '\0' && from[i] != '.'; i++) -+ modname[i] = (from[i] == '-') ? '_' : from[i]; -+ modname[i] = 0; -+ -+ return modname; -+} -+ -+const char * FAST_FUNC moderror(int err) -+{ -+ switch (err) { -+ case ENOEXEC: -+ return "invalid module format"; -+ case ENOENT: -+ return "unknown symbol in module, or unknown parameter"; -+ case ESRCH: -+ return "module has wrong symbol version"; -+ case ENOSYS: -+ return "kernel does not support requested operation"; -+ default: -+ return strerror(err); -+ } -+} -+ -+char * FAST_FUNC parse_cmdline_module_options(char **argv) -+{ -+ char *options; -+ int optlen; -+ -+ options = xzalloc(1); -+ optlen = 0; -+ while (*++argv) { -+ options = xrealloc(options, optlen + 2 + strlen(*argv) + 2); -+ /* Spaces handled by "" pairs, but no way of escaping quotes */ -+ optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv); -+ } -+ return options; -+} -+ -+int FAST_FUNC bb_init_module(const char *filename, const char *options) -+{ -+ size_t len = MAXINT(ssize_t); -+ char *image; -+ int rc = ENOENT; -+ -+#if ENABLE_FEATURE_2_4_MODULES -+ if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) -+ return bb_init_module_24(filename, options); -+#endif -+ -+ /* Use the 2.6 way */ -+ image = (char *) xmalloc_open_zipped_read_close(filename, &len); -+ if (image) { -+ if (init_module(image, len, options) != 0) -+ rc = errno; -+ else -+ rc = 0; -+ free(image); -+ } -+ -+ return rc; -+} -+ -+int FAST_FUNC bb_delete_module(const char *module, unsigned int flags) -+{ -+ return delete_module(module, flags); -+} -Index: modutils/modutils-24.c -=================================================================== ---- modutils/modutils-24.c (revision 0) -+++ modutils/modutils-24.c (revision 0) -@@ -0,0 +1,3936 @@ -+/* vi: set sw=4 ts=4: */ -+/* -+ * Mini insmod implementation for busybox -+ * -+ * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64, -+ * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64. -+ * -+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> -+ * and Ron Alder <alder@lineo.com> -+ * -+ * Rodney Radford <rradford@mindspring.com> 17-Aug-2004. -+ * Added x86_64 support. -+ * -+ * Miles Bader <miles@gnu.org> added NEC V850E support. -+ * -+ * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 -+ * and (theoretically) SH3. I have only tested SH4 in little endian mode. -+ * -+ * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and -+ * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only -+ * very minor changes required to also work with StrongArm and presumably -+ * all ARM based systems. -+ * -+ * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004. -+ * added Renesas H8/300 support. -+ * -+ * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003. -+ * Integrated support for sh64 (SH-5), from preliminary modutils -+ * patches from Benedict Gaster <benedict.gaster@superh.com>. -+ * Currently limited to support for 32bit ABI. -+ * -+ * Magnus Damm <damm@opensource.se> 22-May-2002. -+ * The plt and got code are now using the same structs. -+ * Added generic linked list code to fully support PowerPC. -+ * Replaced the mess in arch_apply_relocation() with architecture blocks. -+ * The arch_create_got() function got cleaned up with architecture blocks. -+ * These blocks should be easy maintain and sync with obj_xxx.c in modutils. -+ * -+ * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001. -+ * PowerPC specific code stolen from modutils-2.3.16, -+ * written by Paul Mackerras, Copyright 1996, 1997 Linux International. -+ * I've only tested the code on mpc8xx platforms in big-endian mode. -+ * Did some cleanup and added USE_xxx_ENTRIES... -+ * -+ * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001. -+ * based on modutils-2.4.2 -+ * MIPS specific support for Elf loading and relocation. -+ * Copyright 1996, 1997 Linux International. -+ * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu> -+ * -+ * Based almost entirely on the Linux modutils-2.3.11 implementation. -+ * Copyright 1996, 1997 Linux International. -+ * New implementation contributed by Richard Henderson <rth@tamu.edu> -+ * Based on original work by Bjorn Ekwall <bj0rn@blox.se> -+ * Restructured (and partly rewritten) by: -+ * Björn Ekwall <bj0rn@blox.se> February 1999 -+ * -+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. -+ */ -+ -+#include "libbb.h" -+#include "modutils.h" -+#include <libgen.h> -+#include <sys/utsname.h> -+ -+#if ENABLE_FEATURE_INSMOD_LOADINKMEM -+#define LOADBITS 0 -+#else -+#define LOADBITS 1 -+#endif -+ -+/* Alpha */ -+#if defined(__alpha__) -+#define MATCH_MACHINE(x) (x == EM_ALPHA) -+#define SHT_RELM SHT_RELA -+#define Elf64_RelM Elf64_Rela -+#define ELFCLASSM ELFCLASS64 -+#endif -+ -+/* ARM support */ -+#if defined(__arm__) -+#define MATCH_MACHINE(x) (x == EM_ARM) -+#define SHT_RELM SHT_REL -+#define Elf32_RelM Elf32_Rel -+#define ELFCLASSM ELFCLASS32 -+#define USE_PLT_ENTRIES -+#define PLT_ENTRY_SIZE 8 -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 8 -+#define USE_SINGLE -+#endif -+ -+/* blackfin */ -+#if defined(BFIN) -+#define MATCH_MACHINE(x) (x == EM_BLACKFIN) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#endif -+ -+/* CRIS */ -+#if defined(__cris__) -+#define MATCH_MACHINE(x) (x == EM_CRIS) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#ifndef EM_CRIS -+#define EM_CRIS 76 -+#define R_CRIS_NONE 0 -+#define R_CRIS_32 3 -+#endif -+#endif -+ -+/* H8/300 */ -+#if defined(__H8300H__) || defined(__H8300S__) -+#define MATCH_MACHINE(x) (x == EM_H8_300) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_SINGLE -+#define SYMBOL_PREFIX "_" -+#endif -+ -+/* PA-RISC / HP-PA */ -+#if defined(__hppa__) -+#define MATCH_MACHINE(x) (x == EM_PARISC) -+#define SHT_RELM SHT_RELA -+#if defined(__LP64__) -+#define Elf64_RelM Elf64_Rela -+#define ELFCLASSM ELFCLASS64 -+#else -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#endif -+#endif -+ -+/* x86 */ -+#if defined(__i386__) -+#ifndef EM_486 -+#define MATCH_MACHINE(x) (x == EM_386) -+#else -+#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) -+#endif -+#define SHT_RELM SHT_REL -+#define Elf32_RelM Elf32_Rel -+#define ELFCLASSM ELFCLASS32 -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 4 -+#define USE_SINGLE -+#endif -+ -+/* IA64, aka Itanium */ -+#if defined(__ia64__) -+#define MATCH_MACHINE(x) (x == EM_IA_64) -+#define SHT_RELM SHT_RELA -+#define Elf64_RelM Elf64_Rela -+#define ELFCLASSM ELFCLASS64 -+#endif -+ -+/* m68k */ -+#if defined(__mc68000__) -+#define MATCH_MACHINE(x) (x == EM_68K) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 4 -+#define USE_SINGLE -+#endif -+ -+/* Microblaze */ -+#if defined(__microblaze__) -+#define USE_SINGLE -+#include <linux/elf-em.h> -+#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#endif -+ -+/* MIPS */ -+#if defined(__mips__) -+#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) -+#define SHT_RELM SHT_REL -+#define Elf32_RelM Elf32_Rel -+#define ELFCLASSM ELFCLASS32 -+/* Account for ELF spec changes. */ -+#ifndef EM_MIPS_RS3_LE -+#ifdef EM_MIPS_RS4_BE -+#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE -+#else -+#define EM_MIPS_RS3_LE 10 -+#endif -+#endif /* !EM_MIPS_RS3_LE */ -+#define ARCHDATAM "__dbe_table" -+#endif -+ -+/* Nios II */ -+#if defined(__nios2__) -+#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#endif -+ -+/* PowerPC */ -+#if defined(__powerpc64__) -+#define MATCH_MACHINE(x) (x == EM_PPC64) -+#define SHT_RELM SHT_RELA -+#define Elf64_RelM Elf64_Rela -+#define ELFCLASSM ELFCLASS64 -+#elif defined(__powerpc__) -+#define MATCH_MACHINE(x) (x == EM_PPC) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_PLT_ENTRIES -+#define PLT_ENTRY_SIZE 16 -+#define USE_PLT_LIST -+#define LIST_ARCHTYPE ElfW(Addr) -+#define USE_LIST -+#define ARCHDATAM "__ftr_fixup" -+#endif -+ -+/* S390 */ -+#if defined(__s390__) -+#define MATCH_MACHINE(x) (x == EM_S390) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_PLT_ENTRIES -+#define PLT_ENTRY_SIZE 8 -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 8 -+#define USE_SINGLE -+#endif -+ -+/* SuperH */ -+#if defined(__sh__) -+#define MATCH_MACHINE(x) (x == EM_SH) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 4 -+#define USE_SINGLE -+/* the SH changes have only been tested in =little endian= mode */ -+/* I'm not sure about big endian, so let's warn: */ -+#if defined(__sh__) && BB_BIG_ENDIAN -+# error insmod.c may require changes for use on big endian SH -+#endif -+/* it may or may not work on the SH1/SH2... Error on those also */ -+#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__)) -+#error insmod.c may require changes for SH1 or SH2 use -+#endif -+#endif -+ -+/* Sparc */ -+#if defined(__sparc__) -+#define MATCH_MACHINE(x) (x == EM_SPARC) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#endif -+ -+/* v850e */ -+#if defined(__v850e__) -+#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850) -+#define SHT_RELM SHT_RELA -+#define Elf32_RelM Elf32_Rela -+#define ELFCLASSM ELFCLASS32 -+#define USE_PLT_ENTRIES -+#define PLT_ENTRY_SIZE 8 -+#define USE_SINGLE -+#ifndef EM_CYGNUS_V850 /* grumble */ -+#define EM_CYGNUS_V850 0x9080 -+#endif -+#define SYMBOL_PREFIX "_" -+#endif -+ -+/* X86_64 */ -+#if defined(__x86_64__) -+#define MATCH_MACHINE(x) (x == EM_X86_64) -+#define SHT_RELM SHT_RELA -+#define USE_GOT_ENTRIES -+#define GOT_ENTRY_SIZE 8 -+#define USE_SINGLE -+#define Elf64_RelM Elf64_Rela -+#define ELFCLASSM ELFCLASS64 -+#endif -+ -+#ifndef SHT_RELM -+#error Sorry, but insmod.c does not yet support this architecture... -+#endif -+ -+ -+//---------------------------------------------------------------------------- -+//--------modutils module.h, lines 45-242 -+//---------------------------------------------------------------------------- -+ -+/* Definitions for the Linux module syscall interface. -+ Copyright 1996, 1997 Linux International. -+ -+ Contributed by Richard Henderson <rth@tamu.edu> -+ -+ This file is part of the Linux modutils. -+ -+ 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 MODUTILS_MODULE_H -+ -+/*======================================================================*/ -+/* For sizeof() which are related to the module platform and not to the -+ environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */ -+ -+#define tgt_sizeof_char sizeof(char) -+#define tgt_sizeof_short sizeof(short) -+#define tgt_sizeof_int sizeof(int) -+#define tgt_sizeof_long sizeof(long) -+#define tgt_sizeof_char_p sizeof(char *) -+#define tgt_sizeof_void_p sizeof(void *) -+#define tgt_long long -+ -+#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64) -+#undef tgt_sizeof_long -+#undef tgt_sizeof_char_p -+#undef tgt_sizeof_void_p -+#undef tgt_long -+enum { -+ tgt_sizeof_long = 8, -+ tgt_sizeof_char_p = 8, -+ tgt_sizeof_void_p = 8 -+}; -+#define tgt_long long long -+#endif -+ -+/*======================================================================*/ -+/* The structures used in Linux 2.1. */ -+ -+/* Note: new_module_symbol does not use tgt_long intentionally */ -+struct new_module_symbol { -+ unsigned long value; -+ unsigned long name; -+}; -+ -+struct new_module_persist; -+ -+struct new_module_ref { -+ unsigned tgt_long dep; /* kernel addresses */ -+ unsigned tgt_long ref; -+ unsigned tgt_long next_ref; -+}; -+ -+struct new_module { -+ unsigned tgt_long size_of_struct; /* == sizeof(module) */ -+ unsigned tgt_long next; -+ unsigned tgt_long name; -+ unsigned tgt_long size; -+ -+ tgt_long usecount; -+ unsigned tgt_long flags; /* AUTOCLEAN et al */ -+ -+ unsigned nsyms; -+ unsigned ndeps; -+ -+ unsigned tgt_long syms; -+ unsigned tgt_long deps; -+ unsigned tgt_long refs; -+ unsigned tgt_long init; -+ unsigned tgt_long cleanup; -+ unsigned tgt_long ex_table_start; -+ unsigned tgt_long ex_table_end; -+#ifdef __alpha__ -+ unsigned tgt_long gp; -+#endif -+ /* Everything after here is extension. */ -+ unsigned tgt_long persist_start; -+ unsigned tgt_long persist_end; -+ unsigned tgt_long can_unload; -+ unsigned tgt_long runsize; -+ const char *kallsyms_start; /* All symbols for kernel debugging */ -+ const char *kallsyms_end; -+ const char *archdata_start; /* arch specific data for module */ -+ const char *archdata_end; -+ const char *kernel_data; /* Reserved for kernel internal use */ -+}; -+ -+#ifdef ARCHDATAM -+#define ARCHDATA_SEC_NAME ARCHDATAM -+#else -+#define ARCHDATA_SEC_NAME "__archdata" -+#endif -+#define KALLSYMS_SEC_NAME "__kallsyms" -+ -+ -+struct new_module_info { -+ unsigned long addr; -+ unsigned long size; -+ unsigned long flags; -+ long usecount; -+}; -+ -+/* Bits of module.flags. */ -+enum { -+ NEW_MOD_RUNNING = 1, -+ NEW_MOD_DELETED = 2, -+ NEW_MOD_AUTOCLEAN = 4, -+ NEW_MOD_VISITED = 8, -+ NEW_MOD_USED_ONCE = 16 -+}; -+ -+int init_module(const char *name, const struct new_module *); -+int query_module(const char *name, int which, void *buf, -+ size_t bufsize, size_t *ret); -+ -+/* Values for query_module's which. */ -+enum { -+ QM_MODULES = 1, -+ QM_DEPS = 2, -+ QM_REFS = 3, -+ QM_SYMBOLS = 4, -+ QM_INFO = 5 -+}; -+ -+/*======================================================================*/ -+/* The system calls unchanged between 2.0 and 2.1. */ -+ -+unsigned long create_module(const char *, size_t); -+int delete_module(const char *module, unsigned int flags); -+ -+ -+#endif /* module.h */ -+ -+//---------------------------------------------------------------------------- -+//--------end of modutils module.h -+//---------------------------------------------------------------------------- -+ -+ -+ -+//---------------------------------------------------------------------------- -+//--------modutils obj.h, lines 253-462 -+//---------------------------------------------------------------------------- -+ -+/* Elf object file loading and relocation routines. -+ Copyright 1996, 1997 Linux International. -+ -+ Contributed by Richard Henderson <rth@tamu.edu> -+ -+ This file is part of the Linux modutils. -+ -+ 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 MODUTILS_OBJ_H -+ -+/* The relocatable object is manipulated using elfin types. */ -+ -+#include <elf.h> -+#include <endian.h> -+ -+#ifndef ElfW -+# if ELFCLASSM == ELFCLASS32 -+# define ElfW(x) Elf32_ ## x -+# define ELFW(x) ELF32_ ## x -+# else -+# define ElfW(x) Elf64_ ## x -+# define ELFW(x) ELF64_ ## x -+# endif -+#endif -+ -+/* For some reason this is missing from some ancient C libraries.... */ -+#ifndef ELF32_ST_INFO -+# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -+#endif -+ -+#ifndef ELF64_ST_INFO -+# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -+#endif -+ -+#define ELF_ST_BIND(info) ELFW(ST_BIND)(info) -+#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info) -+#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type) -+#define ELF_R_TYPE(val) ELFW(R_TYPE)(val) -+#define ELF_R_SYM(val) ELFW(R_SYM)(val) -+ -+struct obj_string_patch; -+struct obj_symbol_patch; -+ -+struct obj_section -+{ -+ ElfW(Shdr) header; -+ const char *name; -+ char *contents; -+ struct obj_section *load_next; -+ int idx; -+}; -+ -+struct obj_symbol -+{ -+ struct obj_symbol *next; /* hash table link */ -+ const char *name; -+ unsigned long value; -+ unsigned long size; -+ int secidx; /* the defining section index/module */ -+ int info; -+ int ksymidx; /* for export to the kernel symtab */ -+ int referenced; /* actually used in the link */ -+}; -+ -+/* Hardcode the hash table size. We shouldn't be needing so many -+ symbols that we begin to degrade performance, and we get a big win -+ by giving the compiler a constant divisor. */ -+ -+#define HASH_BUCKETS 521 -+ -+struct obj_file { -+ ElfW(Ehdr) header; -+ ElfW(Addr) baseaddr; -+ struct obj_section **sections; -+ struct obj_section *load_order; -+ struct obj_section **load_order_search_start; -+ struct obj_string_patch *string_patches; -+ struct obj_symbol_patch *symbol_patches; -+ int (*symbol_cmp)(const char *, const char *); -+ unsigned long (*symbol_hash)(const char *); -+ unsigned long local_symtab_size; -+ struct obj_symbol **local_symtab; -+ struct obj_symbol *symtab[HASH_BUCKETS]; -+}; -+ -+enum obj_reloc { -+ obj_reloc_ok, -+ obj_reloc_overflow, -+ obj_reloc_dangerous, -+ obj_reloc_unhandled -+}; -+ -+struct obj_string_patch { -+ struct obj_string_patch *next; -+ int reloc_secidx; -+ ElfW(Addr) reloc_offset; -+ ElfW(Addr) string_offset; -+}; -+ -+struct obj_symbol_patch { -+ struct obj_symbol_patch *next; -+ int reloc_secidx; -+ ElfW(Addr) reloc_offset; -+ struct obj_symbol *sym; -+}; -+ -+ -+/* Generic object manipulation routines. */ -+ -+static unsigned long obj_elf_hash(const char *); -+ -+static unsigned long obj_elf_hash_n(const char *, unsigned long len); -+ -+static struct obj_symbol *obj_find_symbol(struct obj_file *f, -+ const char *name); -+ -+static ElfW(Addr) obj_symbol_final_value(struct obj_file *f, -+ struct obj_symbol *sym); -+ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+static void obj_set_symbol_compare(struct obj_file *f, -+ int (*cmp)(const char *, const char *), -+ unsigned long (*hash)(const char *)); -+#endif -+ -+static struct obj_section *obj_find_section(struct obj_file *f, -+ const char *name); -+ -+static void obj_insert_section_load_order(struct obj_file *f, -+ struct obj_section *sec); -+ -+static struct obj_section *obj_create_alloced_section(struct obj_file *f, -+ const char *name, -+ unsigned long align, -+ unsigned long size); -+ -+static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, -+ const char *name, -+ unsigned long align, -+ unsigned long size); -+ -+static void *obj_extend_section(struct obj_section *sec, unsigned long more); -+ -+static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -+ const char *string); -+ -+static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -+ struct obj_symbol *sym); -+ -+static void obj_check_undefineds(struct obj_file *f); -+ -+static void obj_allocate_commons(struct obj_file *f); -+ -+static unsigned long obj_load_size(struct obj_file *f); -+ -+static int obj_relocate(struct obj_file *f, ElfW(Addr) base); -+ -+static struct obj_file *obj_load(FILE *f, int loadprogbits); -+ -+static int obj_create_image(struct obj_file *f, char *image); -+ -+/* Architecture specific manipulation routines. */ -+ -+static struct obj_file *arch_new_file(void); -+ -+static struct obj_section *arch_new_section(void); -+ -+static struct obj_symbol *arch_new_symbol(void); -+ -+static enum obj_reloc arch_apply_relocation(struct obj_file *f, -+ struct obj_section *targsec, -+ /*struct obj_section *symsec,*/ -+ struct obj_symbol *sym, -+ ElfW(RelM) *rel, ElfW(Addr) value); -+ -+static void arch_create_got(struct obj_file *f); -+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -+static int obj_gpl_license(struct obj_file *f, const char **license); -+#endif /* FEATURE_CHECK_TAINTED_MODULE */ -+#endif /* obj.h */ -+//---------------------------------------------------------------------------- -+//--------end of modutils obj.h -+//---------------------------------------------------------------------------- -+ -+ -+/* SPFX is always a string, so it can be concatenated to string constants. */ -+#ifdef SYMBOL_PREFIX -+#define SPFX SYMBOL_PREFIX -+#else -+#define SPFX "" -+#endif -+ -+enum { STRVERSIONLEN = 64 }; -+ -+/*======================================================================*/ -+ -+#define flag_force_load (option_mask32 & INSMOD_OPT_FORCE) -+#define flag_autoclean (option_mask32 & INSMOD_OPT_KERNELD) -+#define flag_verbose (option_mask32 & INSMOD_OPT_VERBOSE) -+#define flag_quiet (option_mask32 & INSMOD_OPT_SILENT) -+#define flag_noexport (option_mask32 & INSMOD_OPT_NO_EXPORT) -+#define flag_print_load_map (option_mask32 & INSMOD_OPT_PRINT_MAP) -+ -+/*======================================================================*/ -+ -+#if defined(USE_LIST) -+ -+struct arch_list_entry -+{ -+ struct arch_list_entry *next; -+ LIST_ARCHTYPE addend; -+ int offset; -+ int inited : 1; -+}; -+ -+#endif -+ -+#if defined(USE_SINGLE) -+ -+struct arch_single_entry -+{ -+ int offset; -+ int inited : 1; -+ int allocated : 1; -+}; -+ -+#endif -+ -+#if defined(__mips__) -+struct mips_hi16 -+{ -+ struct mips_hi16 *next; -+ ElfW(Addr) *addr; -+ ElfW(Addr) value; -+}; -+#endif -+ -+struct arch_file { -+ struct obj_file root; -+#if defined(USE_PLT_ENTRIES) -+ struct obj_section *plt; -+#endif -+#if defined(USE_GOT_ENTRIES) -+ struct obj_section *got; -+#endif -+#if defined(__mips__) -+ struct mips_hi16 *mips_hi16_list; -+#endif -+}; -+ -+struct arch_symbol { -+ struct obj_symbol root; -+#if defined(USE_PLT_ENTRIES) -+#if defined(USE_PLT_LIST) -+ struct arch_list_entry *pltent; -+#else -+ struct arch_single_entry pltent; -+#endif -+#endif -+#if defined(USE_GOT_ENTRIES) -+ struct arch_single_entry gotent; -+#endif -+}; -+ -+ -+struct external_module { -+ const char *name; -+ ElfW(Addr) addr; -+ int used; -+ size_t nsyms; -+ struct new_module_symbol *syms; -+}; -+ -+static struct new_module_symbol *ksyms; -+static size_t nksyms; -+ -+static struct external_module *ext_modules; -+static int n_ext_modules; -+static int n_ext_modules_used; -+ -+/*======================================================================*/ -+ -+ -+static struct obj_file *arch_new_file(void) -+{ -+ struct arch_file *f; -+ f = xzalloc(sizeof(*f)); -+ return &f->root; /* it's a first member */ -+} -+ -+static struct obj_section *arch_new_section(void) -+{ -+ return xzalloc(sizeof(struct obj_section)); -+} -+ -+static struct obj_symbol *arch_new_symbol(void) -+{ -+ struct arch_symbol *sym; -+ sym = xzalloc(sizeof(*sym)); -+ return &sym->root; -+} -+ -+static enum obj_reloc -+arch_apply_relocation(struct obj_file *f, -+ struct obj_section *targsec, -+ /*struct obj_section *symsec,*/ -+ struct obj_symbol *sym, -+ ElfW(RelM) *rel, ElfW(Addr) v) -+{ -+#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ -+ || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \ -+ || defined(__powerpc__) || defined(__mips__) -+ struct arch_file *ifile = (struct arch_file *) f; -+#endif -+ enum obj_reloc ret = obj_reloc_ok; -+ ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); -+#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \ -+ || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \ -+ || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \ -+ || defined(__s390__) || defined(__sh__) || defined(__x86_64__) -+ ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; -+#endif -+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -+ struct arch_symbol *isym = (struct arch_symbol *) sym; -+#endif -+#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ -+ || defined(__sh__) || defined(__s390__) -+#if defined(USE_GOT_ENTRIES) -+ ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; -+#endif -+#endif -+#if defined(USE_PLT_ENTRIES) -+ ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; -+ unsigned long *ip; -+# if defined(USE_PLT_LIST) -+ struct arch_list_entry *pe; -+# else -+ struct arch_single_entry *pe; -+# endif -+#endif -+ -+ switch (ELF_R_TYPE(rel->r_info)) { -+ -+#if defined(__arm__) -+ -+ case R_ARM_NONE: -+ break; -+ -+ case R_ARM_ABS32: -+ *loc += v; -+ break; -+ -+ case R_ARM_GOT32: -+ goto bb_use_got; -+ -+ case R_ARM_GOTPC: -+ /* relative reloc, always to _GLOBAL_OFFSET_TABLE_ -+ * (which is .got) similar to branch, -+ * but is full 32 bits relative */ -+ -+ *loc += got - dot; -+ break; -+ -+ case R_ARM_PC24: -+ case R_ARM_PLT32: -+ goto bb_use_plt; -+ -+ case R_ARM_GOTOFF: /* address relative to the got */ -+ *loc += v - got; -+ break; -+ -+#elif defined(__cris__) -+ -+ case R_CRIS_NONE: -+ break; -+ -+ case R_CRIS_32: -+ /* CRIS keeps the relocation value in the r_addend field and -+ * should not use whats in *loc at all -+ */ -+ *loc = v; -+ break; -+ -+#elif defined(__H8300H__) || defined(__H8300S__) -+ -+ case R_H8_DIR24R8: -+ loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1); -+ *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); -+ break; -+ case R_H8_DIR24A8: -+ *loc += v; -+ break; -+ case R_H8_DIR32: -+ case R_H8_DIR32A16: -+ *loc += v; -+ break; -+ case R_H8_PCREL16: -+ v -= dot + 2; -+ if ((ElfW(Sword))v > 0x7fff || -+ (ElfW(Sword))v < -(ElfW(Sword))0x8000) -+ ret = obj_reloc_overflow; -+ else -+ *(unsigned short *)loc = v; -+ break; -+ case R_H8_PCREL8: -+ v -= dot + 1; -+ if ((ElfW(Sword))v > 0x7f || -+ (ElfW(Sword))v < -(ElfW(Sword))0x80) -+ ret = obj_reloc_overflow; -+ else -+ *(unsigned char *)loc = v; -+ break; -+ -+#elif defined(__i386__) -+ -+ case R_386_NONE: -+ break; -+ -+ case R_386_32: -+ *loc += v; -+ break; -+ -+ case R_386_PLT32: -+ case R_386_PC32: -+ case R_386_GOTOFF: -+ *loc += v - dot; -+ break; -+ -+ case R_386_GLOB_DAT: -+ case R_386_JMP_SLOT: -+ *loc = v; -+ break; -+ -+ case R_386_RELATIVE: -+ *loc += f->baseaddr; -+ break; -+ -+ case R_386_GOTPC: -+ *loc += got - dot; -+ break; -+ -+ case R_386_GOT32: -+ goto bb_use_got; -+ break; -+ -+#elif defined(__microblaze__) -+ case R_MICROBLAZE_NONE: -+ case R_MICROBLAZE_64_NONE: -+ case R_MICROBLAZE_32_SYM_OP_SYM: -+ case R_MICROBLAZE_32_PCREL: -+ break; -+ -+ case R_MICROBLAZE_64_PCREL: { -+ /* dot is the address of the current instruction. -+ * v is the target symbol address. -+ * So we need to extract the offset in the code, -+ * adding v, then subtrating the current address -+ * of this instruction. -+ * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000" -+ */ -+ -+ /* Get split offset stored in code */ -+ unsigned int temp = (loc[0] & 0xFFFF) << 16 | -+ (loc[1] & 0xFFFF); -+ -+ /* Adjust relative offset. -4 adjustment required -+ * because dot points to the IMM insn, but branch -+ * is computed relative to the branch instruction itself. -+ */ -+ temp += v - dot - 4; -+ -+ /* Store back into code */ -+ loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16; -+ loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF); -+ -+ break; -+ } -+ -+ case R_MICROBLAZE_32: -+ *loc += v; -+ break; -+ -+ case R_MICROBLAZE_64: { -+ /* Get split pointer stored in code */ -+ unsigned int temp1 = (loc[0] & 0xFFFF) << 16 | -+ (loc[1] & 0xFFFF); -+ -+ /* Add reloc offset */ -+ temp1+=v; -+ -+ /* Store back into code */ -+ loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; -+ loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF); -+ -+ break; -+ } -+ -+ case R_MICROBLAZE_32_PCREL_LO: -+ case R_MICROBLAZE_32_LO: -+ case R_MICROBLAZE_SRO32: -+ case R_MICROBLAZE_SRW32: -+ ret = obj_reloc_unhandled; -+ break; -+ -+#elif defined(__mc68000__) -+ -+ case R_68K_NONE: -+ break; -+ -+ case R_68K_32: -+ *loc += v; -+ break; -+ -+ case R_68K_8: -+ if (v > 0xff) { -+ ret = obj_reloc_overflow; -+ } -+ *(char *)loc = v; -+ break; -+ -+ case R_68K_16: -+ if (v > 0xffff) { -+ ret = obj_reloc_overflow; -+ } -+ *(short *)loc = v; -+ break; -+ -+ case R_68K_PC8: -+ v -= dot; -+ if ((ElfW(Sword))v > 0x7f || -+ (ElfW(Sword))v < -(ElfW(Sword))0x80) { -+ ret = obj_reloc_overflow; -+ } -+ *(char *)loc = v; -+ break; -+ -+ case R_68K_PC16: -+ v -= dot; -+ if ((ElfW(Sword))v > 0x7fff || -+ (ElfW(Sword))v < -(ElfW(Sword))0x8000) { -+ ret = obj_reloc_overflow; -+ } -+ *(short *)loc = v; -+ break; -+ -+ case R_68K_PC32: -+ *(int *)loc = v - dot; -+ break; -+ -+ case R_68K_GLOB_DAT: -+ case R_68K_JMP_SLOT: -+ *loc = v; -+ break; -+ -+ case R_68K_RELATIVE: -+ *(int *)loc += f->baseaddr; -+ break; -+ -+ case R_68K_GOT32: -+ goto bb_use_got; -+ -+# ifdef R_68K_GOTOFF -+ case R_68K_GOTOFF: -+ *loc += v - got; -+ break; -+# endif -+ -+#elif defined(__mips__) -+ -+ case R_MIPS_NONE: -+ break; -+ -+ case R_MIPS_32: -+ *loc += v; -+ break; -+ -+ case R_MIPS_26: -+ if (v % 4) -+ ret = obj_reloc_dangerous; -+ if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000)) -+ ret = obj_reloc_overflow; -+ *loc = -+ (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) & -+ 0x03ffffff); -+ break; -+ -+ case R_MIPS_HI16: -+ { -+ struct mips_hi16 *n; -+ -+ /* We cannot relocate this one now because we don't know the value -+ of the carry we need to add. Save the information, and let LO16 -+ do the actual relocation. */ -+ n = xmalloc(sizeof *n); -+ n->addr = loc; -+ n->value = v; -+ n->next = ifile->mips_hi16_list; -+ ifile->mips_hi16_list = n; -+ break; -+ } -+ -+ case R_MIPS_LO16: -+ { -+ unsigned long insnlo = *loc; -+ ElfW(Addr) val, vallo; -+ -+ /* Sign extend the addend we extract from the lo insn. */ -+ vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; -+ -+ if (ifile->mips_hi16_list != NULL) { -+ struct mips_hi16 *l; -+ -+ l = ifile->mips_hi16_list; -+ while (l != NULL) { -+ struct mips_hi16 *next; -+ unsigned long insn; -+ -+ /* Do the HI16 relocation. Note that we actually don't -+ need to know anything about the LO16 itself, except where -+ to find the low 16 bits of the addend needed by the LO16. */ -+ insn = *l->addr; -+ val = -+ ((insn & 0xffff) << 16) + -+ vallo; -+ val += v; -+ -+ /* Account for the sign extension that will happen in the -+ low bits. */ -+ val = -+ ((val >> 16) + -+ ((val & 0x8000) != -+ 0)) & 0xffff; -+ -+ insn = (insn & ~0xffff) | val; -+ *l->addr = insn; -+ -+ next = l->next; -+ free(l); -+ l = next; -+ } -+ -+ ifile->mips_hi16_list = NULL; -+ } -+ -+ /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */ -+ val = v + vallo; -+ insnlo = (insnlo & ~0xffff) | (val & 0xffff); -+ *loc = insnlo; -+ break; -+ } -+ -+#elif defined(__nios2__) -+ -+ case R_NIOS2_NONE: -+ break; -+ -+ case R_NIOS2_BFD_RELOC_32: -+ *loc += v; -+ break; -+ -+ case R_NIOS2_BFD_RELOC_16: -+ if (v > 0xffff) { -+ ret = obj_reloc_overflow; -+ } -+ *(short *)loc = v; -+ break; -+ -+ case R_NIOS2_BFD_RELOC_8: -+ if (v > 0xff) { -+ ret = obj_reloc_overflow; -+ } -+ *(char *)loc = v; -+ break; -+ -+ case R_NIOS2_S16: -+ { -+ Elf32_Addr word; -+ -+ if ((Elf32_Sword)v > 0x7fff || -+ (Elf32_Sword)v < -(Elf32_Sword)0x8000) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -+ (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_U16: -+ { -+ Elf32_Addr word; -+ -+ if (v > 0xffff) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -+ (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_PCREL16: -+ { -+ Elf32_Addr word; -+ -+ v -= dot + 4; -+ if ((Elf32_Sword)v > 0x7fff || -+ (Elf32_Sword)v < -(Elf32_Sword)0x8000) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_GPREL: -+ { -+ Elf32_Addr word, gp; -+ /* get _gp */ -+ gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp")); -+ v-=gp; -+ if ((Elf32_Sword)v > 0x7fff || -+ (Elf32_Sword)v < -(Elf32_Sword)0x8000) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_CALL26: -+ if (v & 3) -+ ret = obj_reloc_dangerous; -+ if ((v >> 28) != (dot >> 28)) -+ ret = obj_reloc_overflow; -+ *loc = (*loc & 0x3f) | ((v >> 2) << 6); -+ break; -+ -+ case R_NIOS2_IMM5: -+ { -+ Elf32_Addr word; -+ -+ if (v > 0x1f) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc & ~0x7c0; -+ *loc = word | ((v & 0x1f) << 6); -+ } -+ break; -+ -+ case R_NIOS2_IMM6: -+ { -+ Elf32_Addr word; -+ -+ if (v > 0x3f) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc & ~0xfc0; -+ *loc = word | ((v & 0x3f) << 6); -+ } -+ break; -+ -+ case R_NIOS2_IMM8: -+ { -+ Elf32_Addr word; -+ -+ if (v > 0xff) { -+ ret = obj_reloc_overflow; -+ } -+ -+ word = *loc & ~0x3fc0; -+ *loc = word | ((v & 0xff) << 6); -+ } -+ break; -+ -+ case R_NIOS2_HI16: -+ { -+ Elf32_Addr word; -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) | -+ (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_LO16: -+ { -+ Elf32_Addr word; -+ -+ word = *loc; -+ *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -+ (word & 0x3f); -+ } -+ break; -+ -+ case R_NIOS2_HIADJ16: -+ { -+ Elf32_Addr word1, word2; -+ -+ word1 = *loc; -+ word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff; -+ *loc = ((((word1 >> 22) << 16) | word2) << 6) | -+ (word1 & 0x3f); -+ } -+ break; -+ -+#elif defined(__powerpc64__) -+ /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */ -+ -+#elif defined(__powerpc__) -+ -+ case R_PPC_ADDR16_HA: -+ *(unsigned short *)loc = (v + 0x8000) >> 16; -+ break; -+ -+ case R_PPC_ADDR16_HI: -+ *(unsigned short *)loc = v >> 16; -+ break; -+ -+ case R_PPC_ADDR16_LO: -+ *(unsigned short *)loc = v; -+ break; -+ -+ case R_PPC_REL24: -+ goto bb_use_plt; -+ -+ case R_PPC_REL32: -+ *loc = v - dot; -+ break; -+ -+ case R_PPC_ADDR32: -+ *loc = v; -+ break; -+ -+#elif defined(__s390__) -+ -+ case R_390_32: -+ *(unsigned int *) loc += v; -+ break; -+ case R_390_16: -+ *(unsigned short *) loc += v; -+ break; -+ case R_390_8: -+ *(unsigned char *) loc += v; -+ break; -+ -+ case R_390_PC32: -+ *(unsigned int *) loc += v - dot; -+ break; -+ case R_390_PC16DBL: -+ *(unsigned short *) loc += (v - dot) >> 1; -+ break; -+ case R_390_PC16: -+ *(unsigned short *) loc += v - dot; -+ break; -+ -+ case R_390_PLT32: -+ case R_390_PLT16DBL: -+ /* find the plt entry and initialize it. */ -+ pe = (struct arch_single_entry *) &isym->pltent; -+ if (pe->inited == 0) { -+ ip = (unsigned long *)(ifile->plt->contents + pe->offset); -+ ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */ -+ ip[1] = 0x100607f1; -+ if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL) -+ ip[2] = v - 2; -+ else -+ ip[2] = v; -+ pe->inited = 1; -+ } -+ -+ /* Insert relative distance to target. */ -+ v = plt + pe->offset - dot; -+ if (ELF_R_TYPE(rel->r_info) == R_390_PLT32) -+ *(unsigned int *) loc = (unsigned int) v; -+ else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL) -+ *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1); -+ break; -+ -+ case R_390_GLOB_DAT: -+ case R_390_JMP_SLOT: -+ *loc = v; -+ break; -+ -+ case R_390_RELATIVE: -+ *loc += f->baseaddr; -+ break; -+ -+ case R_390_GOTPC: -+ *(unsigned long *) loc += got - dot; -+ break; -+ -+ case R_390_GOT12: -+ case R_390_GOT16: -+ case R_390_GOT32: -+ if (!isym->gotent.inited) -+ { -+ isym->gotent.inited = 1; -+ *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v; -+ } -+ if (ELF_R_TYPE(rel->r_info) == R_390_GOT12) -+ *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff; -+ else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16) -+ *(unsigned short *) loc += isym->gotent.offset; -+ else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32) -+ *(unsigned int *) loc += isym->gotent.offset; -+ break; -+ -+# ifndef R_390_GOTOFF32 -+# define R_390_GOTOFF32 R_390_GOTOFF -+# endif -+ case R_390_GOTOFF32: -+ *loc += v - got; -+ break; -+ -+#elif defined(__sh__) -+ -+ case R_SH_NONE: -+ break; -+ -+ case R_SH_DIR32: -+ *loc += v; -+ break; -+ -+ case R_SH_REL32: -+ *loc += v - dot; -+ break; -+ -+ case R_SH_PLT32: -+ *loc = v - dot; -+ break; -+ -+ case R_SH_GLOB_DAT: -+ case R_SH_JMP_SLOT: -+ *loc = v; -+ break; -+ -+ case R_SH_RELATIVE: -+ *loc = f->baseaddr + rel->r_addend; -+ break; -+ -+ case R_SH_GOTPC: -+ *loc = got - dot + rel->r_addend; -+ break; -+ -+ case R_SH_GOT32: -+ goto bb_use_got; -+ -+ case R_SH_GOTOFF: -+ *loc = v - got; -+ break; -+ -+# if defined(__SH5__) -+ case R_SH_IMM_MEDLOW16: -+ case R_SH_IMM_LOW16: -+ { -+ ElfW(Addr) word; -+ -+ if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16) -+ v >>= 16; -+ -+ /* -+ * movi and shori have the format: -+ * -+ * | op | imm | reg | reserved | -+ * 31..26 25..10 9.. 4 3 .. 0 -+ * -+ * so we simply mask and or in imm. -+ */ -+ word = *loc & ~0x3fffc00; -+ word |= (v & 0xffff) << 10; -+ -+ *loc = word; -+ -+ break; -+ } -+ -+ case R_SH_IMM_MEDLOW16_PCREL: -+ case R_SH_IMM_LOW16_PCREL: -+ { -+ ElfW(Addr) word; -+ -+ word = *loc & ~0x3fffc00; -+ -+ v -= dot; -+ -+ if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL) -+ v >>= 16; -+ -+ word |= (v & 0xffff) << 10; -+ -+ *loc = word; -+ -+ break; -+ } -+# endif /* __SH5__ */ -+ -+#elif defined(__v850e__) -+ -+ case R_V850_NONE: -+ break; -+ -+ case R_V850_32: -+ /* We write two shorts instead of a long because even -+ 32-bit insns only need half-word alignment, but -+ 32-bit data needs to be long-word aligned. */ -+ v += ((unsigned short *)loc)[0]; -+ v += ((unsigned short *)loc)[1] << 16; -+ ((unsigned short *)loc)[0] = v & 0xffff; -+ ((unsigned short *)loc)[1] = (v >> 16) & 0xffff; -+ break; -+ -+ case R_V850_22_PCREL: -+ goto bb_use_plt; -+ -+#elif defined(__x86_64__) -+ -+ case R_X86_64_NONE: -+ break; -+ -+ case R_X86_64_64: -+ *loc += v; -+ break; -+ -+ case R_X86_64_32: -+ *(unsigned int *) loc += v; -+ if (v > 0xffffffff) -+ { -+ ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */ -+ /* error("Possibly is module compiled without -mcmodel=kernel!"); */ -+ } -+ break; -+ -+ case R_X86_64_32S: -+ *(signed int *) loc += v; -+ break; -+ -+ case R_X86_64_16: -+ *(unsigned short *) loc += v; -+ break; -+ -+ case R_X86_64_8: -+ *(unsigned char *) loc += v; -+ break; -+ -+ case R_X86_64_PC32: -+ *(unsigned int *) loc += v - dot; -+ break; -+ -+ case R_X86_64_PC16: -+ *(unsigned short *) loc += v - dot; -+ break; -+ -+ case R_X86_64_PC8: -+ *(unsigned char *) loc += v - dot; -+ break; -+ -+ case R_X86_64_GLOB_DAT: -+ case R_X86_64_JUMP_SLOT: -+ *loc = v; -+ break; -+ -+ case R_X86_64_RELATIVE: -+ *loc += f->baseaddr; -+ break; -+ -+ case R_X86_64_GOT32: -+ case R_X86_64_GOTPCREL: -+ goto bb_use_got; -+# if 0 -+ if (!isym->gotent.reloc_done) -+ { -+ isym->gotent.reloc_done = 1; -+ *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v; -+ } -+ /* XXX are these really correct? */ -+ if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL) -+ *(unsigned int *) loc += v + isym->gotent.offset; -+ else -+ *loc += isym->gotent.offset; -+ break; -+# endif -+ -+#else -+# warning "no idea how to handle relocations on your arch" -+#endif -+ -+ default: -+ printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info)); -+ ret = obj_reloc_unhandled; -+ break; -+ -+#if defined(USE_PLT_ENTRIES) -+ -+bb_use_plt: -+ -+ /* find the plt entry and initialize it if necessary */ -+ -+#if defined(USE_PLT_LIST) -+ for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;) -+ pe = pe->next; -+#else -+ pe = &isym->pltent; -+#endif -+ -+ if (! pe->inited) { -+ ip = (unsigned long *) (ifile->plt->contents + pe->offset); -+ -+ /* generate some machine code */ -+ -+#if defined(__arm__) -+ ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ -+ ip[1] = v; /* sym@ */ -+#endif -+#if defined(__powerpc__) -+ ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */ -+ ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */ -+ ip[2] = 0x7d6903a6; /* mtctr r11 */ -+ ip[3] = 0x4e800420; /* bctr */ -+#endif -+#if defined(__v850e__) -+ /* We have to trash a register, so we assume that any control -+ transfer more than 21-bits away must be a function call -+ (so we can use a call-clobbered register). */ -+ ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */ -+ ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */ -+#endif -+ pe->inited = 1; -+ } -+ -+ /* relative distance to target */ -+ v -= dot; -+ /* if the target is too far away.... */ -+#if defined(__arm__) || defined(__powerpc__) -+ if ((int)v < -0x02000000 || (int)v >= 0x02000000) -+#elif defined(__v850e__) -+ if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000) -+#endif -+ /* go via the plt */ -+ v = plt + pe->offset - dot; -+ -+#if defined(__v850e__) -+ if (v & 1) -+#else -+ if (v & 3) -+#endif -+ ret = obj_reloc_dangerous; -+ -+ /* merge the offset into the instruction. */ -+#if defined(__arm__) -+ /* Convert to words. */ -+ v >>= 2; -+ -+ *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); -+#endif -+#if defined(__powerpc__) -+ *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc); -+#endif -+#if defined(__v850e__) -+ /* We write two shorts instead of a long because even 32-bit insns -+ only need half-word alignment, but the 32-bit data write needs -+ to be long-word aligned. */ -+ ((unsigned short *)loc)[0] = -+ (*(unsigned short *)loc & 0xffc0) /* opcode + reg */ -+ | ((v >> 16) & 0x3f); /* offs high part */ -+ ((unsigned short *)loc)[1] = -+ (v & 0xffff); /* offs low part */ -+#endif -+ break; -+#endif /* USE_PLT_ENTRIES */ -+ -+#if defined(USE_GOT_ENTRIES) -+bb_use_got: -+ -+ /* needs an entry in the .got: set it, once */ -+ if (!isym->gotent.inited) { -+ isym->gotent.inited = 1; -+ *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; -+ } -+ /* make the reloc with_respect_to_.got */ -+#if defined(__sh__) -+ *loc += isym->gotent.offset + rel->r_addend; -+#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__) -+ *loc += isym->gotent.offset; -+#endif -+ break; -+ -+#endif /* USE_GOT_ENTRIES */ -+ } -+ -+ return ret; -+} -+ -+ -+#if defined(USE_LIST) -+ -+static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list, -+ int offset, int size) -+{ -+ struct arch_list_entry *pe; -+ -+ for (pe = *list; pe != NULL; pe = pe->next) { -+ if (pe->addend == rel->r_addend) { -+ break; -+ } -+ } -+ -+ if (pe == NULL) { -+ pe = xmalloc(sizeof(struct arch_list_entry)); -+ pe->next = *list; -+ pe->addend = rel->r_addend; -+ pe->offset = offset; -+ pe->inited = 0; -+ *list = pe; -+ return size; -+ } -+ return 0; -+} -+ -+#endif -+ -+#if defined(USE_SINGLE) -+ -+static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single, -+ int offset, int size) -+{ -+ if (single->allocated == 0) { -+ single->allocated = 1; -+ single->offset = offset; -+ single->inited = 0; -+ return size; -+ } -+ return 0; -+} -+ -+#endif -+ -+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -+ -+static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name, -+ int offset, int size) -+{ -+ struct obj_section *myrelsec = obj_find_section(f, name); -+ -+ if (offset == 0) { -+ offset += size; -+ } -+ -+ if (myrelsec) { -+ obj_extend_section(myrelsec, offset); -+ } else { -+ myrelsec = obj_create_alloced_section(f, name, -+ size, offset); -+ } -+ -+ return myrelsec; -+} -+ -+#endif -+ -+static void arch_create_got(struct obj_file *f) -+{ -+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -+ struct arch_file *ifile = (struct arch_file *) f; -+ int i; -+#if defined(USE_GOT_ENTRIES) -+ int got_offset = 0, got_needed = 0, got_allocate; -+#endif -+#if defined(USE_PLT_ENTRIES) -+ int plt_offset = 0, plt_needed = 0, plt_allocate; -+#endif -+ struct obj_section *relsec, *symsec, *strsec; -+ ElfW(RelM) *rel, *relend; -+ ElfW(Sym) *symtab, *extsym; -+ const char *strtab, *name; -+ struct arch_symbol *intsym; -+ -+ for (i = 0; i < f->header.e_shnum; ++i) { -+ relsec = f->sections[i]; -+ if (relsec->header.sh_type != SHT_RELM) -+ continue; -+ -+ symsec = f->sections[relsec->header.sh_link]; -+ strsec = f->sections[symsec->header.sh_link]; -+ -+ rel = (ElfW(RelM) *) relsec->contents; -+ relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); -+ symtab = (ElfW(Sym) *) symsec->contents; -+ strtab = (const char *) strsec->contents; -+ -+ for (; rel < relend; ++rel) { -+ extsym = &symtab[ELF_R_SYM(rel->r_info)]; -+ -+#if defined(USE_GOT_ENTRIES) -+ got_allocate = 0; -+#endif -+#if defined(USE_PLT_ENTRIES) -+ plt_allocate = 0; -+#endif -+ -+ switch (ELF_R_TYPE(rel->r_info)) { -+#if defined(__arm__) -+ case R_ARM_PC24: -+ case R_ARM_PLT32: -+ plt_allocate = 1; -+ break; -+ -+ case R_ARM_GOTOFF: -+ case R_ARM_GOTPC: -+ got_needed = 1; -+ continue; -+ -+ case R_ARM_GOT32: -+ got_allocate = 1; -+ break; -+ -+#elif defined(__i386__) -+ case R_386_GOTPC: -+ case R_386_GOTOFF: -+ got_needed = 1; -+ continue; -+ -+ case R_386_GOT32: -+ got_allocate = 1; -+ break; -+ -+#elif defined(__powerpc__) -+ case R_PPC_REL24: -+ plt_allocate = 1; -+ break; -+ -+#elif defined(__mc68000__) -+ case R_68K_GOT32: -+ got_allocate = 1; -+ break; -+ -+#ifdef R_68K_GOTOFF -+ case R_68K_GOTOFF: -+ got_needed = 1; -+ continue; -+#endif -+ -+#elif defined(__sh__) -+ case R_SH_GOT32: -+ got_allocate = 1; -+ break; -+ -+ case R_SH_GOTPC: -+ case R_SH_GOTOFF: -+ got_needed = 1; -+ continue; -+ -+#elif defined(__v850e__) -+ case R_V850_22_PCREL: -+ plt_needed = 1; -+ break; -+ -+#endif -+ default: -+ continue; -+ } -+ -+ if (extsym->st_name != 0) { -+ name = strtab + extsym->st_name; -+ } else { -+ name = f->sections[extsym->st_shndx]->name; -+ } -+ intsym = (struct arch_symbol *) obj_find_symbol(f, name); -+#if defined(USE_GOT_ENTRIES) -+ if (got_allocate) { -+ got_offset += arch_single_init( -+ /*rel,*/ &intsym->gotent, -+ got_offset, GOT_ENTRY_SIZE); -+ -+ got_needed = 1; -+ } -+#endif -+#if defined(USE_PLT_ENTRIES) -+ if (plt_allocate) { -+#if defined(USE_PLT_LIST) -+ plt_offset += arch_list_add( -+ rel, &intsym->pltent, -+ plt_offset, PLT_ENTRY_SIZE); -+#else -+ plt_offset += arch_single_init( -+ /*rel,*/ &intsym->pltent, -+ plt_offset, PLT_ENTRY_SIZE); -+#endif -+ plt_needed = 1; -+ } -+#endif -+ } -+ } -+ -+#if defined(USE_GOT_ENTRIES) -+ if (got_needed) { -+ ifile->got = arch_xsect_init(f, ".got", got_offset, -+ GOT_ENTRY_SIZE); -+ } -+#endif -+ -+#if defined(USE_PLT_ENTRIES) -+ if (plt_needed) { -+ ifile->plt = arch_xsect_init(f, ".plt", plt_offset, -+ PLT_ENTRY_SIZE); -+ } -+#endif -+ -+#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */ -+} -+ -+/*======================================================================*/ -+ -+/* Standard ELF hash function. */ -+static unsigned long obj_elf_hash_n(const char *name, unsigned long n) -+{ -+ unsigned long h = 0; -+ unsigned long g; -+ unsigned char ch; -+ -+ while (n > 0) { -+ ch = *name++; -+ h = (h << 4) + ch; -+ g = (h & 0xf0000000); -+ if (g != 0) { -+ h ^= g >> 24; -+ h &= ~g; -+ } -+ n--; -+ } -+ return h; -+} -+ -+static unsigned long obj_elf_hash(const char *name) -+{ -+ return obj_elf_hash_n(name, strlen(name)); -+} -+ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+/* String comparison for non-co-versioned kernel and module. */ -+ -+static int ncv_strcmp(const char *a, const char *b) -+{ -+ size_t alen = strlen(a), blen = strlen(b); -+ -+ if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R') -+ return strncmp(a, b, alen); -+ else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R') -+ return strncmp(a, b, blen); -+ else -+ return strcmp(a, b); -+} -+ -+/* String hashing for non-co-versioned kernel and module. Here -+ we are simply forced to drop the crc from the hash. */ -+ -+static unsigned long ncv_symbol_hash(const char *str) -+{ -+ size_t len = strlen(str); -+ if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R') -+ len -= 10; -+ return obj_elf_hash_n(str, len); -+} -+ -+static void -+obj_set_symbol_compare(struct obj_file *f, -+ int (*cmp) (const char *, const char *), -+ unsigned long (*hash) (const char *)) -+{ -+ if (cmp) -+ f->symbol_cmp = cmp; -+ if (hash) { -+ struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next; -+ int i; -+ -+ f->symbol_hash = hash; -+ -+ memcpy(tmptab, f->symtab, sizeof(tmptab)); -+ memset(f->symtab, 0, sizeof(f->symtab)); -+ -+ for (i = 0; i < HASH_BUCKETS; ++i) -+ for (sym = tmptab[i]; sym; sym = next) { -+ unsigned long h = hash(sym->name) % HASH_BUCKETS; -+ next = sym->next; -+ sym->next = f->symtab[h]; -+ f->symtab[h] = sym; -+ } -+ } -+} -+ -+#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -+ -+static struct obj_symbol * -+obj_add_symbol(struct obj_file *f, const char *name, -+ unsigned long symidx, int info, -+ int secidx, ElfW(Addr) value, -+ unsigned long size) -+{ -+ struct obj_symbol *sym; -+ unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; -+ int n_type = ELF_ST_TYPE(info); -+ int n_binding = ELF_ST_BIND(info); -+ -+ for (sym = f->symtab[hash]; sym; sym = sym->next) { -+ if (f->symbol_cmp(sym->name, name) == 0) { -+ int o_secidx = sym->secidx; -+ int o_info = sym->info; -+ int o_type = ELF_ST_TYPE(o_info); -+ int o_binding = ELF_ST_BIND(o_info); -+ -+ /* A redefinition! Is it legal? */ -+ -+ if (secidx == SHN_UNDEF) -+ return sym; -+ else if (o_secidx == SHN_UNDEF) -+ goto found; -+ else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) { -+ /* Cope with local and global symbols of the same name -+ in the same object file, as might have been created -+ by ld -r. The only reason locals are now seen at this -+ level at all is so that we can do semi-sensible things -+ with parameters. */ -+ -+ struct obj_symbol *nsym, **p; -+ -+ nsym = arch_new_symbol(); -+ nsym->next = sym->next; -+ nsym->ksymidx = -1; -+ -+ /* Excise the old (local) symbol from the hash chain. */ -+ for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next) -+ continue; -+ *p = sym = nsym; -+ goto found; -+ } else if (n_binding == STB_LOCAL) { -+ /* Another symbol of the same name has already been defined. -+ Just add this to the local table. */ -+ sym = arch_new_symbol(); -+ sym->next = NULL; -+ sym->ksymidx = -1; -+ f->local_symtab[symidx] = sym; -+ goto found; -+ } else if (n_binding == STB_WEAK) -+ return sym; -+ else if (o_binding == STB_WEAK) -+ goto found; -+ /* Don't unify COMMON symbols with object types the programmer -+ doesn't expect. */ -+ else if (secidx == SHN_COMMON -+ && (o_type == STT_NOTYPE || o_type == STT_OBJECT)) -+ return sym; -+ else if (o_secidx == SHN_COMMON -+ && (n_type == STT_NOTYPE || n_type == STT_OBJECT)) -+ goto found; -+ else { -+ /* Don't report an error if the symbol is coming from -+ the kernel or some external module. */ -+ if (secidx <= SHN_HIRESERVE) -+ bb_error_msg("%s multiply defined", name); -+ return sym; -+ } -+ } -+ } -+ -+ /* Completely new symbol. */ -+ sym = arch_new_symbol(); -+ sym->next = f->symtab[hash]; -+ f->symtab[hash] = sym; -+ sym->ksymidx = -1; -+ if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) { -+ if (symidx >= f->local_symtab_size) -+ bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld", -+ name, (long) symidx, (long) f->local_symtab_size); -+ else -+ f->local_symtab[symidx] = sym; -+ } -+ -+found: -+ sym->name = name; -+ sym->value = value; -+ sym->size = size; -+ sym->secidx = secidx; -+ sym->info = info; -+ -+ return sym; -+} -+ -+static struct obj_symbol * -+obj_find_symbol(struct obj_file *f, const char *name) -+{ -+ struct obj_symbol *sym; -+ unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; -+ -+ for (sym = f->symtab[hash]; sym; sym = sym->next) -+ if (f->symbol_cmp(sym->name, name) == 0) -+ return sym; -+ -+ return NULL; -+} -+ -+static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym) -+{ -+ if (sym) { -+ if (sym->secidx >= SHN_LORESERVE) -+ return sym->value; -+ -+ return sym->value + f->sections[sym->secidx]->header.sh_addr; -+ } else { -+ /* As a special case, a NULL sym has value zero. */ -+ return 0; -+ } -+} -+ -+static struct obj_section *obj_find_section(struct obj_file *f, const char *name) -+{ -+ int i, n = f->header.e_shnum; -+ -+ for (i = 0; i < n; ++i) -+ if (strcmp(f->sections[i]->name, name) == 0) -+ return f->sections[i]; -+ -+ return NULL; -+} -+ -+static int obj_load_order_prio(struct obj_section *a) -+{ -+ unsigned long af, ac; -+ -+ af = a->header.sh_flags; -+ -+ ac = 0; -+ if (a->name[0] != '.' || strlen(a->name) != 10 || -+ strcmp(a->name + 5, ".init")) -+ ac |= 32; -+ if (af & SHF_ALLOC) -+ ac |= 16; -+ if (!(af & SHF_WRITE)) -+ ac |= 8; -+ if (af & SHF_EXECINSTR) -+ ac |= 4; -+ if (a->header.sh_type != SHT_NOBITS) -+ ac |= 2; -+ -+ return ac; -+} -+ -+static void -+obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec) -+{ -+ struct obj_section **p; -+ int prio = obj_load_order_prio(sec); -+ for (p = f->load_order_search_start; *p; p = &(*p)->load_next) -+ if (obj_load_order_prio(*p) < prio) -+ break; -+ sec->load_next = *p; -+ *p = sec; -+} -+ -+static struct obj_section *obj_create_alloced_section(struct obj_file *f, -+ const char *name, -+ unsigned long align, -+ unsigned long size) -+{ -+ int newidx = f->header.e_shnum++; -+ struct obj_section *sec; -+ -+ f->sections = xrealloc_vector(f->sections, 2, newidx); -+ f->sections[newidx] = sec = arch_new_section(); -+ -+ sec->header.sh_type = SHT_PROGBITS; -+ sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -+ sec->header.sh_size = size; -+ sec->header.sh_addralign = align; -+ sec->name = name; -+ sec->idx = newidx; -+ if (size) -+ sec->contents = xmalloc(size); -+ -+ obj_insert_section_load_order(f, sec); -+ -+ return sec; -+} -+ -+static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, -+ const char *name, -+ unsigned long align, -+ unsigned long size) -+{ -+ int newidx = f->header.e_shnum++; -+ struct obj_section *sec; -+ -+ f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); -+ f->sections[newidx] = sec = arch_new_section(); -+ -+ sec->header.sh_type = SHT_PROGBITS; -+ sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -+ sec->header.sh_size = size; -+ sec->header.sh_addralign = align; -+ sec->name = name; -+ sec->idx = newidx; -+ if (size) -+ sec->contents = xmalloc(size); -+ -+ sec->load_next = f->load_order; -+ f->load_order = sec; -+ if (f->load_order_search_start == &f->load_order) -+ f->load_order_search_start = &sec->load_next; -+ -+ return sec; -+} -+ -+static void *obj_extend_section(struct obj_section *sec, unsigned long more) -+{ -+ unsigned long oldsize = sec->header.sh_size; -+ if (more) { -+ sec->header.sh_size += more; -+ sec->contents = xrealloc(sec->contents, sec->header.sh_size); -+ } -+ return sec->contents + oldsize; -+} -+ -+ -+/* Conditionally add the symbols from the given symbol set to the -+ new module. */ -+ -+static int -+add_symbols_from( struct obj_file *f, -+ int idx, struct new_module_symbol *syms, size_t nsyms) -+{ -+ struct new_module_symbol *s; -+ size_t i; -+ int used = 0; -+#ifdef SYMBOL_PREFIX -+ char *name_buf = 0; -+ size_t name_alloced_size = 0; -+#endif -+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -+ int gpl; -+ -+ gpl = obj_gpl_license(f, NULL) == 0; -+#endif -+ for (i = 0, s = syms; i < nsyms; ++i, ++s) { -+ /* Only add symbols that are already marked external. -+ If we override locals we may cause problems for -+ argument initialization. We will also create a false -+ dependency on the module. */ -+ struct obj_symbol *sym; -+ char *name; -+ -+ /* GPL licensed modules can use symbols exported with -+ * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the -+ * exported names. Non-GPL modules never see any GPLONLY_ -+ * symbols so they cannot fudge it by adding the prefix on -+ * their references. -+ */ -+ if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) { -+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -+ if (gpl) -+ s->name += 8; -+ else -+#endif -+ continue; -+ } -+ name = (char *)s->name; -+ -+#ifdef SYMBOL_PREFIX -+ /* Prepend SYMBOL_PREFIX to the symbol's name (the -+ kernel exports `C names', but module object files -+ reference `linker names'). */ -+ size_t extra = sizeof SYMBOL_PREFIX; -+ size_t name_size = strlen(name) + extra; -+ if (name_size > name_alloced_size) { -+ name_alloced_size = name_size * 2; -+ name_buf = alloca(name_alloced_size); -+ } -+ strcpy(name_buf, SYMBOL_PREFIX); -+ strcpy(name_buf + extra - 1, name); -+ name = name_buf; -+#endif /* SYMBOL_PREFIX */ -+ -+ sym = obj_find_symbol(f, name); -+ if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) { -+#ifdef SYMBOL_PREFIX -+ /* Put NAME_BUF into more permanent storage. */ -+ name = xmalloc(name_size); -+ strcpy(name, name_buf); -+#endif -+ sym = obj_add_symbol(f, name, -1, -+ ELF_ST_INFO(STB_GLOBAL, -+ STT_NOTYPE), -+ idx, s->value, 0); -+ /* Did our symbol just get installed? If so, mark the -+ module as "used". */ -+ if (sym->secidx == idx) -+ used = 1; -+ } -+ } -+ -+ return used; -+} -+ -+static void add_kernel_symbols(struct obj_file *f) -+{ -+ struct external_module *m; -+ int i, nused = 0; -+ -+ /* Add module symbols first. */ -+ -+ for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) { -+ if (m->nsyms -+ && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms) -+ ) { -+ m->used = 1; -+ ++nused; -+ } -+ } -+ -+ n_ext_modules_used = nused; -+ -+ /* And finally the symbols from the kernel proper. */ -+ -+ if (nksyms) -+ add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms); -+} -+ -+static char *get_modinfo_value(struct obj_file *f, const char *key) -+{ -+ struct obj_section *sec; -+ char *p, *v, *n, *ep; -+ size_t klen = strlen(key); -+ -+ sec = obj_find_section(f, ".modinfo"); -+ if (sec == NULL) -+ return NULL; -+ p = sec->contents; -+ ep = p + sec->header.sh_size; -+ while (p < ep) { -+ v = strchr(p, '='); -+ n = strchr(p, '\0'); -+ if (v) { -+ if (p + klen == v && strncmp(p, key, klen) == 0) -+ return v + 1; -+ } else { -+ if (p + klen == n && strcmp(p, key) == 0) -+ return n; -+ } -+ p = n + 1; -+ } -+ -+ return NULL; -+} -+ -+ -+/*======================================================================*/ -+/* Functions relating to module loading after 2.1.18. */ -+ -+/* From Linux-2.6 sources */ -+/* You can use " around spaces, but can't escape ". */ -+/* Hyphens and underscores equivalent in parameter names. */ -+static char *next_arg(char *args, char **param, char **val) -+{ -+ unsigned int i, equals = 0; -+ int in_quote = 0, quoted = 0; -+ char *next; -+ -+ if (*args == '"') { -+ args++; -+ in_quote = 1; -+ quoted = 1; -+ } -+ -+ for (i = 0; args[i]; i++) { -+ if (args[i] == ' ' && !in_quote) -+ break; -+ if (equals == 0) { -+ if (args[i] == '=') -+ equals = i; -+ } -+ if (args[i] == '"') -+ in_quote = !in_quote; -+ } -+ -+ *param = args; -+ if (!equals) -+ *val = NULL; -+ else { -+ args[equals] = '\0'; -+ *val = args + equals + 1; -+ -+ /* Don't include quotes in value. */ -+ if (**val == '"') { -+ (*val)++; -+ if (args[i-1] == '"') -+ args[i-1] = '\0'; -+ } -+ if (quoted && args[i-1] == '"') -+ args[i-1] = '\0'; -+ } -+ -+ if (args[i]) { -+ args[i] = '\0'; -+ next = args + i + 1; -+ } else -+ next = args + i; -+ -+ /* Chew up trailing spaces. */ -+ return skip_whitespace(next); -+} -+ -+static void -+new_process_module_arguments(struct obj_file *f, const char *options) -+{ -+ char *xoptions, *pos; -+ char *param, *val; -+ -+ xoptions = pos = xstrdup(skip_whitespace(options)); -+ while (*pos) { -+ unsigned long charssize = 0; -+ char *tmp, *contents, *loc, *pinfo, *p; -+ struct obj_symbol *sym; -+ int min, max, n, len; -+ -+ pos = next_arg(pos, ¶m, &val); -+ -+ tmp = xasprintf("parm_%s", param); -+ pinfo = get_modinfo_value(f, tmp); -+ free(tmp); -+ if (pinfo == NULL) -+ bb_error_msg_and_die("invalid parameter %s", param); -+ -+#ifdef SYMBOL_PREFIX -+ tmp = xasprintf(SYMBOL_PREFIX "%s", param); -+ sym = obj_find_symbol(f, tmp); -+ free(tmp); -+#else -+ sym = obj_find_symbol(f, param); -+#endif -+ -+ /* Also check that the parameter was not resolved from the kernel. */ -+ if (sym == NULL || sym->secidx > SHN_HIRESERVE) -+ bb_error_msg_and_die("symbol for parameter %s not found", param); -+ -+ /* Number of parameters */ -+ if (isdigit(*pinfo)) { -+ min = strtoul(pinfo, &pinfo, 10); -+ if (*pinfo == '-') -+ max = strtoul(pinfo + 1, &pinfo, 10); -+ else -+ max = min; -+ } else -+ min = max = 1; -+ -+ contents = f->sections[sym->secidx]->contents; -+ loc = contents + sym->value; -+ -+ if (*pinfo == 'c') { -+ if (!isdigit(*(pinfo + 1))) { -+ bb_error_msg_and_die("parameter type 'c' for %s must be followed by" -+ " the maximum size", param); -+ } -+ charssize = strtoul(pinfo + 1, (char **) NULL, 10); -+ } -+ -+ if (val == NULL) { -+ if (*pinfo != 'b') -+ bb_error_msg_and_die("argument expected for parameter %s", param); -+ val = (char *) "1"; -+ } -+ -+ /* Parse parameter values */ -+ n = 0; -+ p = val; -+ while (*p != 0) { -+ if (++n > max) -+ bb_error_msg_and_die("too many values for %s (max %d)", param, max); -+ -+ switch (*pinfo) { -+ case 's': -+ len = strcspn(p, ","); -+ p[len] = 0; -+ obj_string_patch(f, sym->secidx, -+ loc - contents, p); -+ loc += tgt_sizeof_char_p; -+ p += len; -+ break; -+ case 'c': -+ len = strcspn(p, ","); -+ p[len] = 0; -+ if (len >= charssize) -+ bb_error_msg_and_die("string too long for %s (max %ld)", param, -+ charssize - 1); -+ strcpy((char *) loc, p); -+ loc += charssize; -+ p += len; -+ break; -+ case 'b': -+ *loc++ = strtoul(p, &p, 0); -+ break; -+ case 'h': -+ *(short *) loc = strtoul(p, &p, 0); -+ loc += tgt_sizeof_short; -+ break; -+ case 'i': -+ *(int *) loc = strtoul(p, &p, 0); -+ loc += tgt_sizeof_int; -+ break; -+ case 'l': -+ *(long *) loc = strtoul(p, &p, 0); -+ loc += tgt_sizeof_long; -+ break; -+ default: -+ bb_error_msg_and_die("unknown parameter type '%c' for %s", -+ *pinfo, param); -+ } -+ -+ p = skip_whitespace(p); -+ if (*p != ',') -+ break; -+ p = skip_whitespace(p + 1); -+ } -+ -+ if (n < min) -+ bb_error_msg_and_die("parameter %s requires at least %d arguments", param, min); -+ if (*p != '\0') -+ bb_error_msg_and_die("invalid argument syntax for %s", param); -+ } -+ -+ free(xoptions); -+} -+ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+static int new_is_module_checksummed(struct obj_file *f) -+{ -+ const char *p = get_modinfo_value(f, "using_checksums"); -+ if (p) -+ return xatoi(p); -+ return 0; -+} -+ -+/* Get the module's kernel version in the canonical integer form. */ -+ -+static int -+new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) -+{ -+ char *p, *q; -+ int a, b, c; -+ -+ p = get_modinfo_value(f, "kernel_version"); -+ if (p == NULL) -+ return -1; -+ safe_strncpy(str, p, STRVERSIONLEN); -+ -+ a = strtoul(p, &p, 10); -+ if (*p != '.') -+ return -1; -+ b = strtoul(p + 1, &p, 10); -+ if (*p != '.') -+ return -1; -+ c = strtoul(p + 1, &q, 10); -+ if (p + 1 == q) -+ return -1; -+ -+ return a << 16 | b << 8 | c; -+} -+ -+#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -+ -+ -+/* Fetch the loaded modules, and all currently exported symbols. */ -+ -+static void new_get_kernel_symbols(void) -+{ -+ char *module_names, *mn; -+ struct external_module *modules, *m; -+ struct new_module_symbol *syms, *s; -+ size_t ret, bufsize, nmod, nsyms, i, j; -+ -+ /* Collect the loaded modules. */ -+ -+ bufsize = 256; -+ module_names = xmalloc(bufsize); -+ -+ retry_modules_load: -+ if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { -+ if (errno == ENOSPC && bufsize < ret) { -+ bufsize = ret; -+ module_names = xrealloc(module_names, bufsize); -+ goto retry_modules_load; -+ } -+ bb_perror_msg_and_die("QM_MODULES"); -+ } -+ -+ n_ext_modules = nmod = ret; -+ -+ /* Collect the modules' symbols. */ -+ -+ if (nmod) { -+ ext_modules = modules = xmalloc(nmod * sizeof(*modules)); -+ memset(modules, 0, nmod * sizeof(*modules)); -+ for (i = 0, mn = module_names, m = modules; -+ i < nmod; ++i, ++m, mn += strlen(mn) + 1) { -+ struct new_module_info info; -+ -+ if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) { -+ if (errno == ENOENT) { -+ /* The module was removed out from underneath us. */ -+ continue; -+ } -+ bb_perror_msg_and_die("query_module: QM_INFO: %s", mn); -+ } -+ -+ bufsize = 1024; -+ syms = xmalloc(bufsize); -+ retry_mod_sym_load: -+ if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { -+ switch (errno) { -+ case ENOSPC: -+ bufsize = ret; -+ syms = xrealloc(syms, bufsize); -+ goto retry_mod_sym_load; -+ case ENOENT: -+ /* The module was removed out from underneath us. */ -+ continue; -+ default: -+ bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn); -+ } -+ } -+ nsyms = ret; -+ -+ m->name = mn; -+ m->addr = info.addr; -+ m->nsyms = nsyms; -+ m->syms = syms; -+ -+ for (j = 0, s = syms; j < nsyms; ++j, ++s) { -+ s->name += (unsigned long) syms; -+ } -+ } -+ } -+ -+ /* Collect the kernel's symbols. */ -+ -+ syms = xmalloc(bufsize = 16 * 1024); -+ retry_kern_sym_load: -+ if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { -+ if (errno == ENOSPC && bufsize < ret) { -+ bufsize = ret; -+ syms = xrealloc(syms, bufsize); -+ goto retry_kern_sym_load; -+ } -+ bb_perror_msg_and_die("kernel: QM_SYMBOLS"); -+ } -+ nksyms = nsyms = ret; -+ ksyms = syms; -+ -+ for (j = 0, s = syms; j < nsyms; ++j, ++s) { -+ s->name += (unsigned long) syms; -+ } -+} -+ -+ -+/* Return the kernel symbol checksum version, or zero if not used. */ -+ -+static int new_is_kernel_checksummed(void) -+{ -+ struct new_module_symbol *s; -+ size_t i; -+ -+ /* Using_Versions is not the first symbol, but it should be in there. */ -+ -+ for (i = 0, s = ksyms; i < nksyms; ++i, ++s) -+ if (strcmp((char *) s->name, "Using_Versions") == 0) -+ return s->value; -+ -+ return 0; -+} -+ -+ -+static void new_create_this_module(struct obj_file *f, const char *m_name) -+{ -+ struct obj_section *sec; -+ -+ sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long, -+ sizeof(struct new_module)); -+ memset(sec->contents, 0, sizeof(struct new_module)); -+ -+ obj_add_symbol(f, SPFX "__this_module", -1, -+ ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0, -+ sizeof(struct new_module)); -+ -+ obj_string_patch(f, sec->idx, offsetof(struct new_module, name), -+ m_name); -+} -+ -+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS -+/* add an entry to the __ksymtab section, creating it if necessary */ -+static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym) -+{ -+ struct obj_section *sec; -+ ElfW(Addr) ofs; -+ -+ /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section. -+ * If __ksymtab is defined but not marked alloc, x out the first character -+ * (no obj_delete routine) and create a new __ksymtab with the correct -+ * characteristics. -+ */ -+ sec = obj_find_section(f, "__ksymtab"); -+ if (sec && !(sec->header.sh_flags & SHF_ALLOC)) { -+ *((char *)(sec->name)) = 'x'; /* override const */ -+ sec = NULL; -+ } -+ if (!sec) -+ sec = obj_create_alloced_section(f, "__ksymtab", -+ tgt_sizeof_void_p, 0); -+ if (!sec) -+ return; -+ sec->header.sh_flags |= SHF_ALLOC; -+ /* Empty section might be byte-aligned */ -+ sec->header.sh_addralign = tgt_sizeof_void_p; -+ ofs = sec->header.sh_size; -+ obj_symbol_patch(f, sec->idx, ofs, sym); -+ obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name); -+ obj_extend_section(sec, 2 * tgt_sizeof_char_p); -+} -+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -+ -+static int new_create_module_ksymtab(struct obj_file *f) -+{ -+ struct obj_section *sec; -+ int i; -+ -+ /* We must always add the module references. */ -+ -+ if (n_ext_modules_used) { -+ struct new_module_ref *dep; -+ struct obj_symbol *tm; -+ -+ sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p, -+ (sizeof(struct new_module_ref) -+ * n_ext_modules_used)); -+ if (!sec) -+ return 0; -+ -+ tm = obj_find_symbol(f, SPFX "__this_module"); -+ dep = (struct new_module_ref *) sec->contents; -+ for (i = 0; i < n_ext_modules; ++i) -+ if (ext_modules[i].used) { -+ dep->dep = ext_modules[i].addr; -+ obj_symbol_patch(f, sec->idx, -+ (char *) &dep->ref - sec->contents, tm); -+ dep->next_ref = 0; -+ ++dep; -+ } -+ } -+ -+ if (!flag_noexport && !obj_find_section(f, "__ksymtab")) { -+ size_t nsyms; -+ int *loaded; -+ -+ sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0); -+ -+ /* We don't want to export symbols residing in sections that -+ aren't loaded. There are a number of these created so that -+ we make sure certain module options don't appear twice. */ -+ -+ loaded = alloca(sizeof(int) * (i = f->header.e_shnum)); -+ while (--i >= 0) -+ loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; -+ -+ for (nsyms = i = 0; i < HASH_BUCKETS; ++i) { -+ struct obj_symbol *sym; -+ for (sym = f->symtab[i]; sym; sym = sym->next) -+ if (ELF_ST_BIND(sym->info) != STB_LOCAL -+ && sym->secidx <= SHN_HIRESERVE -+ && (sym->secidx >= SHN_LORESERVE -+ || loaded[sym->secidx])) { -+ ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p; -+ -+ obj_symbol_patch(f, sec->idx, ofs, sym); -+ obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, -+ sym->name); -+ -+ nsyms++; -+ } -+ } -+ -+ obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p); -+ } -+ -+ return 1; -+} -+ -+ -+static int -+new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) -+{ -+ struct new_module *module; -+ struct obj_section *sec; -+ void *image; -+ int ret; -+ tgt_long m_addr; -+ -+ sec = obj_find_section(f, ".this"); -+ if (!sec || !sec->contents) { -+ bb_perror_msg_and_die("corrupt module %s?", m_name); -+ } -+ module = (struct new_module *) sec->contents; -+ m_addr = sec->header.sh_addr; -+ -+ module->size_of_struct = sizeof(*module); -+ module->size = m_size; -+ module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0; -+ -+ sec = obj_find_section(f, "__ksymtab"); -+ if (sec && sec->header.sh_size) { -+ module->syms = sec->header.sh_addr; -+ module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p); -+ } -+ -+ if (n_ext_modules_used) { -+ sec = obj_find_section(f, ".kmodtab"); -+ module->deps = sec->header.sh_addr; -+ module->ndeps = n_ext_modules_used; -+ } -+ -+ module->init = -+ obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module")); -+ module->cleanup = -+ obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module")); -+ -+ sec = obj_find_section(f, "__ex_table"); -+ if (sec) { -+ module->ex_table_start = sec->header.sh_addr; -+ module->ex_table_end = sec->header.sh_addr + sec->header.sh_size; -+ } -+ -+ sec = obj_find_section(f, ".text.init"); -+ if (sec) { -+ module->runsize = sec->header.sh_addr - m_addr; -+ } -+ sec = obj_find_section(f, ".data.init"); -+ if (sec) { -+ if (!module->runsize || -+ module->runsize > sec->header.sh_addr - m_addr) -+ module->runsize = sec->header.sh_addr - m_addr; -+ } -+ sec = obj_find_section(f, ARCHDATA_SEC_NAME); -+ if (sec && sec->header.sh_size) { -+ module->archdata_start = (void*)sec->header.sh_addr; -+ module->archdata_end = module->archdata_start + sec->header.sh_size; -+ } -+ sec = obj_find_section(f, KALLSYMS_SEC_NAME); -+ if (sec && sec->header.sh_size) { -+ module->kallsyms_start = (void*)sec->header.sh_addr; -+ module->kallsyms_end = module->kallsyms_start + sec->header.sh_size; -+ } -+ -+ /* Whew! All of the initialization is complete. Collect the final -+ module image and give it to the kernel. */ -+ -+ image = xmalloc(m_size); -+ obj_create_image(f, image); -+ -+ ret = init_module(m_name, (struct new_module *) image); -+ if (ret) -+ bb_perror_msg("init_module: %s", m_name); -+ -+ free(image); -+ -+ return ret == 0; -+} -+ -+ -+/*======================================================================*/ -+ -+static void -+obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -+ const char *string) -+{ -+ struct obj_string_patch *p; -+ struct obj_section *strsec; -+ size_t len = strlen(string) + 1; -+ char *loc; -+ -+ p = xmalloc(sizeof(*p)); -+ p->next = f->string_patches; -+ p->reloc_secidx = secidx; -+ p->reloc_offset = offset; -+ f->string_patches = p; -+ -+ strsec = obj_find_section(f, ".kstrtab"); -+ if (strsec == NULL) { -+ strsec = obj_create_alloced_section(f, ".kstrtab", 1, len); -+ p->string_offset = 0; -+ loc = strsec->contents; -+ } else { -+ p->string_offset = strsec->header.sh_size; -+ loc = obj_extend_section(strsec, len); -+ } -+ memcpy(loc, string, len); -+} -+ -+static void -+obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -+ struct obj_symbol *sym) -+{ -+ struct obj_symbol_patch *p; -+ -+ p = xmalloc(sizeof(*p)); -+ p->next = f->symbol_patches; -+ p->reloc_secidx = secidx; -+ p->reloc_offset = offset; -+ p->sym = sym; -+ f->symbol_patches = p; -+} -+ -+static void obj_check_undefineds(struct obj_file *f) -+{ -+ unsigned i; -+ -+ for (i = 0; i < HASH_BUCKETS; ++i) { -+ struct obj_symbol *sym; -+ for (sym = f->symtab[i]; sym; sym = sym->next) -+ if (sym->secidx == SHN_UNDEF) { -+ if (ELF_ST_BIND(sym->info) == STB_WEAK) { -+ sym->secidx = SHN_ABS; -+ sym->value = 0; -+ } else { -+ if (!flag_quiet) -+ bb_error_msg_and_die("unresolved symbol %s", sym->name); -+ } -+ } -+ } -+} -+ -+static void obj_allocate_commons(struct obj_file *f) -+{ -+ struct common_entry { -+ struct common_entry *next; -+ struct obj_symbol *sym; -+ } *common_head = NULL; -+ -+ unsigned long i; -+ -+ for (i = 0; i < HASH_BUCKETS; ++i) { -+ struct obj_symbol *sym; -+ for (sym = f->symtab[i]; sym; sym = sym->next) -+ if (sym->secidx == SHN_COMMON) { -+ /* Collect all COMMON symbols and sort them by size so as to -+ minimize space wasted by alignment requirements. */ -+ { -+ struct common_entry **p, *n; -+ for (p = &common_head; *p; p = &(*p)->next) -+ if (sym->size <= (*p)->sym->size) -+ break; -+ -+ n = alloca(sizeof(*n)); -+ n->next = *p; -+ n->sym = sym; -+ *p = n; -+ } -+ } -+ } -+ -+ for (i = 1; i < f->local_symtab_size; ++i) { -+ struct obj_symbol *sym = f->local_symtab[i]; -+ if (sym && sym->secidx == SHN_COMMON) { -+ struct common_entry **p, *n; -+ for (p = &common_head; *p; p = &(*p)->next) -+ if (sym == (*p)->sym) -+ break; -+ else if (sym->size < (*p)->sym->size) { -+ n = alloca(sizeof(*n)); -+ n->next = *p; -+ n->sym = sym; -+ *p = n; -+ break; -+ } -+ } -+ } -+ -+ if (common_head) { -+ /* Find the bss section. */ -+ for (i = 0; i < f->header.e_shnum; ++i) -+ if (f->sections[i]->header.sh_type == SHT_NOBITS) -+ break; -+ -+ /* If for some reason there hadn't been one, create one. */ -+ if (i == f->header.e_shnum) { -+ struct obj_section *sec; -+ -+ f->sections = xrealloc_vector(f->sections, 2, i); -+ f->sections[i] = sec = arch_new_section(); -+ f->header.e_shnum = i + 1; -+ -+ sec->header.sh_type = SHT_PROGBITS; -+ sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -+ sec->name = ".bss"; -+ sec->idx = i; -+ } -+ -+ /* Allocate the COMMONS. */ -+ { -+ ElfW(Addr) bss_size = f->sections[i]->header.sh_size; -+ ElfW(Addr) max_align = f->sections[i]->header.sh_addralign; -+ struct common_entry *c; -+ -+ for (c = common_head; c; c = c->next) { -+ ElfW(Addr) align = c->sym->value; -+ -+ if (align > max_align) -+ max_align = align; -+ if (bss_size & (align - 1)) -+ bss_size = (bss_size | (align - 1)) + 1; -+ -+ c->sym->secidx = i; -+ c->sym->value = bss_size; -+ -+ bss_size += c->sym->size; -+ } -+ -+ f->sections[i]->header.sh_size = bss_size; -+ f->sections[i]->header.sh_addralign = max_align; -+ } -+ } -+ -+ /* For the sake of patch relocation and parameter initialization, -+ allocate zeroed data for NOBITS sections now. Note that after -+ this we cannot assume NOBITS are really empty. */ -+ for (i = 0; i < f->header.e_shnum; ++i) { -+ struct obj_section *s = f->sections[i]; -+ if (s->header.sh_type == SHT_NOBITS) { -+ if (s->header.sh_size != 0) -+ s->contents = memset(xmalloc(s->header.sh_size), -+ 0, s->header.sh_size); -+ else -+ s->contents = NULL; -+ -+ s->header.sh_type = SHT_PROGBITS; -+ } -+ } -+} -+ -+static unsigned long obj_load_size(struct obj_file *f) -+{ -+ unsigned long dot = 0; -+ struct obj_section *sec; -+ -+ /* Finalize the positions of the sections relative to one another. */ -+ -+ for (sec = f->load_order; sec; sec = sec->load_next) { -+ ElfW(Addr) align; -+ -+ align = sec->header.sh_addralign; -+ if (align && (dot & (align - 1))) -+ dot = (dot | (align - 1)) + 1; -+ -+ sec->header.sh_addr = dot; -+ dot += sec->header.sh_size; -+ } -+ -+ return dot; -+} -+ -+static int obj_relocate(struct obj_file *f, ElfW(Addr) base) -+{ -+ int i, n = f->header.e_shnum; -+ int ret = 1; -+ -+ /* Finalize the addresses of the sections. */ -+ -+ f->baseaddr = base; -+ for (i = 0; i < n; ++i) -+ f->sections[i]->header.sh_addr += base; -+ -+ /* And iterate over all of the relocations. */ -+ -+ for (i = 0; i < n; ++i) { -+ struct obj_section *relsec, *symsec, *targsec, *strsec; -+ ElfW(RelM) * rel, *relend; -+ ElfW(Sym) * symtab; -+ const char *strtab; -+ -+ relsec = f->sections[i]; -+ if (relsec->header.sh_type != SHT_RELM) -+ continue; -+ -+ symsec = f->sections[relsec->header.sh_link]; -+ targsec = f->sections[relsec->header.sh_info]; -+ strsec = f->sections[symsec->header.sh_link]; -+ -+ rel = (ElfW(RelM) *) relsec->contents; -+ relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); -+ symtab = (ElfW(Sym) *) symsec->contents; -+ strtab = (const char *) strsec->contents; -+ -+ for (; rel < relend; ++rel) { -+ ElfW(Addr) value = 0; -+ struct obj_symbol *intsym = NULL; -+ unsigned long symndx; -+ ElfW(Sym) * extsym = 0; -+ const char *errmsg; -+ -+ /* Attempt to find a value to use for this relocation. */ -+ -+ symndx = ELF_R_SYM(rel->r_info); -+ if (symndx) { -+ /* Note we've already checked for undefined symbols. */ -+ -+ extsym = &symtab[symndx]; -+ if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) { -+ /* Local symbols we look up in the local table to be sure -+ we get the one that is really intended. */ -+ intsym = f->local_symtab[symndx]; -+ } else { -+ /* Others we look up in the hash table. */ -+ const char *name; -+ if (extsym->st_name) -+ name = strtab + extsym->st_name; -+ else -+ name = f->sections[extsym->st_shndx]->name; -+ intsym = obj_find_symbol(f, name); -+ } -+ -+ value = obj_symbol_final_value(f, intsym); -+ intsym->referenced = 1; -+ } -+#if SHT_RELM == SHT_RELA -+#if defined(__alpha__) && defined(AXP_BROKEN_GAS) -+ /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */ -+ if (!extsym || !extsym->st_name || -+ ELF_ST_BIND(extsym->st_info) != STB_LOCAL) -+#endif -+ value += rel->r_addend; -+#endif -+ -+ /* Do it! */ -+ switch (arch_apply_relocation -+ (f, targsec, /*symsec,*/ intsym, rel, value) -+ ) { -+ case obj_reloc_ok: -+ break; -+ -+ case obj_reloc_overflow: -+ errmsg = "Relocation overflow"; -+ goto bad_reloc; -+ case obj_reloc_dangerous: -+ errmsg = "Dangerous relocation"; -+ goto bad_reloc; -+ case obj_reloc_unhandled: -+ errmsg = "Unhandled relocation"; -+bad_reloc: -+ if (extsym) { -+ bb_error_msg("%s of type %ld for %s", errmsg, -+ (long) ELF_R_TYPE(rel->r_info), -+ strtab + extsym->st_name); -+ } else { -+ bb_error_msg("%s of type %ld", errmsg, -+ (long) ELF_R_TYPE(rel->r_info)); -+ } -+ ret = 0; -+ break; -+ } -+ } -+ } -+ -+ /* Finally, take care of the patches. */ -+ -+ if (f->string_patches) { -+ struct obj_string_patch *p; -+ struct obj_section *strsec; -+ ElfW(Addr) strsec_base; -+ strsec = obj_find_section(f, ".kstrtab"); -+ strsec_base = strsec->header.sh_addr; -+ -+ for (p = f->string_patches; p; p = p->next) { -+ struct obj_section *targsec = f->sections[p->reloc_secidx]; -+ *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) -+ = strsec_base + p->string_offset; -+ } -+ } -+ -+ if (f->symbol_patches) { -+ struct obj_symbol_patch *p; -+ -+ for (p = f->symbol_patches; p; p = p->next) { -+ struct obj_section *targsec = f->sections[p->reloc_secidx]; -+ *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) -+ = obj_symbol_final_value(f, p->sym); -+ } -+ } -+ -+ return ret; -+} -+ -+static int obj_create_image(struct obj_file *f, char *image) -+{ -+ struct obj_section *sec; -+ ElfW(Addr) base = f->baseaddr; -+ -+ for (sec = f->load_order; sec; sec = sec->load_next) { -+ char *secimg; -+ -+ if (sec->contents == 0 || sec->header.sh_size == 0) -+ continue; -+ -+ secimg = image + (sec->header.sh_addr - base); -+ -+ /* Note that we allocated data for NOBITS sections earlier. */ -+ memcpy(secimg, sec->contents, sec->header.sh_size); -+ } -+ -+ return 1; -+} -+ -+/*======================================================================*/ -+ -+static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM) -+{ -+ struct obj_file *f; -+ ElfW(Shdr) * section_headers; -+ size_t shnum, i; -+ char *shstrtab; -+ -+ /* Read the file header. */ -+ -+ f = arch_new_file(); -+ f->symbol_cmp = strcmp; -+ f->symbol_hash = obj_elf_hash; -+ f->load_order_search_start = &f->load_order; -+ -+ fseek(fp, 0, SEEK_SET); -+ if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { -+ bb_perror_msg_and_die("error reading ELF header"); -+ } -+ -+ if (f->header.e_ident[EI_MAG0] != ELFMAG0 -+ || f->header.e_ident[EI_MAG1] != ELFMAG1 -+ || f->header.e_ident[EI_MAG2] != ELFMAG2 -+ || f->header.e_ident[EI_MAG3] != ELFMAG3) { -+ bb_error_msg_and_die("not an ELF file"); -+ } -+ if (f->header.e_ident[EI_CLASS] != ELFCLASSM -+ || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN -+ ? ELFDATA2MSB : ELFDATA2LSB) -+ || f->header.e_ident[EI_VERSION] != EV_CURRENT -+ || !MATCH_MACHINE(f->header.e_machine)) { -+ bb_error_msg_and_die("ELF file not for this architecture"); -+ } -+ if (f->header.e_type != ET_REL) { -+ bb_error_msg_and_die("ELF file not a relocatable object"); -+ } -+ -+ /* Read the section headers. */ -+ -+ if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { -+ bb_error_msg_and_die("section header size mismatch: %lu != %lu", -+ (unsigned long) f->header.e_shentsize, -+ (unsigned long) sizeof(ElfW(Shdr))); -+ } -+ -+ shnum = f->header.e_shnum; -+ f->sections = xmalloc(sizeof(struct obj_section *) * shnum); -+ memset(f->sections, 0, sizeof(struct obj_section *) * shnum); -+ -+ section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); -+ fseek(fp, f->header.e_shoff, SEEK_SET); -+ if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { -+ bb_perror_msg_and_die("error reading ELF section headers"); -+ } -+ -+ /* Read the section data. */ -+ -+ for (i = 0; i < shnum; ++i) { -+ struct obj_section *sec; -+ -+ f->sections[i] = sec = arch_new_section(); -+ -+ sec->header = section_headers[i]; -+ sec->idx = i; -+ -+ if (sec->header.sh_size) { -+ switch (sec->header.sh_type) { -+ case SHT_NULL: -+ case SHT_NOTE: -+ case SHT_NOBITS: -+ /* ignore */ -+ break; -+ -+ case SHT_PROGBITS: -+#if LOADBITS -+ if (!loadprogbits) { -+ sec->contents = NULL; -+ break; -+ } -+#endif -+ case SHT_SYMTAB: -+ case SHT_STRTAB: -+ case SHT_RELM: -+ if (sec->header.sh_size > 0) { -+ sec->contents = xmalloc(sec->header.sh_size); -+ fseek(fp, sec->header.sh_offset, SEEK_SET); -+ if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { -+ bb_perror_msg_and_die("error reading ELF section data"); -+ } -+ } else { -+ sec->contents = NULL; -+ } -+ break; -+ -+#if SHT_RELM == SHT_REL -+ case SHT_RELA: -+ bb_error_msg_and_die("RELA relocations not supported on this architecture"); -+#else -+ case SHT_REL: -+ bb_error_msg_and_die("REL relocations not supported on this architecture"); -+#endif -+ default: -+ if (sec->header.sh_type >= SHT_LOPROC) { -+ /* Assume processor specific section types are debug -+ info and can safely be ignored. If this is ever not -+ the case (Hello MIPS?), don't put ifdefs here but -+ create an arch_load_proc_section(). */ -+ break; -+ } -+ -+ bb_error_msg_and_die("can't handle sections of type %ld", -+ (long) sec->header.sh_type); -+ } -+ } -+ } -+ -+ /* Do what sort of interpretation as needed by each section. */ -+ -+ shstrtab = f->sections[f->header.e_shstrndx]->contents; -+ -+ for (i = 0; i < shnum; ++i) { -+ struct obj_section *sec = f->sections[i]; -+ sec->name = shstrtab + sec->header.sh_name; -+ } -+ -+ for (i = 0; i < shnum; ++i) { -+ struct obj_section *sec = f->sections[i]; -+ -+ /* .modinfo should be contents only but gcc has no attribute for that. -+ * The kernel may have marked .modinfo as ALLOC, ignore this bit. -+ */ -+ if (strcmp(sec->name, ".modinfo") == 0) -+ sec->header.sh_flags &= ~SHF_ALLOC; -+ -+ if (sec->header.sh_flags & SHF_ALLOC) -+ obj_insert_section_load_order(f, sec); -+ -+ switch (sec->header.sh_type) { -+ case SHT_SYMTAB: -+ { -+ unsigned long nsym, j; -+ char *strtab; -+ ElfW(Sym) * sym; -+ -+ if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { -+ bb_error_msg_and_die("symbol size mismatch: %lu != %lu", -+ (unsigned long) sec->header.sh_entsize, -+ (unsigned long) sizeof(ElfW(Sym))); -+ } -+ -+ nsym = sec->header.sh_size / sizeof(ElfW(Sym)); -+ strtab = f->sections[sec->header.sh_link]->contents; -+ sym = (ElfW(Sym) *) sec->contents; -+ -+ /* Allocate space for a table of local symbols. */ -+ j = f->local_symtab_size = sec->header.sh_info; -+ f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *)); -+ -+ /* Insert all symbols into the hash table. */ -+ for (j = 1, ++sym; j < nsym; ++j, ++sym) { -+ ElfW(Addr) val = sym->st_value; -+ const char *name; -+ if (sym->st_name) -+ name = strtab + sym->st_name; -+ else if (sym->st_shndx < shnum) -+ name = f->sections[sym->st_shndx]->name; -+ else -+ continue; -+#if defined(__SH5__) -+ /* -+ * For sh64 it is possible that the target of a branch -+ * requires a mode switch (32 to 16 and back again). -+ * -+ * This is implied by the lsb being set in the target -+ * address for SHmedia mode and clear for SHcompact. -+ */ -+ val |= sym->st_other & 4; -+#endif -+ obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, -+ val, sym->st_size); -+ } -+ } -+ break; -+ -+ case SHT_RELM: -+ if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { -+ bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu", -+ (unsigned long) sec->header.sh_entsize, -+ (unsigned long) sizeof(ElfW(RelM))); -+ } -+ break; -+ /* XXX Relocation code from modutils-2.3.19 is not here. -+ * Why? That's about 20 lines of code from obj/obj_load.c, -+ * which gets done in a second pass through the sections. -+ * This BusyBox insmod does similar work in obj_relocate(). */ -+ } -+ } -+ -+ return f; -+} -+ -+#if ENABLE_FEATURE_INSMOD_LOADINKMEM -+/* -+ * load the unloaded sections directly into the memory allocated by -+ * kernel for the module -+ */ -+ -+static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase) -+{ -+ ElfW(Addr) base = f->baseaddr; -+ struct obj_section* sec; -+ -+ for (sec = f->load_order; sec; sec = sec->load_next) { -+ -+ /* section already loaded? */ -+ if (sec->contents != NULL) -+ continue; -+ -+ if (sec->header.sh_size == 0) -+ continue; -+ -+ sec->contents = imagebase + (sec->header.sh_addr - base); -+ fseek(fp, sec->header.sh_offset, SEEK_SET); -+ if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { -+ bb_perror_msg("error reading ELF section data"); -+ return 0; -+ } -+ -+ } -+ return 1; -+} -+#endif -+ -+static void hide_special_symbols(struct obj_file *f) -+{ -+ static const char *const specials[] = { -+ SPFX "cleanup_module", -+ SPFX "init_module", -+ SPFX "kernel_version", -+ NULL -+ }; -+ -+ struct obj_symbol *sym; -+ const char *const *p; -+ -+ for (p = specials; *p; ++p) { -+ sym = obj_find_symbol(f, *p); -+ if (sym != NULL) -+ sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info)); -+ } -+} -+ -+ -+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -+static int obj_gpl_license(struct obj_file *f, const char **license) -+{ -+ struct obj_section *sec; -+ /* This list must match *exactly* the list of allowable licenses in -+ * linux/include/linux/module.h. Checking for leading "GPL" will not -+ * work, somebody will use "GPL sucks, this is proprietary". -+ */ -+ static const char *const gpl_licenses[] = { -+ "GPL", -+ "GPL v2", -+ "GPL and additional rights", -+ "Dual BSD/GPL", -+ "Dual MPL/GPL" -+ }; -+ -+ sec = obj_find_section(f, ".modinfo"); -+ if (sec) { -+ const char *value, *ptr, *endptr; -+ ptr = sec->contents; -+ endptr = ptr + sec->header.sh_size; -+ while (ptr < endptr) { -+ value = strchr(ptr, '='); -+ if (value && strncmp(ptr, "license", value-ptr) == 0) { -+ unsigned i; -+ if (license) -+ *license = value+1; -+ for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) { -+ if (strcmp(value+1, gpl_licenses[i]) == 0) -+ return 0; -+ } -+ return 2; -+ } -+ ptr = strchr(ptr, '\0'); -+ if (ptr) -+ ptr++; -+ else -+ ptr = endptr; -+ } -+ } -+ return 1; -+} -+ -+#define TAINT_FILENAME "/proc/sys/kernel/tainted" -+#define TAINT_PROPRIETORY_MODULE (1 << 0) -+#define TAINT_FORCED_MODULE (1 << 1) -+#define TAINT_UNSAFE_SMP (1 << 2) -+#define TAINT_URL "http://www.tux.org/lkml/#export-tainted" -+ -+static void set_tainted(int fd, const char *m_name, -+ int kernel_has_tainted, int taint, const char *text1, const char *text2) -+{ -+ static smallint printed_info; -+ -+ char buf[80]; -+ int oldval; -+ -+ if (fd < 0 && !kernel_has_tainted) -+ return; /* New modutils on old kernel */ -+ printf("Warning: loading %s will taint the kernel: %s%s\n", -+ m_name, text1, text2); -+ if (!printed_info) { -+ printf(" See %s for information about tainted modules\n", TAINT_URL); -+ printed_info = 1; -+ } -+ if (fd >= 0) { -+ read(fd, buf, sizeof(buf)-1); -+ buf[sizeof(buf)-1] = '\0'; -+ oldval = strtoul(buf, NULL, 10); -+ sprintf(buf, "%d\n", oldval | taint); -+ write(fd, buf, strlen(buf)); -+ } -+} -+ -+/* Check if loading this module will taint the kernel. */ -+static void check_tainted_module(struct obj_file *f, const char *m_name) -+{ -+ static const char tainted_file[] ALIGN1 = TAINT_FILENAME; -+ -+ int fd, kernel_has_tainted; -+ const char *ptr; -+ -+ kernel_has_tainted = 1; -+ fd = open(tainted_file, O_RDWR); -+ if (fd < 0) { -+ if (errno == ENOENT) -+ kernel_has_tainted = 0; -+ else if (errno == EACCES) -+ kernel_has_tainted = 1; -+ else { -+ perror(tainted_file); -+ kernel_has_tainted = 0; -+ } -+ } -+ -+ switch (obj_gpl_license(f, &ptr)) { -+ case 0: -+ break; -+ case 1: -+ set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); -+ break; -+ case 2: -+ /* The module has a non-GPL license so we pretend that the -+ * kernel always has a taint flag to get a warning even on -+ * kernels without the proc flag. -+ */ -+ set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); -+ break; -+ default: -+ set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); -+ break; -+ } -+ -+ if (flag_force_load) -+ set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); -+ -+ if (fd >= 0) -+ close(fd); -+} -+#else /* FEATURE_CHECK_TAINTED_MODULE */ -+#define check_tainted_module(x, y) do { } while (0); -+#endif /* FEATURE_CHECK_TAINTED_MODULE */ -+ -+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS -+/* add module source, timestamp, kernel version and a symbol for the -+ * start of some sections. this info is used by ksymoops to do better -+ * debugging. -+ */ -+#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+#define get_module_version(f, str) get_module_version(str) -+#endif -+static int -+get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) -+{ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+ return new_get_module_version(f, str); -+#else /* FEATURE_INSMOD_VERSION_CHECKING */ -+ strncpy(str, "???", sizeof(str)); -+ return -1; -+#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -+} -+ -+/* add module source, timestamp, kernel version and a symbol for the -+ * start of some sections. this info is used by ksymoops to do better -+ * debugging. -+ */ -+static void -+add_ksymoops_symbols(struct obj_file *f, const char *filename, -+ const char *m_name) -+{ -+ static const char symprefix[] ALIGN1 = "__insmod_"; -+ static const char section_names[][8] = { -+ ".text", -+ ".rodata", -+ ".data", -+ ".bss", -+ ".sbss" -+ }; -+ -+ struct obj_section *sec; -+ struct obj_symbol *sym; -+ char *name, *absolute_filename; -+ char str[STRVERSIONLEN]; -+ unsigned i; -+ int l, lm_name, lfilename, use_ksymtab, version; -+ struct stat statbuf; -+ -+ /* WARNING: was using realpath, but replaced by readlink to stop using -+ * lots of stack. But here it seems to be able to cause problems? */ -+ absolute_filename = xmalloc_readlink(filename); -+ if (!absolute_filename) -+ absolute_filename = xstrdup(filename); -+ -+ lm_name = strlen(m_name); -+ lfilename = strlen(absolute_filename); -+ -+ /* add to ksymtab if it already exists or there is no ksymtab and other symbols -+ * are not to be exported. otherwise leave ksymtab alone for now, the -+ * "export all symbols" compatibility code will export these symbols later. -+ */ -+ use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport; -+ -+ sec = obj_find_section(f, ".this"); -+ if (sec) { -+ /* tag the module header with the object name, last modified -+ * timestamp and module version. worst case for module version -+ * is 0xffffff, decimal 16777215. putting all three fields in -+ * one symbol is less readable but saves kernel space. -+ */ -+ l = sizeof(symprefix) + /* "__insmod_" */ -+ lm_name + /* module name */ -+ 2 + /* "_O" */ -+ lfilename + /* object filename */ -+ 2 + /* "_M" */ -+ 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */ -+ 2 + /* "_V" */ -+ 8 + /* version in dec */ -+ 1; /* nul */ -+ name = xmalloc(l); -+ if (stat(absolute_filename, &statbuf) != 0) -+ statbuf.st_mtime = 0; -+ version = get_module_version(f, str); /* -1 if not found */ -+ snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", -+ symprefix, m_name, absolute_filename, -+ (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime, -+ version); -+ sym = obj_add_symbol(f, name, -1, -+ ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -+ sec->idx, sec->header.sh_addr, 0); -+ if (use_ksymtab) -+ new_add_ksymtab(f, sym); -+ } -+ free(absolute_filename); -+#ifdef _NOT_SUPPORTED_ -+ /* record where the persistent data is going, same address as previous symbol */ -+ -+ if (f->persist) { -+ l = sizeof(symprefix) + /* "__insmod_" */ -+ lm_name + /* module name */ -+ 2 + /* "_P" */ -+ strlen(f->persist) + /* data store */ -+ 1; /* nul */ -+ name = xmalloc(l); -+ snprintf(name, l, "%s%s_P%s", -+ symprefix, m_name, f->persist); -+ sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -+ sec->idx, sec->header.sh_addr, 0); -+ if (use_ksymtab) -+ new_add_ksymtab(f, sym); -+ } -+#endif /* _NOT_SUPPORTED_ */ -+ /* tag the desired sections if size is non-zero */ -+ -+ for (i = 0; i < ARRAY_SIZE(section_names); ++i) { -+ sec = obj_find_section(f, section_names[i]); -+ if (sec && sec->header.sh_size) { -+ l = sizeof(symprefix) + /* "__insmod_" */ -+ lm_name + /* module name */ -+ 2 + /* "_S" */ -+ strlen(sec->name) + /* section name */ -+ 2 + /* "_L" */ -+ 8 + /* length in dec */ -+ 1; /* nul */ -+ name = xmalloc(l); -+ snprintf(name, l, "%s%s_S%s_L%ld", -+ symprefix, m_name, sec->name, -+ (long)sec->header.sh_size); -+ sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -+ sec->idx, sec->header.sh_addr, 0); -+ if (use_ksymtab) -+ new_add_ksymtab(f, sym); -+ } -+ } -+} -+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -+ -+#if ENABLE_FEATURE_INSMOD_LOAD_MAP -+static void print_load_map(struct obj_file *f) -+{ -+ struct obj_section *sec; -+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL -+ struct obj_symbol **all, **p; -+ int i, nsyms, *loaded; -+ struct obj_symbol *sym; -+#endif -+ /* Report on the section layout. */ -+ -+ printf("Sections: Size %-*s Align\n", -+ (int) (2 * sizeof(void *)), "Address"); -+ -+ for (sec = f->load_order; sec; sec = sec->load_next) { -+ int a; -+ unsigned long tmp; -+ -+ for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a) -+ tmp >>= 1; -+ if (a == -1) -+ a = 0; -+ -+ printf("%-15s %08lx %0*lx 2**%d\n", -+ sec->name, -+ (long)sec->header.sh_size, -+ (int) (2 * sizeof(void *)), -+ (long)sec->header.sh_addr, -+ a); -+ } -+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL -+ /* Quick reference which section indices are loaded. */ -+ -+ i = f->header.e_shnum; -+ loaded = alloca(sizeof(int) * i); -+ while (--i >= 0) -+ loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0); -+ -+ /* Collect the symbols we'll be listing. */ -+ -+ for (nsyms = i = 0; i < HASH_BUCKETS; ++i) -+ for (sym = f->symtab[i]; sym; sym = sym->next) -+ if (sym->secidx <= SHN_HIRESERVE -+ && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])) -+ ++nsyms; -+ -+ all = alloca(nsyms * sizeof(struct obj_symbol *)); -+ -+ for (i = 0, p = all; i < HASH_BUCKETS; ++i) -+ for (sym = f->symtab[i]; sym; sym = sym->next) -+ if (sym->secidx <= SHN_HIRESERVE -+ && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])) -+ *p++ = sym; -+ -+ /* And list them. */ -+ printf("\nSymbols:\n"); -+ for (p = all; p < all + nsyms; ++p) { -+ char type = '?'; -+ unsigned long value; -+ -+ sym = *p; -+ if (sym->secidx == SHN_ABS) { -+ type = 'A'; -+ value = sym->value; -+ } else if (sym->secidx == SHN_UNDEF) { -+ type = 'U'; -+ value = 0; -+ } else { -+ sec = f->sections[sym->secidx]; -+ -+ if (sec->header.sh_type == SHT_NOBITS) -+ type = 'B'; -+ else if (sec->header.sh_flags & SHF_ALLOC) { -+ if (sec->header.sh_flags & SHF_EXECINSTR) -+ type = 'T'; -+ else if (sec->header.sh_flags & SHF_WRITE) -+ type = 'D'; -+ else -+ type = 'R'; -+ } -+ value = sym->value + sec->header.sh_addr; -+ } -+ -+ if (ELF_ST_BIND(sym->info) == STB_LOCAL) -+ type = tolower(type); -+ -+ printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value, -+ type, sym->name); -+ } -+#endif -+} -+#else /* !FEATURE_INSMOD_LOAD_MAP */ -+static void print_load_map(struct obj_file *f UNUSED_PARAM) -+{ -+} -+#endif -+ -+int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options UNUSED_PARAM) -+{ -+ int k_crcs; -+ unsigned long m_size; -+ ElfW(Addr) m_addr; -+ struct obj_file *f; -+ struct utsname uts; -+ int exit_status = EXIT_FAILURE; -+ int m_has_modinfo; -+ char *m_name; -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+ char m_strversion[STRVERSIONLEN]; -+ int m_version, m_crcs; -+#endif -+ FILE *fp; -+ -+ uname(&uts); -+ fp = fopen_for_read(m_filename); -+ if (fp == NULL) -+ return EXIT_FAILURE; -+ -+ m_name = xstrdup(bb_basename(m_filename)); -+ *strrchr(m_name, '.') = 0; -+ -+ f = obj_load(fp, LOADBITS); -+ -+ if (get_modinfo_value(f, "kernel_version") == NULL) -+ m_has_modinfo = 0; -+ else -+ m_has_modinfo = 1; -+ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+ /* Version correspondence? */ -+ if (!flag_quiet) { -+ if (m_has_modinfo) { -+ m_version = new_get_module_version(f, m_strversion); -+ if (m_version == -1) { -+ bb_error_msg_and_die("cannot find the kernel version the module was " -+ "compiled for"); -+ } -+ } -+ -+ if (strncmp(uts.release, m_strversion, STRVERSIONLEN) != 0) { -+ bb_error_msg("%skernel-module version mismatch\n" -+ "\t%s was compiled for kernel version %s\n" -+ "\twhile this kernel is version %s", -+ flag_force_load ? "warning: " : "", -+ m_name, m_strversion, uts.release); -+ if (!flag_force_load) -+ goto out; -+ } -+ } -+ k_crcs = 0; -+#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -+ -+ if (query_module(NULL, 0, NULL, 0, NULL)) -+ bb_error_msg_and_die("not configured to support old kernels"); -+ new_get_kernel_symbols(); -+ k_crcs = new_is_kernel_checksummed(); -+ -+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -+ m_crcs = 0; -+ if (m_has_modinfo) -+ m_crcs = new_is_module_checksummed(f); -+ -+ if (m_crcs != k_crcs) -+ obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash); -+#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -+ -+ /* Let the module know about the kernel symbols. */ -+ add_kernel_symbols(f); -+ -+ /* Allocate common symbols, symbol tables, and string tables. */ -+ -+ new_create_this_module(f, m_name); -+ obj_check_undefineds(f); -+ obj_allocate_commons(f); -+ check_tainted_module(f, m_name); -+ -+ /* done with the module name, on to the optional var=value arguments */ -+ new_process_module_arguments(f, options); -+ -+ arch_create_got(f); -+ hide_special_symbols(f); -+ -+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS -+ add_ksymoops_symbols(f, m_filename, m_name); -+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -+ -+ new_create_module_ksymtab(f); -+ -+ /* Find current size of the module */ -+ m_size = obj_load_size(f); -+ -+ m_addr = create_module(m_name, m_size); -+ if (m_addr == (ElfW(Addr))(-1)) switch (errno) { -+ case EEXIST: -+ bb_error_msg_and_die("a module named %s already exists", m_name); -+ case ENOMEM: -+ bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes", -+ m_size); -+ default: -+ bb_perror_msg_and_die("create_module: %s", m_name); -+ } -+ -+#if !LOADBITS -+ /* -+ * the PROGBITS section was not loaded by the obj_load -+ * now we can load them directly into the kernel memory -+ */ -+ if (!obj_load_progbits(fp, f, (char*)m_addr)) { -+ delete_module(m_name, 0); -+ goto out; -+ } -+#endif -+ -+ if (!obj_relocate(f, m_addr)) { -+ delete_module(m_name, 0); -+ goto out; -+ } -+ -+ if (!new_init_module(m_name, f, m_size)) { -+ delete_module(m_name, 0); -+ goto out; -+ } -+ -+ if (flag_print_load_map) -+ print_load_map(f); -+ -+ exit_status = EXIT_SUCCESS; -+ -+ out: -+ if (fp) -+ fclose(fp); -+ free(m_name); -+ -+ return exit_status; -+} -Index: modutils/modutils.h -=================================================================== ---- modutils/modutils.h (revision 0) -+++ modutils/modutils.h (revision 0) -@@ -0,0 +1,65 @@ -+/* -+ * Common modutils related functions for busybox -+ * -+ * Copyright (C) 2008 by Timo Teras <timo.teras@iki.fi> -+ * -+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. -+ */ -+ -+#ifndef __MODUTILS_H__ -+#define __MODUTILS_H__ -+ -+#include "libbb.h" -+#include <stdio.h> -+ -+#if __GNUC_PREREQ(4,1) -+# pragma GCC visibility push(hidden) -+#endif -+ -+/* As defined in linux/include/linux/module.h */ -+#define MODULE_NAME_LEN 64 -+ -+int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC ; -+const char *moderror(int err) FAST_FUNC; -+char *filename2modname(const char *filename, char *modname) FAST_FUNC; -+char *parse_cmdline_module_options(char **argv) FAST_FUNC; -+ -+#define INSMOD_OPTS "vq" USE_FEATURE_2_4_MODULES("sLo:fkx") \ -+ USE_FEATURE_INSMOD_LOAD_MAP("m") -+#define INSMOD_ARGS USE_FEATURE_2_4_MODULES(, &insmod_outputname) -+ -+enum { -+ INSMOD_OPT_VERBOSE = 0x0001, -+ INSMOD_OPT_SILENT = 0x0002, -+ INSMOD_OPT_SYSLOG = 0x0004 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_LOCK = 0x0008 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_OUTPUTNAME = 0x0010 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_FORCE = 0x0020 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_KERNELD = 0x0040 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_NO_EXPORT = 0x0080 * ENABLE_FEATURE_2_4_MODULES, -+ INSMOD_OPT_PRINT_MAP = 0x0100 * ENABLE_FEATURE_INSMOD_LOAD_MAP, -+#if ENABLE_FEATURE_2_4_MODULES -+#if ENABLE_FEATURE_INSMOD_LOAD_MAP -+ INSMOD_OPT_UNUSED = 0x0200, -+#else /* ENABLE_FEATURE_INSMOD_LOAD_MAP */ -+ INSMOD_OPT_UNUSED = 0x0100 -+#endif -+#else /* ENABLE_FEATURE_2_4_MODULES */ -+ INSMOD_OPT_UNUSED = 0x0004 -+#endif -+}; -+ -+int FAST_FUNC bb_init_module(const char *module, const char *options); -+int FAST_FUNC bb_delete_module(const char *module, unsigned int flags); -+ -+#if ENABLE_FEATURE_2_4_MODULES -+extern char *insmod_outputname; -+ -+int FAST_FUNC bb_init_module_24(const char *module, const char *options); -+#endif -+ -+#if __GNUC_PREREQ(4,1) -+# pragma GCC visibility pop -+#endif -+ -+#endif -Index: modutils/modprobe.c -=================================================================== ---- modutils/modprobe.c (revision 23360) -+++ modutils/modprobe.c (working copy) -@@ -2,951 +2,294 @@ - /* - * Modprobe written from scratch for BusyBox - * -- * Copyright (c) 2002 by Robert Griebl, griebl@gmx.de -- * Copyright (c) 2003 by Andrew Dennison, andrew.dennison@motec.com.au -- * Copyright (c) 2005 by Jim Bauer, jfbauer@nfr.com -+ * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi> -+ * Copyright (c) 2008 Vladimir Dronnikov - * -- * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998@anciens.enib.fr -- * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. --*/ -+ */ - - #include "libbb.h" -+#include "modutils.h" - #include <sys/utsname.h> - #include <fnmatch.h> - --#define line_buffer bb_common_bufsiz1 -- --struct mod_opt_t { /* one-way list of options to pass to a module */ -- char * m_opt_val; -- struct mod_opt_t * m_next; -+struct modprobe_option { -+ char *module; -+ char *option; - }; - --struct dep_t { /* one-way list of dependency rules */ -- /* a dependency rule */ -- char * m_name; /* the module name*/ -- char * m_path; /* the module file path */ -- struct mod_opt_t * m_options; /* the module options */ -- -- unsigned int m_isalias :1; /* the module is an alias */ -- unsigned int m_isblacklisted:1; /* the module is blacklisted */ -- unsigned int m_reserved :14; /* stuffin' */ -- -- unsigned int m_depcnt :16; /* the number of dependable module(s) */ -- char ** m_deparr; /* the list of dependable module(s) */ -- -- struct dep_t * m_next; /* the next dependency rule */ -+struct modprobe_conf { -+ char probename[MODULE_NAME_LEN]; -+ llist_t *options; -+ llist_t *aliases; -+#if ENABLE_FEATURE_MODPROBE_BLACKLIST -+#define add_to_blacklist(conf, name) llist_add_to(&conf->blacklist, name) -+#define check_blacklist(conf, name) (llist_find(conf->blacklist, name) == NULL) -+ llist_t *blacklist; -+#else -+#define add_to_blacklist(conf, name) do {} while (0) -+#define check_blacklist(conf, name) (1) -+#endif - }; - --struct mod_list_t { /* two-way list of modules to process */ -- /* a module description */ -- const char * m_name; -- char * m_path; -- struct mod_opt_t * m_options; -- -- struct mod_list_t * m_prev; -- struct mod_list_t * m_next; -+#define MODPROBE_OPTS "acdlnrt:VC:" USE_FEATURE_MODPROBE_BLACKLIST("b") -+enum { -+ MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ -+ MODPROBE_OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << 1), /* c */ -+ MODPROBE_OPT_D = (INSMOD_OPT_UNUSED << 2), /* d */ -+ MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 3), /* l */ -+ MODPROBE_OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << 4), /* n */ -+ MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 5), /* r */ -+ MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << 6), /* t */ -+ MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << 7), /* V */ -+ MODPROBE_OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << 8), /* C */ -+ MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST, - }; - --struct include_conf_t { -- struct dep_t *first; -- struct dep_t *current; --}; -+static llist_t *loaded; - --static struct dep_t *depend; -+static int read_config(struct modprobe_conf *conf, const char *path); - --#define MAIN_OPT_STR "acdklnqrst:vVC:" --#define INSERT_ALL 1 /* a */ --#define DUMP_CONF_EXIT 2 /* c */ --#define D_OPT_IGNORED 4 /* d */ --#define AUTOCLEAN_FLG 8 /* k */ --#define LIST_ALL 16 /* l */ --#define SHOW_ONLY 32 /* n */ --#define QUIET 64 /* q */ --#define REMOVE_OPT 128 /* r */ --#define DO_SYSLOG 256 /* s */ --#define RESTRICT_DIR 512 /* t */ --#define VERBOSE 1024 /* v */ --#define VERSION_ONLY 2048 /* V */ --#define CONFIG_FILE 4096 /* C */ -- --#define autoclean (option_mask32 & AUTOCLEAN_FLG) --#define show_only (option_mask32 & SHOW_ONLY) --#define quiet (option_mask32 & QUIET) --#define remove_opt (option_mask32 & REMOVE_OPT) --#define do_syslog (option_mask32 & DO_SYSLOG) --#define verbose (option_mask32 & VERBOSE) -- --static int parse_tag_value(char *buffer, char **ptag, char **pvalue) -+static void add_option(llist_t **all_opts, const char *module, const char *opts) - { -- char *tag, *value; -+ struct modprobe_option *o; - -- buffer = skip_whitespace(buffer); -- tag = value = buffer; -- while (!isspace(*value)) { -- if (!*value) -- return 0; -- value++; -- } -- *value++ = '\0'; -- value = skip_whitespace(value); -- if (!*value) -- return 0; -- -- *ptag = tag; -- *pvalue = value; -- -- return 1; -+ o = xzalloc(sizeof(struct modprobe_option)); -+ if (module) -+ o->module = filename2modname(module, NULL); -+ o->option = xstrdup(opts); -+ llist_add_to(all_opts, o); - } - --/* -- * This function appends an option to a list -- */ --static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt) -+static int FAST_FUNC config_file_action(const char *filename, -+ struct stat *statbuf UNUSED_PARAM, -+ void *userdata, -+ int depth UNUSED_PARAM) - { -- struct mod_opt_t *ol = opt_list; -+ struct modprobe_conf *conf = (struct modprobe_conf *) userdata; -+ RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN); -+ char *tokens[3]; -+ parser_t *p; -+ int rc = TRUE; - -- if (ol) { -- while (ol->m_next) { -- ol = ol->m_next; -- } -- ol->m_next = xzalloc(sizeof(struct mod_opt_t)); -- ol = ol->m_next; -- } else { -- ol = opt_list = xzalloc(sizeof(struct mod_opt_t)); -- } -+ if (bb_basename(filename)[0] == '.') -+ goto error; - -- ol->m_opt_val = xstrdup(opt); -- /*ol->m_next = NULL; - done by xzalloc*/ -- -- return opt_list; --} -- --#if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS --/* static char* parse_command_string(char* src, char **dst); -- * src: pointer to string containing argument -- * dst: pointer to where to store the parsed argument -- * return value: the pointer to the first char after the parsed argument, -- * NULL if there was no argument parsed (only trailing spaces). -- * Note that memory is allocated with xstrdup when a new argument was -- * parsed. Don't forget to free it! -- */ --#define ARG_EMPTY 0x00 --#define ARG_IN_DQUOTES 0x01 --#define ARG_IN_SQUOTES 0x02 --static char *parse_command_string(char *src, char **dst) --{ -- int opt_status = ARG_EMPTY; -- char* tmp_str; -- -- /* Dumb you, I have nothing to do... */ -- if (src == NULL) return src; -- -- /* Skip leading spaces */ -- while (*src == ' ') { -- src++; -+ p = config_open2(filename, fopen_for_read); -+ if (p == NULL) { -+ rc = FALSE; -+ goto error; - } -- /* Is the end of string reached? */ -- if (*src == '\0') { -- return NULL; -- } -- /* Reached the start of an argument -- * By the way, we duplicate a little too much -- * here but what is too much is freed later. */ -- *dst = tmp_str = xstrdup(src); -- /* Get to the end of that argument */ -- while (*tmp_str != '\0' -- && (*tmp_str != ' ' || (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES))) -- ) { -- switch (*tmp_str) { -- case '\'': -- if (opt_status & ARG_IN_DQUOTES) { -- /* Already in double quotes, keep current char as is */ -- } else { -- /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ -- memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); -- /* mark me: we enter or leave single quotes */ -- opt_status ^= ARG_IN_SQUOTES; -- /* Back one char, as we need to re-scan the new char there. */ -- tmp_str--; -- } -- break; -- case '"': -- if (opt_status & ARG_IN_SQUOTES) { -- /* Already in single quotes, keep current char as is */ -- } else { -- /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ -- memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); -- /* mark me: we enter or leave double quotes */ -- opt_status ^= ARG_IN_DQUOTES; -- /* Back one char, as we need to re-scan the new char there. */ -- tmp_str--; -- } -- break; -- case '\\': -- if (opt_status & ARG_IN_SQUOTES) { -- /* Between single quotes: keep as is. */ -- } else { -- switch (*(tmp_str+1)) { -- case 'a': -- case 'b': -- case 't': -- case 'n': -- case 'v': -- case 'f': -- case 'r': -- case '0': -- /* We escaped a special character. For now, keep -- * both the back-slash and the following char. */ -- tmp_str++; -- src++; -- break; -- default: -- /* We escaped a space or a single or double quote, -- * or a back-slash, or a non-escapable char. Remove -- * the '\' and keep the new current char as is. */ -- memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); -- break; -- } -- } -- break; -- /* Any other char that is special shall appear here. -- * Example: $ starts a variable -- case '$': -- do_variable_expansion(); -- break; -- * */ -- default: -- /* any other char is kept as is. */ -- break; -+ -+ while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) { -+ if (strcmp(tokens[0], "alias") == 0) { -+ filename2modname(tokens[1], modname); -+ if (tokens[2] && -+ fnmatch(modname, conf->probename, 0) == 0) -+ llist_add_to(&conf->aliases, -+ filename2modname(tokens[2], NULL)); -+ } else if (strcmp(tokens[0], "options") == 0) { -+ if (tokens[2]) -+ add_option(&conf->options, tokens[1], tokens[2]); -+ } else if (strcmp(tokens[0], "include") == 0) { -+ read_config(conf, tokens[1]); -+ } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST && -+ strcmp(tokens[0], "blacklist") == 0) { -+ add_to_blacklist(conf, xstrdup(tokens[1])); - } -- tmp_str++; /* Go to next char */ -- src++; /* Go to next char to find the end of the argument. */ - } -- /* End of string, but still no ending quote */ -- if (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)) { -- bb_error_msg_and_die("unterminated (single or double) quote in options list: %s", src); -- } -- *tmp_str++ = '\0'; -- *dst = xrealloc(*dst, (tmp_str - *dst)); -- return src; -+ config_close(p); -+error: -+ if (ENABLE_FEATURE_CLEAN_UP) -+ RELEASE_CONFIG_BUFFER(modname); -+ return rc; - } --#else --#define parse_command_string(src, dst) (0) --#endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */ - --static int is_conf_command(char *buffer, const char *command) -+static int read_config(struct modprobe_conf *conf, const char *path) - { -- int len = strlen(command); -- return ((strstr(buffer, command) == buffer) && -- isspace(buffer[len])); -+ return recursive_action(path, ACTION_RECURSE | ACTION_QUIET, -+ config_file_action, NULL, conf, 1); - } - --/* -- * This function reads aliases and default module options from a configuration file -- * (/etc/modprobe.conf syntax). It supports includes (only files, no directories). -- */ -- --static int FAST_FUNC include_conf_file_act(const char *filename, -- struct stat *statbuf UNUSED_PARAM, -- void *userdata, -- int depth UNUSED_PARAM); -- --static int FAST_FUNC include_conf_dir_act(const char *filename UNUSED_PARAM, -- struct stat *statbuf UNUSED_PARAM, -- void *userdata UNUSED_PARAM, -- int depth) -+static llist_t *llist_find(llist_t *first, const char *str) - { -- if (depth > 1) -- return SKIP; -- -- return TRUE; -+ while (first != NULL) { -+ if (strcmp(first->data, str) == 0) -+ return first; -+ first = first->link; -+ } -+ return NULL; - } - --static int include_conf_recursive(struct include_conf_t *conf, const char *filename) -+static char *gather_options(llist_t *first, const char *module, int usecmdline) - { -- return recursive_action(filename, ACTION_RECURSE, -- include_conf_file_act, -- include_conf_dir_act, -- conf, 1); --} -+ struct modprobe_option *opt; -+ llist_t *n; -+ char *opts = xstrdup(""); -+ int optlen = 0; - --static int FAST_FUNC include_conf_file_act(const char *filename, -- struct stat *statbuf UNUSED_PARAM, -- void *userdata, -- int depth UNUSED_PARAM) --{ -- struct include_conf_t *conf = (struct include_conf_t *) userdata; -- struct dep_t **first = &conf->first; -- struct dep_t **current = &conf->current; -- int continuation_line = 0; -- FILE *f; -+ for (n = first; n != NULL; n = n->link) { -+ opt = (struct modprobe_option *) n->data; - -- if (bb_basename(filename)[0] == '.') -- return TRUE; -- -- f = fopen_for_read(filename); -- if (f == NULL) -- return FALSE; -- -- // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)! -- -- while (fgets(line_buffer, sizeof(line_buffer), f)) { -- int l; -- -- *strchrnul(line_buffer, '#') = '\0'; -- -- l = strlen(line_buffer); -- -- while (l && isspace(line_buffer[l-1])) { -- line_buffer[l-1] = '\0'; -- l--; -- } -- -- if (l == 0) { -- continuation_line = 0; -+ if (opt->module == NULL && !usecmdline) - continue; -- } -- -- if (continuation_line) -+ if (opt->module != NULL && strcmp(opt->module, module) != 0) - continue; - -- if (is_conf_command(line_buffer, "alias")) { -- char *alias, *mod; -- -- if (parse_tag_value(line_buffer + 6, &alias, &mod)) { -- /* handle alias as a module dependent on the aliased module */ -- if (!*current) { -- (*first) = (*current) = xzalloc(sizeof(struct dep_t)); -- } else { -- (*current)->m_next = xzalloc(sizeof(struct dep_t)); -- (*current) = (*current)->m_next; -- } -- (*current)->m_name = xstrdup(alias); -- (*current)->m_isalias = 1; -- -- if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) { -- /*(*current)->m_depcnt = 0; - done by xzalloc */ -- /*(*current)->m_deparr = 0;*/ -- } else { -- (*current)->m_depcnt = 1; -- (*current)->m_deparr = xmalloc(sizeof(char *)); -- (*current)->m_deparr[0] = xstrdup(mod); -- } -- /*(*current)->m_next = NULL; - done by xzalloc */ -- } -- } else if (is_conf_command(line_buffer, "options")) { -- char *mod, *opt; -- -- /* split the line in the module/alias name, and options */ -- if (parse_tag_value(line_buffer + 8, &mod, &opt)) { -- struct dep_t *dt; -- -- /* find the corresponding module */ -- for (dt = *first; dt; dt = dt->m_next) { -- if (strcmp(dt->m_name, mod) == 0) -- break; -- } -- if (dt) { -- if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) { -- char* new_opt = NULL; -- while ((opt = parse_command_string(opt, &new_opt))) { -- dt->m_options = append_option(dt->m_options, new_opt); -- } -- } else { -- dt->m_options = append_option(dt->m_options, opt); -- } -- } -- } -- } else if (is_conf_command(line_buffer, "include")) { -- char *includefile; -- -- includefile = skip_whitespace(line_buffer + 8); -- include_conf_recursive(conf, includefile); -- } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST && -- (is_conf_command(line_buffer, "blacklist"))) { -- char *mod; -- struct dep_t *dt; -- -- mod = skip_whitespace(line_buffer + 10); -- for (dt = *first; dt; dt = dt->m_next) { -- if (strcmp(dt->m_name, mod) == 0) -- break; -- } -- if (dt) -- dt->m_isblacklisted = 1; -- } -- } /* while (fgets(...)) */ -- -- fclose(f); -- return TRUE; -+ opts = xrealloc(opts, optlen + strlen(opt->option) + 2); -+ optlen += sprintf(opts + optlen, "%s ", opt->option); -+ } -+ return opts; - } - --static int include_conf_file(struct include_conf_t *conf, -- const char *filename) -+static int do_modprobe(struct modprobe_conf *conf, const char *module) - { -- return include_conf_file_act(filename, NULL, conf, 0); --} -+ RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN); -+ llist_t *deps = NULL; -+ char *fn, *options, *colon = NULL, *tokens[2]; -+ parser_t *p; -+ int rc = -1; - --static int include_conf_file2(struct include_conf_t *conf, -- const char *filename, const char *oldname) --{ -- if (include_conf_file(conf, filename) == TRUE) -- return TRUE; -- return include_conf_file(conf, oldname); --} -+ p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, fopen_for_read); -+ if (p == NULL) -+ goto error; - --/* -- * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep. -- * It then fills every modules and aliases with their default options, found by parsing -- * modprobe.conf (or modules.conf, or conf.modules). -- */ --static struct dep_t *build_dep(void) --{ -- FILE *f; -- struct utsname un; -- struct include_conf_t conf = { NULL, NULL }; -- char *filename; -- int continuation_line = 0; -- int k_version; -+ while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) { -+ colon = last_char_is(tokens[0], ':'); -+ if (colon == NULL) -+ continue; - -- uname(&un); /* never fails */ -+ filename2modname(tokens[0], modname); -+ if (strcmp(modname, module) == 0) -+ break; - -- k_version = 0; -- if (un.release[0] == '2') { -- k_version = un.release[2] - '0'; -+ colon = NULL; - } -+ if (colon == NULL) -+ goto error_not_found; - -- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/"CONFIG_DEFAULT_DEPMOD_FILE, un.release); -- f = fopen_for_read(filename); -- if (ENABLE_FEATURE_CLEAN_UP) -- free(filename); -- if (f == NULL) { -- /* Ok, that didn't work. Fall back to looking in /lib/modules */ -- f = fopen_for_read(CONFIG_DEFAULT_MODULES_DIR"/"CONFIG_DEFAULT_DEPMOD_FILE); -- if (f == NULL) { -- bb_error_msg_and_die("cannot parse "CONFIG_DEFAULT_DEPMOD_FILE); -- } -- } -+ colon[0] = '\0'; -+ llist_add_to(&deps, xstrdup(tokens[0])); -+ if (tokens[1]) -+ string_to_llist(tokens[1], &deps, " "); - -- while (fgets(line_buffer, sizeof(line_buffer), f)) { -- int l = strlen(line_buffer); -- char *p = NULL; -+ if (!(option_mask32 & MODPROBE_OPT_REMOVE)) -+ deps = llist_rev(deps); - -- while (l > 0 && isspace(line_buffer[l-1])) { -- line_buffer[l-1] = '\0'; -- l--; -+ rc = 0; -+ while (deps && rc == 0) { -+ fn = llist_pop(&deps); -+ filename2modname(fn, modname); -+ if (option_mask32 & MODPROBE_OPT_REMOVE) { -+ if (bb_delete_module(modname, O_EXCL) != 0) -+ rc = errno; -+ } else if (llist_find(loaded, modname) == NULL) { -+ options = gather_options(conf->options, modname, -+ strcmp(modname, module) == 0); -+ rc = bb_init_module(fn, options); -+ if (rc == 0) -+ llist_add_to(&loaded, xstrdup(modname)); -+ if (ENABLE_FEATURE_CLEAN_UP) -+ free(options); - } - -- if (l == 0) { -- continuation_line = 0; -- continue; -- } -- -- /* Is this a new module dep description? */ -- if (!continuation_line) { -- /* find the dep beginning */ -- char *col = strchr(line_buffer, ':'); -- char *dot = col; -- -- if (col) { -- /* This line is a dep description */ -- const char *mods; -- char *modpath; -- char *mod; -- -- /* Find the beginning of the module file name */ -- *col = '\0'; -- mods = bb_basename(line_buffer); -- -- /* find the path of the module */ -- modpath = strchr(line_buffer, '/'); /* ... and this is the path */ -- if (!modpath) -- modpath = line_buffer; /* module with no path */ -- /* find the end of the module name in the file name */ -- if (ENABLE_FEATURE_2_6_MODULES && -- (k_version > 4) && (col[-3] == '.') && -- (col[-2] == 'k') && (col[-1] == 'o')) -- dot = col - 3; -- else if ((col[-2] == '.') && (col[-1] == 'o')) -- dot = col - 2; -- -- mod = xstrndup(mods, dot - mods); -- -- /* enqueue new module */ -- if (!conf.current) { -- conf.first = conf.current = xzalloc(sizeof(struct dep_t)); -- } else { -- conf.current->m_next = xzalloc(sizeof(struct dep_t)); -- conf.current = conf.current->m_next; -- } -- conf.current->m_name = mod; -- conf.current->m_path = xstrdup(modpath); -- /*current->m_options = NULL; - xzalloc did it*/ -- /*current->m_isalias = 0;*/ -- /*current->m_depcnt = 0;*/ -- /*current->m_deparr = 0;*/ -- /*current->m_next = 0;*/ -- -- p = col + 1; -- } else -- /* this line is not a dep description */ -- p = NULL; -- } else -- /* It's a dep description continuation */ -- p = line_buffer; -- -- /* p points to the first dependable module; if NULL, no dependable module */ -- if (p && (p = skip_whitespace(p))[0] != '\0') { -- char *end = &line_buffer[l-1]; -- const char *deps; -- char *dep; -- char *next; -- int ext = 0; -- -- while (isblank(*end) || (*end == '\\')) -- end--; -- -- do { -- /* search the end of the dependency */ -- next = strchr(p, ' '); -- if (next) { -- *next = '\0'; -- next--; -- } else -- next = end; -- -- /* find the beginning of the module file name */ -- deps = bb_basename(p); -- if (deps == p) -- deps = skip_whitespace(deps); -- -- /* find the end of the module name in the file name */ -- if (ENABLE_FEATURE_2_6_MODULES -- && (k_version > 4) && (next[-2] == '.') -- && (next[-1] == 'k') && (next[0] == 'o')) -- ext = 3; -- else if ((next[-1] == '.') && (next[0] == 'o')) -- ext = 2; -- -- /* Cope with blank lines */ -- if ((next - deps - ext + 1) <= 0) -- continue; -- dep = xstrndup(deps, next - deps - ext + 1); -- -- /* Add the new dependable module name */ -- conf.current->m_deparr = xrealloc_vector(conf.current->m_deparr, 2, conf.current->m_depcnt); -- conf.current->m_deparr[conf.current->m_depcnt++] = dep; -- -- p = next + 2; -- } while (next < end); -- } -- -- /* is there other dependable module(s) ? */ -- continuation_line = (line_buffer[l-1] == '\\'); -- } /* while (fgets(...)) */ -- fclose(f); -- -- /* -- * First parse system-specific options and aliases -- * as they take precedence over the kernel ones. -- * >=2.6: we only care about modprobe.conf -- * <=2.4: we care about modules.conf and conf.modules -- */ -- { -- int r = FALSE; -- -- if (ENABLE_FEATURE_2_6_MODULES) { -- if (include_conf_file(&conf, "/etc/modprobe.conf")) -- r = TRUE; -- if (include_conf_recursive(&conf, "/etc/modprobe.d")) -- r = TRUE; -- } -- if (ENABLE_FEATURE_2_4_MODULES && !r) -- include_conf_file2(&conf, -- "/etc/modules.conf", -- "/etc/conf.modules"); -- } -- -- /* Only 2.6 has a modules.alias file */ -- if (ENABLE_FEATURE_2_6_MODULES) { -- /* Parse kernel-declared module aliases */ -- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.alias", un.release); -- include_conf_file2(&conf, -- filename, -- CONFIG_DEFAULT_MODULES_DIR"/modules.alias"); - if (ENABLE_FEATURE_CLEAN_UP) -- free(filename); -- -- /* Parse kernel-declared symbol aliases */ -- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.symbols", un.release); -- include_conf_file2(&conf, -- filename, -- CONFIG_DEFAULT_MODULES_DIR"/modules.symbols"); -- if (ENABLE_FEATURE_CLEAN_UP) -- free(filename); -+ free(fn); - } - -- return conf.first; -+error_not_found: -+ config_close(p); -+error: -+ if (ENABLE_FEATURE_CLEAN_UP) -+ RELEASE_CONFIG_BUFFER(modname); -+ if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) -+ bb_error_msg("Failed to %sload module %s: %s.", -+ (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", -+ module, moderror(rc)); -+ return rc; - } - --/* return 1 = loaded, 0 = not loaded, -1 = can't tell */ --static int already_loaded(const char *name) -+int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -+int modprobe_main(int argc UNUSED_PARAM, char **argv) - { -- FILE *f; -- int ret; -+ struct utsname uts; -+ int num_modules, i, rc; -+ llist_t *options = NULL; -+ parser_t *parser; - -- f = fopen_for_read("/proc/modules"); -- if (f == NULL) -- return -1; -+ opt_complementary = "q-v:v-q"; -+ getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS, -+ NULL, NULL); -+ argv += optind; -+ argc -= optind; - -- ret = 0; -- while (fgets(line_buffer, sizeof(line_buffer), f)) { -- char *p = line_buffer; -- const char *n = name; -+ if (option_mask32 & (MODPROBE_OPT_DUMP_ONLY | MODPROBE_OPT_LIST_ONLY | -+ MODPROBE_OPT_SHOW_ONLY)) -+ bb_error_msg_and_die("not supported"); - -- while (1) { -- char cn = *n; -- char cp = *p; -- if (cp == ' ' || cp == '\0') { -- if (cn == '\0') { -- ret = 1; /* match! */ -- goto done; -- } -- break; /* no match on this line, take next one */ -- } -- if (cn == '-') cn = '_'; -- if (cp == '-') cp = '_'; -- if (cp != cn) -- break; /* no match on this line, take next one */ -- n++; -- p++; -- } -- } -- done: -- fclose(f); -- return ret; --} -+ /* goto modules location */ -+ xchdir(CONFIG_DEFAULT_MODULES_DIR); -+ uname(&uts); -+ chdir(uts.release); - --static int mod_process(const struct mod_list_t *list, int do_insert) --{ -- int rc = 0; -- char **argv = NULL; -- struct mod_opt_t *opts; -- int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */ -- int argc; -- -- while (list) { -- argc = 0; -- if (ENABLE_FEATURE_CLEAN_UP) -- argc_malloc = 0; -- /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory -- * each time we allocate memory for argv. -- * But it is (quite) small amounts of memory that leak each -- * time a module is loaded, and it is reclaimed when modprobe -- * exits anyway (even when standalone shell? Yes --vda). -- * This could become a problem when loading a module with LOTS of -- * dependencies, with LOTS of options for each dependencies, with -- * very little memory on the target... But in that case, the module -- * would not load because there is no more memory, so there's no -- * problem. */ -- /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */ -- argv = xmalloc(6 * sizeof(char*)); -- if (do_insert) { -- if (already_loaded(list->m_name) != 1) { -- argv[argc++] = (char*)"insmod"; -- if (ENABLE_FEATURE_2_4_MODULES) { -- if (do_syslog) -- argv[argc++] = (char*)"-s"; -- if (autoclean) -- argv[argc++] = (char*)"-k"; -- if (quiet) -- argv[argc++] = (char*)"-q"; -- else if (verbose) /* verbose and quiet are mutually exclusive */ -- argv[argc++] = (char*)"-v"; -- } -- argv[argc++] = list->m_path; -- if (ENABLE_FEATURE_CLEAN_UP) -- argc_malloc = argc; -- opts = list->m_options; -- while (opts) { -- /* Add one more option */ -- argc++; -- argv = xrealloc(argv, (argc + 1) * sizeof(char*)); -- argv[argc-1] = opts->m_opt_val; -- opts = opts->m_next; -- } -- } -- } else { -- /* modutils uses short name for removal */ -- if (already_loaded(list->m_name) != 0) { -- argv[argc++] = (char*)"rmmod"; -- if (do_syslog) -- argv[argc++] = (char*)"-s"; -- argv[argc++] = (char*)list->m_name; -- if (ENABLE_FEATURE_CLEAN_UP) -- argc_malloc = argc; -- } -+ if (option_mask32 & (MODPROBE_OPT_REMOVE | MODPROBE_OPT_INSERT_ALL)) { -+ /* each parameter is a module name */ -+ num_modules = argc; -+ if (num_modules == 0) { -+ if (bb_delete_module(NULL, O_NONBLOCK|O_EXCL) != 0) -+ bb_perror_msg_and_die("rmmod"); -+ return EXIT_SUCCESS; - } -- argv[argc] = NULL; -- -- if (argc) { -- if (verbose) { -- printf("%s module %s\n", do_insert?"Loading":"Unloading", list->m_name); -- } -- if (!show_only) { -- int rc2 = wait4pid(spawn(argv)); -- -- if (do_insert) { -- rc = rc2; /* only last module matters */ -- } else if (!rc2) { -- rc = 0; /* success if remove any mod */ -- } -- } -- if (ENABLE_FEATURE_CLEAN_UP) { -- /* the last value in the array has index == argc, but -- * it is the terminating NULL, so we must not free it. */ -- while (argc_malloc < argc) { -- free(argv[argc_malloc++]); -- } -- } -- } -- if (ENABLE_FEATURE_CLEAN_UP) { -- free(argv); -- argv = NULL; -- } -- list = do_insert ? list->m_prev : list->m_next; -+ } else { -+ /* the only module, the rest of parameters are options */ -+ num_modules = 1; -+ add_option(&options, NULL, parse_cmdline_module_options(argv)); - } -- return (show_only) ? 0 : rc; --} - --/* -- * Check the matching between a pattern and a module name. -- * We need this as *_* is equivalent to *-*, even in pattern matching. -- */ --static int check_pattern(const char* pat_src, const char* mod_src) --{ -- int ret; -- -- if (ENABLE_FEATURE_MODPROBE_FANCY_ALIAS) { -- char* pat; -- char* mod; -- char* p; -- -- pat = xstrdup(pat_src); -- mod = xstrdup(mod_src); -- -- for (p = pat; (p = strchr(p, '-')); *p++ = '_'); -- for (p = mod; (p = strchr(p, '-')); *p++ = '_'); -- -- ret = fnmatch(pat, mod, 0); -- -- if (ENABLE_FEATURE_CLEAN_UP) { -- free(pat); -- free(mod); -- } -- -- return ret; -+ /* cache modules */ -+ parser = config_open2("/proc/modules", fopen_for_read); -+ if (parser) { -+ char *s; -+ while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) -+ llist_add_to(&loaded, xstrdup(s)); -+ config_close(parser); - } -- return fnmatch(pat_src, mod_src, 0); --} - --/* -- * Builds the dependency list (aka stack) of a module. -- * head: the highest module in the stack (last to insmod, first to rmmod) -- * tail: the lowest module in the stack (first to insmod, last to rmmod) -- */ --static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **tail) --{ -- struct mod_list_t *find; -- struct dep_t *dt; -- struct mod_opt_t *opt = NULL; -- char *path = NULL; -+ for (i = 0; i < num_modules; i++) { -+ struct modprobe_conf *conf; - -- /* Search for the given module name amongst all dependency rules. -- * The module name in a dependency rule can be a shell pattern, -- * so try to match the given module name against such a pattern. -- * Of course if the name in the dependency rule is a plain string, -- * then we consider it a pattern, and matching will still work. */ -- for (dt = depend; dt; dt = dt->m_next) { -- if (check_pattern(dt->m_name, mod) == 0) { -- break; -- } -- } -+ conf = xzalloc(sizeof(struct modprobe_conf)); -+ conf->options = options; -+ filename2modname(argv[i], conf->probename); -+ read_config(conf, "/etc/modprobe.conf"); -+ read_config(conf, "/etc/modprobe.d"); -+ if (ENABLE_FEATURE_MODUTILS_SYMBOLS && -+ conf->aliases == NULL && strncmp(argv[i], "symbol:", 7) == 0) -+ read_config(conf, "modules.symbols"); - -- if (!dt) { -- bb_error_msg("module %s not found", mod); -- return; -- } -+ if (ENABLE_FEATURE_MODUTILS_ALIAS && conf->aliases == NULL) -+ read_config(conf, "modules.alias"); - -- // resolve alias names -- while (dt->m_isalias) { -- if (dt->m_depcnt == 1) { -- struct dep_t *adt; -- -- for (adt = depend; adt; adt = adt->m_next) { -- if (check_pattern(adt->m_name, dt->m_deparr[0]) == 0 && -- !(ENABLE_FEATURE_MODPROBE_BLACKLIST && -- adt->m_isblacklisted)) -- break; -+ if (conf->aliases == NULL) { -+ /* Try if module by literal name is found; literal -+ * names are blacklist only if '-b' is given. */ -+ if (!(option_mask32 & MODPROBE_OPT_BLACKLIST) || -+ check_blacklist(conf, conf->probename)) { -+ rc = do_modprobe(conf, conf->probename); -+ if (rc < 0 && !(option_mask32 & INSMOD_OPT_SILENT)) -+ bb_error_msg("Module %s not found.", argv[i]); - } -- if (adt) { -- /* This is the module we are aliased to */ -- struct mod_opt_t *opts = dt->m_options; -- /* Option of the alias are appended to the options of the module */ -- while (opts) { -- adt->m_options = append_option(adt->m_options, opts->m_opt_val); -- opts = opts->m_next; -- } -- dt = adt; -- } else { -- bb_error_msg("module %s not found", mod); -- return; -- } - } else { -- bb_error_msg("bad alias %s", dt->m_name); -- return; -+ /* Probe all aliases */ -+ while (conf->aliases != NULL) { -+ char *realname = llist_pop(&conf->aliases); -+ if (check_blacklist(conf, realname)) -+ do_modprobe(conf, realname); -+ if (ENABLE_FEATURE_CLEAN_UP) -+ free(realname); -+ } - } - } - -- mod = dt->m_name; -- path = dt->m_path; -- opt = dt->m_options; -- -- // search for duplicates -- for (find = *head; find; find = find->m_next) { -- if (strcmp(mod, find->m_name) == 0) { -- // found -> dequeue it -- -- if (find->m_prev) -- find->m_prev->m_next = find->m_next; -- else -- *head = find->m_next; -- -- if (find->m_next) -- find->m_next->m_prev = find->m_prev; -- else -- *tail = find->m_prev; -- -- break; // there can be only one duplicate -- } -- } -- -- if (!find) { // did not find a duplicate -- find = xzalloc(sizeof(struct mod_list_t)); -- find->m_name = mod; -- find->m_path = path; -- find->m_options = opt; -- } -- -- // enqueue at tail -- if (*tail) -- (*tail)->m_next = find; -- find->m_prev = *tail; -- find->m_next = NULL; /* possibly NOT done by xzalloc! */ -- -- if (!*head) -- *head = find; -- *tail = find; -- -- if (dt) { -- int i; -- -- /* Add all dependable module for that new module */ -- for (i = 0; i < dt->m_depcnt; i++) -- check_dep(dt->m_deparr[i], head, tail); -- } -+ return EXIT_SUCCESS; - } -- --static int mod_insert(char **argv) --{ -- struct mod_list_t *tail = NULL; -- struct mod_list_t *head = NULL; -- char *modname = *argv++; -- int rc; -- -- // get dep list for module mod -- check_dep(modname, &head, &tail); -- -- rc = 1; -- if (head && tail) { -- while (*argv) -- head->m_options = append_option(head->m_options, *argv++); -- -- // process tail ---> head -- rc = mod_process(tail, 1); -- if (rc) { -- /* -- * In case of using udev, multiple instances of modprobe can be -- * spawned to load the same module (think of two same usb devices, -- * for example; or cold-plugging at boot time). Thus we shouldn't -- * fail if the module was loaded, and not by us. -- */ -- if (already_loaded(modname)) -- rc = 0; -- } -- } -- return rc; --} -- --static int mod_remove(char *modname) --{ -- static const struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL }; -- -- int rc; -- struct mod_list_t *head = NULL; -- struct mod_list_t *tail = NULL; -- -- if (modname) -- check_dep(modname, &head, &tail); -- else // autoclean -- head = tail = (struct mod_list_t*) &rm_a_dummy; -- -- rc = 1; -- if (head && tail) -- rc = mod_process(head, 0); // process head ---> tail -- return rc; --} -- --int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; --int modprobe_main(int argc UNUSED_PARAM, char **argv) --{ -- int rc = EXIT_SUCCESS; -- unsigned opt; -- char *unused; -- -- opt_complementary = "q-v:v-q"; -- opt = getopt32(argv, MAIN_OPT_STR, &unused, &unused); -- argv += optind; -- -- if (opt & (DUMP_CONF_EXIT | LIST_ALL)) -- return EXIT_SUCCESS; -- if (opt & (RESTRICT_DIR | CONFIG_FILE)) -- bb_error_msg_and_die("-t and -C not supported"); -- -- depend = build_dep(); -- -- if (!depend) -- bb_error_msg_and_die("cannot parse "CONFIG_DEFAULT_DEPMOD_FILE); -- -- if (remove_opt) { -- do { -- /* (*argv) can be NULL here */ -- if (mod_remove(*argv)) { -- bb_perror_msg("failed to %s module %s", "remove", -- *argv); -- rc = EXIT_FAILURE; -- } -- } while (*argv && *++argv); -- } else { -- if (!*argv) -- bb_error_msg_and_die("no module or pattern provided"); -- -- if (mod_insert(argv)) -- bb_perror_msg_and_die("failed to %s module %s", "load", *argv); -- } -- -- /* Here would be a good place to free up memory allocated during the dependencies build. */ -- -- return rc; --} -Index: modutils/depmod.c -=================================================================== ---- modutils/depmod.c (revision 23360) -+++ modutils/depmod.c (working copy) -@@ -2,6 +2,8 @@ - /* - * depmod - generate modules.dep - * Copyright (c) 2008 Bernhard Fischer -+ * Copyrihgt (c) 2008 Timo Teras <timo.teras@iki.fi> -+ * Copyright (c) 2008 Vladimir Dronnikov - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ -@@ -10,6 +12,8 @@ - #define _GNU_SOURCE - #include <libbb.h> - #include <sys/utsname.h> /* uname() */ -+#include "modutils.h" -+ - /* - * Theory of operation: - * - iterate over all modules and record their full path -@@ -17,272 +21,194 @@ - * for each depends, look through our list of full paths and emit if found - */ - --typedef struct dep_lst_t { -- char *name; -+typedef struct module_info { -+ struct module_info *next; -+ char *name, *modname; - llist_t *dependencies; - llist_t *aliases; -- struct dep_lst_t *next; --} dep_lst_t; -+ llist_t *symbols; -+ struct module_info *dnext, *dprev; -+} module_info; - --struct globals { -- dep_lst_t *lst; /* modules without their corresponding extension */ -+enum { -+ ARG_a = (1<<0), /* All modules, ignore mods in argv */ -+ ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */ -+ ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */ -+ ARG_e = (1<<3), /* with -F, print unresolved symbols */ -+ ARG_F = (1<<4), /* System.map that contains the symbols */ -+ ARG_n = (1<<5) /* dry-run, print to stdout only */ - }; --#define G (*(struct globals*)&bb_common_bufsiz1) --/* We have to zero it out because of NOEXEC */ --#define INIT_G() memset(&G, 0, sizeof(G)) - --static char* find_keyword(void *the_module, size_t len, const char * const word) -+static int FAST_FUNC parse_module(const char *fname, struct stat *sb, -+ void *data, int UNUSED_PARAM depth) - { -- char *ptr = the_module; -- do { -- /* search for the first char in word */ -- ptr = memchr(ptr, *word, len - (ptr - (char*)the_module)); -- if (ptr == NULL) /* no occurance left, done */ -- return NULL; -- if (!strncmp(ptr, word, strlen(word))) { -- ptr += strlen(word); -- break; -+ module_info **first = (module_info **) data; -+ char *image, *ptr; -+ module_info *info; -+ size_t len = sb->st_size; -+ -+ if (strrstr(fname, ".ko") == NULL) -+ return TRUE; -+ -+ image = (char *) xmalloc_open_zipped_read_close(fname, &len); -+ info = xzalloc(sizeof(module_info)); -+ -+ info->next = *first; -+ *first = info; -+ -+ info->dnext = info->dprev = info; -+ info->name = xstrdup(fname); -+ info->modname = filename2modname(fname, NULL); -+ for (ptr = image; ptr < image + len - 10; ptr++) { -+ if (strncmp(ptr, "depends=", 8) == 0) { -+ char *u; -+ -+ ptr += 8; -+ for (u = ptr; *u; u++) -+ if (*u == '-') -+ *u = '_'; -+ ptr += string_to_llist(ptr, &info->dependencies, ","); -+ } else if (ENABLE_FEATURE_MODUTILS_ALIAS && -+ strncmp(ptr, "alias=", 6) == 0) { -+ llist_add_to(&info->aliases, xstrdup(ptr + 6)); -+ ptr += strlen(ptr); -+ } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS && -+ strncmp(ptr, "__ksymtab_", 10) == 0) { -+ ptr += 10; -+ if (strncmp(ptr, "gpl", 3) == 0 || -+ strcmp(ptr, "strings") == 0) -+ continue; -+ llist_add_to(&info->symbols, xstrdup(ptr)); -+ ptr += strlen(ptr); - } -- ++ptr; -- } while (1); -- return ptr; -+ } -+ free(image); -+ -+ return TRUE; - } --static int FAST_FUNC fileAction(const char *fname, struct stat *sb, -- void UNUSED_PARAM *data, int UNUSED_PARAM depth) -+ -+static module_info *find_module(module_info *modules, const char *modname) - { -- size_t len = sb->st_size; -- void *the_module; -- char *ptr; -- int fd; -- char *depends, *deps; -- dep_lst_t *this; -+ module_info *m; - -- if (strrstr(fname, ".ko") == NULL) /* not a module */ -- goto skip; -+ for (m = modules; m != NULL; m = m->next) -+ if (strcmp(m->modname, modname) == 0) -+ return m; -+ return NULL; -+} - --/*XXX: FIXME: does not handle compressed modules! -- * There should be a function that looks at the extension and sets up -- * open_transformer for us. -- */ -- fd = xopen(fname, O_RDONLY); -- the_module = mmap(NULL, len, PROT_READ, MAP_SHARED --#if defined MAP_POPULATE -- |MAP_POPULATE --#endif -- , fd, 0); -- close(fd); -- if (the_module == MAP_FAILED) -- bb_perror_msg_and_die("mmap"); -+static void order_dep_list(module_info *modules, module_info *start, -+ llist_t *add) -+{ -+ module_info *m; -+ llist_t *n; - -- this = xzalloc(sizeof(dep_lst_t)); -- this->name = xstrdup(fname); -- this->next = G.lst; -- G.lst = this; --//bb_info_msg("fname='%s'", fname); -- ptr = find_keyword(the_module, len, "depends="); -- if (!*ptr) -- goto d_none; -- deps = depends = xstrdup(ptr); --//bb_info_msg(" depends='%s'", depends); -- while (deps) { -- ptr = strsep(&deps, ","); --//bb_info_msg("[%s] -> '%s'", fname, (char*)ptr); -- llist_add_to_end(&this->dependencies, xstrdup(ptr)); -+ for (n = add; n != NULL; n = n->link) { -+ m = find_module(modules, n->data); -+ if (m == NULL) -+ continue; -+ -+ /* unlink current entry */ -+ m->dnext->dprev = m->dprev; -+ m->dprev->dnext = m->dnext; -+ -+ /* and add it to tail */ -+ m->dnext = start; -+ m->dprev = start->dprev; -+ start->dprev->dnext = m; -+ start->dprev = m; -+ -+ /* recurse */ -+ order_dep_list(modules, start, m->dependencies); - } -- free(depends); -- d_none: -- if (ENABLE_FEATURE_DEPMOD_ALIAS) -- { -- size_t pos = 0; -- do { -- ptr = find_keyword(the_module + pos, len - pos, "alias="); -- if (ptr) { --//bb_info_msg("[%s] alias '%s'", fname, (char*)ptr); -- llist_add_to_end(&this->aliases, xstrdup(ptr)); -- } else -- break; -- pos = (ptr - (char*)the_module); -- } while (1); -- } -- munmap(the_module, sb->st_size); -- skip: -- return TRUE; - } - - int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int depmod_main(int argc UNUSED_PARAM, char **argv) - { -- int ret; -- size_t moddir_base_len = 0; /* length of the "-b basedir" */ -- char *moddir_base = NULL, *moddir, *system_map, *chp; -- FILE *filedes = stdout; -- enum { -- ARG_a = (1<<0), /* All modules, ignore mods in argv */ -- ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */ -- ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */ -- ARG_e = (1<<3), /* with -F, print unresolved symbols */ -- ARG_F = (1<<4), /* System.map that contains the symbols */ -- ARG_n = (1<<5) /* dry-run, print to stdout only */ -- }; -- INIT_G(); -+ module_info *modules = NULL, *m, *dep; -+ char *moddir_base = (char *)CONFIG_DEFAULT_MODULES_DIR; -+ int tmp; - -- getopt32(argv, "aAb:eF:n", &moddir_base, &system_map); -+ getopt32(argv, "aAb:eF:n", &moddir_base, NULL); - argv += optind; - -- /* If a version is provided, then that kernel version’s module directory -+ /* goto modules location */ -+ -+ /* If a version is provided, then that kernel version's module directory - * is used, rather than the current kernel version (as returned by - * "uname -r"). */ -- if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) { -- moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++); -+ xchdir(moddir_base); -+ if (*argv && (sscanf(*argv, "%d.%d.%d", &tmp, &tmp, &tmp) == 3)) { -+ chdir(*argv++); - } else { - struct utsname uts; -- if (uname(&uts) < 0) -- bb_simple_perror_msg_and_die("uname"); -- moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release); -+ uname(&uts); -+ chdir(uts.release); - } - /* If no modules are given on the command-line, -a is on per default. */ - option_mask32 |= *argv == NULL; - -- if (option_mask32 & ARG_b) { -- moddir_base_len = strlen(moddir_base) + 1; -- xchdir(moddir_base); -- } -- -- if (!(option_mask32 & ARG_n)) { /* --dry-run */ -- chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE); -- filedes = xfopen_for_write(chp); -- if (ENABLE_FEATURE_CLEAN_UP) -- free(chp); -- } -- ret = EXIT_SUCCESS; -+ /* Scan modules */ -+ moddir_base = xrealloc_getcwd_or_warn(NULL); - do { -- chp = option_mask32 & ARG_a ? moddir : (*argv + moddir_base_len); -+ recursive_action((option_mask32 & ARG_a) ? moddir_base : *argv, -+ ACTION_RECURSE, parse_module, NULL, &modules, 0); -+ } while (!(option_mask32 & ARG_a) && *(++argv)); -+ if (ENABLE_FEATURE_CLEAN_UP) -+ free(moddir_base); - -- if (!recursive_action(chp, -- ACTION_RECURSE, /* flags */ -- fileAction, /* file action */ -- NULL, /* dir action */ -- NULL, /* user data */ -- 0)) { /* depth */ -- ret = EXIT_FAILURE; -- } -- } while (!(option_mask32 & ARG_a) && *++argv); -+ /* Generate dependency and alias files */ -+ if (!(option_mask32 & ARG_n)) -+ freopen(CONFIG_DEFAULT_DEPMOD_FILE, "w", stdout); -+ for (m = modules; m != NULL; m = m->next) { -+ printf("%s:", m->name); - -- { -- dep_lst_t *mods = G.lst; -+ order_dep_list(modules, m, m->dependencies); -+ while (m->dnext != m) { -+ dep = m->dnext; -+ printf(" %s", dep->name); - -- /* Fixup the module names in the depends list */ -- while (mods) { -- llist_t *deps = NULL, *old_deps = mods->dependencies; -- -- while (old_deps) { -- dep_lst_t *all = G.lst; -- char *longname = NULL; -- char *shortname = llist_pop(&old_deps); -- -- while (all) { -- char *nam = -- xstrdup(bb_get_last_path_component_nostrip(all->name)); -- char *tmp = strrstr(nam, ".ko"); -- -- *tmp = '\0'; -- if (!strcmp(nam, shortname)) { -- if (ENABLE_FEATURE_CLEAN_UP) -- free(nam); -- longname = all->name; -- break; -- } -- free(nam); -- all = all->next; -- } -- llist_add_to_end(&deps, longname); -+ /* unlink current entry */ -+ dep->dnext->dprev = dep->dprev; -+ dep->dprev->dnext = dep->dnext; -+ dep->dnext = dep->dprev = dep; - } -- mods->dependencies = deps; -- mods = mods->next; -+ puts(""); - } - --#if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY -- /* modprobe allegedly wants dependencies without duplicates, i.e. -- * mod1: mod2 mod3 -- * mod2: mod3 -- * mod3: -- * implies that mod1 directly depends on mod2 and _not_ mod3 as mod3 is -- * already implicitely pulled in via mod2. This leaves us with: -- * mod1: mod2 -- * mod2: mod3 -- * mod3: -- */ -- mods = G.lst; -- while (mods) { -- llist_t *deps = mods->dependencies; -- while (deps) { -- dep_lst_t *all = G.lst; -- while (all) { -- if (!strcmp(all->name, deps->data)) { -- llist_t *implied = all->dependencies; -- while (implied) { -- /* XXX:FIXME: erm, it would be nicer to just -- * llist_unlink(&mods->dependencies, implied) */ -- llist_t *prune = mods->dependencies; -- while (prune) { -- if (!strcmp(implied->data, prune->data)) -- break; -- prune = prune->link; -- } --//if (prune) bb_info_msg("[%s] '%s' implies '%s', removing", mods->name, all->name, implied->data); -- llist_unlink(&mods->dependencies, prune); -- implied = implied->link; -- } -- } -- all = all->next; -- } -- deps = deps->link; -+#if ENABLE_FEATURE_MODUTILS_ALIAS -+ if (!(option_mask32 & ARG_n)) -+ freopen("modules.alias", "w", stdout); -+ for (m = modules; m != NULL; m = m->next) { -+ while (m->aliases) { -+ printf("alias %s %s\n", -+ (char*)llist_pop(&m->aliases), -+ m->modname); - } -- mods = mods->next; - } - #endif -- -- mods = G.lst; -- /* Finally print them. */ -- while (mods) { -- fprintf(filedes, "%s:", mods->name); -- /* If we did not resolve all modules, then it's likely that we just did -- * not see the names of all prerequisites (which will be NULL in this -- * case). */ -- while (mods->dependencies) { -- char *the_dep = llist_pop(&mods->dependencies); -- if (the_dep) -- fprintf(filedes, " %s", the_dep); -+#if ENABLE_FEATURE_MODUTILS_SYMBOLS -+ if (!(option_mask32 & ARG_n)) -+ freopen("modules.symbols", "w", stdout); -+ for (m = modules; m != NULL; m = m->next) { -+ while (m->symbols) { -+ printf("alias symbol:%s %s\n", -+ (char*)llist_pop(&m->symbols), -+ m->modname); - } -- fprintf(filedes, "\n"); -- if (ENABLE_FEATURE_DEPMOD_ALIAS) -- { -- char *shortname = -- xstrdup(bb_get_last_path_component_nostrip(mods->name)); -- char *tmp = strrstr(shortname, ".ko"); -- -- *tmp = '\0'; -- -- while (mods->aliases) { -- fprintf(filedes, "alias %s %s\n", -- (char*)llist_pop(&mods->aliases), -- shortname); -- } -- free(shortname); -- } -- mods = mods->next; - } -- } -+#endif - - if (ENABLE_FEATURE_CLEAN_UP) { -- fclose_if_not_stdin(filedes); -- free(moddir); -- while (G.lst) { -- dep_lst_t *old = G.lst; -- G.lst = G.lst->next; -+ while (modules) { -+ module_info *old = modules; -+ modules = modules->next; - free(old->name); -+ free(old->modname); - free(old); - } - } -- return ret; -+ -+ return EXIT_SUCCESS; - } -Index: modutils/Config.in -=================================================================== ---- modutils/Config.in (revision 23360) -+++ modutils/Config.in (working copy) -@@ -5,43 +5,35 @@ - - menu "Linux Module Utilities" - --config MODPROBE_SMALL -- bool "Simplified modutils" -- default n -+choice -+ prompt "Module Utilities Flavor" -+ default MODUTILS_STANDARD -+ -+config MODUTILS_STANDARD -+ bool "standard" - help -- Simplified modutils. -+ module-init-tools compliant version of module utilities. -+ Select this if unsure. - -- With this option modprobe does not require modules.dep file -- and does not use /etc/modules.conf file. -- It scans module files in /lib/modules/`uname -r` and -- determines dependencies and module alias names on the fly. -- This may make module loading slower, most notably -- when one needs to load module by alias (this requires -- scanning through module _bodies_). -+config MODUTILS_FAST -+ bool "fast and small" -+ help -+ Alternate module utilities implementation that uses a custom -+ modules.dep.bb file for the module dependency and alias information. -+ The module blacklist and argument information is parsed and stored -+ to this file. In practice you get a lot faster modprobe, but you -+ need to regenerate the dependency information if configuration -+ is changed. - -- At the first attempt to load a module by alias modprobe -- will try to generate modules.dep.bb file in order to speed up -- future loads by alias. Failure to do so (read-only /lib/modules, -- etc) is not reported, and future modprobes will be slow too. -+ This option produces faster and slightly smaller module utilities. -+ Select standard variant if unsure. - -- NB: modules.dep.bb file format is not compatible -- with modules.dep file as created/used by standard module tools. -+endchoice - -- Additional module parameters can be stored in -- /etc/modules/$module_name files. -- -- Apart from modprobe, other utilities are also provided: -- - insmod is an alias to modprobe -- - rmmod is an alias to modprobe -r -- - depmod generates modules.dep.bb -- -- As of 2008-07, this code is experimental. It is 14kb smaller -- than "non-small" modutils. -- - config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE - bool "Accept module options on modprobe command line" - default n -- depends on MODPROBE_SMALL -+ depends on MODUTILS_FAST - help - Allow insmod and modprobe take module options from command line. - N.B. Very bloaty. -@@ -49,53 +41,88 @@ - config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED - bool "Skip loading of already loaded modules" - default n -- depends on MODPROBE_SMALL -+ depends on MODUTILS_FAST - help - Check if the module is already loaded. - N.B. It's racy. - --config DEPMOD -- bool "depmod" -+config INSMOD -+ bool "insmod" - default n -- depends on !MODPROBE_SMALL -+ depends on MODUTILS_STANDARD - help -- depmod generates modules.dep (FIXME: elaborate) -+ insmod is used to load specified modules in the running kernel. - --config FEATURE_DEPMOD_PRUNE_FANCY -- bool "Fancy dependency pruning" -+config RMMOD -+ bool "rmmod" - default n -- depends on DEPMOD -+ depends on MODUTILS_STANDARD - help -- By default modules.dep contains all dependencies as listed by -- the modules. -- If you enable this option then we remove implied modules from -- the dependencies. -- This makes depmod somewhat bigger but generates a smaller -- modules.dep file. -+ rmmod is used to unload specified modules from the kernel. - -- If unsure, say N. -+config LSMOD -+ bool "lsmod" -+ default n -+ depends on MODUTILS_STANDARD -+ help -+ lsmod is used to display a list of loaded modules. - --config FEATURE_DEPMOD_ALIAS -- bool "Alias support" -+config FEATURE_LSMOD_PRETTY_2_6_OUTPUT -+ bool "Pretty output" - default n -- depends on DEPMOD -+ depends on MODUTILS_STANDARD && LSMOD - help -- By default modules.dep does not contain alias information. -- Enable this to emit aliases of the form: -+ This option makes output format of lsmod adjusted to -+ the format of module-init-tools for Linux kernel 2.6. -+ Increases size somewhat. - -- alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs -+config MODPROBE -+ bool "modprobe" -+ default n -+ depends on MODUTILS_STANDARD -+ help -+ Handle the loading of modules, and their dependencies on a high -+ level. - --config INSMOD -- bool "insmod" -+ Note that in the state, modprobe does not understand multiple -+ module options from the configuration file. See option below. -+ -+config FEATURE_MODPROBE_BLACKLIST -+ bool -+ prompt "Blacklist support" - default n -- depends on !MODPROBE_SMALL -+ depends on MODUTILS_STANDARD && MODPROBE - help -- insmod is used to load specified modules in the running kernel. -+ Say 'y' here to enable support for the 'blacklist' command in -+ modprobe.conf. This prevents the alias resolver to resolve -+ blacklisted modules. This is useful if you want to prevent your -+ hardware autodetection scripts to load modules like evdev, frame -+ buffer drivers etc. - -+config DEPMOD -+ bool "depmod" -+ default n -+ depends on MODUTILS_STANDARD -+ help -+ depmod generates modules.dep (and potentially modules.alias -+ and modules.symbols) that contain dependency information -+ for modprobe. -+ -+comment "Options common to multiple modutils" -+ -+config FEATURE_2_4_MODULES -+ bool "Support version 2.2/2.4 Linux kernels" -+ default n -+ depends on MODUTILS_FAST || INSMOD || RMMOD || LSMOD -+ help -+ Support module loading for 2.2.x and 2.4.x Linux kernels. -+ This increases size considerably. Say N unless you plan -+ to run ancient kernels. -+ - config FEATURE_INSMOD_VERSION_CHECKING -- bool "Module version checking" -+ bool "Enable module version checking" - default n -- depends on INSMOD && FEATURE_2_4_MODULES -+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - help - Support checking of versions for modules. This is used to - ensure that the kernel and module are made for each other. -@@ -103,7 +130,7 @@ - config FEATURE_INSMOD_KSYMOOPS_SYMBOLS - bool "Add module symbols to kernel symbol table" - default n -- depends on INSMOD && FEATURE_2_4_MODULES -+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - help - By adding module symbols to the kernel symbol table, Oops messages - occuring within kernel modules can be properly debugged. By enabling -@@ -114,7 +141,7 @@ - config FEATURE_INSMOD_LOADINKMEM - bool "In kernel memory optimization (uClinux only)" - default n -- depends on INSMOD && FEATURE_2_4_MODULES -+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - help - This is a special uClinux only memory optimization that lets insmod - load the specified kernel module directly into kernel space, reducing -@@ -122,9 +149,9 @@ - being loaded into memory. - - config FEATURE_INSMOD_LOAD_MAP -- bool "Enable load map (-m) option" -+ bool "Enable insmod load map (-m) option" - default n -- depends on INSMOD && ( FEATURE_2_4_MODULES || FEATURE_2_6_MODULES ) -+ depends on FEATURE_2_4_MODULES && INSMOD - help - Enabling this, one would be able to get a load map - output on stdout. This makes kernel module debugging -@@ -141,132 +168,54 @@ - load map. With this option, -m will also output - symbols load map. - --config RMMOD -- bool "rmmod" -- default n -- depends on !MODPROBE_SMALL -- help -- rmmod is used to unload specified modules from the kernel. -- --config LSMOD -- bool "lsmod" -- default n -- depends on !MODPROBE_SMALL -- help -- lsmod is used to display a list of loaded modules. -- --config FEATURE_LSMOD_PRETTY_2_6_OUTPUT -- bool "Pretty output for 2.6.x Linux kernels" -- default n -- depends on LSMOD -- help -- This option makes output format of lsmod adjusted to -- the format of module-init-tools for Linux kernel 2.6. -- --config MODPROBE -- bool "modprobe" -- default n -- depends on !MODPROBE_SMALL -- help -- Handle the loading of modules, and their dependencies on a high -- level. -- -- Note that in the state, modprobe does not understand multiple -- module options from the configuration file. See option below. -- --config FEATURE_MODPROBE_MULTIPLE_OPTIONS -- bool -- prompt "Multiple options parsing" -- default y -- depends on MODPROBE -- help -- Allow modprobe to understand more than one option to pass to -- modules. -- -- This is a WIP, while waiting for a common argument parsing -- common amongst all BB applets (shell, modprobe, etc...) and -- adds around 600 bytes on x86, 700 bytes on ARM. The code is -- biggish and uggly, but just works. -- -- Saying Y here is not a bad idea if you're not that short -- on storage capacity. -- --config FEATURE_MODPROBE_FANCY_ALIAS -- bool -- prompt "Fancy alias parsing" -- default y -- depends on MODPROBE && FEATURE_2_6_MODULES -- help -- Say 'y' here to enable parsing of aliases with underscore/dash -- mismatch between module name and file name, along with bus-specific -- aliases (such as pci:... or usb:... aliases). -- --config FEATURE_MODPROBE_BLACKLIST -- bool -- prompt "Blacklist support" -- default n -- depends on MODPROBE && FEATURE_2_6_MODULES -- help -- Say 'y' here to enable support for the 'blacklist' command in -- modprobe.conf. This prevents the alias resolver to resolve -- blacklisted modules. This is useful if you want to prevent your -- hardware autodetection scripts to load modules like evdev, frame -- buffer drivers etc. -- --comment "Options common to multiple modutils" -- depends on INSMOD || RMMOD || MODPROBE || LSMOD || DEPMOD -- - config FEATURE_CHECK_TAINTED_MODULE -- # Simulate indentation - bool "Support tainted module checking with new kernels" - default y -- depends on INSMOD || LSMOD - help - Support checking for tainted modules. These are usually binary - only modules that will make the linux-kernel list ignore your - support request. - This option is required to support GPLONLY modules. - --config FEATURE_2_4_MODULES -- # Simulate indentation -- bool "Support version 2.2.x to 2.4.x Linux kernels" -+config FEATURE_MODUTILS_ALIAS -+ bool "Support for module.aliases file" - default y -- depends on INSMOD || RMMOD || MODPROBE -+ depends on MODUTILS_STANDARD && (DEPMOD || MODPROBE) - help -- Support module loading for 2.2.x and 2.4.x Linux kernels. -+ Generate and parse modules.alias containing aliases for bus -+ identifiers: -+ alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs - -- Note: -- This is automatically enabled if 2.6 modules are not enabled. -+ and aliases for logical modules names e.g.: -+ alias padlock_aes aes -+ alias aes_i586 aes -+ alias aes_generic aes - --config FEATURE_2_6_MODULES -- # Simulate indentation -- bool "Support version 2.6.x Linux kernels" -+ Say Y if unsure. -+ -+config FEATURE_MODUTILS_SYMBOLS -+ bool "Support for module.symbols file" - default y -- depends on INSMOD || RMMOD || MODPROBE -+ depends on MODUTILS_STANDARD && (DEPMOD || MODPROBE) - help -- Support module loading for newer 2.6.x Linux kernels. -+ Generate and parse modules.symbols containing aliases for -+ symbol_request() kernel calls, such as: -+ alias symbol:usb_sg_init usbcore - -+ Say Y if unsure. -+ - config DEFAULT_MODULES_DIR -- # Simulate indentation - string "Default directory containing modules" - default "/lib/modules" -- depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD - help - Directory that contains kernel modules. - Defaults to "/lib/modules" - - config DEFAULT_DEPMOD_FILE -- # Simulate indentation - string "Default name of modules.dep" - default "modules.dep" -- depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD - help - Filename that contains kernel modules dependencies. - Defaults to "modules.dep" - --config FEATURE_QUERY_MODULE_INTERFACE -- bool -- default y -- depends on FEATURE_2_4_MODULES && !FEATURE_2_6_MODULES -- - endmenu -Index: modutils/Kbuild -=================================================================== ---- modutils/Kbuild (revision 23360) -+++ modutils/Kbuild (working copy) -@@ -5,9 +5,10 @@ - # Licensed under the GPL v2, see the file LICENSE in this tarball. - - lib-y:= --lib-$(CONFIG_DEPMOD) += depmod.o --lib-$(CONFIG_INSMOD) += insmod.o --lib-$(CONFIG_LSMOD) += lsmod.o --lib-$(CONFIG_MODPROBE) += modprobe.o --lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o --lib-$(CONFIG_RMMOD) += rmmod.o -+lib-$(CONFIG_DEPMOD) += depmod.o modutils.o -+lib-$(CONFIG_INSMOD) += insmod.o modutils.o -+lib-$(CONFIG_LSMOD) += lsmod.o modutils.o -+lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o -+lib-$(CONFIG_RMMOD) += rmmod.o modutils.o -+lib-$(CONFIG_MODUTILS_SMALL) += modprobe-small.o modutils.o -+lib-$(CONFIG_FEATURE_2_4_MODULES) += modutils-24.o -Index: modutils/insmod.c -=================================================================== ---- modutils/insmod.c (revision 23360) -+++ modutils/insmod.c (working copy) -@@ -2,4286 +2,31 @@ - /* - * Mini insmod implementation for busybox - * -- * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64, -- * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64. -+ * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi> - * -- * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> -- * and Ron Alder <alder@lineo.com> -- * -- * Rodney Radford <rradford@mindspring.com> 17-Aug-2004. -- * Added x86_64 support. -- * -- * Miles Bader <miles@gnu.org> added NEC V850E support. -- * -- * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 -- * and (theoretically) SH3. I have only tested SH4 in little endian mode. -- * -- * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and -- * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only -- * very minor changes required to also work with StrongArm and presumably -- * all ARM based systems. -- * -- * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004. -- * added Renesas H8/300 support. -- * -- * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003. -- * Integrated support for sh64 (SH-5), from preliminary modutils -- * patches from Benedict Gaster <benedict.gaster@superh.com>. -- * Currently limited to support for 32bit ABI. -- * -- * Magnus Damm <damm@opensource.se> 22-May-2002. -- * The plt and got code are now using the same structs. -- * Added generic linked list code to fully support PowerPC. -- * Replaced the mess in arch_apply_relocation() with architecture blocks. -- * The arch_create_got() function got cleaned up with architecture blocks. -- * These blocks should be easy maintain and sync with obj_xxx.c in modutils. -- * -- * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001. -- * PowerPC specific code stolen from modutils-2.3.16, -- * written by Paul Mackerras, Copyright 1996, 1997 Linux International. -- * I've only tested the code on mpc8xx platforms in big-endian mode. -- * Did some cleanup and added USE_xxx_ENTRIES... -- * -- * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001. -- * based on modutils-2.4.2 -- * MIPS specific support for Elf loading and relocation. -- * Copyright 1996, 1997 Linux International. -- * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu> -- * -- * Based almost entirely on the Linux modutils-2.3.11 implementation. -- * Copyright 1996, 1997 Linux International. -- * New implementation contributed by Richard Henderson <rth@tamu.edu> -- * Based on original work by Bjorn Ekwall <bj0rn@blox.se> -- * Restructured (and partly rewritten) by: -- * Björn Ekwall <bj0rn@blox.se> February 1999 -- * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - - #include "libbb.h" --#include <libgen.h> --#include <sys/utsname.h> -+#include "modutils.h" - --#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES --#undef ENABLE_FEATURE_2_4_MODULES --#define ENABLE_FEATURE_2_4_MODULES 1 --#endif -- --/* -- * Big piece of 2.4-specific code -- */ --#if ENABLE_FEATURE_2_4_MODULES -- --#if ENABLE_FEATURE_2_6_MODULES --static int insmod_ng_main(int argc, char **argv); --#endif -- --#if ENABLE_FEATURE_INSMOD_LOADINKMEM --#define LOADBITS 0 --#else --#define LOADBITS 1 --#endif -- --/* Alpha */ --#if defined(__alpha__) --#define MATCH_MACHINE(x) (x == EM_ALPHA) --#define SHT_RELM SHT_RELA --#define Elf64_RelM Elf64_Rela --#define ELFCLASSM ELFCLASS64 --#endif -- --/* ARM support */ --#if defined(__arm__) --#define MATCH_MACHINE(x) (x == EM_ARM) --#define SHT_RELM SHT_REL --#define Elf32_RelM Elf32_Rel --#define ELFCLASSM ELFCLASS32 --#define USE_PLT_ENTRIES --#define PLT_ENTRY_SIZE 8 --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 8 --#define USE_SINGLE --#endif -- --/* blackfin */ --#if defined(BFIN) --#define MATCH_MACHINE(x) (x == EM_BLACKFIN) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#endif -- --/* CRIS */ --#if defined(__cris__) --#define MATCH_MACHINE(x) (x == EM_CRIS) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#ifndef EM_CRIS --#define EM_CRIS 76 --#define R_CRIS_NONE 0 --#define R_CRIS_32 3 --#endif --#endif -- --/* H8/300 */ --#if defined(__H8300H__) || defined(__H8300S__) --#define MATCH_MACHINE(x) (x == EM_H8_300) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_SINGLE --#define SYMBOL_PREFIX "_" --#endif -- --/* PA-RISC / HP-PA */ --#if defined(__hppa__) --#define MATCH_MACHINE(x) (x == EM_PARISC) --#define SHT_RELM SHT_RELA --#if defined(__LP64__) --#define Elf64_RelM Elf64_Rela --#define ELFCLASSM ELFCLASS64 --#else --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#endif --#endif -- --/* x86 */ --#if defined(__i386__) --#ifndef EM_486 --#define MATCH_MACHINE(x) (x == EM_386) --#else --#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) --#endif --#define SHT_RELM SHT_REL --#define Elf32_RelM Elf32_Rel --#define ELFCLASSM ELFCLASS32 --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 4 --#define USE_SINGLE --#endif -- --/* IA64, aka Itanium */ --#if defined(__ia64__) --#define MATCH_MACHINE(x) (x == EM_IA_64) --#define SHT_RELM SHT_RELA --#define Elf64_RelM Elf64_Rela --#define ELFCLASSM ELFCLASS64 --#endif -- --/* m68k */ --#if defined(__mc68000__) --#define MATCH_MACHINE(x) (x == EM_68K) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 4 --#define USE_SINGLE --#endif -- --/* Microblaze */ --#if defined(__microblaze__) --#define USE_SINGLE --#include <linux/elf-em.h> --#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#endif -- --/* MIPS */ --#if defined(__mips__) --#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) --#define SHT_RELM SHT_REL --#define Elf32_RelM Elf32_Rel --#define ELFCLASSM ELFCLASS32 --/* Account for ELF spec changes. */ --#ifndef EM_MIPS_RS3_LE --#ifdef EM_MIPS_RS4_BE --#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE --#else --#define EM_MIPS_RS3_LE 10 --#endif --#endif /* !EM_MIPS_RS3_LE */ --#define ARCHDATAM "__dbe_table" --#endif -- --/* Nios II */ --#if defined(__nios2__) --#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#endif -- --/* PowerPC */ --#if defined(__powerpc64__) --#define MATCH_MACHINE(x) (x == EM_PPC64) --#define SHT_RELM SHT_RELA --#define Elf64_RelM Elf64_Rela --#define ELFCLASSM ELFCLASS64 --#elif defined(__powerpc__) --#define MATCH_MACHINE(x) (x == EM_PPC) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_PLT_ENTRIES --#define PLT_ENTRY_SIZE 16 --#define USE_PLT_LIST --#define LIST_ARCHTYPE ElfW(Addr) --#define USE_LIST --#define ARCHDATAM "__ftr_fixup" --#endif -- --/* S390 */ --#if defined(__s390__) --#define MATCH_MACHINE(x) (x == EM_S390) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_PLT_ENTRIES --#define PLT_ENTRY_SIZE 8 --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 8 --#define USE_SINGLE --#endif -- --/* SuperH */ --#if defined(__sh__) --#define MATCH_MACHINE(x) (x == EM_SH) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 4 --#define USE_SINGLE --/* the SH changes have only been tested in =little endian= mode */ --/* I'm not sure about big endian, so let's warn: */ --#if defined(__sh__) && BB_BIG_ENDIAN --# error insmod.c may require changes for use on big endian SH --#endif --/* it may or may not work on the SH1/SH2... Error on those also */ --#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__)) --#error insmod.c may require changes for SH1 or SH2 use --#endif --#endif -- --/* Sparc */ --#if defined(__sparc__) --#define MATCH_MACHINE(x) (x == EM_SPARC) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#endif -- --/* v850e */ --#if defined(__v850e__) --#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850) --#define SHT_RELM SHT_RELA --#define Elf32_RelM Elf32_Rela --#define ELFCLASSM ELFCLASS32 --#define USE_PLT_ENTRIES --#define PLT_ENTRY_SIZE 8 --#define USE_SINGLE --#ifndef EM_CYGNUS_V850 /* grumble */ --#define EM_CYGNUS_V850 0x9080 --#endif --#define SYMBOL_PREFIX "_" --#endif -- --/* X86_64 */ --#if defined(__x86_64__) --#define MATCH_MACHINE(x) (x == EM_X86_64) --#define SHT_RELM SHT_RELA --#define USE_GOT_ENTRIES --#define GOT_ENTRY_SIZE 8 --#define USE_SINGLE --#define Elf64_RelM Elf64_Rela --#define ELFCLASSM ELFCLASS64 --#endif -- --#ifndef SHT_RELM --#error Sorry, but insmod.c does not yet support this architecture... --#endif -- -- --//---------------------------------------------------------------------------- --//--------modutils module.h, lines 45-242 --//---------------------------------------------------------------------------- -- --/* Definitions for the Linux module syscall interface. -- Copyright 1996, 1997 Linux International. -- -- Contributed by Richard Henderson <rth@tamu.edu> -- -- This file is part of the Linux modutils. -- -- 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 MODUTILS_MODULE_H -- --/*======================================================================*/ --/* For sizeof() which are related to the module platform and not to the -- environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */ -- --#define tgt_sizeof_char sizeof(char) --#define tgt_sizeof_short sizeof(short) --#define tgt_sizeof_int sizeof(int) --#define tgt_sizeof_long sizeof(long) --#define tgt_sizeof_char_p sizeof(char *) --#define tgt_sizeof_void_p sizeof(void *) --#define tgt_long long -- --#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64) --#undef tgt_sizeof_long --#undef tgt_sizeof_char_p --#undef tgt_sizeof_void_p --#undef tgt_long --enum { -- tgt_sizeof_long = 8, -- tgt_sizeof_char_p = 8, -- tgt_sizeof_void_p = 8 --}; --#define tgt_long long long --#endif -- --/*======================================================================*/ --/* The structures used in Linux 2.1. */ -- --/* Note: new_module_symbol does not use tgt_long intentionally */ --struct new_module_symbol { -- unsigned long value; -- unsigned long name; --}; -- --struct new_module_persist; -- --struct new_module_ref { -- unsigned tgt_long dep; /* kernel addresses */ -- unsigned tgt_long ref; -- unsigned tgt_long next_ref; --}; -- --struct new_module { -- unsigned tgt_long size_of_struct; /* == sizeof(module) */ -- unsigned tgt_long next; -- unsigned tgt_long name; -- unsigned tgt_long size; -- -- tgt_long usecount; -- unsigned tgt_long flags; /* AUTOCLEAN et al */ -- -- unsigned nsyms; -- unsigned ndeps; -- -- unsigned tgt_long syms; -- unsigned tgt_long deps; -- unsigned tgt_long refs; -- unsigned tgt_long init; -- unsigned tgt_long cleanup; -- unsigned tgt_long ex_table_start; -- unsigned tgt_long ex_table_end; --#ifdef __alpha__ -- unsigned tgt_long gp; --#endif -- /* Everything after here is extension. */ -- unsigned tgt_long persist_start; -- unsigned tgt_long persist_end; -- unsigned tgt_long can_unload; -- unsigned tgt_long runsize; -- const char *kallsyms_start; /* All symbols for kernel debugging */ -- const char *kallsyms_end; -- const char *archdata_start; /* arch specific data for module */ -- const char *archdata_end; -- const char *kernel_data; /* Reserved for kernel internal use */ --}; -- --#ifdef ARCHDATAM --#define ARCHDATA_SEC_NAME ARCHDATAM --#else --#define ARCHDATA_SEC_NAME "__archdata" --#endif --#define KALLSYMS_SEC_NAME "__kallsyms" -- -- --struct new_module_info { -- unsigned long addr; -- unsigned long size; -- unsigned long flags; -- long usecount; --}; -- --/* Bits of module.flags. */ --enum { -- NEW_MOD_RUNNING = 1, -- NEW_MOD_DELETED = 2, -- NEW_MOD_AUTOCLEAN = 4, -- NEW_MOD_VISITED = 8, -- NEW_MOD_USED_ONCE = 16 --}; -- --int init_module(const char *name, const struct new_module *); --int query_module(const char *name, int which, void *buf, -- size_t bufsize, size_t *ret); -- --/* Values for query_module's which. */ --enum { -- QM_MODULES = 1, -- QM_DEPS = 2, -- QM_REFS = 3, -- QM_SYMBOLS = 4, -- QM_INFO = 5 --}; -- --/*======================================================================*/ --/* The system calls unchanged between 2.0 and 2.1. */ -- --unsigned long create_module(const char *, size_t); --int delete_module(const char *module, unsigned int flags); -- -- --#endif /* module.h */ -- --//---------------------------------------------------------------------------- --//--------end of modutils module.h --//---------------------------------------------------------------------------- -- -- -- --//---------------------------------------------------------------------------- --//--------modutils obj.h, lines 253-462 --//---------------------------------------------------------------------------- -- --/* Elf object file loading and relocation routines. -- Copyright 1996, 1997 Linux International. -- -- Contributed by Richard Henderson <rth@tamu.edu> -- -- This file is part of the Linux modutils. -- -- 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 MODUTILS_OBJ_H -- --/* The relocatable object is manipulated using elfin types. */ -- --#include <elf.h> --#include <endian.h> -- --#ifndef ElfW --# if ELFCLASSM == ELFCLASS32 --# define ElfW(x) Elf32_ ## x --# define ELFW(x) ELF32_ ## x --# else --# define ElfW(x) Elf64_ ## x --# define ELFW(x) ELF64_ ## x --# endif --#endif -- --/* For some reason this is missing from some ancient C libraries.... */ --#ifndef ELF32_ST_INFO --# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) --#endif -- --#ifndef ELF64_ST_INFO --# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) --#endif -- --#define ELF_ST_BIND(info) ELFW(ST_BIND)(info) --#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info) --#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type) --#define ELF_R_TYPE(val) ELFW(R_TYPE)(val) --#define ELF_R_SYM(val) ELFW(R_SYM)(val) -- --struct obj_string_patch; --struct obj_symbol_patch; -- --struct obj_section --{ -- ElfW(Shdr) header; -- const char *name; -- char *contents; -- struct obj_section *load_next; -- int idx; --}; -- --struct obj_symbol --{ -- struct obj_symbol *next; /* hash table link */ -- const char *name; -- unsigned long value; -- unsigned long size; -- int secidx; /* the defining section index/module */ -- int info; -- int ksymidx; /* for export to the kernel symtab */ -- int referenced; /* actually used in the link */ --}; -- --/* Hardcode the hash table size. We shouldn't be needing so many -- symbols that we begin to degrade performance, and we get a big win -- by giving the compiler a constant divisor. */ -- --#define HASH_BUCKETS 521 -- --struct obj_file { -- ElfW(Ehdr) header; -- ElfW(Addr) baseaddr; -- struct obj_section **sections; -- struct obj_section *load_order; -- struct obj_section **load_order_search_start; -- struct obj_string_patch *string_patches; -- struct obj_symbol_patch *symbol_patches; -- int (*symbol_cmp)(const char *, const char *); -- unsigned long (*symbol_hash)(const char *); -- unsigned long local_symtab_size; -- struct obj_symbol **local_symtab; -- struct obj_symbol *symtab[HASH_BUCKETS]; --}; -- --enum obj_reloc { -- obj_reloc_ok, -- obj_reloc_overflow, -- obj_reloc_dangerous, -- obj_reloc_unhandled --}; -- --struct obj_string_patch { -- struct obj_string_patch *next; -- int reloc_secidx; -- ElfW(Addr) reloc_offset; -- ElfW(Addr) string_offset; --}; -- --struct obj_symbol_patch { -- struct obj_symbol_patch *next; -- int reloc_secidx; -- ElfW(Addr) reloc_offset; -- struct obj_symbol *sym; --}; -- -- --/* Generic object manipulation routines. */ -- --static unsigned long obj_elf_hash(const char *); -- --static unsigned long obj_elf_hash_n(const char *, unsigned long len); -- --static struct obj_symbol *obj_find_symbol(struct obj_file *f, -- const char *name); -- --static ElfW(Addr) obj_symbol_final_value(struct obj_file *f, -- struct obj_symbol *sym); -- --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING --static void obj_set_symbol_compare(struct obj_file *f, -- int (*cmp)(const char *, const char *), -- unsigned long (*hash)(const char *)); --#endif -- --static struct obj_section *obj_find_section(struct obj_file *f, -- const char *name); -- --static void obj_insert_section_load_order(struct obj_file *f, -- struct obj_section *sec); -- --static struct obj_section *obj_create_alloced_section(struct obj_file *f, -- const char *name, -- unsigned long align, -- unsigned long size); -- --static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, -- const char *name, -- unsigned long align, -- unsigned long size); -- --static void *obj_extend_section(struct obj_section *sec, unsigned long more); -- --static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -- const char *string); -- --static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -- struct obj_symbol *sym); -- --static void obj_check_undefineds(struct obj_file *f); -- --static void obj_allocate_commons(struct obj_file *f); -- --static unsigned long obj_load_size(struct obj_file *f); -- --static int obj_relocate(struct obj_file *f, ElfW(Addr) base); -- --static struct obj_file *obj_load(FILE *f, int loadprogbits); -- --static int obj_create_image(struct obj_file *f, char *image); -- --/* Architecture specific manipulation routines. */ -- --static struct obj_file *arch_new_file(void); -- --static struct obj_section *arch_new_section(void); -- --static struct obj_symbol *arch_new_symbol(void); -- --static enum obj_reloc arch_apply_relocation(struct obj_file *f, -- struct obj_section *targsec, -- /*struct obj_section *symsec,*/ -- struct obj_symbol *sym, -- ElfW(RelM) *rel, ElfW(Addr) value); -- --static void arch_create_got(struct obj_file *f); --#if ENABLE_FEATURE_CHECK_TAINTED_MODULE --static int obj_gpl_license(struct obj_file *f, const char **license); --#endif /* FEATURE_CHECK_TAINTED_MODULE */ --#endif /* obj.h */ --//---------------------------------------------------------------------------- --//--------end of modutils obj.h --//---------------------------------------------------------------------------- -- -- --/* SPFX is always a string, so it can be concatenated to string constants. */ --#ifdef SYMBOL_PREFIX --#define SPFX SYMBOL_PREFIX --#else --#define SPFX "" --#endif -- --enum { STRVERSIONLEN = 64 }; -- --/*======================================================================*/ -- --#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m") --enum { -- OPT_s = 0x1, // -s /* log to syslog */ -- /* Not supported but kernel needs this for request_module(), -- as this calls: modprobe -k -s -- <module> -- so silently ignore this flag */ -- OPT_L = 0x2, // -L /* Stub warning */ -- /* Compatibility with modprobe. -- In theory, this does locking, but we don't do -- that. So be careful and plan your life around not -- loading the same module 50 times concurrently. */ -- OPT_o = 0x4, // -o /* name the output module */ -- OPT_f = 0x8, // -f /* force loading */ -- OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */ -- OPT_v = 0x20, // -v /* verbose output */ -- OPT_q = 0x40, // -q /* silent */ -- OPT_x = 0x80, // -x /* do not export externs */ -- OPT_m = 0x100, // -m /* print module load map */ --}; --#define flag_force_load (option_mask32 & OPT_f) --#define flag_autoclean (option_mask32 & OPT_k) --#define flag_verbose (option_mask32 & OPT_v) --#define flag_quiet (option_mask32 & OPT_q) --#define flag_noexport (option_mask32 & OPT_x) --#if ENABLE_FEATURE_INSMOD_LOAD_MAP --#define flag_print_load_map (option_mask32 & OPT_m) --#else --#define flag_print_load_map 0 --#endif -- --/*======================================================================*/ -- --#if defined(USE_LIST) -- --struct arch_list_entry --{ -- struct arch_list_entry *next; -- LIST_ARCHTYPE addend; -- int offset; -- int inited : 1; --}; -- --#endif -- --#if defined(USE_SINGLE) -- --struct arch_single_entry --{ -- int offset; -- int inited : 1; -- int allocated : 1; --}; -- --#endif -- --#if defined(__mips__) --struct mips_hi16 --{ -- struct mips_hi16 *next; -- ElfW(Addr) *addr; -- ElfW(Addr) value; --}; --#endif -- --struct arch_file { -- struct obj_file root; --#if defined(USE_PLT_ENTRIES) -- struct obj_section *plt; --#endif --#if defined(USE_GOT_ENTRIES) -- struct obj_section *got; --#endif --#if defined(__mips__) -- struct mips_hi16 *mips_hi16_list; --#endif --}; -- --struct arch_symbol { -- struct obj_symbol root; --#if defined(USE_PLT_ENTRIES) --#if defined(USE_PLT_LIST) -- struct arch_list_entry *pltent; --#else -- struct arch_single_entry pltent; --#endif --#endif --#if defined(USE_GOT_ENTRIES) -- struct arch_single_entry gotent; --#endif --}; -- -- --struct external_module { -- const char *name; -- ElfW(Addr) addr; -- int used; -- size_t nsyms; -- struct new_module_symbol *syms; --}; -- --static struct new_module_symbol *ksyms; --static size_t nksyms; -- --static struct external_module *ext_modules; --static int n_ext_modules; --static int n_ext_modules_used; -- --static char *m_filename; --static char *m_fullName; -- -- --/*======================================================================*/ -- -- --static int FAST_FUNC check_module_name_match(const char *filename, -- struct stat *statbuf UNUSED_PARAM, -- void *userdata, int depth UNUSED_PARAM) --{ -- char *fullname = (char *) userdata; -- char *tmp; -- -- if (fullname[0] == '\0') -- return FALSE; -- -- tmp = bb_get_last_path_component_nostrip(filename); -- if (strcmp(tmp, fullname) == 0) { -- /* Stop searching if we find a match */ -- m_filename = xstrdup(filename); -- return FALSE; -- } -- return TRUE; --} -- -- --/*======================================================================*/ -- --static struct obj_file *arch_new_file(void) --{ -- struct arch_file *f; -- f = xzalloc(sizeof(*f)); -- return &f->root; /* it's a first member */ --} -- --static struct obj_section *arch_new_section(void) --{ -- return xzalloc(sizeof(struct obj_section)); --} -- --static struct obj_symbol *arch_new_symbol(void) --{ -- struct arch_symbol *sym; -- sym = xzalloc(sizeof(*sym)); -- return &sym->root; --} -- --static enum obj_reloc --arch_apply_relocation(struct obj_file *f, -- struct obj_section *targsec, -- /*struct obj_section *symsec,*/ -- struct obj_symbol *sym, -- ElfW(RelM) *rel, ElfW(Addr) v) --{ --#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ -- || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \ -- || defined(__powerpc__) || defined(__mips__) -- struct arch_file *ifile = (struct arch_file *) f; --#endif -- enum obj_reloc ret = obj_reloc_ok; -- ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); --#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \ -- || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \ -- || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \ -- || defined(__s390__) || defined(__sh__) || defined(__x86_64__) -- ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; --#endif --#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -- struct arch_symbol *isym = (struct arch_symbol *) sym; --#endif --#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \ -- || defined(__sh__) || defined(__s390__) --#if defined(USE_GOT_ENTRIES) -- ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; --#endif --#endif --#if defined(USE_PLT_ENTRIES) -- ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; -- unsigned long *ip; --# if defined(USE_PLT_LIST) -- struct arch_list_entry *pe; --# else -- struct arch_single_entry *pe; --# endif --#endif -- -- switch (ELF_R_TYPE(rel->r_info)) { -- --#if defined(__arm__) -- -- case R_ARM_NONE: -- break; -- -- case R_ARM_ABS32: -- *loc += v; -- break; -- -- case R_ARM_GOT32: -- goto bb_use_got; -- -- case R_ARM_GOTPC: -- /* relative reloc, always to _GLOBAL_OFFSET_TABLE_ -- * (which is .got) similar to branch, -- * but is full 32 bits relative */ -- -- *loc += got - dot; -- break; -- -- case R_ARM_PC24: -- case R_ARM_PLT32: -- goto bb_use_plt; -- -- case R_ARM_GOTOFF: /* address relative to the got */ -- *loc += v - got; -- break; -- --#elif defined(__cris__) -- -- case R_CRIS_NONE: -- break; -- -- case R_CRIS_32: -- /* CRIS keeps the relocation value in the r_addend field and -- * should not use whats in *loc at all -- */ -- *loc = v; -- break; -- --#elif defined(__H8300H__) || defined(__H8300S__) -- -- case R_H8_DIR24R8: -- loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1); -- *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); -- break; -- case R_H8_DIR24A8: -- *loc += v; -- break; -- case R_H8_DIR32: -- case R_H8_DIR32A16: -- *loc += v; -- break; -- case R_H8_PCREL16: -- v -= dot + 2; -- if ((ElfW(Sword))v > 0x7fff || -- (ElfW(Sword))v < -(ElfW(Sword))0x8000) -- ret = obj_reloc_overflow; -- else -- *(unsigned short *)loc = v; -- break; -- case R_H8_PCREL8: -- v -= dot + 1; -- if ((ElfW(Sword))v > 0x7f || -- (ElfW(Sword))v < -(ElfW(Sword))0x80) -- ret = obj_reloc_overflow; -- else -- *(unsigned char *)loc = v; -- break; -- --#elif defined(__i386__) -- -- case R_386_NONE: -- break; -- -- case R_386_32: -- *loc += v; -- break; -- -- case R_386_PLT32: -- case R_386_PC32: -- case R_386_GOTOFF: -- *loc += v - dot; -- break; -- -- case R_386_GLOB_DAT: -- case R_386_JMP_SLOT: -- *loc = v; -- break; -- -- case R_386_RELATIVE: -- *loc += f->baseaddr; -- break; -- -- case R_386_GOTPC: -- *loc += got - dot; -- break; -- -- case R_386_GOT32: -- goto bb_use_got; -- break; -- --#elif defined(__microblaze__) -- case R_MICROBLAZE_NONE: -- case R_MICROBLAZE_64_NONE: -- case R_MICROBLAZE_32_SYM_OP_SYM: -- case R_MICROBLAZE_32_PCREL: -- break; -- -- case R_MICROBLAZE_64_PCREL: { -- /* dot is the address of the current instruction. -- * v is the target symbol address. -- * So we need to extract the offset in the code, -- * adding v, then subtrating the current address -- * of this instruction. -- * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000" -- */ -- -- /* Get split offset stored in code */ -- unsigned int temp = (loc[0] & 0xFFFF) << 16 | -- (loc[1] & 0xFFFF); -- -- /* Adjust relative offset. -4 adjustment required -- * because dot points to the IMM insn, but branch -- * is computed relative to the branch instruction itself. -- */ -- temp += v - dot - 4; -- -- /* Store back into code */ -- loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16; -- loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF); -- -- break; -- } -- -- case R_MICROBLAZE_32: -- *loc += v; -- break; -- -- case R_MICROBLAZE_64: { -- /* Get split pointer stored in code */ -- unsigned int temp1 = (loc[0] & 0xFFFF) << 16 | -- (loc[1] & 0xFFFF); -- -- /* Add reloc offset */ -- temp1+=v; -- -- /* Store back into code */ -- loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16; -- loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF); -- -- break; -- } -- -- case R_MICROBLAZE_32_PCREL_LO: -- case R_MICROBLAZE_32_LO: -- case R_MICROBLAZE_SRO32: -- case R_MICROBLAZE_SRW32: -- ret = obj_reloc_unhandled; -- break; -- --#elif defined(__mc68000__) -- -- case R_68K_NONE: -- break; -- -- case R_68K_32: -- *loc += v; -- break; -- -- case R_68K_8: -- if (v > 0xff) { -- ret = obj_reloc_overflow; -- } -- *(char *)loc = v; -- break; -- -- case R_68K_16: -- if (v > 0xffff) { -- ret = obj_reloc_overflow; -- } -- *(short *)loc = v; -- break; -- -- case R_68K_PC8: -- v -= dot; -- if ((ElfW(Sword))v > 0x7f -- || (ElfW(Sword))v < -(ElfW(Sword))0x80 -- ) { -- ret = obj_reloc_overflow; -- } -- *(char *)loc = v; -- break; -- -- case R_68K_PC16: -- v -= dot; -- if ((ElfW(Sword))v > 0x7fff -- || (ElfW(Sword))v < -(ElfW(Sword))0x8000 -- ) { -- ret = obj_reloc_overflow; -- } -- *(short *)loc = v; -- break; -- -- case R_68K_PC32: -- *(int *)loc = v - dot; -- break; -- -- case R_68K_GLOB_DAT: -- case R_68K_JMP_SLOT: -- *loc = v; -- break; -- -- case R_68K_RELATIVE: -- *(int *)loc += f->baseaddr; -- break; -- -- case R_68K_GOT32: -- goto bb_use_got; -- --# ifdef R_68K_GOTOFF -- case R_68K_GOTOFF: -- *loc += v - got; -- break; --# endif -- --#elif defined(__mips__) -- -- case R_MIPS_NONE: -- break; -- -- case R_MIPS_32: -- *loc += v; -- break; -- -- case R_MIPS_26: -- if (v % 4) -- ret = obj_reloc_dangerous; -- if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000)) -- ret = obj_reloc_overflow; -- *loc = -- (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) & -- 0x03ffffff); -- break; -- -- case R_MIPS_HI16: -- { -- struct mips_hi16 *n; -- -- /* We cannot relocate this one now because we don't know the value -- of the carry we need to add. Save the information, and let LO16 -- do the actual relocation. */ -- n = xmalloc(sizeof *n); -- n->addr = loc; -- n->value = v; -- n->next = ifile->mips_hi16_list; -- ifile->mips_hi16_list = n; -- break; -- } -- -- case R_MIPS_LO16: -- { -- unsigned long insnlo = *loc; -- ElfW(Addr) val, vallo; -- -- /* Sign extend the addend we extract from the lo insn. */ -- vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; -- -- if (ifile->mips_hi16_list != NULL) { -- struct mips_hi16 *l; -- -- l = ifile->mips_hi16_list; -- while (l != NULL) { -- struct mips_hi16 *next; -- unsigned long insn; -- -- /* Do the HI16 relocation. Note that we actually don't -- need to know anything about the LO16 itself, except where -- to find the low 16 bits of the addend needed by the LO16. */ -- insn = *l->addr; -- val = -- ((insn & 0xffff) << 16) + -- vallo; -- val += v; -- -- /* Account for the sign extension that will happen in the -- low bits. */ -- val = -- ((val >> 16) + -- ((val & 0x8000) != -- 0)) & 0xffff; -- -- insn = (insn & ~0xffff) | val; -- *l->addr = insn; -- -- next = l->next; -- free(l); -- l = next; -- } -- -- ifile->mips_hi16_list = NULL; -- } -- -- /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */ -- val = v + vallo; -- insnlo = (insnlo & ~0xffff) | (val & 0xffff); -- *loc = insnlo; -- break; -- } -- --#elif defined(__nios2__) -- -- case R_NIOS2_NONE: -- break; -- -- case R_NIOS2_BFD_RELOC_32: -- *loc += v; -- break; -- -- case R_NIOS2_BFD_RELOC_16: -- if (v > 0xffff) { -- ret = obj_reloc_overflow; -- } -- *(short *)loc = v; -- break; -- -- case R_NIOS2_BFD_RELOC_8: -- if (v > 0xff) { -- ret = obj_reloc_overflow; -- } -- *(char *)loc = v; -- break; -- -- case R_NIOS2_S16: -- { -- Elf32_Addr word; -- -- if ((Elf32_Sword)v > 0x7fff -- || (Elf32_Sword)v < -(Elf32_Sword)0x8000 -- ) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -- (word & 0x3f); -- } -- break; -- -- case R_NIOS2_U16: -- { -- Elf32_Addr word; -- -- if (v > 0xffff) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -- (word & 0x3f); -- } -- break; -- -- case R_NIOS2_PCREL16: -- { -- Elf32_Addr word; -- -- v -= dot + 4; -- if ((Elf32_Sword)v > 0x7fff -- || (Elf32_Sword)v < -(Elf32_Sword)0x8000 -- ) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f); -- } -- break; -- -- case R_NIOS2_GPREL: -- { -- Elf32_Addr word, gp; -- /* get _gp */ -- gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp")); -- v -= gp; -- if ((Elf32_Sword)v > 0x7fff -- || (Elf32_Sword)v < -(Elf32_Sword)0x8000 -- ) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f); -- } -- break; -- -- case R_NIOS2_CALL26: -- if (v & 3) -- ret = obj_reloc_dangerous; -- if ((v >> 28) != (dot >> 28)) -- ret = obj_reloc_overflow; -- *loc = (*loc & 0x3f) | ((v >> 2) << 6); -- break; -- -- case R_NIOS2_IMM5: -- { -- Elf32_Addr word; -- -- if (v > 0x1f) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc & ~0x7c0; -- *loc = word | ((v & 0x1f) << 6); -- } -- break; -- -- case R_NIOS2_IMM6: -- { -- Elf32_Addr word; -- -- if (v > 0x3f) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc & ~0xfc0; -- *loc = word | ((v & 0x3f) << 6); -- } -- break; -- -- case R_NIOS2_IMM8: -- { -- Elf32_Addr word; -- -- if (v > 0xff) { -- ret = obj_reloc_overflow; -- } -- -- word = *loc & ~0x3fc0; -- *loc = word | ((v & 0xff) << 6); -- } -- break; -- -- case R_NIOS2_HI16: -- { -- Elf32_Addr word; -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) | -- (word & 0x3f); -- } -- break; -- -- case R_NIOS2_LO16: -- { -- Elf32_Addr word; -- -- word = *loc; -- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | -- (word & 0x3f); -- } -- break; -- -- case R_NIOS2_HIADJ16: -- { -- Elf32_Addr word1, word2; -- -- word1 = *loc; -- word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff; -- *loc = ((((word1 >> 22) << 16) | word2) << 6) | -- (word1 & 0x3f); -- } -- break; -- --#elif defined(__powerpc64__) -- /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */ -- --#elif defined(__powerpc__) -- -- case R_PPC_ADDR16_HA: -- *(unsigned short *)loc = (v + 0x8000) >> 16; -- break; -- -- case R_PPC_ADDR16_HI: -- *(unsigned short *)loc = v >> 16; -- break; -- -- case R_PPC_ADDR16_LO: -- *(unsigned short *)loc = v; -- break; -- -- case R_PPC_REL24: -- goto bb_use_plt; -- -- case R_PPC_REL32: -- *loc = v - dot; -- break; -- -- case R_PPC_ADDR32: -- *loc = v; -- break; -- --#elif defined(__s390__) -- -- case R_390_32: -- *(unsigned int *) loc += v; -- break; -- case R_390_16: -- *(unsigned short *) loc += v; -- break; -- case R_390_8: -- *(unsigned char *) loc += v; -- break; -- -- case R_390_PC32: -- *(unsigned int *) loc += v - dot; -- break; -- case R_390_PC16DBL: -- *(unsigned short *) loc += (v - dot) >> 1; -- break; -- case R_390_PC16: -- *(unsigned short *) loc += v - dot; -- break; -- -- case R_390_PLT32: -- case R_390_PLT16DBL: -- /* find the plt entry and initialize it. */ -- pe = (struct arch_single_entry *) &isym->pltent; -- if (pe->inited == 0) { -- ip = (unsigned long *)(ifile->plt->contents + pe->offset); -- ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */ -- ip[1] = 0x100607f1; -- if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL) -- ip[2] = v - 2; -- else -- ip[2] = v; -- pe->inited = 1; -- } -- -- /* Insert relative distance to target. */ -- v = plt + pe->offset - dot; -- if (ELF_R_TYPE(rel->r_info) == R_390_PLT32) -- *(unsigned int *) loc = (unsigned int) v; -- else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL) -- *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1); -- break; -- -- case R_390_GLOB_DAT: -- case R_390_JMP_SLOT: -- *loc = v; -- break; -- -- case R_390_RELATIVE: -- *loc += f->baseaddr; -- break; -- -- case R_390_GOTPC: -- *(unsigned long *) loc += got - dot; -- break; -- -- case R_390_GOT12: -- case R_390_GOT16: -- case R_390_GOT32: -- if (!isym->gotent.inited) -- { -- isym->gotent.inited = 1; -- *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v; -- } -- if (ELF_R_TYPE(rel->r_info) == R_390_GOT12) -- *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff; -- else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16) -- *(unsigned short *) loc += isym->gotent.offset; -- else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32) -- *(unsigned int *) loc += isym->gotent.offset; -- break; -- --# ifndef R_390_GOTOFF32 --# define R_390_GOTOFF32 R_390_GOTOFF --# endif -- case R_390_GOTOFF32: -- *loc += v - got; -- break; -- --#elif defined(__sh__) -- -- case R_SH_NONE: -- break; -- -- case R_SH_DIR32: -- *loc += v; -- break; -- -- case R_SH_REL32: -- *loc += v - dot; -- break; -- -- case R_SH_PLT32: -- *loc = v - dot; -- break; -- -- case R_SH_GLOB_DAT: -- case R_SH_JMP_SLOT: -- *loc = v; -- break; -- -- case R_SH_RELATIVE: -- *loc = f->baseaddr + rel->r_addend; -- break; -- -- case R_SH_GOTPC: -- *loc = got - dot + rel->r_addend; -- break; -- -- case R_SH_GOT32: -- goto bb_use_got; -- -- case R_SH_GOTOFF: -- *loc = v - got; -- break; -- --# if defined(__SH5__) -- case R_SH_IMM_MEDLOW16: -- case R_SH_IMM_LOW16: -- { -- ElfW(Addr) word; -- -- if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16) -- v >>= 16; -- -- /* -- * movi and shori have the format: -- * -- * | op | imm | reg | reserved | -- * 31..26 25..10 9.. 4 3 .. 0 -- * -- * so we simply mask and or in imm. -- */ -- word = *loc & ~0x3fffc00; -- word |= (v & 0xffff) << 10; -- -- *loc = word; -- -- break; -- } -- -- case R_SH_IMM_MEDLOW16_PCREL: -- case R_SH_IMM_LOW16_PCREL: -- { -- ElfW(Addr) word; -- -- word = *loc & ~0x3fffc00; -- -- v -= dot; -- -- if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL) -- v >>= 16; -- -- word |= (v & 0xffff) << 10; -- -- *loc = word; -- -- break; -- } --# endif /* __SH5__ */ -- --#elif defined(__v850e__) -- -- case R_V850_NONE: -- break; -- -- case R_V850_32: -- /* We write two shorts instead of a long because even -- 32-bit insns only need half-word alignment, but -- 32-bit data needs to be long-word aligned. */ -- v += ((unsigned short *)loc)[0]; -- v += ((unsigned short *)loc)[1] << 16; -- ((unsigned short *)loc)[0] = v & 0xffff; -- ((unsigned short *)loc)[1] = (v >> 16) & 0xffff; -- break; -- -- case R_V850_22_PCREL: -- goto bb_use_plt; -- --#elif defined(__x86_64__) -- -- case R_X86_64_NONE: -- break; -- -- case R_X86_64_64: -- *loc += v; -- break; -- -- case R_X86_64_32: -- *(unsigned int *) loc += v; -- if (v > 0xffffffff) -- { -- ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */ -- /* error("Possibly is module compiled without -mcmodel=kernel!"); */ -- } -- break; -- -- case R_X86_64_32S: -- *(signed int *) loc += v; -- break; -- -- case R_X86_64_16: -- *(unsigned short *) loc += v; -- break; -- -- case R_X86_64_8: -- *(unsigned char *) loc += v; -- break; -- -- case R_X86_64_PC32: -- *(unsigned int *) loc += v - dot; -- break; -- -- case R_X86_64_PC16: -- *(unsigned short *) loc += v - dot; -- break; -- -- case R_X86_64_PC8: -- *(unsigned char *) loc += v - dot; -- break; -- -- case R_X86_64_GLOB_DAT: -- case R_X86_64_JUMP_SLOT: -- *loc = v; -- break; -- -- case R_X86_64_RELATIVE: -- *loc += f->baseaddr; -- break; -- -- case R_X86_64_GOT32: -- case R_X86_64_GOTPCREL: -- goto bb_use_got; --# if 0 -- if (!isym->gotent.reloc_done) -- { -- isym->gotent.reloc_done = 1; -- *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v; -- } -- /* XXX are these really correct? */ -- if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL) -- *(unsigned int *) loc += v + isym->gotent.offset; -- else -- *loc += isym->gotent.offset; -- break; --# endif -- --#else --# warning "no idea how to handle relocations on your arch" --#endif -- -- default: -- printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info)); -- ret = obj_reloc_unhandled; -- break; -- --#if defined(USE_PLT_ENTRIES) -- --bb_use_plt: -- -- /* find the plt entry and initialize it if necessary */ -- --#if defined(USE_PLT_LIST) -- for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;) -- pe = pe->next; --#else -- pe = &isym->pltent; --#endif -- -- if (! pe->inited) { -- ip = (unsigned long *) (ifile->plt->contents + pe->offset); -- -- /* generate some machine code */ -- --#if defined(__arm__) -- ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ -- ip[1] = v; /* sym@ */ --#endif --#if defined(__powerpc__) -- ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */ -- ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */ -- ip[2] = 0x7d6903a6; /* mtctr r11 */ -- ip[3] = 0x4e800420; /* bctr */ --#endif --#if defined(__v850e__) -- /* We have to trash a register, so we assume that any control -- transfer more than 21-bits away must be a function call -- (so we can use a call-clobbered register). */ -- ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */ -- ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */ --#endif -- pe->inited = 1; -- } -- -- /* relative distance to target */ -- v -= dot; -- /* if the target is too far away.... */ --#if defined(__arm__) || defined(__powerpc__) -- if ((int)v < -0x02000000 || (int)v >= 0x02000000) --#elif defined(__v850e__) -- if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000) --#endif -- /* go via the plt */ -- v = plt + pe->offset - dot; -- --#if defined(__v850e__) -- if (v & 1) --#else -- if (v & 3) --#endif -- ret = obj_reloc_dangerous; -- -- /* merge the offset into the instruction. */ --#if defined(__arm__) -- /* Convert to words. */ -- v >>= 2; -- -- *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); --#endif --#if defined(__powerpc__) -- *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc); --#endif --#if defined(__v850e__) -- /* We write two shorts instead of a long because even 32-bit insns -- only need half-word alignment, but the 32-bit data write needs -- to be long-word aligned. */ -- ((unsigned short *)loc)[0] = -- (*(unsigned short *)loc & 0xffc0) /* opcode + reg */ -- | ((v >> 16) & 0x3f); /* offs high part */ -- ((unsigned short *)loc)[1] = -- (v & 0xffff); /* offs low part */ --#endif -- break; --#endif /* USE_PLT_ENTRIES */ -- --#if defined(USE_GOT_ENTRIES) --bb_use_got: -- -- /* needs an entry in the .got: set it, once */ -- if (!isym->gotent.inited) { -- isym->gotent.inited = 1; -- *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; -- } -- /* make the reloc with_respect_to_.got */ --#if defined(__sh__) -- *loc += isym->gotent.offset + rel->r_addend; --#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__) -- *loc += isym->gotent.offset; --#endif -- break; -- --#endif /* USE_GOT_ENTRIES */ -- } -- -- return ret; --} -- -- --#if defined(USE_LIST) -- --static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list, -- int offset, int size) --{ -- struct arch_list_entry *pe; -- -- for (pe = *list; pe != NULL; pe = pe->next) { -- if (pe->addend == rel->r_addend) { -- break; -- } -- } -- -- if (pe == NULL) { -- pe = xmalloc(sizeof(struct arch_list_entry)); -- pe->next = *list; -- pe->addend = rel->r_addend; -- pe->offset = offset; -- pe->inited = 0; -- *list = pe; -- return size; -- } -- return 0; --} -- --#endif -- --#if defined(USE_SINGLE) -- --static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single, -- int offset, int size) --{ -- if (single->allocated == 0) { -- single->allocated = 1; -- single->offset = offset; -- single->inited = 0; -- return size; -- } -- return 0; --} -- --#endif -- --#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -- --static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name, -- int offset, int size) --{ -- struct obj_section *myrelsec = obj_find_section(f, name); -- -- if (offset == 0) { -- offset += size; -- } -- -- if (myrelsec) { -- obj_extend_section(myrelsec, offset); -- } else { -- myrelsec = obj_create_alloced_section(f, name, -- size, offset); -- } -- -- return myrelsec; --} -- --#endif -- --static void arch_create_got(struct obj_file *f) --{ --#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) -- struct arch_file *ifile = (struct arch_file *) f; -- int i; --#if defined(USE_GOT_ENTRIES) -- int got_offset = 0, got_needed = 0, got_allocate; --#endif --#if defined(USE_PLT_ENTRIES) -- int plt_offset = 0, plt_needed = 0, plt_allocate; --#endif -- struct obj_section *relsec, *symsec, *strsec; -- ElfW(RelM) *rel, *relend; -- ElfW(Sym) *symtab, *extsym; -- const char *strtab, *name; -- struct arch_symbol *intsym; -- -- for (i = 0; i < f->header.e_shnum; ++i) { -- relsec = f->sections[i]; -- if (relsec->header.sh_type != SHT_RELM) -- continue; -- -- symsec = f->sections[relsec->header.sh_link]; -- strsec = f->sections[symsec->header.sh_link]; -- -- rel = (ElfW(RelM) *) relsec->contents; -- relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); -- symtab = (ElfW(Sym) *) symsec->contents; -- strtab = (const char *) strsec->contents; -- -- for (; rel < relend; ++rel) { -- extsym = &symtab[ELF_R_SYM(rel->r_info)]; -- --#if defined(USE_GOT_ENTRIES) -- got_allocate = 0; --#endif --#if defined(USE_PLT_ENTRIES) -- plt_allocate = 0; --#endif -- -- switch (ELF_R_TYPE(rel->r_info)) { --#if defined(__arm__) -- case R_ARM_PC24: -- case R_ARM_PLT32: -- plt_allocate = 1; -- break; -- -- case R_ARM_GOTOFF: -- case R_ARM_GOTPC: -- got_needed = 1; -- continue; -- -- case R_ARM_GOT32: -- got_allocate = 1; -- break; -- --#elif defined(__i386__) -- case R_386_GOTPC: -- case R_386_GOTOFF: -- got_needed = 1; -- continue; -- -- case R_386_GOT32: -- got_allocate = 1; -- break; -- --#elif defined(__powerpc__) -- case R_PPC_REL24: -- plt_allocate = 1; -- break; -- --#elif defined(__mc68000__) -- case R_68K_GOT32: -- got_allocate = 1; -- break; -- --#ifdef R_68K_GOTOFF -- case R_68K_GOTOFF: -- got_needed = 1; -- continue; --#endif -- --#elif defined(__sh__) -- case R_SH_GOT32: -- got_allocate = 1; -- break; -- -- case R_SH_GOTPC: -- case R_SH_GOTOFF: -- got_needed = 1; -- continue; -- --#elif defined(__v850e__) -- case R_V850_22_PCREL: -- plt_needed = 1; -- break; -- --#endif -- default: -- continue; -- } -- -- if (extsym->st_name != 0) { -- name = strtab + extsym->st_name; -- } else { -- name = f->sections[extsym->st_shndx]->name; -- } -- intsym = (struct arch_symbol *) obj_find_symbol(f, name); --#if defined(USE_GOT_ENTRIES) -- if (got_allocate) { -- got_offset += arch_single_init( -- /*rel,*/ &intsym->gotent, -- got_offset, GOT_ENTRY_SIZE); -- -- got_needed = 1; -- } --#endif --#if defined(USE_PLT_ENTRIES) -- if (plt_allocate) { --#if defined(USE_PLT_LIST) -- plt_offset += arch_list_add( -- rel, &intsym->pltent, -- plt_offset, PLT_ENTRY_SIZE); --#else -- plt_offset += arch_single_init( -- /*rel,*/ &intsym->pltent, -- plt_offset, PLT_ENTRY_SIZE); --#endif -- plt_needed = 1; -- } --#endif -- } -- } -- --#if defined(USE_GOT_ENTRIES) -- if (got_needed) { -- ifile->got = arch_xsect_init(f, ".got", got_offset, -- GOT_ENTRY_SIZE); -- } --#endif -- --#if defined(USE_PLT_ENTRIES) -- if (plt_needed) { -- ifile->plt = arch_xsect_init(f, ".plt", plt_offset, -- PLT_ENTRY_SIZE); -- } --#endif -- --#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */ --} -- --/*======================================================================*/ -- --/* Standard ELF hash function. */ --static unsigned long obj_elf_hash_n(const char *name, unsigned long n) --{ -- unsigned long h = 0; -- unsigned long g; -- unsigned char ch; -- -- while (n > 0) { -- ch = *name++; -- h = (h << 4) + ch; -- g = (h & 0xf0000000); -- if (g != 0) { -- h ^= g >> 24; -- h &= ~g; -- } -- n--; -- } -- return h; --} -- --static unsigned long obj_elf_hash(const char *name) --{ -- return obj_elf_hash_n(name, strlen(name)); --} -- --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING --/* String comparison for non-co-versioned kernel and module. */ -- --static int ncv_strcmp(const char *a, const char *b) --{ -- size_t alen = strlen(a), blen = strlen(b); -- -- if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R') -- return strncmp(a, b, alen); -- else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R') -- return strncmp(a, b, blen); -- else -- return strcmp(a, b); --} -- --/* String hashing for non-co-versioned kernel and module. Here -- we are simply forced to drop the crc from the hash. */ -- --static unsigned long ncv_symbol_hash(const char *str) --{ -- size_t len = strlen(str); -- if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R') -- len -= 10; -- return obj_elf_hash_n(str, len); --} -- --static void --obj_set_symbol_compare(struct obj_file *f, -- int (*cmp) (const char *, const char *), -- unsigned long (*hash) (const char *)) --{ -- if (cmp) -- f->symbol_cmp = cmp; -- if (hash) { -- struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next; -- int i; -- -- f->symbol_hash = hash; -- -- memcpy(tmptab, f->symtab, sizeof(tmptab)); -- memset(f->symtab, 0, sizeof(f->symtab)); -- -- for (i = 0; i < HASH_BUCKETS; ++i) -- for (sym = tmptab[i]; sym; sym = next) { -- unsigned long h = hash(sym->name) % HASH_BUCKETS; -- next = sym->next; -- sym->next = f->symtab[h]; -- f->symtab[h] = sym; -- } -- } --} -- --#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -- --static struct obj_symbol * --obj_add_symbol(struct obj_file *f, const char *name, -- unsigned long symidx, int info, -- int secidx, ElfW(Addr) value, -- unsigned long size) --{ -- struct obj_symbol *sym; -- unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; -- int n_type = ELF_ST_TYPE(info); -- int n_binding = ELF_ST_BIND(info); -- -- for (sym = f->symtab[hash]; sym; sym = sym->next) { -- if (f->symbol_cmp(sym->name, name) == 0) { -- int o_secidx = sym->secidx; -- int o_info = sym->info; -- int o_type = ELF_ST_TYPE(o_info); -- int o_binding = ELF_ST_BIND(o_info); -- -- /* A redefinition! Is it legal? */ -- -- if (secidx == SHN_UNDEF) -- return sym; -- else if (o_secidx == SHN_UNDEF) -- goto found; -- else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) { -- /* Cope with local and global symbols of the same name -- in the same object file, as might have been created -- by ld -r. The only reason locals are now seen at this -- level at all is so that we can do semi-sensible things -- with parameters. */ -- -- struct obj_symbol *nsym, **p; -- -- nsym = arch_new_symbol(); -- nsym->next = sym->next; -- nsym->ksymidx = -1; -- -- /* Excise the old (local) symbol from the hash chain. */ -- for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next) -- continue; -- *p = sym = nsym; -- goto found; -- } else if (n_binding == STB_LOCAL) { -- /* Another symbol of the same name has already been defined. -- Just add this to the local table. */ -- sym = arch_new_symbol(); -- sym->next = NULL; -- sym->ksymidx = -1; -- f->local_symtab[symidx] = sym; -- goto found; -- } else if (n_binding == STB_WEAK) -- return sym; -- else if (o_binding == STB_WEAK) -- goto found; -- /* Don't unify COMMON symbols with object types the programmer -- doesn't expect. */ -- else if (secidx == SHN_COMMON -- && (o_type == STT_NOTYPE || o_type == STT_OBJECT)) -- return sym; -- else if (o_secidx == SHN_COMMON -- && (n_type == STT_NOTYPE || n_type == STT_OBJECT)) -- goto found; -- else { -- /* Don't report an error if the symbol is coming from -- the kernel or some external module. */ -- if (secidx <= SHN_HIRESERVE) -- bb_error_msg("%s multiply defined", name); -- return sym; -- } -- } -- } -- -- /* Completely new symbol. */ -- sym = arch_new_symbol(); -- sym->next = f->symtab[hash]; -- f->symtab[hash] = sym; -- sym->ksymidx = -1; -- if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) { -- if (symidx >= f->local_symtab_size) -- bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld", -- name, (long) symidx, (long) f->local_symtab_size); -- else -- f->local_symtab[symidx] = sym; -- } -- --found: -- sym->name = name; -- sym->value = value; -- sym->size = size; -- sym->secidx = secidx; -- sym->info = info; -- -- return sym; --} -- --static struct obj_symbol * --obj_find_symbol(struct obj_file *f, const char *name) --{ -- struct obj_symbol *sym; -- unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; -- -- for (sym = f->symtab[hash]; sym; sym = sym->next) -- if (f->symbol_cmp(sym->name, name) == 0) -- return sym; -- return NULL; --} -- --static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym) --{ -- if (sym) { -- if (sym->secidx >= SHN_LORESERVE) -- return sym->value; -- return sym->value + f->sections[sym->secidx]->header.sh_addr; -- } -- /* As a special case, a NULL sym has value zero. */ -- return 0; --} -- --static struct obj_section *obj_find_section(struct obj_file *f, const char *name) --{ -- int i, n = f->header.e_shnum; -- -- for (i = 0; i < n; ++i) -- if (strcmp(f->sections[i]->name, name) == 0) -- return f->sections[i]; -- return NULL; --} -- --static int obj_load_order_prio(struct obj_section *a) --{ -- unsigned long af, ac; -- -- af = a->header.sh_flags; -- -- ac = 0; -- if (a->name[0] != '.' || strlen(a->name) != 10 -- || strcmp(a->name + 5, ".init") != 0 -- ) { -- ac |= 32; -- } -- if (af & SHF_ALLOC) -- ac |= 16; -- if (!(af & SHF_WRITE)) -- ac |= 8; -- if (af & SHF_EXECINSTR) -- ac |= 4; -- if (a->header.sh_type != SHT_NOBITS) -- ac |= 2; -- -- return ac; --} -- --static void --obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec) --{ -- struct obj_section **p; -- int prio = obj_load_order_prio(sec); -- for (p = f->load_order_search_start; *p; p = &(*p)->load_next) -- if (obj_load_order_prio(*p) < prio) -- break; -- sec->load_next = *p; -- *p = sec; --} -- --static struct obj_section *obj_create_alloced_section(struct obj_file *f, -- const char *name, -- unsigned long align, -- unsigned long size) --{ -- int newidx = f->header.e_shnum++; -- struct obj_section *sec; -- -- f->sections = xrealloc_vector(f->sections, 2, newidx); -- f->sections[newidx] = sec = arch_new_section(); -- -- sec->header.sh_type = SHT_PROGBITS; -- sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -- sec->header.sh_size = size; -- sec->header.sh_addralign = align; -- sec->name = name; -- sec->idx = newidx; -- if (size) -- sec->contents = xzalloc(size); -- -- obj_insert_section_load_order(f, sec); -- -- return sec; --} -- --static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, -- const char *name, -- unsigned long align, -- unsigned long size) --{ -- int newidx = f->header.e_shnum++; -- struct obj_section *sec; -- -- f->sections = xrealloc_vector(f->sections, 2, newidx); -- f->sections[newidx] = sec = arch_new_section(); -- -- sec->header.sh_type = SHT_PROGBITS; -- sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -- sec->header.sh_size = size; -- sec->header.sh_addralign = align; -- sec->name = name; -- sec->idx = newidx; -- if (size) -- sec->contents = xzalloc(size); -- -- sec->load_next = f->load_order; -- f->load_order = sec; -- if (f->load_order_search_start == &f->load_order) -- f->load_order_search_start = &sec->load_next; -- -- return sec; --} -- --static void *obj_extend_section(struct obj_section *sec, unsigned long more) --{ -- unsigned long oldsize = sec->header.sh_size; -- if (more) { -- sec->header.sh_size += more; -- sec->contents = xrealloc(sec->contents, sec->header.sh_size); -- } -- return sec->contents + oldsize; --} -- -- --/* Conditionally add the symbols from the given symbol set to the -- new module. */ -- --static int --add_symbols_from( struct obj_file *f, -- int idx, struct new_module_symbol *syms, size_t nsyms) --{ -- struct new_module_symbol *s; -- size_t i; -- int used = 0; --#ifdef SYMBOL_PREFIX -- char *name_buf = 0; -- size_t name_alloced_size = 0; --#endif --#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -- int gpl; -- -- gpl = obj_gpl_license(f, NULL) == 0; --#endif -- for (i = 0, s = syms; i < nsyms; ++i, ++s) { -- /* Only add symbols that are already marked external. -- If we override locals we may cause problems for -- argument initialization. We will also create a false -- dependency on the module. */ -- struct obj_symbol *sym; -- char *name; -- -- /* GPL licensed modules can use symbols exported with -- * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the -- * exported names. Non-GPL modules never see any GPLONLY_ -- * symbols so they cannot fudge it by adding the prefix on -- * their references. -- */ -- if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) { --#if ENABLE_FEATURE_CHECK_TAINTED_MODULE -- if (gpl) -- s->name += 8; -- else --#endif -- continue; -- } -- name = (char *)s->name; -- --#ifdef SYMBOL_PREFIX -- /* Prepend SYMBOL_PREFIX to the symbol's name (the -- kernel exports `C names', but module object files -- reference `linker names'). */ -- size_t extra = sizeof SYMBOL_PREFIX; -- size_t name_size = strlen(name) + extra; -- if (name_size > name_alloced_size) { -- name_alloced_size = name_size * 2; -- name_buf = alloca(name_alloced_size); -- } -- strcpy(name_buf, SYMBOL_PREFIX); -- strcpy(name_buf + extra - 1, name); -- name = name_buf; --#endif /* SYMBOL_PREFIX */ -- -- sym = obj_find_symbol(f, name); -- if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) { --#ifdef SYMBOL_PREFIX -- /* Put NAME_BUF into more permanent storage. */ -- name = xmalloc(name_size); -- strcpy(name, name_buf); --#endif -- sym = obj_add_symbol(f, name, -1, -- ELF_ST_INFO(STB_GLOBAL, -- STT_NOTYPE), -- idx, s->value, 0); -- /* Did our symbol just get installed? If so, mark the -- module as "used". */ -- if (sym->secidx == idx) -- used = 1; -- } -- } -- -- return used; --} -- --static void add_kernel_symbols(struct obj_file *f) --{ -- struct external_module *m; -- int i, nused = 0; -- -- /* Add module symbols first. */ -- -- for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) { -- if (m->nsyms -- && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms) -- ) { -- m->used = 1; -- ++nused; -- } -- } -- -- n_ext_modules_used = nused; -- -- /* And finally the symbols from the kernel proper. */ -- -- if (nksyms) -- add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms); --} -- --static char *get_modinfo_value(struct obj_file *f, const char *key) --{ -- struct obj_section *sec; -- char *p, *v, *n, *ep; -- size_t klen = strlen(key); -- -- sec = obj_find_section(f, ".modinfo"); -- if (sec == NULL) -- return NULL; -- p = sec->contents; -- ep = p + sec->header.sh_size; -- while (p < ep) { -- v = strchr(p, '='); -- n = strchr(p, '\0'); -- if (v) { -- if (p + klen == v && strncmp(p, key, klen) == 0) -- return v + 1; -- } else { -- if (p + klen == n && strcmp(p, key) == 0) -- return n; -- } -- p = n + 1; -- } -- -- return NULL; --} -- -- --/*======================================================================*/ --/* Functions relating to module loading after 2.1.18. */ -- --static void --new_process_module_arguments(struct obj_file *f, int argc, char **argv) --{ -- while (argc > 0) { -- char *p, *q, *key, *sym_name; -- struct obj_symbol *sym; -- char *contents, *loc; -- int min, max, n; -- -- p = *argv; -- q = strchr(p, '='); -- if (q == NULL) { -- argc--; -- continue; -- } -- -- key = alloca(q - p + 6); -- memcpy(key, "parm_", 5); -- memcpy(key + 5, p, q - p); -- key[q - p + 5] = 0; -- -- p = get_modinfo_value(f, key); -- key += 5; -- if (p == NULL) { -- bb_error_msg_and_die("invalid parameter %s", key); -- } -- --#ifdef SYMBOL_PREFIX -- sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX); -- strcpy(sym_name, SYMBOL_PREFIX); -- strcat(sym_name, key); --#else -- sym_name = key; --#endif -- sym = obj_find_symbol(f, sym_name); -- -- /* Also check that the parameter was not resolved from the kernel. */ -- if (sym == NULL || sym->secidx > SHN_HIRESERVE) { -- bb_error_msg_and_die("symbol for parameter %s not found", key); -- } -- -- if (isdigit(*p)) { -- min = strtoul(p, &p, 10); -- if (*p == '-') -- max = strtoul(p + 1, &p, 10); -- else -- max = min; -- } else -- min = max = 1; -- -- contents = f->sections[sym->secidx]->contents; -- loc = contents + sym->value; -- n = (*++q != '\0'); -- -- while (1) { -- if ((*p == 's') || (*p == 'c')) { -- char *str; -- -- /* Do C quoting if we begin with a ", else slurp the lot. */ -- if (*q == '"') { -- char *r; -- -- str = alloca(strlen(q)); -- for (r = str, q++; *q != '"'; ++q, ++r) { -- if (*q == '\0') -- bb_error_msg_and_die("improperly terminated string argument for %s", -- key); -- if (*q == '\\') -- switch (*++q) { -- case 'a': -- *r = '\a'; -- break; -- case 'b': -- *r = '\b'; -- break; -- case 'e': -- *r = '\033'; -- break; -- case 'f': -- *r = '\f'; -- break; -- case 'n': -- *r = '\n'; -- break; -- case 'r': -- *r = '\r'; -- break; -- case 't': -- *r = '\t'; -- break; -- -- case '0': -- case '1': -- case '2': -- case '3': -- case '4': -- case '5': -- case '6': -- case '7': -- { -- int c = *q - '0'; -- if (q[1] >= '0' && q[1] <= '7') { -- c = (c * 8) + *++q - '0'; -- if (q[1] >= '0' && q[1] <= '7') -- c = (c * 8) + *++q - '0'; -- } -- *r = c; -- } -- break; -- -- default: -- *r = *q; -- break; -- } -- else -- *r = *q; -- } -- *r = '\0'; -- ++q; -- } else { -- char *r; -- -- /* In this case, the string is not quoted. We will break -- it using the coma (like for ints). If the user wants to -- include comas in a string, he just has to quote it */ -- -- /* Search the next coma */ -- r = strchr(q, ','); -- -- /* Found ? */ -- if (r != (char *) NULL) { -- /* Recopy the current field */ -- str = alloca(r - q + 1); -- memcpy(str, q, r - q); -- -- /* I don't know if it is useful, as the previous case -- doesn't nul terminate the string ??? */ -- str[r - q] = '\0'; -- -- /* Keep next fields */ -- q = r; -- } else { -- /* last string */ -- str = q; -- q = (char*)""; -- } -- } -- -- if (*p == 's') { -- /* Normal string */ -- obj_string_patch(f, sym->secidx, loc - contents, str); -- loc += tgt_sizeof_char_p; -- } else { -- /* Array of chars (in fact, matrix!) */ -- unsigned long charssize; /* size of each member */ -- -- /* Get the size of each member */ -- /* Probably we should do that outside the loop ? */ -- if (!isdigit(*(p + 1))) { -- bb_error_msg_and_die("parameter type 'c' for %s must be followed by" -- " the maximum size", key); -- } -- charssize = strtoul(p + 1, (char **) NULL, 10); -- -- /* Check length */ -- if (strlen(str) >= charssize) { -- bb_error_msg_and_die("string too long for %s (max %ld)", key, -- charssize - 1); -- } -- -- /* Copy to location */ -- strcpy((char *) loc, str); -- loc += charssize; -- } -- } else { -- long v = strtoul(q, &q, 0); -- switch (*p) { -- case 'b': -- *loc++ = v; -- break; -- case 'h': -- *(short *) loc = v; -- loc += tgt_sizeof_short; -- break; -- case 'i': -- *(int *) loc = v; -- loc += tgt_sizeof_int; -- break; -- case 'l': -- *(long *) loc = v; -- loc += tgt_sizeof_long; -- break; -- -- default: -- bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key); -- } -- } -- retry_end_of_value: -- switch (*q) { -- case '\0': -- goto end_of_arg; -- -- case ' ': -- case '\t': -- case '\n': -- case '\r': -- ++q; -- goto retry_end_of_value; -- -- case ',': -- if (++n > max) { -- bb_error_msg_and_die("too many values for %s (max %d)", key, max); -- } -- ++q; -- break; -- -- default: -- bb_error_msg_and_die("invalid argument syntax for %s", key); -- } -- } -- end_of_arg: -- if (n < min) { -- bb_error_msg_and_die("too few values for %s (min %d)", key, min); -- } -- -- argc--; -- argv++; -- } --} -- --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING --static int new_is_module_checksummed(struct obj_file *f) --{ -- const char *p = get_modinfo_value(f, "using_checksums"); -- if (p) -- return xatoi(p); -- return 0; --} -- --/* Get the module's kernel version in the canonical integer form. */ -- --static int --new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) --{ -- char *p, *q; -- int a, b, c; -- -- p = get_modinfo_value(f, "kernel_version"); -- if (p == NULL) -- return -1; -- safe_strncpy(str, p, STRVERSIONLEN); -- -- a = strtoul(p, &p, 10); -- if (*p != '.') -- return -1; -- b = strtoul(p + 1, &p, 10); -- if (*p != '.') -- return -1; -- c = strtoul(p + 1, &q, 10); -- if (p + 1 == q) -- return -1; -- -- return a << 16 | b << 8 | c; --} -- --#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -- -- --/* Fetch the loaded modules, and all currently exported symbols. */ -- --static void new_get_kernel_symbols(void) --{ -- char *module_names, *mn; -- struct external_module *modules, *m; -- struct new_module_symbol *syms, *s; -- size_t ret, bufsize, nmod, nsyms, i, j; -- -- /* Collect the loaded modules. */ -- -- bufsize = 256; -- module_names = xmalloc(bufsize); -- -- retry_modules_load: -- if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { -- if (errno == ENOSPC && bufsize < ret) { -- bufsize = ret; -- module_names = xrealloc(module_names, bufsize); -- goto retry_modules_load; -- } -- bb_perror_msg_and_die("QM_MODULES"); -- } -- -- n_ext_modules = nmod = ret; -- -- /* Collect the modules' symbols. */ -- -- if (nmod) { -- ext_modules = modules = xzalloc(nmod * sizeof(*modules)); -- for (i = 0, mn = module_names, m = modules; -- i < nmod; ++i, ++m, mn += strlen(mn) + 1) { -- struct new_module_info info; -- -- if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) { -- if (errno == ENOENT) { -- /* The module was removed out from underneath us. */ -- continue; -- } -- bb_perror_msg_and_die("query_module: QM_INFO: %s", mn); -- } -- -- bufsize = 1024; -- syms = xmalloc(bufsize); -- retry_mod_sym_load: -- if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { -- switch (errno) { -- case ENOSPC: -- bufsize = ret; -- syms = xrealloc(syms, bufsize); -- goto retry_mod_sym_load; -- case ENOENT: -- /* The module was removed out from underneath us. */ -- continue; -- default: -- bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn); -- } -- } -- nsyms = ret; -- -- m->name = mn; -- m->addr = info.addr; -- m->nsyms = nsyms; -- m->syms = syms; -- -- for (j = 0, s = syms; j < nsyms; ++j, ++s) { -- s->name += (unsigned long) syms; -- } -- } -- } -- -- /* Collect the kernel's symbols. */ -- -- syms = xmalloc(bufsize = 16 * 1024); -- retry_kern_sym_load: -- if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { -- if (errno == ENOSPC && bufsize < ret) { -- bufsize = ret; -- syms = xrealloc(syms, bufsize); -- goto retry_kern_sym_load; -- } -- bb_perror_msg_and_die("kernel: QM_SYMBOLS"); -- } -- nksyms = nsyms = ret; -- ksyms = syms; -- -- for (j = 0, s = syms; j < nsyms; ++j, ++s) { -- s->name += (unsigned long) syms; -- } --} -- -- --/* Return the kernel symbol checksum version, or zero if not used. */ -- --static int new_is_kernel_checksummed(void) --{ -- struct new_module_symbol *s; -- size_t i; -- -- /* Using_Versions is not the first symbol, but it should be in there. */ -- -- for (i = 0, s = ksyms; i < nksyms; ++i, ++s) -- if (strcmp((char *) s->name, "Using_Versions") == 0) -- return s->value; -- -- return 0; --} -- -- --static void new_create_this_module(struct obj_file *f, const char *m_name) --{ -- struct obj_section *sec; -- -- sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long, -- sizeof(struct new_module)); -- /* done by obj_create_alloced_section_first: */ -- /*memset(sec->contents, 0, sizeof(struct new_module));*/ -- -- obj_add_symbol(f, SPFX "__this_module", -1, -- ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0, -- sizeof(struct new_module)); -- -- obj_string_patch(f, sec->idx, offsetof(struct new_module, name), -- m_name); --} -- --#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS --/* add an entry to the __ksymtab section, creating it if necessary */ --static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym) --{ -- struct obj_section *sec; -- ElfW(Addr) ofs; -- -- /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section. -- * If __ksymtab is defined but not marked alloc, x out the first character -- * (no obj_delete routine) and create a new __ksymtab with the correct -- * characteristics. -- */ -- sec = obj_find_section(f, "__ksymtab"); -- if (sec && !(sec->header.sh_flags & SHF_ALLOC)) { -- *((char *)(sec->name)) = 'x'; /* override const */ -- sec = NULL; -- } -- if (!sec) -- sec = obj_create_alloced_section(f, "__ksymtab", -- tgt_sizeof_void_p, 0); -- if (!sec) -- return; -- sec->header.sh_flags |= SHF_ALLOC; -- /* Empty section might be byte-aligned */ -- sec->header.sh_addralign = tgt_sizeof_void_p; -- ofs = sec->header.sh_size; -- obj_symbol_patch(f, sec->idx, ofs, sym); -- obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name); -- obj_extend_section(sec, 2 * tgt_sizeof_char_p); --} --#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -- --static int new_create_module_ksymtab(struct obj_file *f) --{ -- struct obj_section *sec; -- int i; -- -- /* We must always add the module references. */ -- -- if (n_ext_modules_used) { -- struct new_module_ref *dep; -- struct obj_symbol *tm; -- -- sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p, -- (sizeof(struct new_module_ref) -- * n_ext_modules_used)); -- if (!sec) -- return 0; -- -- tm = obj_find_symbol(f, SPFX "__this_module"); -- dep = (struct new_module_ref *) sec->contents; -- for (i = 0; i < n_ext_modules; ++i) -- if (ext_modules[i].used) { -- dep->dep = ext_modules[i].addr; -- obj_symbol_patch(f, sec->idx, -- (char *) &dep->ref - sec->contents, tm); -- dep->next_ref = 0; -- ++dep; -- } -- } -- -- if (!flag_noexport && !obj_find_section(f, "__ksymtab")) { -- size_t nsyms; -- int *loaded; -- -- sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0); -- -- /* We don't want to export symbols residing in sections that -- aren't loaded. There are a number of these created so that -- we make sure certain module options don't appear twice. */ -- i = f->header.e_shnum; -- loaded = alloca(sizeof(int) * i); -- while (--i >= 0) -- loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; -- -- for (nsyms = i = 0; i < HASH_BUCKETS; ++i) { -- struct obj_symbol *sym; -- for (sym = f->symtab[i]; sym; sym = sym->next) { -- if (ELF_ST_BIND(sym->info) != STB_LOCAL -- && sym->secidx <= SHN_HIRESERVE -- && (sym->secidx >= SHN_LORESERVE -- || loaded[sym->secidx]) -- ) { -- ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p; -- -- obj_symbol_patch(f, sec->idx, ofs, sym); -- obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, -- sym->name); -- -- nsyms++; -- } -- } -- } -- -- obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p); -- } -- -- return 1; --} -- -- --static int --new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) --{ -- struct new_module *module; -- struct obj_section *sec; -- void *image; -- int ret; -- tgt_long m_addr; -- -- sec = obj_find_section(f, ".this"); -- if (!sec || !sec->contents) { -- bb_perror_msg_and_die("corrupt module %s?", m_name); -- } -- module = (struct new_module *) sec->contents; -- m_addr = sec->header.sh_addr; -- -- module->size_of_struct = sizeof(*module); -- module->size = m_size; -- module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0; -- -- sec = obj_find_section(f, "__ksymtab"); -- if (sec && sec->header.sh_size) { -- module->syms = sec->header.sh_addr; -- module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p); -- } -- -- if (n_ext_modules_used) { -- sec = obj_find_section(f, ".kmodtab"); -- module->deps = sec->header.sh_addr; -- module->ndeps = n_ext_modules_used; -- } -- -- module->init = -- obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module")); -- module->cleanup = -- obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module")); -- -- sec = obj_find_section(f, "__ex_table"); -- if (sec) { -- module->ex_table_start = sec->header.sh_addr; -- module->ex_table_end = sec->header.sh_addr + sec->header.sh_size; -- } -- -- sec = obj_find_section(f, ".text.init"); -- if (sec) { -- module->runsize = sec->header.sh_addr - m_addr; -- } -- sec = obj_find_section(f, ".data.init"); -- if (sec) { -- if (!module->runsize -- || module->runsize > sec->header.sh_addr - m_addr -- ) { -- module->runsize = sec->header.sh_addr - m_addr; -- } -- } -- sec = obj_find_section(f, ARCHDATA_SEC_NAME); -- if (sec && sec->header.sh_size) { -- module->archdata_start = (void*)sec->header.sh_addr; -- module->archdata_end = module->archdata_start + sec->header.sh_size; -- } -- sec = obj_find_section(f, KALLSYMS_SEC_NAME); -- if (sec && sec->header.sh_size) { -- module->kallsyms_start = (void*)sec->header.sh_addr; -- module->kallsyms_end = module->kallsyms_start + sec->header.sh_size; -- } -- -- /* Whew! All of the initialization is complete. Collect the final -- module image and give it to the kernel. */ -- -- image = xmalloc(m_size); -- obj_create_image(f, image); -- -- ret = init_module(m_name, (struct new_module *) image); -- if (ret) -- bb_perror_msg("init_module: %s", m_name); -- -- free(image); -- -- return ret == 0; --} -- -- --/*======================================================================*/ -- --static void --obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -- const char *string) --{ -- struct obj_string_patch *p; -- struct obj_section *strsec; -- size_t len = strlen(string) + 1; -- char *loc; -- -- p = xmalloc(sizeof(*p)); -- p->next = f->string_patches; -- p->reloc_secidx = secidx; -- p->reloc_offset = offset; -- f->string_patches = p; -- -- strsec = obj_find_section(f, ".kstrtab"); -- if (strsec == NULL) { -- strsec = obj_create_alloced_section(f, ".kstrtab", 1, len); -- p->string_offset = 0; -- loc = strsec->contents; -- } else { -- p->string_offset = strsec->header.sh_size; -- loc = obj_extend_section(strsec, len); -- } -- memcpy(loc, string, len); --} -- --static void --obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, -- struct obj_symbol *sym) --{ -- struct obj_symbol_patch *p; -- -- p = xmalloc(sizeof(*p)); -- p->next = f->symbol_patches; -- p->reloc_secidx = secidx; -- p->reloc_offset = offset; -- p->sym = sym; -- f->symbol_patches = p; --} -- --static void obj_check_undefineds(struct obj_file *f) --{ -- unsigned i; -- -- for (i = 0; i < HASH_BUCKETS; ++i) { -- struct obj_symbol *sym; -- for (sym = f->symtab[i]; sym; sym = sym->next) -- if (sym->secidx == SHN_UNDEF) { -- if (ELF_ST_BIND(sym->info) == STB_WEAK) { -- sym->secidx = SHN_ABS; -- sym->value = 0; -- } else { -- if (!flag_quiet) -- bb_error_msg_and_die("unresolved symbol %s", sym->name); -- } -- } -- } --} -- --static void obj_allocate_commons(struct obj_file *f) --{ -- struct common_entry { -- struct common_entry *next; -- struct obj_symbol *sym; -- } *common_head = NULL; -- -- unsigned long i; -- -- for (i = 0; i < HASH_BUCKETS; ++i) { -- struct obj_symbol *sym; -- for (sym = f->symtab[i]; sym; sym = sym->next) -- if (sym->secidx == SHN_COMMON) { -- /* Collect all COMMON symbols and sort them by size so as to -- minimize space wasted by alignment requirements. */ -- { -- struct common_entry **p, *n; -- for (p = &common_head; *p; p = &(*p)->next) -- if (sym->size <= (*p)->sym->size) -- break; -- -- n = alloca(sizeof(*n)); -- n->next = *p; -- n->sym = sym; -- *p = n; -- } -- } -- } -- -- for (i = 1; i < f->local_symtab_size; ++i) { -- struct obj_symbol *sym = f->local_symtab[i]; -- if (sym && sym->secidx == SHN_COMMON) { -- struct common_entry **p, *n; -- for (p = &common_head; *p; p = &(*p)->next) -- if (sym == (*p)->sym) -- break; -- else if (sym->size < (*p)->sym->size) { -- n = alloca(sizeof(*n)); -- n->next = *p; -- n->sym = sym; -- *p = n; -- break; -- } -- } -- } -- -- if (common_head) { -- /* Find the bss section. */ -- for (i = 0; i < f->header.e_shnum; ++i) -- if (f->sections[i]->header.sh_type == SHT_NOBITS) -- break; -- -- /* If for some reason there hadn't been one, create one. */ -- if (i == f->header.e_shnum) { -- struct obj_section *sec; -- -- f->header.e_shnum++; -- f->sections = xrealloc_vector(f->sections, 2, i); -- f->sections[i] = sec = arch_new_section(); -- -- sec->header.sh_type = SHT_PROGBITS; -- sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; -- sec->name = ".bss"; -- sec->idx = i; -- } -- -- /* Allocate the COMMONS. */ -- { -- ElfW(Addr) bss_size = f->sections[i]->header.sh_size; -- ElfW(Addr) max_align = f->sections[i]->header.sh_addralign; -- struct common_entry *c; -- -- for (c = common_head; c; c = c->next) { -- ElfW(Addr) align = c->sym->value; -- -- if (align > max_align) -- max_align = align; -- if (bss_size & (align - 1)) -- bss_size = (bss_size | (align - 1)) + 1; -- -- c->sym->secidx = i; -- c->sym->value = bss_size; -- -- bss_size += c->sym->size; -- } -- -- f->sections[i]->header.sh_size = bss_size; -- f->sections[i]->header.sh_addralign = max_align; -- } -- } -- -- /* For the sake of patch relocation and parameter initialization, -- allocate zeroed data for NOBITS sections now. Note that after -- this we cannot assume NOBITS are really empty. */ -- for (i = 0; i < f->header.e_shnum; ++i) { -- struct obj_section *s = f->sections[i]; -- if (s->header.sh_type == SHT_NOBITS) { -- s->contents = NULL; -- if (s->header.sh_size != 0) -- s->contents = xzalloc(s->header.sh_size), -- s->header.sh_type = SHT_PROGBITS; -- } -- } --} -- --static unsigned long obj_load_size(struct obj_file *f) --{ -- unsigned long dot = 0; -- struct obj_section *sec; -- -- /* Finalize the positions of the sections relative to one another. */ -- -- for (sec = f->load_order; sec; sec = sec->load_next) { -- ElfW(Addr) align; -- -- align = sec->header.sh_addralign; -- if (align && (dot & (align - 1))) -- dot = (dot | (align - 1)) + 1; -- -- sec->header.sh_addr = dot; -- dot += sec->header.sh_size; -- } -- -- return dot; --} -- --static int obj_relocate(struct obj_file *f, ElfW(Addr) base) --{ -- int i, n = f->header.e_shnum; -- int ret = 1; -- -- /* Finalize the addresses of the sections. */ -- -- f->baseaddr = base; -- for (i = 0; i < n; ++i) -- f->sections[i]->header.sh_addr += base; -- -- /* And iterate over all of the relocations. */ -- -- for (i = 0; i < n; ++i) { -- struct obj_section *relsec, *symsec, *targsec, *strsec; -- ElfW(RelM) * rel, *relend; -- ElfW(Sym) * symtab; -- const char *strtab; -- -- relsec = f->sections[i]; -- if (relsec->header.sh_type != SHT_RELM) -- continue; -- -- symsec = f->sections[relsec->header.sh_link]; -- targsec = f->sections[relsec->header.sh_info]; -- strsec = f->sections[symsec->header.sh_link]; -- -- rel = (ElfW(RelM) *) relsec->contents; -- relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); -- symtab = (ElfW(Sym) *) symsec->contents; -- strtab = (const char *) strsec->contents; -- -- for (; rel < relend; ++rel) { -- ElfW(Addr) value = 0; -- struct obj_symbol *intsym = NULL; -- unsigned long symndx; -- ElfW(Sym) * extsym = 0; -- const char *errmsg; -- -- /* Attempt to find a value to use for this relocation. */ -- -- symndx = ELF_R_SYM(rel->r_info); -- if (symndx) { -- /* Note we've already checked for undefined symbols. */ -- -- extsym = &symtab[symndx]; -- if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) { -- /* Local symbols we look up in the local table to be sure -- we get the one that is really intended. */ -- intsym = f->local_symtab[symndx]; -- } else { -- /* Others we look up in the hash table. */ -- const char *name; -- if (extsym->st_name) -- name = strtab + extsym->st_name; -- else -- name = f->sections[extsym->st_shndx]->name; -- intsym = obj_find_symbol(f, name); -- } -- -- value = obj_symbol_final_value(f, intsym); -- intsym->referenced = 1; -- } --#if SHT_RELM == SHT_RELA --#if defined(__alpha__) && defined(AXP_BROKEN_GAS) -- /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */ -- if (!extsym || !extsym->st_name -- || ELF_ST_BIND(extsym->st_info) != STB_LOCAL) --#endif -- value += rel->r_addend; --#endif -- -- /* Do it! */ -- switch (arch_apply_relocation -- (f, targsec, /*symsec,*/ intsym, rel, value) -- ) { -- case obj_reloc_ok: -- break; -- -- case obj_reloc_overflow: -- errmsg = "Relocation overflow"; -- goto bad_reloc; -- case obj_reloc_dangerous: -- errmsg = "Dangerous relocation"; -- goto bad_reloc; -- case obj_reloc_unhandled: -- errmsg = "Unhandled relocation"; --bad_reloc: -- if (extsym) { -- bb_error_msg("%s of type %ld for %s", errmsg, -- (long) ELF_R_TYPE(rel->r_info), -- strtab + extsym->st_name); -- } else { -- bb_error_msg("%s of type %ld", errmsg, -- (long) ELF_R_TYPE(rel->r_info)); -- } -- ret = 0; -- break; -- } -- } -- } -- -- /* Finally, take care of the patches. */ -- -- if (f->string_patches) { -- struct obj_string_patch *p; -- struct obj_section *strsec; -- ElfW(Addr) strsec_base; -- strsec = obj_find_section(f, ".kstrtab"); -- strsec_base = strsec->header.sh_addr; -- -- for (p = f->string_patches; p; p = p->next) { -- struct obj_section *targsec = f->sections[p->reloc_secidx]; -- *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) -- = strsec_base + p->string_offset; -- } -- } -- -- if (f->symbol_patches) { -- struct obj_symbol_patch *p; -- -- for (p = f->symbol_patches; p; p = p->next) { -- struct obj_section *targsec = f->sections[p->reloc_secidx]; -- *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) -- = obj_symbol_final_value(f, p->sym); -- } -- } -- -- return ret; --} -- --static int obj_create_image(struct obj_file *f, char *image) --{ -- struct obj_section *sec; -- ElfW(Addr) base = f->baseaddr; -- -- for (sec = f->load_order; sec; sec = sec->load_next) { -- char *secimg; -- -- if (sec->contents == 0 || sec->header.sh_size == 0) -- continue; -- -- secimg = image + (sec->header.sh_addr - base); -- -- /* Note that we allocated data for NOBITS sections earlier. */ -- memcpy(secimg, sec->contents, sec->header.sh_size); -- } -- -- return 1; --} -- --/*======================================================================*/ -- --static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM) --{ -- struct obj_file *f; -- ElfW(Shdr) * section_headers; -- size_t shnum, i; -- char *shstrtab; -- -- /* Read the file header. */ -- -- f = arch_new_file(); -- f->symbol_cmp = strcmp; -- f->symbol_hash = obj_elf_hash; -- f->load_order_search_start = &f->load_order; -- -- fseek(fp, 0, SEEK_SET); -- if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { -- bb_perror_msg_and_die("error reading ELF header"); -- } -- -- if (f->header.e_ident[EI_MAG0] != ELFMAG0 -- || f->header.e_ident[EI_MAG1] != ELFMAG1 -- || f->header.e_ident[EI_MAG2] != ELFMAG2 -- || f->header.e_ident[EI_MAG3] != ELFMAG3 -- ) { -- bb_error_msg_and_die("not an ELF file"); -- } -- if (f->header.e_ident[EI_CLASS] != ELFCLASSM -- || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB) -- || f->header.e_ident[EI_VERSION] != EV_CURRENT -- || !MATCH_MACHINE(f->header.e_machine) -- ) { -- bb_error_msg_and_die("ELF file not for this architecture"); -- } -- if (f->header.e_type != ET_REL) { -- bb_error_msg_and_die("ELF file not a relocatable object"); -- } -- -- /* Read the section headers. */ -- -- if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { -- bb_error_msg_and_die("section header size mismatch: %lu != %lu", -- (unsigned long) f->header.e_shentsize, -- (unsigned long) sizeof(ElfW(Shdr))); -- } -- -- shnum = f->header.e_shnum; -- /* Growth of ->sections vector will be done by -- * xrealloc_vector(..., 2, ...), therefore we must allocate -- * at least 2^2 = 4 extra elements here. */ -- f->sections = xzalloc(sizeof(f->sections[0]) * (shnum + 4)); -- -- section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); -- fseek(fp, f->header.e_shoff, SEEK_SET); -- if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { -- bb_perror_msg_and_die("error reading ELF section headers"); -- } -- -- /* Read the section data. */ -- -- for (i = 0; i < shnum; ++i) { -- struct obj_section *sec; -- -- f->sections[i] = sec = arch_new_section(); -- -- sec->header = section_headers[i]; -- sec->idx = i; -- -- if (sec->header.sh_size) { -- switch (sec->header.sh_type) { -- case SHT_NULL: -- case SHT_NOTE: -- case SHT_NOBITS: -- /* ignore */ -- break; -- -- case SHT_PROGBITS: --#if LOADBITS -- if (!loadprogbits) { -- sec->contents = NULL; -- break; -- } --#endif -- case SHT_SYMTAB: -- case SHT_STRTAB: -- case SHT_RELM: -- sec->contents = NULL; -- if (sec->header.sh_size > 0) { -- sec->contents = xzalloc(sec->header.sh_size); -- fseek(fp, sec->header.sh_offset, SEEK_SET); -- if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { -- bb_perror_msg_and_die("error reading ELF section data"); -- } -- } -- break; -- --#if SHT_RELM == SHT_REL -- case SHT_RELA: -- bb_error_msg_and_die("RELA relocations not supported on this architecture"); --#else -- case SHT_REL: -- bb_error_msg_and_die("REL relocations not supported on this architecture"); --#endif -- default: -- if (sec->header.sh_type >= SHT_LOPROC) { -- /* Assume processor specific section types are debug -- info and can safely be ignored. If this is ever not -- the case (Hello MIPS?), don't put ifdefs here but -- create an arch_load_proc_section(). */ -- break; -- } -- -- bb_error_msg_and_die("can't handle sections of type %ld", -- (long) sec->header.sh_type); -- } -- } -- } -- -- /* Do what sort of interpretation as needed by each section. */ -- -- shstrtab = f->sections[f->header.e_shstrndx]->contents; -- -- for (i = 0; i < shnum; ++i) { -- struct obj_section *sec = f->sections[i]; -- sec->name = shstrtab + sec->header.sh_name; -- } -- -- for (i = 0; i < shnum; ++i) { -- struct obj_section *sec = f->sections[i]; -- -- /* .modinfo should be contents only but gcc has no attribute for that. -- * The kernel may have marked .modinfo as ALLOC, ignore this bit. -- */ -- if (strcmp(sec->name, ".modinfo") == 0) -- sec->header.sh_flags &= ~SHF_ALLOC; -- -- if (sec->header.sh_flags & SHF_ALLOC) -- obj_insert_section_load_order(f, sec); -- -- switch (sec->header.sh_type) { -- case SHT_SYMTAB: -- { -- unsigned long nsym, j; -- char *strtab; -- ElfW(Sym) * sym; -- -- if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { -- bb_error_msg_and_die("symbol size mismatch: %lu != %lu", -- (unsigned long) sec->header.sh_entsize, -- (unsigned long) sizeof(ElfW(Sym))); -- } -- -- nsym = sec->header.sh_size / sizeof(ElfW(Sym)); -- strtab = f->sections[sec->header.sh_link]->contents; -- sym = (ElfW(Sym) *) sec->contents; -- -- /* Allocate space for a table of local symbols. */ -- j = f->local_symtab_size = sec->header.sh_info; -- f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *)); -- -- /* Insert all symbols into the hash table. */ -- for (j = 1, ++sym; j < nsym; ++j, ++sym) { -- ElfW(Addr) val = sym->st_value; -- const char *name; -- if (sym->st_name) -- name = strtab + sym->st_name; -- else if (sym->st_shndx < shnum) -- name = f->sections[sym->st_shndx]->name; -- else -- continue; --#if defined(__SH5__) -- /* -- * For sh64 it is possible that the target of a branch -- * requires a mode switch (32 to 16 and back again). -- * -- * This is implied by the lsb being set in the target -- * address for SHmedia mode and clear for SHcompact. -- */ -- val |= sym->st_other & 4; --#endif -- obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, -- val, sym->st_size); -- } -- } -- break; -- -- case SHT_RELM: -- if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { -- bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu", -- (unsigned long) sec->header.sh_entsize, -- (unsigned long) sizeof(ElfW(RelM))); -- } -- break; -- /* XXX Relocation code from modutils-2.3.19 is not here. -- * Why? That's about 20 lines of code from obj/obj_load.c, -- * which gets done in a second pass through the sections. -- * This BusyBox insmod does similar work in obj_relocate(). */ -- } -- } -- -- return f; --} -- --#if ENABLE_FEATURE_INSMOD_LOADINKMEM --/* -- * load the unloaded sections directly into the memory allocated by -- * kernel for the module -- */ -- --static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase) --{ -- ElfW(Addr) base = f->baseaddr; -- struct obj_section* sec; -- -- for (sec = f->load_order; sec; sec = sec->load_next) { -- -- /* section already loaded? */ -- if (sec->contents != NULL) -- continue; -- -- if (sec->header.sh_size == 0) -- continue; -- -- sec->contents = imagebase + (sec->header.sh_addr - base); -- fseek(fp, sec->header.sh_offset, SEEK_SET); -- if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { -- bb_perror_msg("error reading ELF section data"); -- return 0; -- } -- -- } -- return 1; --} --#endif -- --static void hide_special_symbols(struct obj_file *f) --{ -- static const char *const specials[] = { -- SPFX "cleanup_module", -- SPFX "init_module", -- SPFX "kernel_version", -- NULL -- }; -- -- struct obj_symbol *sym; -- const char *const *p; -- -- for (p = specials; *p; ++p) { -- sym = obj_find_symbol(f, *p); -- if (sym != NULL) -- sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info)); -- } --} -- -- --#if ENABLE_FEATURE_CHECK_TAINTED_MODULE --static int obj_gpl_license(struct obj_file *f, const char **license) --{ -- struct obj_section *sec; -- /* This list must match *exactly* the list of allowable licenses in -- * linux/include/linux/module.h. Checking for leading "GPL" will not -- * work, somebody will use "GPL sucks, this is proprietary". -- */ -- static const char *const gpl_licenses[] = { -- "GPL", -- "GPL v2", -- "GPL and additional rights", -- "Dual BSD/GPL", -- "Dual MPL/GPL" -- }; -- -- sec = obj_find_section(f, ".modinfo"); -- if (sec) { -- const char *value, *ptr, *endptr; -- ptr = sec->contents; -- endptr = ptr + sec->header.sh_size; -- while (ptr < endptr) { -- value = strchr(ptr, '='); -- if (value && strncmp(ptr, "license", value-ptr) == 0) { -- unsigned i; -- if (license) -- *license = value+1; -- for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) { -- if (strcmp(value+1, gpl_licenses[i]) == 0) -- return 0; -- } -- return 2; -- } -- ptr = strchr(ptr, '\0'); -- if (ptr) -- ptr++; -- else -- ptr = endptr; -- } -- } -- return 1; --} -- --#define TAINT_FILENAME "/proc/sys/kernel/tainted" --#define TAINT_PROPRIETORY_MODULE (1 << 0) --#define TAINT_FORCED_MODULE (1 << 1) --#define TAINT_UNSAFE_SMP (1 << 2) --#define TAINT_URL "http://www.tux.org/lkml/#export-tainted" -- --static void set_tainted(int fd, char *m_name, -- int kernel_has_tainted, int taint, const char *text1, const char *text2) --{ -- static smallint printed_info; -- -- char buf[80]; -- int oldval; -- -- if (fd < 0 && !kernel_has_tainted) -- return; /* New modutils on old kernel */ -- printf("Warning: loading %s will taint the kernel: %s%s\n", -- m_name, text1, text2); -- if (!printed_info) { -- printf(" See %s for information about tainted modules\n", TAINT_URL); -- printed_info = 1; -- } -- if (fd >= 0) { -- read(fd, buf, sizeof(buf)-1); -- buf[sizeof(buf)-1] = '\0'; -- oldval = strtoul(buf, NULL, 10); -- sprintf(buf, "%d\n", oldval | taint); -- write(fd, buf, strlen(buf)); -- } --} -- --/* Check if loading this module will taint the kernel. */ --static void check_tainted_module(struct obj_file *f, char *m_name) --{ -- static const char tainted_file[] ALIGN1 = TAINT_FILENAME; -- -- int fd, kernel_has_tainted; -- const char *ptr; -- -- kernel_has_tainted = 1; -- fd = open(tainted_file, O_RDWR); -- if (fd < 0) { -- if (errno == ENOENT) -- kernel_has_tainted = 0; -- else if (errno == EACCES) -- kernel_has_tainted = 1; -- else { -- perror(tainted_file); -- kernel_has_tainted = 0; -- } -- } -- -- switch (obj_gpl_license(f, &ptr)) { -- case 0: -- break; -- case 1: -- set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); -- break; -- case 2: -- /* The module has a non-GPL license so we pretend that the -- * kernel always has a taint flag to get a warning even on -- * kernels without the proc flag. -- */ -- set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); -- break; -- default: -- set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); -- break; -- } -- -- if (flag_force_load) -- set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); -- -- if (fd >= 0) -- close(fd); --} --#else /* FEATURE_CHECK_TAINTED_MODULE */ --#define check_tainted_module(x, y) do { } while (0); --#endif /* FEATURE_CHECK_TAINTED_MODULE */ -- --#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS --/* add module source, timestamp, kernel version and a symbol for the -- * start of some sections. this info is used by ksymoops to do better -- * debugging. -- */ --#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING --#define get_module_version(f, str) get_module_version(str) --#endif --static int --get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) --{ --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -- return new_get_module_version(f, str); --#else /* FEATURE_INSMOD_VERSION_CHECKING */ -- strncpy(str, "???", sizeof(str)); -- return -1; --#endif /* FEATURE_INSMOD_VERSION_CHECKING */ --} -- --/* add module source, timestamp, kernel version and a symbol for the -- * start of some sections. this info is used by ksymoops to do better -- * debugging. -- */ --static void --add_ksymoops_symbols(struct obj_file *f, const char *filename, -- const char *m_name) --{ -- static const char symprefix[] ALIGN1 = "__insmod_"; -- static const char section_names[][8] = { -- ".text", -- ".rodata", -- ".data", -- ".bss", -- ".sbss" -- }; -- -- struct obj_section *sec; -- struct obj_symbol *sym; -- char *name, *absolute_filename; -- char str[STRVERSIONLEN]; -- unsigned i; -- int l, lm_name, lfilename, use_ksymtab, version; -- struct stat statbuf; -- -- /* WARNING: was using realpath, but replaced by readlink to stop using -- * lots of stack. But here it seems to be able to cause problems? */ -- absolute_filename = xmalloc_readlink(filename); -- if (!absolute_filename) -- absolute_filename = xstrdup(filename); -- -- lm_name = strlen(m_name); -- lfilename = strlen(absolute_filename); -- -- /* add to ksymtab if it already exists or there is no ksymtab and other symbols -- * are not to be exported. otherwise leave ksymtab alone for now, the -- * "export all symbols" compatibility code will export these symbols later. -- */ -- use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport; -- -- sec = obj_find_section(f, ".this"); -- if (sec) { -- /* tag the module header with the object name, last modified -- * timestamp and module version. worst case for module version -- * is 0xffffff, decimal 16777215. putting all three fields in -- * one symbol is less readable but saves kernel space. -- */ -- l = sizeof(symprefix) + /* "__insmod_" */ -- lm_name + /* module name */ -- 2 + /* "_O" */ -- lfilename + /* object filename */ -- 2 + /* "_M" */ -- 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */ -- 2 + /* "_V" */ -- 8 + /* version in dec */ -- 1; /* nul */ -- name = xmalloc(l); -- if (stat(absolute_filename, &statbuf) != 0) -- statbuf.st_mtime = 0; -- version = get_module_version(f, str); /* -1 if not found */ -- snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", -- symprefix, m_name, absolute_filename, -- (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime, -- version); -- sym = obj_add_symbol(f, name, -1, -- ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -- sec->idx, sec->header.sh_addr, 0); -- if (use_ksymtab) -- new_add_ksymtab(f, sym); -- } -- free(absolute_filename); --#ifdef _NOT_SUPPORTED_ -- /* record where the persistent data is going, same address as previous symbol */ -- -- if (f->persist) { -- l = sizeof(symprefix) + /* "__insmod_" */ -- lm_name + /* module name */ -- 2 + /* "_P" */ -- strlen(f->persist) + /* data store */ -- 1; /* nul */ -- name = xmalloc(l); -- snprintf(name, l, "%s%s_P%s", -- symprefix, m_name, f->persist); -- sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -- sec->idx, sec->header.sh_addr, 0); -- if (use_ksymtab) -- new_add_ksymtab(f, sym); -- } --#endif /* _NOT_SUPPORTED_ */ -- /* tag the desired sections if size is non-zero */ -- -- for (i = 0; i < ARRAY_SIZE(section_names); ++i) { -- sec = obj_find_section(f, section_names[i]); -- if (sec && sec->header.sh_size) { -- l = sizeof(symprefix) + /* "__insmod_" */ -- lm_name + /* module name */ -- 2 + /* "_S" */ -- strlen(sec->name) + /* section name */ -- 2 + /* "_L" */ -- 8 + /* length in dec */ -- 1; /* nul */ -- name = xmalloc(l); -- snprintf(name, l, "%s%s_S%s_L%ld", -- symprefix, m_name, sec->name, -- (long)sec->header.sh_size); -- sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), -- sec->idx, sec->header.sh_addr, 0); -- if (use_ksymtab) -- new_add_ksymtab(f, sym); -- } -- } --} --#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -- --#if ENABLE_FEATURE_INSMOD_LOAD_MAP --static void print_load_map(struct obj_file *f) --{ -- struct obj_section *sec; --#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL -- struct obj_symbol **all, **p; -- int i, nsyms, *loaded; -- struct obj_symbol *sym; --#endif -- /* Report on the section layout. */ -- -- printf("Sections: Size %-*s Align\n", -- (int) (2 * sizeof(void *)), "Address"); -- -- for (sec = f->load_order; sec; sec = sec->load_next) { -- int a; -- unsigned long tmp; -- -- for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a) -- tmp >>= 1; -- if (a == -1) -- a = 0; -- -- printf("%-15s %08lx %0*lx 2**%d\n", -- sec->name, -- (long)sec->header.sh_size, -- (int) (2 * sizeof(void *)), -- (long)sec->header.sh_addr, -- a); -- } --#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL -- /* Quick reference which section indices are loaded. */ -- -- i = f->header.e_shnum; -- loaded = alloca(sizeof(int) * i); -- while (--i >= 0) -- loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0); -- -- /* Collect the symbols we'll be listing. */ -- -- for (nsyms = i = 0; i < HASH_BUCKETS; ++i) -- for (sym = f->symtab[i]; sym; sym = sym->next) -- if (sym->secidx <= SHN_HIRESERVE -- && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]) -- ) { -- ++nsyms; -- } -- -- all = alloca(nsyms * sizeof(struct obj_symbol *)); -- -- for (i = 0, p = all; i < HASH_BUCKETS; ++i) -- for (sym = f->symtab[i]; sym; sym = sym->next) -- if (sym->secidx <= SHN_HIRESERVE -- && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]) -- ) { -- *p++ = sym; -- } -- -- /* And list them. */ -- printf("\nSymbols:\n"); -- for (p = all; p < all + nsyms; ++p) { -- char type = '?'; -- unsigned long value; -- -- sym = *p; -- if (sym->secidx == SHN_ABS) { -- type = 'A'; -- value = sym->value; -- } else if (sym->secidx == SHN_UNDEF) { -- type = 'U'; -- value = 0; -- } else { -- sec = f->sections[sym->secidx]; -- -- if (sec->header.sh_type == SHT_NOBITS) -- type = 'B'; -- else if (sec->header.sh_flags & SHF_ALLOC) { -- if (sec->header.sh_flags & SHF_EXECINSTR) -- type = 'T'; -- else if (sec->header.sh_flags & SHF_WRITE) -- type = 'D'; -- else -- type = 'R'; -- } -- value = sym->value + sec->header.sh_addr; -- } -- -- if (ELF_ST_BIND(sym->info) == STB_LOCAL) -- type = tolower(type); -- -- printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value, -- type, sym->name); -- } --#endif --} --#else /* !FEATURE_INSMOD_LOAD_MAP */ --void print_load_map(struct obj_file *f); --#endif -- - int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; --int insmod_main(int argc, char **argv) --{ -- char *opt_o, *arg1; -- int len; -- int k_crcs; -- char *tmp, *tmp1; -- unsigned long m_size; -- ElfW(Addr) m_addr; -- struct obj_file *f; -- struct stat st; -- char *m_name = NULL; -- int exit_status = EXIT_FAILURE; -- int m_has_modinfo; --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -- struct utsname uts_info; -- char m_strversion[STRVERSIONLEN]; -- int m_version, m_crcs; --#endif --#if ENABLE_FEATURE_CLEAN_UP -- FILE *fp = NULL; --#else -- FILE *fp; --#endif -- int k_version = 0; -- struct utsname myuname; -- -- /* Parse any options */ -- getopt32(argv, OPTION_STR, &opt_o); -- arg1 = argv[optind]; -- if (option_mask32 & OPT_o) { // -o /* name the output module */ -- free(m_name); -- m_name = xstrdup(opt_o); -- } -- -- if (arg1 == NULL) { -- bb_show_usage(); -- } -- -- /* Grab the module name */ -- tmp1 = xstrdup(arg1); -- tmp = basename(tmp1); -- len = strlen(tmp); -- -- if (uname(&myuname) == 0) { -- if (myuname.release[0] == '2') { -- k_version = myuname.release[2] - '0'; -- } -- } -- --#if ENABLE_FEATURE_2_6_MODULES -- if (k_version > 4 && len > 3 && tmp[len - 3] == '.' -- && tmp[len - 2] == 'k' && tmp[len - 1] == 'o' -- ) { -- len -= 3; -- tmp[len] = '\0'; -- } else --#endif -- if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') { -- len -= 2; -- tmp[len] = '\0'; -- } -- -- --#if ENABLE_FEATURE_2_6_MODULES -- if (k_version > 4) -- m_fullName = xasprintf("%s.ko", tmp); -- else --#endif -- m_fullName = xasprintf("%s.o", tmp); -- -- if (!m_name) { -- m_name = tmp; -- } else { -- free(tmp1); -- tmp1 = NULL; /* flag for free(m_name) before exit() */ -- } -- -- /* Get a filedesc for the module. Check that we have a complete path */ -- if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode) -- || (fp = fopen_for_read(arg1)) == NULL -- ) { -- /* Hmm. Could not open it. First search under /lib/modules/`uname -r`, -- * but do not error out yet if we fail to find it... */ -- if (k_version) { /* uname succeedd */ -- char *module_dir; -- char *tmdn; -- -- tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release); -- /* Jump through hoops in case /lib/modules/`uname -r` -- * is a symlink. We do not want recursive_action to -- * follow symlinks, but we do want to follow the -- * /lib/modules/`uname -r` dir, So resolve it ourselves -- * if it is a link... */ -- module_dir = xmalloc_readlink(tmdn); -- if (!module_dir) -- module_dir = xstrdup(tmdn); -- recursive_action(module_dir, ACTION_RECURSE, -- check_module_name_match, NULL, m_fullName, 0); -- free(module_dir); -- free(tmdn); -- } -- -- /* Check if we have found anything yet */ -- if (!m_filename || ((fp = fopen_for_read(m_filename)) == NULL)) { -- int r; -- char *module_dir; -- -- free(m_filename); -- m_filename = NULL; -- module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR); -- if (!module_dir) -- module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR); -- /* No module found under /lib/modules/`uname -r`, this -- * time cast the net a bit wider. Search /lib/modules/ */ -- r = recursive_action(module_dir, ACTION_RECURSE, -- check_module_name_match, NULL, m_fullName, 0); -- if (r) -- bb_error_msg_and_die("%s: module not found", m_fullName); -- free(module_dir); -- if (m_filename == NULL -- || ((fp = fopen_for_read(m_filename)) == NULL) -- ) { -- bb_error_msg_and_die("%s: module not found", m_fullName); -- } -- } -- } else -- m_filename = xstrdup(arg1); -- -- if (flag_verbose) -- printf("Using %s\n", m_filename); -- --#if ENABLE_FEATURE_2_6_MODULES -- if (k_version > 4) { -- argv[optind] = m_filename; -- optind--; -- return insmod_ng_main(argc - optind, argv + optind); -- } --#endif -- -- f = obj_load(fp, LOADBITS); -- -- if (get_modinfo_value(f, "kernel_version") == NULL) -- m_has_modinfo = 0; -- else -- m_has_modinfo = 1; -- --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -- /* Version correspondence? */ -- if (!flag_quiet) { -- if (uname(&uts_info) < 0) -- uts_info.release[0] = '\0'; -- if (m_has_modinfo) { -- m_version = new_get_module_version(f, m_strversion); -- if (m_version == -1) { -- bb_error_msg_and_die("cannot find the kernel version the module was " -- "compiled for"); -- } -- } -- -- if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) { -- bb_error_msg("%skernel-module version mismatch\n" -- "\t%s was compiled for kernel version %s\n" -- "\twhile this kernel is version %s", -- flag_force_load ? "warning: " : "", -- m_filename, m_strversion, uts_info.release); -- if (!flag_force_load) -- goto out; -- } -- } -- k_crcs = 0; --#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -- -- if (query_module(NULL, 0, NULL, 0, NULL)) -- bb_error_msg_and_die("not configured to support old kernels"); -- new_get_kernel_symbols(); -- k_crcs = new_is_kernel_checksummed(); -- --#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING -- m_crcs = 0; -- if (m_has_modinfo) -- m_crcs = new_is_module_checksummed(f); -- -- if (m_crcs != k_crcs) -- obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash); --#endif /* FEATURE_INSMOD_VERSION_CHECKING */ -- -- /* Let the module know about the kernel symbols. */ -- add_kernel_symbols(f); -- -- /* Allocate common symbols, symbol tables, and string tables. */ -- -- new_create_this_module(f, m_name); -- obj_check_undefineds(f); -- obj_allocate_commons(f); -- check_tainted_module(f, m_name); -- -- /* done with the module name, on to the optional var=value arguments */ -- ++optind; -- if (optind < argc) { -- new_process_module_arguments(f, argc - optind, argv + optind); -- } -- -- arch_create_got(f); -- hide_special_symbols(f); -- --#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS -- add_ksymoops_symbols(f, m_filename, m_name); --#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ -- -- new_create_module_ksymtab(f); -- -- /* Find current size of the module */ -- m_size = obj_load_size(f); -- -- m_addr = create_module(m_name, m_size); -- if (m_addr == (ElfW(Addr))(-1)) switch (errno) { -- case EEXIST: -- bb_error_msg_and_die("a module named %s already exists", m_name); -- case ENOMEM: -- bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes", -- m_size); -- default: -- bb_perror_msg_and_die("create_module: %s", m_name); -- } -- --#if !LOADBITS -- /* -- * the PROGBITS section was not loaded by the obj_load -- * now we can load them directly into the kernel memory -- */ -- if (!obj_load_progbits(fp, f, (char*)m_addr)) { -- delete_module(m_name, 0); -- goto out; -- } --#endif -- -- if (!obj_relocate(f, m_addr)) { -- delete_module(m_name, 0); -- goto out; -- } -- -- if (!new_init_module(m_name, f, m_size)) { -- delete_module(m_name, 0); -- goto out; -- } -- -- if (flag_print_load_map) -- print_load_map(f); -- -- exit_status = EXIT_SUCCESS; -- -- out: --#if ENABLE_FEATURE_CLEAN_UP -- if (fp) -- fclose(fp); -- free(tmp1); -- if (!tmp1) -- free(m_name); -- free(m_filename); --#endif -- return exit_status; --} -- --#endif /* ENABLE_FEATURE_2_4_MODULES */ --/* -- * End of big piece of 2.4-specific code -- */ -- -- --#if ENABLE_FEATURE_2_6_MODULES -- --#include <sys/mman.h> -- --#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES --/* big time suckage. The old prototype above renders our nice fwd-decl wrong */ --extern int init_module(void *module, unsigned long len, const char *options); --#else --#include <asm/unistd.h> --#include <sys/syscall.h> --#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts) --#endif -- --/* We use error numbers in a loose translation... */ --static const char *moderror(int err) --{ -- switch (err) { -- case ENOEXEC: -- return "invalid module format"; -- case ENOENT: -- return "unknown symbol in module"; -- case ESRCH: -- return "module has wrong symbol version"; -- case EINVAL: -- return "invalid parameters"; -- default: -- return strerror(err); -- } --} -- --#if !ENABLE_FEATURE_2_4_MODULES --int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int insmod_main(int argc UNUSED_PARAM, char **argv) --#else --static int insmod_ng_main(int argc UNUSED_PARAM, char **argv) --#endif - { -- size_t len; -- int optlen; -- void *map; -- char *filename, *options; -+ char *filename; -+ int rc; - -+ USE_FEATURE_2_4_MODULES( -+ getopt32(argv, INSMOD_OPTS INSMOD_ARGS); -+ argv += optind-1; -+ ); -+ - filename = *++argv; - if (!filename) - bb_show_usage(); - -- /* Rest is options */ -- options = xzalloc(1); -- optlen = 0; -- while (*++argv) { -- options = xrealloc(options, optlen + 2 + strlen(*argv) + 2); -- /* Spaces handled by "" pairs, but no way of escaping quotes */ -- optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv); -- } -+ if ((rc = bb_init_module(filename, parse_cmdline_module_options(argv))) != 0) -+ bb_error_msg("cannot insert '%s': %s", filename, moderror(rc)); - --#if 0 -- /* Any special reason why mmap? It isn't performance critical. -vda */ -- /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are -- * modules out there that are half a megabyte! mmap()ing is way nicer -- * for small mem boxes, i guess. */ -- /* But after load, these modules will take up that 0.5mb in kernel -- * anyway. Using malloc here causes only a transient spike to 1mb, -- * after module is loaded, we go back to normal 0.5mb usage -- * (in kernel). Also, mmap isn't magic - when we touch mapped data, -- * we use memory. -vda */ -- int fd; -- struct stat st; -- unsigned long len; -- fd = xopen(filename, O_RDONLY); -- fstat(fd, &st); -- len = st.st_size; -- map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); -- if (map == MAP_FAILED) { -- bb_perror_msg_and_die("cannot mmap '%s'", filename); -- } -- -- /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */ -- if (map == NULL) { -- map = xmalloc(len); -- xread(fd, map, len); -- } --#else -- len = MAXINT(ssize_t); -- map = xmalloc_xopen_read_close(filename, &len); --#endif -- -- if (init_module(map, len, options) != 0) -- bb_error_msg_and_die("cannot insert '%s': %s", -- filename, moderror(errno)); -- return 0; -+ return rc; - } -- --#endif -Index: libbb/llist.c -=================================================================== ---- libbb/llist.c (revision 23360) -+++ libbb/llist.c (working copy) -@@ -90,7 +90,6 @@ - } - } - --#ifdef UNUSED - /* Reverse list order. */ - llist_t* FAST_FUNC llist_rev(llist_t *list) - { -@@ -105,4 +104,3 @@ - } - return rev; - } --#endif -Index: include/usage.h -=================================================================== ---- include/usage.h (revision 23360) -+++ include/usage.h (working copy) -@@ -2568,12 +2568,17 @@ - "[-knqrsv] MODULE [symbol=value...]" - #define modprobe_full_usage "\n\n" \ - "Options:" \ -+ USE_FEATURE_2_4_MODULES( \ - "\n -k Make module autoclean-able" \ -+ ) \ - "\n -n Dry run" \ - "\n -q Quiet" \ - "\n -r Remove module (stacks) or do autoclean" \ - "\n -s Report via syslog instead of stderr" \ - "\n -v Verbose" \ -+ USE_FEATURE_MODPROBE_BLACKLIST( \ -+ "\n -b Apply blacklist to module names too" \ -+ ) - - #define modprobe_notes_usage \ - "modprobe can (un)load a stack of modules, passing each module options (when\n" \ -Index: include/applets.h -=================================================================== ---- include/applets.h (revision 23360) -+++ include/applets.h (working copy) -@@ -116,7 +116,7 @@ - USE_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_NEVER, delgroup)) - USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) --USE_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) -+USE_MODUTILS_FAST(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) - USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) -@@ -189,7 +189,7 @@ - USE_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) --USE_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) -+USE_MODUTILS_FAST(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) - USE_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) - #if ENABLE_FEATURE_IP_ADDRESS \ - || ENABLE_FEATURE_IP_ROUTE \ -@@ -233,7 +233,7 @@ - USE_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_NEVER, ls)) - USE_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) --USE_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) -+USE_MODUTILS_FAST(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) - USE_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat)) - USE_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_NEVER)) -@@ -252,7 +252,7 @@ - USE_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER)) --USE_MODPROBE_SMALL(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER)) -+USE_MODUTILS_FAST(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_MOUNT(APPLET(mount, _BB_DIR_BIN, USE_DESKTOP(_BB_SUID_MAYBE) SKIP_DESKTOP(_BB_SUID_NEVER))) - USE_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_NEVER)) -@@ -299,7 +299,7 @@ - USE_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_NEVER, rm)) - USE_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_NEVER, rmdir)) - USE_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) --USE_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) -+USE_MODUTILS_FAST(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe)) - USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) diff --git a/core/busybox/busybox-1.12.0-mdev-exec.patch b/core/busybox/busybox-1.12.0-mdev-exec.patch deleted file mode 100644 index 78f022c0..00000000 --- a/core/busybox/busybox-1.12.0-mdev-exec.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- util-linux/mdev.c.orig 2008-08-21 14:18:38.000000000 +0200 -+++ util-linux/mdev.c 2008-08-21 14:24:18.000000000 +0200 -@@ -220,7 +220,7 @@ - break; - { - const char *s = "@$*"; -- const char *s2 = strchr(s, *val); -+ char *s2 = strchr(s, *val); - - if (!s2) - bb_error_msg_and_die("bad line %u", parser->lineno); diff --git a/core/busybox/busybox-1.12.1-grep.patch b/core/busybox/busybox-1.12.1-grep.patch deleted file mode 100644 index 20404fcc..00000000 --- a/core/busybox/busybox-1.12.1-grep.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- busybox-1.12.1/findutils/grep.c Sun Sep 28 20:04:28 2008 -+++ busybox-1.12.1-grep/findutils/grep.c Wed Oct 1 00:45:49 2008 -@@ -363,12 +363,22 @@ - * (unless -v: -Fov doesnt print anything at all) */ - if (found) - print_line(gl->pattern, strlen(gl->pattern), linenum, ':'); -- } else { -+ } else while (1) { -+ char old = line[gl->matched_range.rm_eo]; - line[gl->matched_range.rm_eo] = '\0'; - print_line(line + gl->matched_range.rm_so, - gl->matched_range.rm_eo - gl->matched_range.rm_so, - linenum, ':'); -- } -+ line[gl->matched_range.rm_eo] = old; -+#if !ENABLE_EXTRA_COMPAT -+ break; -+#else -+ if (re_search(&gl->compiled_regex, line, line_len, -+ gl->matched_range.rm_eo, line_len - gl->matched_range.rm_eo, -+ &gl->matched_range) < 0) -+ break; -+#endif -+ } - } else { - print_line(line, line_len, linenum, ':'); - } diff --git a/core/busybox/busybox-1.12.1-iproute-metric.patch b/core/busybox/busybox-1.12.1-iproute-metric.patch deleted file mode 100644 index 01a24ac8..00000000 --- a/core/busybox/busybox-1.12.1-iproute-metric.patch +++ /dev/null @@ -1,36 +0,0 @@ -Index: networking/libiproute/iproute.c -=================================================================== ---- networking/libiproute/iproute.c (revision 23582) -+++ networking/libiproute/iproute.c (working copy) -@@ -291,7 +291,7 @@ - { - static const char keywords[] ALIGN1 = - "src\0""via\0""mtu\0""lock\0""protocol\0"USE_FEATURE_IP_RULE("table\0") -- "dev\0""oif\0""to\0"; -+ "dev\0""oif\0""to\0""metric\0"; - enum { - ARG_src, - ARG_via, -@@ -300,7 +300,8 @@ - USE_FEATURE_IP_RULE(ARG_table,) - ARG_dev, - ARG_oif, -- ARG_to -+ ARG_to, -+ ARG_metric, - }; - enum { - gw_ok = 1 << 0, -@@ -387,6 +388,12 @@ - } else if (arg == ARG_dev || arg == ARG_oif) { - NEXT_ARG(); - d = *argv; -+ } else if (arg == ARG_metric) { -+ uint32_t metric; -+ NEXT_ARG(); -+ if (get_u32(&metric, *argv, 0)) -+ invarg(*argv, "metric"); -+ addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric); - } else { - int type; - inet_prefix dst; diff --git a/core/busybox/busybox-1.12.1-r1 b/core/busybox/busybox-1.12.1-r1 deleted file mode 100644 index 645fc07b..00000000 --- a/core/busybox/busybox-1.12.1-r1 +++ /dev/null @@ -1,851 +0,0 @@ -# -# Automatically generated make config: don't edit -# Busybox version: 1.12.1 -# Tue Oct 7 08:10:29 2008 -# -CONFIG_HAVE_DOT_CONFIG=y - -# -# Busybox Settings -# - -# -# General Configuration -# -CONFIG_DESKTOP=y -CONFIG_EXTRA_COMPAT=y -CONFIG_FEATURE_ASSUME_UNICODE=y -CONFIG_FEATURE_BUFFERS_USE_MALLOC=y -# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set -# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set -CONFIG_SHOW_USAGE=y -CONFIG_FEATURE_VERBOSE_USAGE=y -CONFIG_FEATURE_COMPRESS_USAGE=y -CONFIG_FEATURE_INSTALLER=y -# CONFIG_LOCALE_SUPPORT is not set -CONFIG_GETOPT_LONG=y -CONFIG_FEATURE_DEVPTS=y -# CONFIG_FEATURE_CLEAN_UP is not set -CONFIG_FEATURE_PIDFILE=y -CONFIG_FEATURE_SUID=y -# CONFIG_FEATURE_SUID_CONFIG is not set -# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set -# CONFIG_SELINUX is not set -# CONFIG_FEATURE_PREFER_APPLETS is not set -CONFIG_BUSYBOX_EXEC_PATH="/bin/busybox" -CONFIG_FEATURE_SYSLOG=y -CONFIG_FEATURE_HAVE_RPC=y - -# -# Build Options -# -# CONFIG_STATIC is not set -CONFIG_PIE=y -# CONFIG_NOMMU is not set -# CONFIG_BUILD_LIBBUSYBOX is not set -# CONFIG_FEATURE_INDIVIDUAL is not set -# CONFIG_FEATURE_SHARED_BUSYBOX is not set -CONFIG_LFS=y -CONFIG_CROSS_COMPILER_PREFIX="" - -# -# Debugging Options -# -# CONFIG_DEBUG is not set -# CONFIG_DEBUG_PESSIMIZE is not set -# CONFIG_WERROR is not set -CONFIG_NO_DEBUG_LIB=y -# CONFIG_DMALLOC is not set -# CONFIG_EFENCE is not set -# CONFIG_INCLUDE_SUSv2 is not set -CONFIG_PARSE=y - -# -# Installation Options -# -# CONFIG_INSTALL_NO_USR is not set -CONFIG_INSTALL_APPLET_SYMLINKS=y -# CONFIG_INSTALL_APPLET_HARDLINKS is not set -# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set -# CONFIG_INSTALL_APPLET_DONT is not set -# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set -# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set -# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set -CONFIG_PREFIX="./_install" - -# -# Busybox Library Tuning -# -CONFIG_PASSWORD_MINLEN=6 -CONFIG_MD5_SIZE_VS_SPEED=0 -CONFIG_FEATURE_FAST_TOP=y -# CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_EDITING=y -CONFIG_FEATURE_EDITING_MAX_LEN=1024 -CONFIG_FEATURE_EDITING_VI=y -CONFIG_FEATURE_EDITING_HISTORY=31 -# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set -CONFIG_FEATURE_TAB_COMPLETION=y -CONFIG_FEATURE_USERNAME_COMPLETION=y -CONFIG_FEATURE_EDITING_FANCY_PROMPT=y -# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set -CONFIG_FEATURE_COPYBUF_KB=16 -CONFIG_MONOTONIC_SYSCALL=y -# CONFIG_IOCTL_HEX2STR_ERROR is not set -CONFIG_FEATURE_HWIB=y - -# -# Applets -# - -# -# Archival Utilities -# -CONFIG_FEATURE_SEAMLESS_LZMA=y -CONFIG_FEATURE_SEAMLESS_BZ2=y -CONFIG_FEATURE_SEAMLESS_GZ=y -CONFIG_FEATURE_SEAMLESS_Z=y -CONFIG_AR=y -CONFIG_FEATURE_AR_LONG_FILENAMES=y -CONFIG_BUNZIP2=y -CONFIG_BZIP2=y -CONFIG_CPIO=y -CONFIG_FEATURE_CPIO_O=y -# CONFIG_DPKG is not set -# CONFIG_DPKG_DEB is not set -# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set -CONFIG_GUNZIP=y -CONFIG_GZIP=y -# CONFIG_RPM2CPIO is not set -# CONFIG_RPM is not set -CONFIG_TAR=y -CONFIG_FEATURE_TAR_CREATE=y -# CONFIG_FEATURE_TAR_AUTODETECT is not set -CONFIG_FEATURE_TAR_FROM=y -CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y -CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y -CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y -# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set -CONFIG_FEATURE_TAR_UNAME_GNAME=y -CONFIG_UNCOMPRESS=y -CONFIG_UNLZMA=y -CONFIG_FEATURE_LZMA_FAST=y -CONFIG_UNZIP=y - -# -# Coreutils -# -CONFIG_BASENAME=y -CONFIG_CAL=y -CONFIG_CAT=y -CONFIG_CATV=y -CONFIG_CHGRP=y -CONFIG_CHMOD=y -CONFIG_CHOWN=y -CONFIG_CHROOT=y -CONFIG_CKSUM=y -CONFIG_COMM=y -CONFIG_CP=y -CONFIG_CUT=y -CONFIG_DATE=y -CONFIG_FEATURE_DATE_ISOFMT=y -CONFIG_DD=y -CONFIG_FEATURE_DD_SIGNAL_HANDLING=y -CONFIG_FEATURE_DD_IBS_OBS=y -CONFIG_DF=y -CONFIG_FEATURE_DF_INODE=y -CONFIG_DIRNAME=y -CONFIG_DOS2UNIX=y -CONFIG_UNIX2DOS=y -CONFIG_DU=y -CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y -CONFIG_ECHO=y -CONFIG_FEATURE_FANCY_ECHO=y -CONFIG_ENV=y -# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set -CONFIG_EXPAND=y -# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set -CONFIG_EXPR=y -CONFIG_EXPR_MATH_SUPPORT_64=y -CONFIG_FALSE=y -CONFIG_FOLD=y -CONFIG_HEAD=y -CONFIG_FEATURE_FANCY_HEAD=y -CONFIG_HOSTID=y -CONFIG_ID=y -CONFIG_INSTALL=y -# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set -CONFIG_LENGTH=y -CONFIG_LN=y -# CONFIG_LOGNAME is not set -CONFIG_LS=y -CONFIG_FEATURE_LS_FILETYPES=y -CONFIG_FEATURE_LS_FOLLOWLINKS=y -CONFIG_FEATURE_LS_RECURSIVE=y -CONFIG_FEATURE_LS_SORTFILES=y -CONFIG_FEATURE_LS_TIMESTAMPS=y -CONFIG_FEATURE_LS_USERNAME=y -CONFIG_FEATURE_LS_COLOR=y -CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y -CONFIG_MD5SUM=y -CONFIG_MKDIR=y -# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set -CONFIG_MKFIFO=y -CONFIG_MKNOD=y -CONFIG_MV=y -# CONFIG_FEATURE_MV_LONG_OPTIONS is not set -CONFIG_NICE=y -CONFIG_NOHUP=y -# CONFIG_OD is not set -CONFIG_PRINTENV=y -CONFIG_PRINTF=y -CONFIG_PWD=y -CONFIG_READLINK=y -CONFIG_FEATURE_READLINK_FOLLOW=y -CONFIG_REALPATH=y -CONFIG_RM=y -CONFIG_RMDIR=y -# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set -CONFIG_SEQ=y -CONFIG_SHA1SUM=y -CONFIG_SLEEP=y -CONFIG_FEATURE_FANCY_SLEEP=y -CONFIG_FEATURE_FLOAT_SLEEP=y -CONFIG_SORT=y -CONFIG_FEATURE_SORT_BIG=y -CONFIG_SPLIT=y -# CONFIG_FEATURE_SPLIT_FANCY is not set -CONFIG_STAT=y -CONFIG_FEATURE_STAT_FORMAT=y -CONFIG_STTY=y -CONFIG_SUM=y -CONFIG_SYNC=y -CONFIG_TAC=y -CONFIG_TAIL=y -CONFIG_FEATURE_FANCY_TAIL=y -CONFIG_TEE=y -CONFIG_FEATURE_TEE_USE_BLOCK_IO=y -CONFIG_TEST=y -CONFIG_FEATURE_TEST_64=y -CONFIG_TOUCH=y -CONFIG_TR=y -CONFIG_FEATURE_TR_CLASSES=y -CONFIG_FEATURE_TR_EQUIV=y -CONFIG_TRUE=y -CONFIG_TTY=y -CONFIG_UNAME=y -CONFIG_UNEXPAND=y -# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set -CONFIG_UNIQ=y -CONFIG_USLEEP=y -# CONFIG_UUDECODE is not set -CONFIG_UUENCODE=y -CONFIG_WC=y -# CONFIG_FEATURE_WC_LARGE is not set -CONFIG_WHO=y -CONFIG_WHOAMI=y -CONFIG_YES=y - -# -# Common options for cp and mv -# -CONFIG_FEATURE_PRESERVE_HARDLINKS=y - -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - -# -# Common options for df, du, ls -# -CONFIG_FEATURE_HUMAN_READABLE=y - -# -# Common options for md5sum, sha1sum -# -CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y - -# -# Console Utilities -# -CONFIG_CHVT=y -CONFIG_CLEAR=y -CONFIG_DEALLOCVT=y -CONFIG_DUMPKMAP=y -CONFIG_KBD_MODE=y -CONFIG_LOADFONT=y -CONFIG_LOADKMAP=y -CONFIG_OPENVT=y -CONFIG_RESET=y -CONFIG_RESIZE=y -CONFIG_FEATURE_RESIZE_PRINT=y -CONFIG_SETCONSOLE=y -# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set -# CONFIG_SETFONT is not set -CONFIG_SETKEYCODES=y -CONFIG_SETLOGCONS=y -CONFIG_SHOWKEY=y - -# -# Debian Utilities -# -CONFIG_MKTEMP=y -CONFIG_PIPE_PROGRESS=y -CONFIG_RUN_PARTS=y -CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y -# CONFIG_FEATURE_RUN_PARTS_FANCY is not set -CONFIG_START_STOP_DAEMON=y -CONFIG_FEATURE_START_STOP_DAEMON_FANCY=y -CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS=y -CONFIG_WHICH=y - -# -# Editors -# -CONFIG_AWK=y -CONFIG_FEATURE_AWK_MATH=y -CONFIG_CMP=y -CONFIG_DIFF=y -CONFIG_FEATURE_DIFF_BINARY=y -CONFIG_FEATURE_DIFF_DIR=y -CONFIG_FEATURE_DIFF_MINIMAL=y -CONFIG_ED=y -CONFIG_PATCH=y -CONFIG_SED=y -CONFIG_VI=y -CONFIG_FEATURE_VI_MAX_LEN=1024 -CONFIG_FEATURE_VI_8BIT=y -CONFIG_FEATURE_VI_COLON=y -CONFIG_FEATURE_VI_YANKMARK=y -CONFIG_FEATURE_VI_SEARCH=y -CONFIG_FEATURE_VI_USE_SIGNALS=y -CONFIG_FEATURE_VI_DOT_CMD=y -CONFIG_FEATURE_VI_READONLY=y -CONFIG_FEATURE_VI_SETOPTS=y -CONFIG_FEATURE_VI_SET=y -CONFIG_FEATURE_VI_WIN_RESIZE=y -CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y -CONFIG_FEATURE_ALLOW_EXEC=y - -# -# Finding Utilities -# -CONFIG_FIND=y -CONFIG_FEATURE_FIND_PRINT0=y -CONFIG_FEATURE_FIND_MTIME=y -CONFIG_FEATURE_FIND_MMIN=y -CONFIG_FEATURE_FIND_PERM=y -CONFIG_FEATURE_FIND_TYPE=y -CONFIG_FEATURE_FIND_XDEV=y -CONFIG_FEATURE_FIND_MAXDEPTH=y -CONFIG_FEATURE_FIND_NEWER=y -CONFIG_FEATURE_FIND_INUM=y -CONFIG_FEATURE_FIND_EXEC=y -CONFIG_FEATURE_FIND_USER=y -CONFIG_FEATURE_FIND_GROUP=y -CONFIG_FEATURE_FIND_NOT=y -CONFIG_FEATURE_FIND_DEPTH=y -CONFIG_FEATURE_FIND_PAREN=y -CONFIG_FEATURE_FIND_SIZE=y -CONFIG_FEATURE_FIND_PRUNE=y -CONFIG_FEATURE_FIND_DELETE=y -CONFIG_FEATURE_FIND_PATH=y -CONFIG_FEATURE_FIND_REGEX=y -# CONFIG_FEATURE_FIND_CONTEXT is not set -CONFIG_GREP=y -CONFIG_FEATURE_GREP_EGREP_ALIAS=y -CONFIG_FEATURE_GREP_FGREP_ALIAS=y -CONFIG_FEATURE_GREP_CONTEXT=y -CONFIG_XARGS=y -CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y -CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y -CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y -CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y - -# -# Init Utilities -# -CONFIG_INIT=y -# CONFIG_DEBUG_INIT is not set -CONFIG_FEATURE_USE_INITTAB=y -CONFIG_FEATURE_KILL_REMOVED=y -CONFIG_FEATURE_KILL_DELAY=0 -CONFIG_FEATURE_INIT_SCTTY=y -CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y -# CONFIG_FEATURE_INIT_COREDUMPS is not set -CONFIG_FEATURE_INITRD=y -CONFIG_HALT=y -CONFIG_MESG=y - -# -# Login/Password Management Utilities -# -CONFIG_FEATURE_SHADOWPASSWDS=y -CONFIG_USE_BB_PWD_GRP=y -CONFIG_USE_BB_SHADOW=y -# CONFIG_USE_BB_CRYPT is not set -CONFIG_ADDGROUP=y -CONFIG_FEATURE_ADDUSER_TO_GROUP=y -CONFIG_DELGROUP=y -CONFIG_FEATURE_DEL_USER_FROM_GROUP=y -CONFIG_FEATURE_CHECK_NAMES=y -CONFIG_ADDUSER=y -# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set -CONFIG_DELUSER=y -CONFIG_GETTY=y -CONFIG_FEATURE_UTMP=y -CONFIG_FEATURE_WTMP=y -CONFIG_LOGIN=y -# CONFIG_PAM is not set -CONFIG_LOGIN_SCRIPTS=y -CONFIG_FEATURE_NOLOGIN=y -CONFIG_FEATURE_SECURETTY=y -CONFIG_PASSWD=y -CONFIG_FEATURE_PASSWD_WEAK_CHECK=y -CONFIG_CRYPTPW=y -CONFIG_CHPASSWD=y -CONFIG_SU=y -CONFIG_FEATURE_SU_SYSLOG=y -CONFIG_FEATURE_SU_CHECKS_SHELLS=y -# CONFIG_SULOGIN is not set -CONFIG_VLOCK=y - -# -# Linux Ext2 FS Progs -# -# CONFIG_CHATTR is not set -# CONFIG_FSCK is not set -# CONFIG_LSATTR is not set - -# -# Linux Module Utilities -# -CONFIG_MODUTILS_STANDARD=y -# CONFIG_MODUTILS_FAST is not set -# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set -# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set -CONFIG_INSMOD=y -CONFIG_RMMOD=y -CONFIG_LSMOD=y -# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set -CONFIG_MODPROBE=y -CONFIG_FEATURE_MODPROBE_BLACKLIST=y -CONFIG_DEPMOD=y - -# -# Options common to multiple modutils -# -# CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set -# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set -# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set -CONFIG_FEATURE_CHECK_TAINTED_MODULE=y -CONFIG_FEATURE_MODUTILS_ALIAS=y -CONFIG_FEATURE_MODUTILS_SYMBOLS=y -CONFIG_DEFAULT_MODULES_DIR="/lib/modules" -CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" - -# -# Linux System Utilities -# -CONFIG_DMESG=y -CONFIG_FEATURE_DMESG_PRETTY=y -CONFIG_FBSET=y -CONFIG_FEATURE_FBSET_FANCY=y -CONFIG_FEATURE_FBSET_READMODE=y -CONFIG_FDFLUSH=y -CONFIG_FDFORMAT=y -CONFIG_FDISK=y -CONFIG_FDISK_SUPPORT_LARGE_DISKS=y -CONFIG_FEATURE_FDISK_WRITABLE=y -CONFIG_FEATURE_AIX_LABEL=y -CONFIG_FEATURE_SGI_LABEL=y -CONFIG_FEATURE_SUN_LABEL=y -CONFIG_FEATURE_OSF_LABEL=y -CONFIG_FEATURE_FDISK_ADVANCED=y -# CONFIG_FINDFS is not set -CONFIG_FREERAMDISK=y -# CONFIG_FSCK_MINIX is not set -# CONFIG_MKFS_MINIX is not set -# CONFIG_FEATURE_MINIX2 is not set -CONFIG_GETOPT=y -CONFIG_HEXDUMP=y -CONFIG_FEATURE_HEXDUMP_REVERSE=y -CONFIG_HD=y -CONFIG_HWCLOCK=y -CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS=y -CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y -CONFIG_IPCRM=y -CONFIG_IPCS=y -CONFIG_LOSETUP=y -CONFIG_MDEV=y -CONFIG_FEATURE_MDEV_CONF=y -CONFIG_FEATURE_MDEV_RENAME=y -CONFIG_FEATURE_MDEV_RENAME_REGEXP=y -CONFIG_FEATURE_MDEV_EXEC=y -CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y -CONFIG_MKSWAP=y -# CONFIG_FEATURE_MKSWAP_V0 is not set -CONFIG_MORE=y -CONFIG_FEATURE_USE_TERMIOS=y -# CONFIG_VOLUMEID is not set -# CONFIG_FEATURE_VOLUMEID_EXT is not set -# CONFIG_FEATURE_VOLUMEID_REISERFS is not set -# CONFIG_FEATURE_VOLUMEID_FAT is not set -# CONFIG_FEATURE_VOLUMEID_HFS is not set -# CONFIG_FEATURE_VOLUMEID_JFS is not set -# CONFIG_FEATURE_VOLUMEID_XFS is not set -# CONFIG_FEATURE_VOLUMEID_NTFS is not set -# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set -# CONFIG_FEATURE_VOLUMEID_UDF is not set -# CONFIG_FEATURE_VOLUMEID_LUKS is not set -# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set -# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set -# CONFIG_FEATURE_VOLUMEID_ROMFS is not set -# CONFIG_FEATURE_VOLUMEID_SYSV is not set -# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set -# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set -CONFIG_MOUNT=y -CONFIG_FEATURE_MOUNT_FAKE=y -CONFIG_FEATURE_MOUNT_VERBOSE=y -CONFIG_FEATURE_MOUNT_HELPERS=y -# CONFIG_FEATURE_MOUNT_LABEL is not set -CONFIG_FEATURE_MOUNT_NFS=y -CONFIG_FEATURE_MOUNT_CIFS=y -CONFIG_FEATURE_MOUNT_FLAGS=y -CONFIG_FEATURE_MOUNT_FSTAB=y -# CONFIG_PIVOT_ROOT is not set -CONFIG_RDATE=y -CONFIG_RDEV=y -CONFIG_READPROFILE=y -# CONFIG_RTCWAKE is not set -# CONFIG_SCRIPT is not set -# CONFIG_SETARCH is not set -CONFIG_SWAPONOFF=y -CONFIG_FEATURE_SWAPON_PRI=y -# CONFIG_SWITCH_ROOT is not set -CONFIG_UMOUNT=y -CONFIG_FEATURE_UMOUNT_ALL=y - -# -# Common options for mount/umount -# -CONFIG_FEATURE_MOUNT_LOOP=y -# CONFIG_FEATURE_MTAB_SUPPORT is not set - -# -# Miscellaneous Utilities -# -CONFIG_ADJTIMEX=y -CONFIG_BBCONFIG=y -# CONFIG_CHAT is not set -# CONFIG_FEATURE_CHAT_NOFAIL is not set -# CONFIG_FEATURE_CHAT_TTY_HIFI is not set -# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set -# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set -# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set -# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set -# CONFIG_FEATURE_CHAT_CLR_ABORT is not set -# CONFIG_CHRT is not set -CONFIG_CROND=y -# CONFIG_DEBUG_CROND_OPTION is not set -CONFIG_FEATURE_CROND_CALL_SENDMAIL=y -CONFIG_CRONTAB=y -CONFIG_DC=y -# CONFIG_DEVFSD is not set -# CONFIG_DEVFSD_MODLOAD is not set -# CONFIG_DEVFSD_FG_NP is not set -# CONFIG_DEVFSD_VERBOSE is not set -# CONFIG_FEATURE_DEVFS is not set -CONFIG_DEVMEM=y -CONFIG_EJECT=y -CONFIG_FEATURE_EJECT_SCSI=y -CONFIG_FBSPLASH=y -# CONFIG_INOTIFYD is not set -CONFIG_LAST=y -CONFIG_FEATURE_LAST_SMALL=y -# CONFIG_FEATURE_LAST_FANCY is not set -CONFIG_LESS=y -CONFIG_FEATURE_LESS_MAXLINES=9999999 -CONFIG_FEATURE_LESS_BRACKETS=y -CONFIG_FEATURE_LESS_FLAGS=y -CONFIG_FEATURE_LESS_FLAGCS=y -CONFIG_FEATURE_LESS_MARKS=y -CONFIG_FEATURE_LESS_REGEXP=y -# CONFIG_HDPARM is not set -# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set -# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set -# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set -CONFIG_MAKEDEVS=y -# CONFIG_FEATURE_MAKEDEVS_LEAF is not set -CONFIG_FEATURE_MAKEDEVS_TABLE=y -CONFIG_MAN=y -CONFIG_MICROCOM=y -CONFIG_MOUNTPOINT=y -CONFIG_MT=y -CONFIG_RAIDAUTORUN=y -CONFIG_READAHEAD=y -CONFIG_RUNLEVEL=y -CONFIG_RX=y -CONFIG_SETSID=y -CONFIG_STRINGS=y -# CONFIG_TASKSET is not set -# CONFIG_FEATURE_TASKSET_FANCY is not set -CONFIG_TIME=y -CONFIG_TTYSIZE=y -CONFIG_WATCHDOG=y - -# -# Networking Utilities -# -CONFIG_FEATURE_IPV6=y -CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y -CONFIG_VERBOSE_RESOLUTION_ERRORS=y -CONFIG_ARP=y -CONFIG_ARPING=y -CONFIG_BRCTL=y -CONFIG_FEATURE_BRCTL_FANCY=y -CONFIG_FEATURE_BRCTL_SHOW=y -CONFIG_DNSD=y -CONFIG_ETHER_WAKE=y -CONFIG_FAKEIDENTD=y -CONFIG_FTPGET=y -CONFIG_FTPPUT=y -# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set -CONFIG_HOSTNAME=y -CONFIG_HTTPD=y -CONFIG_FEATURE_HTTPD_RANGES=y -CONFIG_FEATURE_HTTPD_USE_SENDFILE=y -# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set -CONFIG_FEATURE_HTTPD_SETUID=y -CONFIG_FEATURE_HTTPD_BASIC_AUTH=y -CONFIG_FEATURE_HTTPD_AUTH_MD5=y -CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES=y -CONFIG_FEATURE_HTTPD_CGI=y -CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y -CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y -CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y -CONFIG_FEATURE_HTTPD_ERROR_PAGES=y -CONFIG_FEATURE_HTTPD_PROXY=y -CONFIG_IFCONFIG=y -CONFIG_FEATURE_IFCONFIG_STATUS=y -CONFIG_FEATURE_IFCONFIG_SLIP=y -CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y -CONFIG_FEATURE_IFCONFIG_HW=y -CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y -CONFIG_IFENSLAVE=y -CONFIG_IFUPDOWN=y -CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" -CONFIG_FEATURE_IFUPDOWN_IP=y -CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN=y -# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set -CONFIG_FEATURE_IFUPDOWN_IPV4=y -CONFIG_FEATURE_IFUPDOWN_IPV6=y -# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set -CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP=y -CONFIG_INETD=y -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set -# CONFIG_FEATURE_INETD_RPC is not set -CONFIG_IP=y -CONFIG_FEATURE_IP_ADDRESS=y -CONFIG_FEATURE_IP_LINK=y -CONFIG_FEATURE_IP_ROUTE=y -CONFIG_FEATURE_IP_TUNNEL=y -CONFIG_FEATURE_IP_RULE=y -CONFIG_FEATURE_IP_SHORT_FORMS=y -CONFIG_FEATURE_IP_RARE_PROTOCOLS=y -CONFIG_IPADDR=y -CONFIG_IPLINK=y -CONFIG_IPROUTE=y -CONFIG_IPTUNNEL=y -CONFIG_IPRULE=y -CONFIG_IPCALC=y -CONFIG_FEATURE_IPCALC_FANCY=y -# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set -CONFIG_NAMEIF=y -CONFIG_FEATURE_NAMEIF_EXTENDED=y -CONFIG_NC=y -CONFIG_NC_SERVER=y -CONFIG_NC_EXTRA=y -CONFIG_NETSTAT=y -CONFIG_FEATURE_NETSTAT_WIDE=y -CONFIG_FEATURE_NETSTAT_PRG=y -CONFIG_NSLOOKUP=y -CONFIG_PING=y -CONFIG_PING6=y -CONFIG_FEATURE_FANCY_PING=y -CONFIG_PSCAN=y -CONFIG_ROUTE=y -# CONFIG_SENDMAIL is not set -# CONFIG_FETCHMAIL is not set -CONFIG_SLATTACH=y -CONFIG_TELNET=y -CONFIG_FEATURE_TELNET_TTYPE=y -CONFIG_FEATURE_TELNET_AUTOLOGIN=y -# CONFIG_TELNETD is not set -# CONFIG_FEATURE_TELNETD_STANDALONE is not set -CONFIG_TFTP=y -# CONFIG_TFTPD is not set -CONFIG_FEATURE_TFTP_GET=y -CONFIG_FEATURE_TFTP_PUT=y -CONFIG_FEATURE_TFTP_BLOCKSIZE=y -# CONFIG_DEBUG_TFTP is not set -CONFIG_TRACEROUTE=y -CONFIG_FEATURE_TRACEROUTE_VERBOSE=y -CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y -CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y -CONFIG_APP_UDHCPD=y -CONFIG_APP_DHCPRELAY=y -CONFIG_APP_DUMPLEASES=y -CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y -CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases" -CONFIG_APP_UDHCPC=y -CONFIG_FEATURE_UDHCPC_ARPING=y -# CONFIG_FEATURE_UDHCP_PORT is not set -# CONFIG_FEATURE_UDHCP_DEBUG is not set -CONFIG_FEATURE_RFC3397=y -CONFIG_DHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" -CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 -CONFIG_VCONFIG=y -CONFIG_WGET=y -CONFIG_FEATURE_WGET_STATUSBAR=y -CONFIG_FEATURE_WGET_AUTHENTICATION=y -# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set -CONFIG_ZCIP=y -# CONFIG_TCPSVD is not set -# CONFIG_UDPSVD is not set - -# -# Process Utilities -# -CONFIG_FREE=y -CONFIG_FUSER=y -CONFIG_KILL=y -CONFIG_KILLALL=y -CONFIG_KILLALL5=y -CONFIG_NMETER=y -CONFIG_PGREP=y -CONFIG_PIDOF=y -CONFIG_FEATURE_PIDOF_SINGLE=y -CONFIG_FEATURE_PIDOF_OMIT=y -CONFIG_PKILL=y -CONFIG_PS=y -CONFIG_FEATURE_PS_WIDE=y -# CONFIG_FEATURE_PS_TIME is not set -# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set -CONFIG_RENICE=y -CONFIG_BB_SYSCTL=y -CONFIG_TOP=y -CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y -CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y -# CONFIG_FEATURE_TOP_DECIMALS is not set -CONFIG_FEATURE_TOPMEM=y -CONFIG_UPTIME=y -CONFIG_WATCH=y - -# -# Shells -# -CONFIG_FEATURE_SH_IS_ASH=y -# CONFIG_FEATURE_SH_IS_HUSH is not set -# CONFIG_FEATURE_SH_IS_MSH is not set -# CONFIG_FEATURE_SH_IS_NONE is not set -CONFIG_ASH=y - -# -# Ash Shell Options -# -CONFIG_ASH_BASH_COMPAT=y -CONFIG_ASH_JOB_CONTROL=y -CONFIG_ASH_READ_NCHARS=y -CONFIG_ASH_READ_TIMEOUT=y -CONFIG_ASH_ALIAS=y -CONFIG_ASH_MATH_SUPPORT=y -CONFIG_ASH_MATH_SUPPORT_64=y -CONFIG_ASH_GETOPTS=y -CONFIG_ASH_BUILTIN_ECHO=y -CONFIG_ASH_BUILTIN_PRINTF=y -CONFIG_ASH_BUILTIN_TEST=y -CONFIG_ASH_CMDCMD=y -CONFIG_ASH_MAIL=y -CONFIG_ASH_OPTIMIZE_FOR_SIZE=y -CONFIG_ASH_RANDOM_SUPPORT=y -CONFIG_ASH_EXPAND_PRMT=y -# CONFIG_HUSH is not set -# CONFIG_HUSH_HELP is not set -# CONFIG_HUSH_INTERACTIVE is not set -# CONFIG_HUSH_JOB is not set -# CONFIG_HUSH_TICK is not set -# CONFIG_HUSH_IF is not set -# CONFIG_HUSH_LOOPS is not set -# CONFIG_HUSH_CASE is not set -# CONFIG_LASH is not set -# CONFIG_MSH is not set - -# -# Bourne Shell Options -# -CONFIG_FEATURE_SH_EXTRA_QUIET=y -# CONFIG_FEATURE_SH_STANDALONE is not set -# CONFIG_FEATURE_SH_NOFORK is not set -CONFIG_CTTYHACK=y - -# -# System Logging Utilities -# -CONFIG_SYSLOGD=y -CONFIG_FEATURE_ROTATE_LOGFILE=y -CONFIG_FEATURE_REMOTE_LOG=y -CONFIG_FEATURE_SYSLOGD_DUP=y -CONFIG_FEATURE_IPC_SYSLOG=y -CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 -CONFIG_LOGREAD=y -CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y -CONFIG_KLOGD=y -CONFIG_LOGGER=y - -# -# Runit Utilities -# -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_SV is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_CHCON is not set -# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RESTORECON is not set -# CONFIG_RUNCON is not set -# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set -# CONFIG_SETSEBOOL is not set -# CONFIG_SESTATUS is not set - -# -# Print Utilities -# -# CONFIG_LPD is not set -# CONFIG_LPR is not set -# CONFIG_LPQ is not set diff --git a/core/busybox/busybox-devmem.patch b/core/busybox/busybox-devmem.patch deleted file mode 100644 index 3932119a..00000000 --- a/core/busybox/busybox-devmem.patch +++ /dev/null @@ -1,128 +0,0 @@ -diff -Nrup include/applets.h include/applets.h ---- include/applets.h 2008-04-26 18:22:37.000000000 +0000 -+++ include/applets.h 2008-04-26 18:19:53.000000000 +0000 -@@ -121,6 +121,7 @@ USE_DEALLOCVT(APPLET(deallocvt, _BB_DIR_ - USE_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_NEVER, delgroup)) - USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER)) -+USE_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) - USE_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) -diff -Nrup include/usage.h include/usage.h ---- include/usage.h 2007-12-21 22:00:31.000000000 +0000 -+++ include/usage.h 2008-04-26 18:21:59.000000000 +0000 -@@ -630,6 +630,16 @@ - "\n and processing synthetic REGISTER events," \ - "\n do not poll for events") - -+#define devmem_trivial_usage \ -+ "{ address } [ type [ data ] ]" -+ -+#define devmem_full_usage \ -+ "Read/Write from physical addresses" \ -+ "\n\nUsage: devmem { address } [ type [ data ] ]" \ -+ "\n address : memory address to act upon" \ -+ "\n type : access operation type : [b]yte, [h]alfword, [w]ord" \ -+ "\n data : data to be written" -+ - /* -k is accepted but ignored for !HUMAN_READABLE, - * but we won't mention this (unimportant) */ - #if ENABLE_FEATURE_HUMAN_READABLE || ENABLE_FEATURE_DF_INODE -diff -Nrup miscutils/Config.in miscutils/Config.in ---- miscutils/Config.in 2007-12-21 22:00:31.000000000 +0000 -+++ miscutils/Config.in 2008-04-26 17:54:51.000000000 +0000 -@@ -120,6 +120,13 @@ config FEATURE_DEVFS - /dev/loop0. If your /dev directory has normal names instead of - devfs names, you don't want this. - -+config DEVMEM -+ bool "devmem" -+ default y -+ help -+ devmem is a small program that reads and writes from physical -+ memory using /dev/mem. -+ - config EJECT - bool "eject" - default n -diff -Nrup miscutils/Kbuild miscutils/Kbuild ---- miscutils/Kbuild 2007-12-21 22:00:31.000000000 +0000 -+++ miscutils/Kbuild 2008-04-26 17:56:36.000000000 +0000 -@@ -12,6 +12,7 @@ lib-$(CONFIG_CROND) += crond.o - lib-$(CONFIG_CRONTAB) += crontab.o - lib-$(CONFIG_DC) += dc.o - lib-$(CONFIG_DEVFSD) += devfsd.o -+lib-$(CONFIG_DEVMEM) += devmem.o - lib-$(CONFIG_EJECT) += eject.o - lib-$(CONFIG_HDPARM) += hdparm.o - lib-$(CONFIG_LAST) += last.o -diff -Nrup miscutils/devmem.c miscutils/devmem.c ---- miscutils/devmem.c 1970-01-01 00:00:00.000000000 +0000 -+++ miscutils/devmem.c 2008-04-26 18:18:30.000000000 +0000 -@@ -0,0 +1,65 @@ -+/* -+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. -+ * Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) -+ * Copyright (C) 2008, BusyBox Team. -solar 4/26/08 -+ */ -+ -+#include "libbb.h" -+ -+#define DEVMEM_MAP_SIZE 4096UL -+#define DEVMEM_MAP_MASK (DEVMEM_MAP_SIZE - 1) -+ -+int devmem_main(int argc, char **argv) { -+ void *map_base, *virt_addr; -+ unsigned long read_result, writeval; -+ off_t target; -+ int fd, access_type = 'w'; -+ -+ if (argc < 2) -+ bb_show_usage(); -+ -+ target = bb_strtoul(argv[1], 0, 0); -+ -+ if (argc > 2) -+ access_type = tolower(argv[2][0]); -+ -+ fd = xopen("/dev/mem", O_RDWR | O_SYNC); -+ -+ if ((map_base = mmap(0, DEVMEM_MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~DEVMEM_MAP_MASK)) == MAP_FAILED) -+ bb_perror_msg_and_die("mmap"); -+ -+ printf("Memory mapped at address %p.\n", map_base); -+ -+ virt_addr = map_base + (target & DEVMEM_MAP_MASK); -+ if (access_type == 'b') -+ read_result = *((unsigned char *) virt_addr); -+ else if (access_type == 'h') -+ read_result = *((unsigned short *) virt_addr); -+ else if (access_type == 'w') -+ read_result = *((unsigned long *) virt_addr); -+ else { -+ fprintf(stderr, "Illegal data type '%c'\n", access_type); -+ exit(EXIT_FAILURE); -+ } -+ printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result); -+ -+ if (argc > 3) { -+ writeval = bb_strtoul(argv[3], 0, 0); -+ if (access_type == 'b') { -+ *((unsigned char *) virt_addr) = writeval; -+ read_result = *((unsigned char *) virt_addr); -+ } else if (access_type == 'h') { -+ *((unsigned short *) virt_addr) = writeval; -+ read_result = *((unsigned short *) virt_addr); -+ } else if (access_type == 'w') { -+ *((unsigned long *) virt_addr) = writeval; -+ read_result = *((unsigned long *) virt_addr); -+ } -+ printf("Written 0x%X; readback 0x%X\n", writeval, read_result); -+ } -+ -+ if (munmap(map_base, DEVMEM_MAP_SIZE) == -1) -+ bb_perror_msg_and_die("munmap"); -+ close(fd); -+ fflush_stdout_and_exit(EXIT_SUCCESS); -+} diff --git a/core/busybox/busyboxconfig b/core/busybox/busyboxconfig index e6c64210..9cd9dce6 100644 --- a/core/busybox/busyboxconfig +++ b/core/busybox/busyboxconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.12.1 -# Sun Nov 9 13:12:55 2008 +# Busybox version: 1.13.0 +# Tue Nov 18 11:02:03 2008 # CONFIG_HAVE_DOT_CONFIG=y @@ -58,7 +58,6 @@ CONFIG_NO_DEBUG_LIB=y # CONFIG_DMALLOC is not set # CONFIG_EFENCE is not set # CONFIG_INCLUDE_SUSv2 is not set -CONFIG_PARSE=y # # Installation Options @@ -106,7 +105,7 @@ CONFIG_FEATURE_SEAMLESS_BZ2=y CONFIG_FEATURE_SEAMLESS_GZ=y CONFIG_FEATURE_SEAMLESS_Z=y # CONFIG_AR is not set -CONFIG_FEATURE_AR_LONG_FILENAMES=y +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set CONFIG_BUNZIP2=y CONFIG_BZIP2=y CONFIG_CPIO=y @@ -153,7 +152,7 @@ CONFIG_DD=y CONFIG_FEATURE_DD_SIGNAL_HANDLING=y CONFIG_FEATURE_DD_IBS_OBS=y CONFIG_DF=y -CONFIG_FEATURE_DF_INODE=y +CONFIG_FEATURE_DF_FANCY=y CONFIG_DIRNAME=y CONFIG_DOS2UNIX=y CONFIG_UNIX2DOS=y @@ -283,6 +282,8 @@ CONFIG_FEATURE_RESIZE_PRINT=y CONFIG_SETCONSOLE=y # CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set # CONFIG_SETFONT is not set +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="" CONFIG_SETKEYCODES=y CONFIG_SETLOGCONS=y CONFIG_SHOWKEY=y @@ -304,7 +305,7 @@ CONFIG_WHICH=y # Editors # CONFIG_AWK=y -CONFIG_FEATURE_AWK_MATH=y +CONFIG_FEATURE_AWK_LIBM=y CONFIG_CMP=y CONFIG_DIFF=y CONFIG_FEATURE_DIFF_BINARY=y @@ -367,7 +368,6 @@ CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y # Init Utilities # CONFIG_INIT=y -# CONFIG_DEBUG_INIT is not set CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_REMOVED=y CONFIG_FEATURE_KILL_DELAY=0 @@ -422,14 +422,15 @@ CONFIG_VLOCK=y # # Linux Module Utilities # -CONFIG_MODUTILS_STANDARD=y -# CONFIG_MODUTILS_FAST is not set +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" +# CONFIG_MODPROBE_SMALL is not set # CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set # CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set CONFIG_INSMOD=y CONFIG_RMMOD=y CONFIG_LSMOD=y -# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y CONFIG_MODPROBE=y CONFIG_FEATURE_MODPROBE_BLACKLIST=y CONFIG_DEPMOD=y @@ -446,12 +447,11 @@ CONFIG_DEPMOD=y CONFIG_FEATURE_CHECK_TAINTED_MODULE=y CONFIG_FEATURE_MODUTILS_ALIAS=y CONFIG_FEATURE_MODUTILS_SYMBOLS=y -CONFIG_DEFAULT_MODULES_DIR="/lib/modules" -CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" # # Linux System Utilities # +# CONFIG_BLKID is not set CONFIG_DMESG=y CONFIG_FEATURE_DMESG_PRETTY=y CONFIG_FBSET=y @@ -467,8 +467,8 @@ CONFIG_FEATURE_SGI_LABEL=y CONFIG_FEATURE_SUN_LABEL=y CONFIG_FEATURE_OSF_LABEL=y CONFIG_FEATURE_FDISK_ADVANCED=y -# CONFIG_FINDFS is not set -CONFIG_FREERAMDISK=y +CONFIG_FINDFS=y +# CONFIG_FREERAMDISK is not set # CONFIG_FSCK_MINIX is not set # CONFIG_MKFS_MINIX is not set # CONFIG_FEATURE_MINIX2 is not set @@ -492,7 +492,7 @@ CONFIG_MKSWAP=y # CONFIG_FEATURE_MKSWAP_V0 is not set CONFIG_MORE=y CONFIG_FEATURE_USE_TERMIOS=y -# CONFIG_VOLUMEID is not set +CONFIG_VOLUMEID=y # CONFIG_FEATURE_VOLUMEID_EXT is not set # CONFIG_FEATURE_VOLUMEID_REISERFS is not set # CONFIG_FEATURE_VOLUMEID_FAT is not set @@ -524,7 +524,7 @@ CONFIG_RDEV=y CONFIG_READPROFILE=y # CONFIG_RTCWAKE is not set # CONFIG_SCRIPT is not set -# CONFIG_SETARCH is not set +CONFIG_SETARCH=y CONFIG_SWAPONOFF=y CONFIG_FEATURE_SWAPON_PRI=y # CONFIG_SWITCH_ROOT is not set @@ -552,15 +552,17 @@ CONFIG_BBCONFIG=y # CONFIG_FEATURE_CHAT_CLR_ABORT is not set # CONFIG_CHRT is not set CONFIG_CROND=y -# CONFIG_DEBUG_CROND_OPTION is not set +CONFIG_FEATURE_CROND_D=y CONFIG_FEATURE_CROND_CALL_SENDMAIL=y CONFIG_CRONTAB=y CONFIG_DC=y +CONFIG_FEATURE_DC_LIBM=y # CONFIG_DEVFSD is not set # CONFIG_DEVFSD_MODLOAD is not set # CONFIG_DEVFSD_FG_NP is not set # CONFIG_DEVFSD_VERBOSE is not set # CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set CONFIG_EJECT=y CONFIG_FEATURE_EJECT_SCSI=y CONFIG_FBSPLASH=y @@ -572,9 +574,11 @@ CONFIG_LESS=y CONFIG_FEATURE_LESS_MAXLINES=9999999 CONFIG_FEATURE_LESS_BRACKETS=y CONFIG_FEATURE_LESS_FLAGS=y -CONFIG_FEATURE_LESS_FLAGCS=y +CONFIG_FEATURE_LESS_DASHCMD=y CONFIG_FEATURE_LESS_MARKS=y CONFIG_FEATURE_LESS_REGEXP=y +CONFIG_FEATURE_LESS_LINENUMS=y +CONFIG_FEATURE_LESS_WINCH=y # CONFIG_HDPARM is not set # CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set # CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set @@ -686,8 +690,6 @@ CONFIG_PING6=y CONFIG_FEATURE_FANCY_PING=y CONFIG_PSCAN=y CONFIG_ROUTE=y -# CONFIG_SENDMAIL is not set -# CONFIG_FETCHMAIL is not set CONFIG_SLATTACH=y CONFIG_TELNET=y CONFIG_FEATURE_TELNET_TTYPE=y @@ -699,7 +701,7 @@ CONFIG_TFTP=y CONFIG_FEATURE_TFTP_GET=y CONFIG_FEATURE_TFTP_PUT=y CONFIG_FEATURE_TFTP_BLOCKSIZE=y -# CONFIG_DEBUG_TFTP is not set +# CONFIG_TFTP_DEBUG is not set CONFIG_TRACEROUTE=y CONFIG_FEATURE_TRACEROUTE_VERBOSE=y CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y @@ -712,9 +714,9 @@ CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases" CONFIG_APP_UDHCPC=y CONFIG_FEATURE_UDHCPC_ARPING=y # CONFIG_FEATURE_UDHCP_PORT is not set -# CONFIG_FEATURE_UDHCP_DEBUG is not set -CONFIG_FEATURE_RFC3397=y -CONFIG_DHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +# CONFIG_UDHCP_DEBUG is not set +CONFIG_FEATURE_UDHCP_RFC3397=y +CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 CONFIG_VCONFIG=y CONFIG_WGET=y @@ -726,6 +728,26 @@ CONFIG_ZCIP=y # CONFIG_UDPSVD is not set # +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +# CONFIG_MAKEMIME is not set +CONFIG_FEATURE_MIME_CHARSET="us-ascii" +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +CONFIG_SENDMAIL=y +# CONFIG_FEATURE_SENDMAIL_MAILX is not set +# CONFIG_FEATURE_SENDMAIL_MAILXX is not set + +# # Process Utilities # CONFIG_FREE=y @@ -741,19 +763,51 @@ CONFIG_FEATURE_PIDOF_OMIT=y CONFIG_PKILL=y CONFIG_PS=y CONFIG_FEATURE_PS_WIDE=y -# CONFIG_FEATURE_PS_TIME is not set +CONFIG_FEATURE_PS_TIME=y # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set CONFIG_RENICE=y CONFIG_BB_SYSCTL=y CONFIG_TOP=y CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +CONFIG_FEATURE_TOP_SMP_CPU=y # CONFIG_FEATURE_TOP_DECIMALS is not set +CONFIG_FEATURE_TOP_SMP_PROCESS=y CONFIG_FEATURE_TOPMEM=y CONFIG_UPTIME=y CONFIG_WATCH=y # +# Runit Utilities +# +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVLOGD is not set +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_CHCON is not set +# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RESTORECON is not set +# CONFIG_RUNCON is not set +# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_SETSEBOOL is not set +# CONFIG_SESTATUS is not set + +# # Shells # CONFIG_FEATURE_SH_IS_ASH=y @@ -798,7 +852,7 @@ CONFIG_ASH_EXPAND_PRMT=y CONFIG_FEATURE_SH_EXTRA_QUIET=y # CONFIG_FEATURE_SH_STANDALONE is not set # CONFIG_FEATURE_SH_NOFORK is not set -CONFIG_CTTYHACK=y +# CONFIG_CTTYHACK is not set # # System Logging Utilities @@ -813,38 +867,3 @@ CONFIG_LOGREAD=y CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y CONFIG_KLOGD=y CONFIG_LOGGER=y - -# -# Runit Utilities -# -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_SV is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_CHCON is not set -# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RESTORECON is not set -# CONFIG_RUNCON is not set -# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set -# CONFIG_SETSEBOOL is not set -# CONFIG_SESTATUS is not set - -# -# Print Utilities -# -# CONFIG_LPD is not set -# CONFIG_LPR is not set -# CONFIG_LPQ is not set |