我有一堆没有-fPIC
选项编译的目标文件。因此,对函数的调用不使用@PLT
。 (源代码是C,用clang
编译)。
我想将这些目标文件链接到一个共享库,我可以使用dlopen
在运行时加载它。我需要这样做,因为在加载实际的.so
之前我必须做很多设置。
但是每当我尝试链接-shared
选项时,我都会收到错误 -
在制作共享对象时,不能使用对符号
重新编译R_X86_64_PC32
的重定位splay_tree_lookup
;使用-fPIC
是否有一些我可以与ld
一起使用的标志,以便它生成重新定位库的加载时间。事实上,没有重新安置,我没事。我可以为库提供基地址,如果虚拟地址不可用,dlopen
可能会失败。
我用来编译c
文件的命令等同于 -
clang -m64 -c foo.c
用于链接我正在使用
clang -m64 -shared *.o -o foo.so
我说等效,因为它是一个自定义编译器(分叉clang
)并且有一些额外的步骤。但它是等价的。
答案 0 :(得分:2)
无法动态加载现有的非PIC对象,期望它可以正常工作。
如果无法重新编译原始代码以创建支持PIC的适当共享库,则建议您创建一个服务可执行文件,该可执行文件链接到由那些对象组成的静态库。然后,该服务可执行文件可以提供IPC / RPC / REST API /共享内存/任何内容,以允许程序使用您的目标代码。
然后,您可以编写一个共享库,该共享库由PIC编译,该库提供了包装器API,包装器API可以启动并与服务可执行文件进行通信以执行实际工作。
进一步考虑,此包装器API库也可能是静态的。它的动态方面是通过启动服务可执行文件来完成的。
答案 1 :(得分:-1)
如果可能的话,使用-fpic -shared
选项重新编译库的目标文件将是最好的选择!
man ld
说:
-i
执行增量链接(与选项-r相同)。
-r
--relocatable
生成可重定位输出-即生成一个输出文件,该输出文件又可用作
ld
的输入。这通常称为部分链接。副作用是,在支持标准Unix幻数的环境中,此选项还将输出文件的幻数设置为“ OMAGIC”。如果未指定此选项,则将生成一个绝对文件。链接C ++程序时,此选项不会解析对构造函数的引用;为此,请使用-Ur
。当输入文件的格式与输出文件的格式不同时,仅当该输入文件不包含任何重定位时,才支持部分链接。不同的输出格式可能会有更多限制。例如,某些基于“ a.out”的格式根本不支持与其他格式的输入文件进行部分链接。
我相信您可以将库对象文件部分链接到可重定位(PIC)库中,然后将该库与源代码对象文件链接以创建共享库。
ld -r -o libfoo.so *.o
cp libfoo.so /foodir/libfoo.so
cd foodir
clang -m32 -fpic -c foo.c
clang -m32 -fpic -shared *.o -o foo.so
关于库的基本地址:
(再次从man ld
开始)
--section-start=sectionname=org
在输出文件中的某个部分中,找到org给定的绝对地址。您可以根据需要多次使用此选项,以在命令行中找到多个部分。 org必须是一个十六进制整数;为了与其他链接程序兼容,您可以省略通常与十六进制值关联的前导0x。注意:sectionname,等号(“ =”)和org之间不应有空格。
您也许可以移动图书馆的.text
部分?
--image-base value
使用value作为程序或dll的基地址。这是加载程序或dll时将使用的最低内存位置。为了减少重新定位和提高dll性能的需要,每个dll应该具有唯一的基址,并且不与其他dll重叠。可执行文件的默认值为0x400000,dll文件的默认值为0x10000000。 [此选项特定于链接器的以i386 PE为目标的端口]