Размещайте независимый код, разделяемые библиотеки и виниры кода - заставляя их работать вместе - PullRequest
6 голосов
/ 03 апреля 2012

Я занимаюсь разработкой для встраиваемой платформы, и мне трудно разобраться, как динамически связывать разделяемые библиотеки.Я использую формат файла bFLT и не могу контролировать, куда загружается исполняемая и разделяемая библиотека.

Мой загрузчик правильно загружает разделяемую библиотеку и исполняемый файл в память и изменяет GOT исполняемого файла во время выполнения, чтобы связать его с разделяемой библиотекой.

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

Оказывается, GCC добавляет «кодовую оболочку» при вызове функций совместно используемой библиотеки и делает обход, когда функция вызывается и фактически не ветвитсяпо адресу функции.Адрес, на который ветвится кодовый шпон, не перемещен должным образом, потому что он не отображается в списке перемещений в исполняемом двоичном файле.

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

000008d0 <__library_call_veneer>:
 8d0:   e51ff004    ldr pc, [pc, #-4]   ; 8d4 <__library_call_veneer+0x4>
 8d4:   03000320    .word   0x03000320  ; This address isn't correctly relocated!

Если я возьму адрес функции и вставлю его в указатель функции (следовательно, обходя «кодовую оболочку») и вызову его, совместно используемая библиотека будет работать отлично.

Так, например:

#define DIRECT_LIB_CALL(x, args...) do { \
        typeof(x) * volatile tmp = x; \
        tmp(#args); \
    } while (0)

DIRECT_LIB_CALL(library_call); /* works */
library_call(); /* crashes */

Есть ли способ либо сказать GCC, чтобы он не создавал кодовый шпон и разветвлялся непосредственно по адресу, расположенному в GOT, либо каким-либо образом сделать адрес, который ветвями кодового шпона, отображается в списке перемещенийвыполнять?

1 Ответ

2 голосов
/ 04 апреля 2012

Я нашел решение этой проблемы.Это не самый лучший или самый чистый метод, но он выполняет свою работу в моем случае.

Я воспользовался опцией --wrap в моем компоновщике, которая перенаправляет символы на __wrap_symbol.После этого я установил скрипт awk, который автоматически генерирует файлы ASM, которые загружают правильно перемещенный адрес в компьютер.Любые вызовы библиотеки будут перенаправлены на этот код.По сути, я делал свои собственные виниры кода.Поскольку на сгенерированный винир кода не ссылались, он просто был оптимизирован.

Кроме того, мне пришлось поместить виниры в раздел .data, так как все в разделе .text было перемещено неправильно.Поскольку платформа, над которой я работаю, не сильно различает код и данные, этот хакерский обходной путь работает.

Вот ссылка на проект, над которым я работаю, где выможно посмотреть конкретику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...