Создание перемещаемой общей библиотеки с помощью binutils - PullRequest
0 голосов
/ 25 января 2011

У меня есть собственный набор инструментов, который генерирует перемещаемые общие библиотеки. Это работает с одинаково настраиваемым загрузчиком ELF, который загружает их в память, исправляя их. Сейчас я пытаюсь убедить gcc и binutils создать файлы ELF, совместимые с этим загрузчиком.

К сожалению, похоже, что binutils отказывается генерировать перемещаемые общие объекты. Он будет генерировать общие объекты PIC, но я не хочу этого делать из-за дополнительных затрат GOT / PLT (и, кроме того, пользовательский загрузчик ELF не поддерживает его). И он будет генерировать перемещаемые объекты, но тогда они не являются динамическими объектами и поэтому не имеют соответствующих разделов, которые загрузчик ELF хочет иметь для их загрузки.

Мне не ясно, почему GNU ld отказывается разрешить мне указывать --relocatable и -shared в одной командной строке. Кто-нибудь может просветить меня? А кто-нибудь знает, что заставляет ld генерировать искомые объектные файлы?

1 Ответ

2 голосов
/ 04 июля 2011

Я вижу, что никто не ответил на этот вопрос, поэтому я думаю, что я попробую.

Я попытаюсь показать на практическом примере, как это работает.Вот некоторый C-код, который имеет искусственное, но целенаправленное сочетание внешних глобальных функций и данных - хлеб с маслом перемещений.

/* hello.c */
char* hello = "hello";

/* say.c */
#include "stdio.h"
extern char* hello;
void say(void){
    printf(hello);
}

/* main.c */
extern void say(void);
void please_say(void){
    say();
}
int main(void){
    please_say();
    return 0;
}

Теперь обычным способом получения общего объекта / библиотеки будетскомпилировать каждый файл C с -fPIC и связать партию с -shared.После того, как мы это сделаем, мы можем использовать readelf для проверки перемещений.Примерно так:

gcc -fPIC -c *.c
gcc -shared -o libtemp.so *.o

readelf -r libtemp.so

Данные о перемещении выглядят следующим образом:

Relocation section '.rel.dyn' at offset 0x34c contains 6 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
000016dc  00000008 R_386_RELATIVE
000016e0  00000008 R_386_RELATIVE
000016ac  00000106 R_386_GLOB_DAT    00000000   __gmon_start__
000016b0  00000206 R_386_GLOB_DAT    00000000   _Jv_RegisterClasses
<b>000016b4  00000d06 R_386_GLOB_DAT    000016e0   hello</b>
000016b8  00000406 R_386_GLOB_DAT    00000000   __cxa_finalize

Relocation section '.rel.plt' at offset 0x37c contains 5 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
000016c8  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__
<b>000016cc  00000507 R_386_JUMP_SLOT   000004fc   please_say</b>
<b>000016d0  00000807 R_386_JUMP_SLOT   00000540   say</b>
<b>000016d4  00000307 R_386_JUMP_SLOT   00000000   printf</b>
000016d8  00000407 R_386_JUMP_SLOT   00000000   __cxa_finalize

Элемент R_386_GLOB_DAT для hello - это запись GOT.Аналогично, элементы R_386_JUMP_SLOT для скажем, please_say и printf являются записями PLT.Они происходят от использования позиционно-независимого кода, а не от того, что мы создали общий объект.

После выполнения одного и того же процесса сборки без -fPIC мы получаем различные перемещения.Итак,

gcc -c *.c
gcc -shared -o libtemp.so *.o

readelf -r libtemp.so

дает нам

Relocation section '.rel.dyn' at offset 0x34c contains 9 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00001674  00000008 R_386_RELATIVE
00001678  00000008 R_386_RELATIVE
<b>000004d3  00000802 R_386_PC32        000004f0   say</b>
<b>000004e0  00000502 R_386_PC32        000004cc   please_say</b>
<b>000004f7  00000d01 R_386_32          00001678   hello</b>
<b>000004ff  00000302 R_386_PC32        00000000   printf</b>
00001654  00000106 R_386_GLOB_DAT    00000000   __gmon_start__
00001658  00000206 R_386_GLOB_DAT    00000000   _Jv_RegisterClasses
0000165c  00000406 R_386_GLOB_DAT    00000000   __cxa_finalize

Relocation section '.rel.plt' at offset 0x394 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000166c  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__
00001670  00000407 R_386_JUMP_SLOT   00000000   __cxa_finalize

Теперь общий объект имеет знакомые перемещения для всех определений.Существует абсолютное перемещение hello и относительное перемещение PC для функций.

Что это значит?Ну, таблицы GOT и PLT все еще там.Следует отметить две важные вещи.Во-первых, для скомпилированного кода нет записей GOT или PLT.Во-вторых, таблицы GOT и PLT все еще нужны.Они используются для инициализации и очистки (возможно, для стандартной библиотеки).Поскольку вы используете пользовательский загрузчик ELF, вероятно, было бы целесообразно реализовать некоторую базовую поддержку записей GOT и PLT, даже если вместо этого ваше основное приложение выполняет стандартные перемещения.

После этого ваше приложение будет платить стоимость перемещения., но не от позиции независимости.

...