Kernel linker and undefined references in KLD

Dmitry Krivenok krivenok.dmitry at gmail.com
Thu Jul 15 14:07:43 UTC 2010


Hello Hackers,

I have a question about kernel linker.
Please take a look at an example of simple module:

############################################################################
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/pcpu.h>

/* DECLARING A FUNCTION JUST TO AVOID WARNING WHICH IS TREAT AS ERROR
BY DEFAULT */
void seltdinit(struct thread* t);

static int event_handler(struct module *module, int event, void *arg)
{
  int e = 0;
  switch (event)
    {
      case MOD_LOAD:
        /* CALLING A FUNCTION DECLARED AS STATIC IN kern/sys_generic.c */
        seltdinit(curthread);
        break;
      case MOD_QUIESCE:
        break;
      case MOD_UNLOAD:
        break;
      case MOD_SHUTDOWN:
        break;
      default:
        e = EOPNOTSUPP;
        break;
    }

  return(e);
};
############################################################################

As you can see, this module calls seltdinit function declared as
_static_ in kern/sys_generic.c file.
I added a declaration of seltdinit function w/o static just to avoid
compilation error since -Werror is used
by default in FreeBSD.

Then I successfully built the module:

$ make
Warning: Object directory not changed from original
/usr/home/krived/work/freebsd/trouble
cc -O2 -pipe -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE
-nostdinc   -I. -I@ -I@/contrib/altq -finline-limit=8000 --param
inline-unit-growth=100 --param large-function-growth=1000 -fno-common
-fno-omit-frame-pointer  -mcmodel=kernel -mno-red-zone  -mfpmath=387
-mno-sse -mno-sse2 -mno-sse3 -mno-mmx -mno-3dnow  -msoft-float
-fno-asynchronous-unwind-tables -ffreestanding -fstack-protector
-std=iso9899:1999 -fstack-protector -Wall -Wredundant-decls
-Wnested-externs -Wstrict-prototypes  -Wmissing-prototypes
-Wpointer-arith -Winline -Wcast-qual  -Wundef -Wno-pointer-sign
-fformat-extensions -c trouble.c
ld  -d -warn-common -r -d -o trouble.ko trouble.o
:> export_syms
awk -f /sys/conf/kmod_syms.awk trouble.ko  export_syms | xargs -J%
objcopy % trouble.ko
objcopy --strip-debug trouble.ko
$

As expected, seltdinit symbol is undefined in trouble.ko file:
$ nm trouble.ko | grep seltdinit
                 U seltdinit
$
and is local in kernel binary file:
$ nm /boot/kernel/kernel | grep seltdinit
ffffffff805fda50 t seltdinit
$

I expected to get something like "undefined reference to seltdinit"
error, but the module was loaded w/o any errors:

$ sudo make load
/sbin/kldload -v /usr/home/krived/work/freebsd/trouble/trouble.ko
Loaded /usr/home/krived/work/freebsd/trouble/trouble.ko, id=2
$ kldstat | grep trouble
 2    1 0xffffffff81212000 126      trouble.ko
$ sudo make unload
/sbin/kldunload -v trouble.ko
Unloading trouble.ko, id=2
$

Could you please explain why the linker (or whatever is loading
modules in FreeBSD) doesn't complain?

For example, ld tool complains for the similar user-space example:

############################################################################
$ cat seltdinit.c
static void seltdinit(void* td)
{
  return;
}
$ cat main.c
void seltdinit(void* td);

int main()
{
  seltdinit(0);
  return 0;
}
$ gcc -Wall -c seltdinit.c
seltdinit.c:2: warning: 'seltdinit' defined but not used
$ gcc -Wall -c main.c
$ gcc seltdinit.o main.o -o sel
main.o: In function `main':
main.c:(.text+0xa): undefined reference to `seltdinit'
collect2: ld returned 1 exit status
$
############################################################################

Thanks in advance!

-- 
Sincerely yours, Dmitry V. Krivenok
e-mail: krivenok.dmitry at gmail.com
skype: krivenok_dmitry
jabber: krivenok_dmitry at jabber.ru
icq: 242-526-443


More information about the freebsd-hackers mailing list