0

在我的项目中,我有构建 Solaris 内核模块的 makefile,它们用于gcc编译文件,但用于ld将所有.o文件链接到内核模块中。我试图在我的构建中包含一些覆盖选项,如 gcov ( -fprofile-arcs) 或 tcov ( -xprofile=tcov),因此我也想在链接期间替换ld为。gcc

但是一旦我使用 replace gccwith 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

4

2 回答 2

2

警告选项 -L 允许指定搜索库的路径,指定要与您链接的库(也)必须使用选项 -l

因此,您必须先添加选项-lrpcmod -lnfs -lrpcsec -lklmmod -lzfs

GCC 链接选项中的更多详细信息

于 2019-01-18T12:30:06.963 回答
0

默认情况下,通过gcc编译器驱动程序调用的 GNU 链接器将尝试创建一个标准的可执行文件。因此,如果你不告诉它,ld它将使用它的默认链接器脚本,C 启动代码,它会寻找一个main()例程和其他所有可以生成有效可执行文件的东西。

我对 Solaris 不太熟悉,但我敢打赌这不适合构建内核模块。我希望内核模块至少需要一些选项,例如-ffreestanding-nostdlibs并且很可能是一个非默认链接器脚本,它可能与用于应用程序的默认链接器脚本非常不同。

即使您设法以这种方式链接内核模块,我也严重怀疑您是否会完成。检测例程很可能不希望存在于内核驱动程序中,gcov而是希望有一个适当的 C 执行环境(例如,它至少希望将其发现的文件放在fopen()一个文件中fwrite())。然而,内核驱动程序没有这种舒适性。您可能会发现自己遇到了以gcov某种方式从内核模块中获取数据的问题。

不是说这不可行,但肯定会做很多工作。

于 2019-01-26T16:03:11.930 回答