linux g ++, связывающий код 64-битной разделяемой библиотеки со статическими библиотеками

Контекст: я могу создать библиотеку общих объектов, которая без проблем работает на 32-битной Linux. Когда я пытаюсь сделать то же самое на 64-битной Linux, я вижу эту ошибку компоновщика:

  • перемещение R_X86_64_32S против `локального символа 'не может быть использовано при создании общего объекта; перекомпилировать с -fPIC

Эта ошибка довольно распространена в Интернете. Решение состоит в том, чтобы скомпилировать статически связанную библиотеку с позиционно-независимым кодом (-fPIC).

Я не понимаю, почему это не требуется для 32-битной сборки. Кто-нибудь может помочь?

9
задан Gearoid Murphy 23 August 2010 в 14:45
поделиться

2 ответа

Ок, ответ подробно описан здесь: http://www.technovelty.org/code/c/amd64-pic.html.

Суть объяснения в том, что архитектура i386 неявно разыменовывает указатель кадра для каждой функции (объясняется в последнем абзаце страницы по ссылке). Этот процесс влечет за собой некоторые дополнительные накладные расходы, поэтому в новых 64-битных архитектурах эти накладные расходы на разыменование были устранены в качестве оптимизации.

Следствием этой оптимизации с точки зрения связывания стало то, что если 64-битный код явно не скомпилирован как позиционно-независимый, он будет производить код, жестко закодированный со смещениями для своего контекста выполнения.

Это несовершенное объяснение содержания страницы по ссылке, но для моих целей его достаточно.

4
ответ дан 4 December 2019 в 22:26
поделиться

«Независимый от позиции код» всегда требуется, если ваш объектный модуль будет использоваться в разделяемой библиотеке. Это сильно зависит от платформы и влечет за собой некоторые накладные расходы.

Причина, по которой вы должны явно указывать его на amd64, но не на x386, заключается просто в том, что он используется по умолчанию для x86, но не для amd64.

Также обратите внимание на разницу между "-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. 
4
ответ дан 4 December 2019 в 22:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: