Я разрабатываю для встраиваемой платформы, и мне трудно понять, как динамически связывать разделяемые библиотеки. Я использую формат файла 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, или как-то сделать адрес, по которому ответвления облицовки кода отображаются в списке? перераспределений?