diff options
Diffstat (limited to 'kernel')
-rwxr-xr-x | kernel/strip_modules | 124 |
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 |