tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kernel libraries and dead code in MODULAR kernels



On 3 Sep, 2015, at 18:08 , Masao Uebayashi <uebayasi%gmail.com@localhost> wrote:

> (Coming back to the original post.)
> 
> On Mon, Aug 31, 2015 at 10:55 AM, Dennis Ferguson
> <dennis.c.ferguson%gmail.com@localhost> wrote:
>> I've been compiling the same kernel configuration with and without
>> options MODULAR and noticed that the MODULAR kernels have a not
>> inconsiderable amount of code that is called neither by the kernel
>> nor any of the modules.  I've appended a list of the global symbols
>> from libkern.[ao] that end up being included in amd64 mostly-GENERIC
>> modular kernels that have no callers and are omitted from non-modular
>> kernel builds.
>> 
>> The reason for this is that while non-modular kernels build a libkern.a
>> from which only code that is actually called by something is loaded into
>> the kernel, modular kernels instead build a libkern.o from which everything
>> is unconditionally included.  While I understand why this is done (everything
>> is included in case the separately-compiled modules need it) it causes
>> a difficult problem if you would like to have a modular kernel without
>> the dead code.  A few of those functions are in fact no longer used and
>> could just be eliminated from the build, but the rest seem to end up
>> there either because their use depends on configuration options which may
>> or may not be defined, or they are members of a library that is also used
>> in user space that has a richer API there than the kernel makes use of, or
>> the use of particular functions (e.g. in the runtime library) is dependent
>> on the architecture being built.
> 
> Yes, finding unused functions is hard.  Not only in libkern, but also
> libc, or variables in abandaned `Makefile.kern.inc'.  Removing one
> needs so much mental energy (especially when those picky wandering).

I'm not so interested in ridding the kernel of all unused code (though
I suspect someone clever might be able to use the -ffunction-sections and
-fdata-sections compiler flags plus the ld --gc-sections option to
find some of it).  I'd be happy if modular and non-modular kernels
had the same unused stuff, and that libkern.a could be used when
building either.

It seems to me that both non-modular and modular kernels are both just
single programs at this point.  There is no guarantee that any module
will be useful with a kernel except those that are compiled with it,
as far as I can tell, so a modular kernel is pretty much the same program
as a non-modular kernel but built so that some of the program text doesn't
have to occupy memory if it isn't being used.  I don't really buy that building
a modular kernel turns /netbsd into a shared library.  The fact that the
modules are built before the "library" suggests something else.

>> I do notice that for modular kernels the modules are built before the kernel
>> is.  Is there no way to harvest the undefined global symbols from the modules
>> and include these to force the kernel link to resolve them?
> 
> I don't think there is one, even in userland.  Dependency is per-library/module.

What I would like just doesn't seem all that hard to me, it is just that build
tools are way outside my skill set so anything I did myself is guaranteed to
be an unseemly hack.

For a unseemly hack version, however, I've appended a shell script which, when
pointed at a full set of modules that might be used with a /netbsd being built,
may produce a .o file to link with the /netbsd that should guarantee the kernel
includes all globals from libkern.a required by the modules and cause a complaint
if the kernel is missing something.  It seems like someone who actually knows what
they're doing should be able to figure out a good way to enable loading against
libkern.a for modular kernels.

Dennis Ferguson


#! /bin/sh
#
# kmod_harvest.sh

MODDIR=/stand/amd64             # where modules are
UNDEF_DOT_O=needed_by_modules.o # .o with symbols kernel link must resolve

UNDEF_RAW=/tmp/undef$$.syms
DEF_RAW=/tmp/def$$.syms
C_TMP=/tmp/crap$$.c
OBJ_TMP=/tmp/crap$$.o

(cd ${MODDIR}; find . -name \*.kmod -exec nm -gu '{}' \;) | \
        sed -e 's/^  * U //' | sort | uniq > ${UNDEF_RAW}
(cd ${MODDIR}; find . -name \*.kmod -exec nm -g --defined-only '{}' \;) | \
        sed -e 's/^[^ ]* [ADRTW] //' | sort | uniq > ${DEF_RAW}

SYMS=""
for i in `comm -23 ${UNDEF_RAW} ${DEF_RAW}`; do
        SYMS="${SYMS} -u $i"
done

cp /dev/null ${C_TMP}
gcc -c -o ${OBJ_TMP} ${C_TMP}
eval ld -o ${UNDEF_DOT_O} -r ${SYMS} ${OBJ_TMP}
rm -f ${UNDEF_RAW} ${DEF_RAW} ${C_TMP} ${OBJ_TMP}





Home | Main Index | Thread Index | Old Index