в GCC, как заставить разрешение символов во время выполнения - PullRequest
5 голосов
/ 01 июля 2010

Мой первый пост на этом сайте с огромной надеждой: я пытаюсь понять статические ссылки, динамические ссылки, общие библиотеки, статические библиотеки и т. Д. С помощью gcc.Каждый раз, когда я пытаюсь углубиться в эту тему, у меня появляется что-то, что я не совсем понимаю.

Некоторые практические работы:

bash$ cat main.c

#include "printhello.h"
#include "printbye.h"

void main()
{
PrintHello();
PrintBye();
}

bash$ cat printhello.h
void PrintHello();

bash$ cat printbye.h
void PrintBye();

bash$ cat printbye.c
#include <stdio.h>

void PrintBye()
{
printf("Bye bye\n");
}

bash$ cat printhello.c
#include <stdio.h>

void PrintHello()
{
printf("Hello World\n");
}

gcc -Wall -fPIC -c *.c -I.
gcc -shared -Wl,-soname,libcgreet.so.1 -o libcgreet.so.1.0   *.o
ln -sf libcgreet.so.1.0 libcgreet.so
ln -sf libcgreet.so.1.0 libcgreet.so.1

Итак, я создал общую библиотеку.Теперь я хочу связать эту общую библиотеку с моей основной программой для создания исполняемого файла.

gcc -Wall -L. main.c -lcgreet -o greet

Это очень хорошо работает, и если я установлю LD_LIBRARY_PATH перед запуском greet (или свяжу его с опцией rpath), я смогу заставить его работать.

Мой вопросоднако отличается: поскольку я в любом случае использую разделяемую библиотеку, невозможно ли принудительно разрешать символы во время выполнения (не уверен насчет терминологии, но, возможно, это называется динамическим связыванием в соответствии с книгой «Линкеры и загрузчики»).Я понимаю, что мы, возможно, не захотим делать это, потому что это замедляет работу программы и приводит к накладным расходам каждый раз, когда мы хотим запустить программу, но я пытаюсь понять это, чтобы очистить мои концепции.

Предоставляет ли компоновщик gccЛюбой вариант отложить разрешение символов во время выполнения?(чтобы сделать это с библиотекой, с которой мы фактически собираемся запустить программу) (поскольку библиотека, доступная во время компиляции, может отличаться от библиотеки, доступной во время выполнения, если какие-либо изменения в библиотеке), я хочу иметь возможность делать что-то вроде:

bash $ gcc main.c -I.

(какая опция здесь нужна?), Чтобы мне не приходилось давать имя библиотеки, и просто сказать ей, что я хочу сделать разрешение символов во время выполнения, чтобы заголовки были достаточно хороши на данный момент, фактическая библиотекаимена не нужны.

Спасибо, ученик навсегда.

Ответы [ 2 ]

9 голосов
/ 01 июля 2010

Любой компоновщик (gcc, ld или любой другой) разрешает ссылки только во время компиляции.Это потому, что стандарт ELF (как и большинство других) не определяет связь «во время выполнения», как вы описываете.Они либо связываются статически (то есть lib.a), либо во время запуска (lib.so, которое должно присутствовать при загрузке ELF).Однако, если вы используете динамическую ссылку, компоновщик вставит в ELF только имя файла и символы, которые он должен найти, он не связывает файл напрямую.Итак, если вы хотите обновить библиотеку до более новой версии позже, вы можете сделать это, если система может найти одно и то же имя файла (путь на самом деле может быть другим) и одинаковые имена символов.

Другой способ получения символов во время выполнения - использовать dlopen, который не имеет ничего общего с gcc или ld.dlopen Проще говоря, открывает библиотеку динамических ссылок, точно так же, как fopen, и возвращает вам дескриптор, который затем вы передаете dlsym с именем нужного вам символа, который может быть, например, именем функции,dlsym передаст вам указатель на этот символ, который вы затем сможете использовать для вызова функции или использовать в качестве переменной.Вот как реализованы плагины.

1 голос
/ 08 июня 2015

Я думаю, что вы ищете опцию ld '--unresolved-symbols = ignore-all', да, она действительно может это сделать (игнорировать предыдущий ответ). Представьте себе сценарий, когда разделяемая библиотека загружается поздно (когда программа уже запущена), она может использовать все символы, которые уже были разрешены / загружены основным процессом, и не нужно беспокоиться, чтобы сделать это снова. Кстати, это не нервно делает это медленно, по крайней мере на Linux

...