#!/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 print $0 ":" $3 ":" $5 > "/dev/stderr"; if ($1 ~ /[bdrt]/) to_strip[$2] = ""; else if ($2 ~ /R __ksymtab_/) keep_symbol[substr($2, 11)] = ""; else if ($0 ~ /R __module_parm_/) keep_symbol[substr($2, 15)] = ""; else if ($0 ~ /D __parm_/) keep_symbol[substr($2, 8)] = ""; else if ($3 ~ /__ksymtab/) { print "keep " $5 > "/dev/stderr"; keep_symbol[$5] = ""; } else if ($1 != "?") keep_symbol[$2] = ""; 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