在我的项目中,我拥有用于构建Solaris内核模块的makefile,它们使用gcc
编译文件,但是使用ld
将所有.o
文件链接在一起成为一个内核模块。我试图在构建中包括gcov(-fprofile-arcs
)或tcov(-xprofile=tcov
)之类的覆盖率选项,因此我也想在链接期间用ld
替换gcc
。
但是,一旦我使用gcc
替换ld
,构建就开始失败,并出现许多“未定义符号”错误,即使我使用了一些编译标志并摆脱了这些错误,内核模块根本不会加载到我的Solaris内核中。
例如:
$ /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
可以正常工作,但是使用gcc
时出现以下错误:
/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
答案 0 :(得分:2)
警告选项-L允许指定搜索库的路径,指定要与您链接的库(也),必须使用选项-l
因此,您必须先添加选项-lrpcmod -lnfs -lrpcsec -lklmmod -lzfs
答案 1 :(得分:0)
默认情况下,通过gcc
编译器驱动程序调用的GNU链接器将尝试创建标准可执行文件。因此,如果您没有其他说明,ld
将使用其默认的链接程序脚本,C启动代码,并会寻找main()
例程以及所有可生成有效可执行文件的程序。>
我对Solaris不太熟悉,但是可以肯定,这不适用于构建内核模块。我希望内核模块至少需要一些选项,例如-ffreestanding
,-nostdlibs
,并且很可能是一种非默认的链接脚本,该脚本可能与用于应用程序的默认链接脚本有很大差异。
即使您设法以这种方式链接内核模块,我也严重怀疑您是否会完成。 gcov
检测例程最有可能不希望驻留在内核驱动程序中,而是希望有合适的C执行环境(例如,它至少希望fopen()
个文件来fwrite()
发现) 。但是,内核驱动程序没有这种舒适感。您可能会遇到问题,无法以某种方式从内核模块中获取gcov
数据。
并不是说这是行不通的,但是肯定会做很多工作。