Re: Stripped kernel modules?

Keith Owens (
Fri, 15 May 1998 23:07:55 +1000

On Thu, 14 May 1998 11:39:39 -0700,
"Adam J. Richter" <> wrote:
> It used to be that you could strip the kernel module ".o" files
>and they would still load, as long as those modules did not export
>any symbols. If the module did export symbols and another module
>attempted to reference one of those symbols, you would get a kernel
>panic (this was clearly a bug). Well, it appears that somebody has
>fixed this bug, and the kernel now refused to load any stripped .o
>file. I wish that I could still load stripped .o files for the
>modules that do not export symbols, because stripping these files
>makes a big difference, because only twenty one modules in the 2.1.101
>kernel export any variables that are referenced by other kernel

Try this, a selective strip of modules keeping the special symbols that
insmod needs to initialise modules, handle variables etc. Due to what
appears to be a bug in script, it cannot strip globals.

<quiet complaint>
Many modules have procedures and even variables declared as global when
they are not referred to from outside the module. Making them static
would let you strip even more symbols from the modules and would not
affect the code. I tried to get this cleared up back in 2.1.24 days
without success, oh well, something else for 2.3.
</quiet complaint>

#!/usr/bin/perl -w
# Given a list of objects, strip all static symbols except those
# required by insmod.
# Copyright Keith Owens <>. 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).

require 5;
use strict;
use English;

my $strip = "/usr/bin/strip";
my $nm = "/usr/bin/nm";
my $cp = "/bin/cp";
my $mv = "/bin/mv";
my $rm = "/bin/rm";
my $tmp = "/tmp";
my $command_size = 400; # arbitrary but safe

my $tmpcopy = "$tmp/$PID.object";
my $nmout = "$tmp/$PID.nmout";

my $i;

for ($i = 0; $i <= $#ARGV; ++$i) {

do_command("$rm -f $tmpcopy $nmout");


sub strip_module()
my ($object) = @_;
my (%keep, %to_strip, $symbol, $command, $changed, $line, @f);
do_command("$cp -a $object $tmpcopy");
do_command("$nm $tmpcopy > $nmout");
open(NMOUT, "<$nmout") || die "cannot read $nmout";
while (defined($line = <NMOUT>)) {
my @field = split(' ', substr($line, 9));

if ($field[1] eq 'init_module' ||
$field[1] eq 'cleanup_module') {
$keep{$field[1]} = "";

# b static variable, uninitialised
# d static variable, initialised
# r static array, initialised
# t static label/procedures

# You should be able to strip the following if you are feeling
# brave but the strip command refuses to strip individual global
# symbols. A plain strip will remove them but selective strip
# fails. Bug in strip?
# C global variable, uninitialised
# D global variable, initialised
# R global array, initialised
# T global label/procedure

if ($field[0] =~ /^[bdrt]$/
# || $field[0] =~ /^[CDRT]$/
) {
$to_strip{$field[1]} = "";
elsif ($field[0] ne '?') {
$keep{$field[1]} = "";
elsif ($line =~ /\? __ksymtab_/ ||
$line =~ /\? __kstrtab_/) {
$keep{substr($field[1], 10)} = "";
elsif ($line =~ /\? __module_parm_/) {
$keep{substr($field[1], 14)} = "";
$command = "";
$changed = 0;
foreach $symbol (keys(%to_strip)) {
if (!defined($keep{$symbol})) {
$changed = 1;
if (length($command) > $command_size) {
do_command("$strip $command $tmpcopy");
$command = "";
$command = "$command --strip-symbol=$symbol";
if ($command ne "") {
$changed = 1;
do_command("$strip $command $tmpcopy");
if ($changed) {
do_command("$mv $tmpcopy $object");

sub do_command()
my ($command) = @_;
my $ret;
if (($ret = system($command)) != 0) {
die("command \"$command\" failed $ret");

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to