У меня большой программный проект со сложным процессом сборки, который работает так:
- Компиляция отдельных исходных файлов.
- Частично связать объектные файлы для каждого модуля вместе в другой .o, используя
ld -r
.
- Скрыть личные символы в каждом модуле, используя
objcopy -G
.
- Частично объединить объекты модуля, снова используя
ld -r
.
- Объединение модулей в общий объект.
Шаг 3 необходим, чтобы разрешить глобальные переменные, закрытые для модуля, которые не экспортируются в остальную часть проекта.
Это все отлично работает с ARM и IA32. К сожалению, теперь я должен заставить все работать на mips (в частности, mipsel-linux-gnu для Android). И общий объект MIPS ABI значительно сложнее, чем на других платформах, и он не работает.
Происходит следующее: шаг 5 не выполняется с этой ошибкой:
CALL16 reloc at 0x1234 not against global symbol
Это происходит потому, что компилятор генерирует перемещения CALL16 для вызова функций в другом модуле компиляции, но CALL16 позволяет вам вызывать только глобальные символы - и на шаге 3 некоторые из символов, которые мы пытаемся вызвать больше не глобальны.
На данный момент я вижу несколько возможных вариантов:
- убедить компоновщика разрешить перемещение CALL16 в обычные вызовы, относящиеся к компьютеру внутри компиляции, на шаге 2.
- То же самое, но на шаге 4 или 5.
- сказать компилятору не генерировать перемещения CALL16 для вызовов функций между компиляторами.
- другой.
Отключение шага 3, боюсь, не вариант из-за внешних требований.
Что я действительно, действительно хотел бы сделать, так это генерировать абсолютный код, который исправляется во время загрузки по нужным адресам; он меньше, намного быстрее и значительно проще, и нам не нужно делить библиотеку между процессами. К сожалению, похоже, что Android dlopen()
не поддерживает это.
В настоящее время я вне моей глубины. У кого-нибудь есть предложения?
Это gcc 4.4.5 (от Emdebian), binutils 2.20.1. Целевой BFD - elf32-tradlittlemips. Хост-ОС - это Linux, и я кросс-компилирую для Android.
Добавление
Я также получаю подобные предупреждения с шага 4.
$MODULE.o: Can't find matching LO16 reloc against `$SYMBOLNAME' for R_MIPS_GOT16 at 0x18 in section `.text.$SYMBOLNAME'
Глядя на разбор входных данных для шага 4, я вижу, что сгенерированный код компилятора выглядит так:
50: 8f9e0000 lw s8,0(gp)
50: R_MIPS_GOT16 $SYMBOLNAME
54: 8fd9001c lw t9,28(s8)
58: 0320f809 jalr t9
5c: 00a02021 move a0,a1
Разве GOT16 не фиксирует до верхней половины адреса, и следует ли с LO16 для нижней половины? Но код выглядит так, как будто он пытается сделать GOT-перенаправление. Это озадачивает меня. Я понятия не имею, связано ли это с моей предыдущей проблемой, или это другая проблема, или это вообще не проблема ...
Update
Очевидно MIPS просто не поддерживает скрытые глобальные символы!
Мы обошли это путем искажения названий символов, которые должны быть скрыты, чтобы никто не мог сказать, кто они. Это сильно подталкивает внешние требования, но я продал управление им, указав, что это был единственный способ получить отправляемый продукт.
Это абсолютно ужасно (и включает в себя какую-то очень отвратительную работу с make-файлом), поэтому я бы предпочел лучшее решение, если у кого-то есть такое ...