summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rwxr-xr-xkernel/strip_modules124
1 files changed, 124 insertions, 0 deletions
diff --git a/kernel/strip_modules b/kernel/strip_modules
new file mode 100755
index 000000000..5badbea40
--- /dev/null
+++ b/kernel/strip_modules
@@ -0,0 +1,124 @@
+#!/bin/sh
+#
+# Given a list of objects, strip all static symbols except those
+# required by insmod.
+#
+# Copyright Keith Owens <kaos@ocs.com.au>. GPL.
+# Sat Feb 1 12:52:17 EST 1997
+#
+# Mainly intended for reducing the size of modules to save space
+# on emergency and install disks. Be aware that removing the
+# static symbols reduces the amount of diagnostic information
+# available for oops. Not recommended for normal module usage.
+#
+# This code requires the modules use MODULE_PARM and EXPORT_.
+# Do not strip modules that have not been converted to use
+# MODULE_PARM or are using the old method of exporting symbols.
+# In particular do not use on modules prior to 2.1.20 (approx).
+#
+# The objects are stripped in /tmp, only if the strip works is
+# the original overwritten. If the command line to strip the
+# symbols becomes too long, the strip is done in multiple passes.
+# Running strip_module twice on the same object is safe (and a
+# waste of time).
+#
+
+sizeofptr="/tmp/$$.sizeofptr"
+echo 'int main() { return sizeof(void *); }' | gcc -xc - -o $sizeofptr
+$sizeofptr
+export SIZEOF_POINTER=$?
+rm -f $sizeofptr
+
+cat > /tmp/$$.awk <<\EOF
+BEGIN {
+ strip = "/usr/bin/objcopy";
+ nm = "/usr/bin/nm";
+ cp = "/bin/cp";
+ mv = "/bin/mv";
+ rm = "/bin/rm";
+ tmp = "/tmp";
+ command_size = 400; # arbitrary but safe
+
+ getline < "/proc/self/stat";
+ pid = $1;
+ tmpcopy = tmp "/" pid ".object";
+ nmout = tmp "/" pid ".nmout";
+
+ for (i = 1; i < ARGC; ++i)
+ strip_module(ARGV[i]);
+
+ do_command(rm " -f " tmpcopy " " nmout);
+
+ exit(0);
+}
+
+function strip_module(object,
+ keep_symbol, to_strip, symbol, command, changed) {
+ do_command(cp " -a " object " " tmpcopy);
+ do_command(nm " " tmpcopy " > " nmout);
+ # delete array_name sometimes breaks, internal error, play safe
+ for (symbol in keep_symbol)
+ delete keep_symbol[symbol];
+ for (symbol in to_strip)
+ delete to_strip[symbol];
+ new_module_format = 0;
+ ptrskip = 2 + 2 * ENVIRON["SIZEOF_POINTER"];
+ while ((getline < nmout) > 0) {
+ $0 = substr($0, ptrskip);
+ # b static variable, uninitialised
+ # d static variable, initialised
+ # r static array, initialised
+ # t static label/procedures
+ if ($1 ~ /[bdrt]/)
+ to_strip[$2] = "";
+ else if ($1 != "?")
+ keep_symbol[$2] = "";
+ else if ($0 ~ /\? __ksymtab_/)
+ keep_symbol[substr($2, 11)] = "";
+ else if ($0 ~ /\? __module_parm_/)
+ keep_symbol[substr($2, 15)] = "";
+ if ($2 ~ /__module/)
+ new_module_format = 1;
+ }
+ close(nmout);
+ command = "";
+ changed = 0;
+ failure = 0;
+ if (new_module_format) {
+ for (symbol in to_strip) {
+ if (!(symbol in keep_symbol)) {
+ changed = 1;
+ if (length(command) > command_size) {
+ failure = failure || do_command(strip command " " tmpcopy);
+ command = "";
+ }
+ command = command " --strip-symbol=" symbol;
+ }
+ }
+ }
+ if (command != "") {
+ changed = 1;
+ failure = failure || do_command(strip command " " tmpcopy);
+ }
+ if (changed && !failure)
+ do_command(mv " " tmpcopy " " object);
+}
+
+function do_command(command) {
+ if ((ret = system(command)) != 0) {
+ giveup("command \"" command "\" failed " ret, ret);
+ return 1;
+ }
+ return 0;
+}
+
+function giveup(message, ret) {
+ print "strip_module: " message > "/dev/stderr";
+# exit(ret);
+}
+EOF
+
+awk -f /tmp/$$.awk "$@"
+ret=$?
+rm -f /tmp/$$.awk
+exit $ret