linux g++ linking 64 bit shared library code to static libraries

时间:2022-09-18 11:48:02

Context: I can create a shared object library which is linked to a static library without any problems on 32bit linux. When I attempt the same build on 64bit linux, I see this linker error:

上下文:我可以创建一个链接到静态库的共享对象库,在32位linux上没有任何问题。当我在64位linux上尝试相同的构建时,我看到这个链接器错误:

  • relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
  • 在制作共享对象时,不能使用针对“本地符号”的重定位R_X86_64_32S;用-fPIC重新编译

This error is quite common on the web. The solution is to compile the statically linked library with position independent code (-fPIC).

这个错误在网络上很常见。解决方案是使用位置无关代码(-fPIC)编译静态链接库。

What I do not understand is why this is not required for the 32bit build. Can anyone help out?

我不明白为什么32bit版本不需要这个。任何人都可以帮忙吗?

2 个解决方案

#1


4  

"Position Independent Code" is always required if your object module will be used in a shared library. It's highly platform dependent, and it incurs some overhead.

如果您的目标模块将在共享库中使用,则始终需要“位置无关代码”。它依赖于高度平台,并且会产生一些开销。

The reason you have to specify it explicitly on amd64, but not x386, is simply that it happens to be the default for x86, but not amd64.

你必须在amd64上明确指定它而不是x386的原因只是它恰好是x86的默认值,而不是amd64。

Note, too, the difference between "-fpic" and "-fPIC":

另请注意,“-fpic”和“-fPIC”之间的区别:

-fpic
    Generate position-independent code (PIC) suitable for use in a 
    shared library, if supported for the target machine. Such code 
    accesses all constant addresses through a global offset table 
    (GOT). The dynamic loader resolves the GOT entries when the pro-
    gram starts (the dynamic loader is not part of GCC; it is part
    of the operating system). If the GOT size for the linked execu-
    table exceeds a machine-specific maximum size, you get an error 
    message from the linker indicating that -fpic does not work; in 
    that case, recompile with -fPIC instead. (These maximums are 8k 
    on the SPARC and 32k on the m68k and RS/6000. The 386 has no 
    such limit.)

    Position-independent code requires special support, and there
    fore works only on certain machines. For the 386, GCC supports 
    PIC for System V but not for the Sun 386i. Code generated for 
    the IBM RS/6000 is always position-independent.

    When this flag is set, the macros __pic__ and __PIC__ are defined to 1.

-fPIC
    If supported for the target machine, emit position-independent 
    code, suitable for dynamic linking and avoiding any limit on the 
    size of the global offset table. This option makes a difference 
    on the m68k, PowerPC and SPARC.

    Position-independent code requires special support, and therefore 
    works only on certain machines.

    When this flag is set, the macros __pic__ and __PIC__ are defined to 2. 

#2


4  

Ok the answer is described in detail here: http://www.technovelty.org/code/c/amd64-pic.html.

好的答案在这里详细描述:http://www.technovelty.org/code/c/amd64-pic.html。

The basic gist of the explanation is that the i386 architecture implicitly dereferences the frame pointer for each function (explained on the last paragraph of the linked page). This process incurs some extra overhead so in the new 64-bit architectures, this dereferencing overhead was eliminated as an optimization.

解释的基本要点是i386架构隐式取消引用每个函数的帧指针(在链接页面的最后一段解释)。此过程会产生一些额外开销,因此在新的64位体系结构中,这种解除引用开销作为优化被消除。

The consequence of this optimization from a linking perspective was that unless 64-bit code is explicitly compiled as position independent code, it will produce code that is hard-coded with offsets for its execution context.

从链接角度来看,这种优化的结果是,除非将64位代码显式编译为与位置无关的代码,否则它将生成使用其执行上下文的偏移量进行硬编码的代码。

This is an imperfect explanation of the content in the linked page but it suffices for my purposes.

这是对链接页面中内容的不完美解释,但它足以满足我的目的。

#1


4  

"Position Independent Code" is always required if your object module will be used in a shared library. It's highly platform dependent, and it incurs some overhead.

如果您的目标模块将在共享库中使用,则始终需要“位置无关代码”。它依赖于高度平台,并且会产生一些开销。

The reason you have to specify it explicitly on amd64, but not x386, is simply that it happens to be the default for x86, but not amd64.

你必须在amd64上明确指定它而不是x386的原因只是它恰好是x86的默认值,而不是amd64。

Note, too, the difference between "-fpic" and "-fPIC":

另请注意,“-fpic”和“-fPIC”之间的区别:

-fpic
    Generate position-independent code (PIC) suitable for use in a 
    shared library, if supported for the target machine. Such code 
    accesses all constant addresses through a global offset table 
    (GOT). The dynamic loader resolves the GOT entries when the pro-
    gram starts (the dynamic loader is not part of GCC; it is part
    of the operating system). If the GOT size for the linked execu-
    table exceeds a machine-specific maximum size, you get an error 
    message from the linker indicating that -fpic does not work; in 
    that case, recompile with -fPIC instead. (These maximums are 8k 
    on the SPARC and 32k on the m68k and RS/6000. The 386 has no 
    such limit.)

    Position-independent code requires special support, and there
    fore works only on certain machines. For the 386, GCC supports 
    PIC for System V but not for the Sun 386i. Code generated for 
    the IBM RS/6000 is always position-independent.

    When this flag is set, the macros __pic__ and __PIC__ are defined to 1.

-fPIC
    If supported for the target machine, emit position-independent 
    code, suitable for dynamic linking and avoiding any limit on the 
    size of the global offset table. This option makes a difference 
    on the m68k, PowerPC and SPARC.

    Position-independent code requires special support, and therefore 
    works only on certain machines.

    When this flag is set, the macros __pic__ and __PIC__ are defined to 2. 

#2


4  

Ok the answer is described in detail here: http://www.technovelty.org/code/c/amd64-pic.html.

好的答案在这里详细描述:http://www.technovelty.org/code/c/amd64-pic.html。

The basic gist of the explanation is that the i386 architecture implicitly dereferences the frame pointer for each function (explained on the last paragraph of the linked page). This process incurs some extra overhead so in the new 64-bit architectures, this dereferencing overhead was eliminated as an optimization.

解释的基本要点是i386架构隐式取消引用每个函数的帧指针(在链接页面的最后一段解释)。此过程会产生一些额外开销,因此在新的64位体系结构中,这种解除引用开销作为优化被消除。

The consequence of this optimization from a linking perspective was that unless 64-bit code is explicitly compiled as position independent code, it will produce code that is hard-coded with offsets for its execution context.

从链接角度来看,这种优化的结果是,除非将64位代码显式编译为与位置无关的代码,否则它将生成使用其执行上下文的偏移量进行硬编码的代码。

This is an imperfect explanation of the content in the linked page but it suffices for my purposes.

这是对链接页面中内容的不完美解释,但它足以满足我的目的。