2011-01-25 4 views
0

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

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

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

ответ

2

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

Я попытаюсь показать, как это работает с помощью практического примера. Вот некоторый 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 
000016b4 00000d06 R_386_GLOB_DAT 000016e0 hello 
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__ 
000016cc 00000507 R_386_JUMP_SLOT 000004fc please_say 
000016d0 00000807 R_386_JUMP_SLOT 00000540 say 
000016d4 00000307 R_386_JUMP_SLOT 00000000 printf 
000016d8 00000407 R_386_JUMP_SLOT 00000000 __cxa_finalize 

R_386_GLOB_DAT элемент для привета является записью 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 
000004d3 00000802 R_386_PC32  000004f0 say 
000004e0 00000502 R_386_PC32  000004cc please_say 
000004f7 00000d01 R_386_32   00001678 hello 
000004ff 00000302 R_386_PC32  00000000 printf 
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 

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

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

Ваша заявка будет оплачиваться за счет перемещения, но не независимости от позиции.