I want to replace 'ld' with 'gcc' in my Makefile to link my kernel objects

465 Views Asked by At

In my project I have makefiles which build Solaris kernel modules, and they use gcc to compile files but use ld to link all .o files together into a kernel module. I am trying to include some coverage options like gcov (-fprofile-arcs) or tcov (-xprofile=tcov) in my build, hence I want to replace ld with gcc during linking also.

But as soon as I use replace gcc with ld, the builds start failing with lot of "undefined symbol" errors, even if I use some compile flags and get rid of these errors, the kernel module will not load into my Solaris kernel at all.

For example:

$ /usr/ccs/bin/ld -r -dy -Nstrmod/rpcmod -Nfs/nfs \
                  -Nmisc/rpcsec -Nmisc/klmmod -Nfs/zfs \
                  -o debug64/nfssrv \
                  debug64/nfs_server.o debug64/nfs_srv.o debug64/nfs3_srv.o \
                  debug64/nfs_acl_srv.o debug64/nfs_auth.o obj64/nfs41_srv.o \
                  obj64/ctl_ds_srv.o obj64/dserv_server.o

ld works fine but with gcc I get following errors:

/opt/gcc-4.4.4/bin/gcc -m64 -z muldefs \
                       -Lmod/rpcmod -Lfs/nfs -Lmisc/rpcsec \
                       -Lmisc/klmmod -Lfs/zfs \
                       -o obj64/nfssrv \
                       obj64/nfs_server.o obj64/nfs_srv.o obj64/nfs3_srv.o
                       obj64/nfs_acl_srv.o obj64/nfs_auth.o obj64/nfs41_srv.o 
                       obj64/ctl_ds_srv.o obj64/dserv_server.o

Undefined                       first referenced
 symbol                             in file
hz                                  obj64/nfs_server.o
p0                                  obj64/nfs_server.o
nfs_range_set                       obj64/nfs41_srv.o
getf                                obj64/nfs_server.o
log2                                obj64/nfs4_state.o
main                                /usr/lib/amd64/crt1.o
stoi                                obj64/ctl_ds_srv.o
dmu_object_alloc                    obj64/dserv_server.o
nvpair_name                         obj64/nfs4_srv.o
__dtrace_probe_nfss41__i__destroy_encap_session obj64/nfs41_srv.o
__dtrace_probe_nfssrv__i__dscp_freeing_device_entries obj64/ctl_ds_srv.o
mod_install                         obj64/nfs_server.o
xdr_faststatfs                      obj64/nfs_server.o
xdr_WRITE3res                       obj64/nfs_server.o
svc_pool_control                    obj64/nfs_server.o

2

There are 2 best solutions below

0
bruno On

Warning the option -L allows to specify a path where to search for libraries, to specify a library you want to link with you (also) have to use the option -l

So a priori you have to add the options -lrpcmod -lnfs -lrpcsec -lklmmod -lzfs

More details in GCC Linking Options

0
mfro On

By default, the GNU linker called through the gcc compiler driver will try to create a standard executable. Consequently, if you don't tell it otherwise, ld will use its default linker script, the C startup code and it will look for a main() routine and everything else that makes a valid executable.

I'm not too familiar with Solaris, but would bet this will not be suitable to build kernel modules. I would expect kernel modules will at least require some options like -ffreestanding, -nostdlibs and most likely a non-default linker script that's probably very different from the default one used for applications.

Even if you manage to link your kernel modules this way, I seriously doubt you will be finished. The gcov instrumentation routines most likely do not expect to live within a kernel driver but expect a proper C execution environment (e.g. it will at least expect to fopen() a file to fwrite() its findings). A kernel driver, however, does not have this comfort. You'll probably find yourself confronted with the problem to get the gcov data somehow out of your kernel modules.

Not saying this is not doable, but it certainly will be a lot of work.