使用ld创建非PIC共享库

时间:2018-02-21 08:41:30

标签: c linux linker ld

我有一堆没有-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)并且有一些额外的步骤。但它是等价的。

2 个答案:

答案 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为目标的端口]