summaryrefslogtreecommitdiffstats
path: root/core/busybox
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2008-11-25 08:23:15 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2008-11-25 08:23:15 +0000
commitadac189d8f791809898e770aa7ad329bbc0c8d2a (patch)
treebdb2ca453106cc6a8d7eb2ca78dd67887d7e14d2 /core/busybox
parent36b7d352a71fcb43221c3c834ba94383d4f989b1 (diff)
downloadaports-adac189d8f791809898e770aa7ad329bbc0c8d2a.tar.bz2
aports-adac189d8f791809898e770aa7ad329bbc0c8d2a.tar.xz
core/busybox: upgrade to 1.13.0
Diffstat (limited to 'core/busybox')
-rw-r--r--core/busybox/APKBUILD60
-rw-r--r--core/busybox/bb-modprobe-v9.diff10876
-rw-r--r--core/busybox/busybox-1.12.0-mdev-exec.patch11
-rw-r--r--core/busybox/busybox-1.12.1-grep.patch27
-rw-r--r--core/busybox/busybox-1.12.1-iproute-metric.patch36
-rw-r--r--core/busybox/busybox-1.12.1-r1851
-rw-r--r--core/busybox/busybox-devmem.patch128
-rw-r--r--core/busybox/busyboxconfig141
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, &param, &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