• Если при динамической загрузке разделяемой библиотеки (см. подраздел 42.1.1) указать в функции dlopen() флаг RTLD_GLOBAL, то символы, определенные в этой библиотеке, будут доступны для привязки только тем библиотекам, которые загружаются после нее. Параметр компоновщика — export — dynamic позволяет сделать глобальные символы главной программы доступными для динамически загружаемых библиотек.

Больше подробностей о видимости символов см. в [Drepper, 2004 (b)].

42.3. Версионные сценарии компоновщика

Версионный сценарий — это текстовый файл, содержащий инструкции для компоновщика, ld. Чтобы использовать версионный сценарий, компоновщику следует указать параметр — version-script:

$ gcc — Wl, — version-script,myscriptfile.map…

Версионные сценарии обычно (но не всегда) имеют расширение. map. Некоторые из способов их применения описаны в следующих подразделах.

42.3.1. Управление видимостью символов с помощью версионных сценариев

Одно из применений версионных сценариев заключается в управлении видимостью символов, которые могут случайно стать глобальными (то есть доступными для приложения, скомпонованного с этой библиотекой). В качестве простого примера рассмотрим такую ситуацию: мы собираем разделяемую библиотеку из трех исходных файлов — vis_comm.c, vis_f1.c и vis_f2.c, в которых определены функции vis_comm(), vis_f1() и vis_f2() соответственно. Функция vis_comm() не рассчитана на непосредственный доступ из приложений, скомпонованных с библиотекой, и должна вызываться из vis_f1() и vis_f2(). Представьте, что мы собираем эту библиотеку обычным способом:

$ gcc — g — c — fPIC — Wall vis_comm.c vis_f1.c vis_f2.c

$ gcc — g — shared — o vis.so vis_comm.o vis_f1.o vis_f2.o

Если вывести с помощью следующей команды readelf динамические символы, экспортируемые библиотекой, то можно увидеть следующее:

$ readelf — syms — use-dynamic vis.so | grep vis_

30 12: 00000790 59 FUNC GLOBAL DEFAULT 10 vis_f1

25 13: 000007d0 73 FUNC GLOBAL DEFAULT 10 vis_f2

27 16: 00000770 20 FUNC GLOBAL DEFAULT 10 vis_comm

Эта разделяемая библиотека экспортирует три символа: vis_comm(), vis_f1() и vis_f2(). Однако нам нужно, чтобы экспортировались только символы vis_f1() и vis_f2(). Для этого можно воспользоваться следующим версионным сценарием:

$ cat vis.map

VER_1 {

global:

vis_f1;

vis_f2;

local:

*;

};

Идентификатор VER_1 является примером версионной метки. Как вы увидите в подразделе 42.3.2, версионный сценарий может содержать множество таких разделов, заключенных в фигурные скобки ({}) и обозначенных уникальной версионной меткой. Если нужно всего лишь управлять видимостью символов, то данную метку можно опустить; так позволено делать в современных версиях утилиты ld, хотя старые версии этого компоновщика требуют ее наличия. В данном случае мы используем анонимную версионную метку, при этом в сценарии больше не должно содержаться ни одного другого раздела.

Внутри раздела находится ключевое слово global, после которого через точку с запятой перечисляются символы, видимые за пределами библиотеки. Ключевое слово local описывает символы, не скрытые от внешнего мира. Для этого можно использовать шаблоны, такие как звездочка (*). Данные шаблоны аналогичны тем, что применяются при поиске по именам файлов — например, * и? (больше подробностей см. на странице glob(7) руководства). В нашем примере звездочка в списке local говорит о том, что все символы, не перечисленные в подразделе global, будут скрыты. Без этого функция vis_comm() осталась бы видимой, поскольку глобальные символы в языке C по умолчанию доступны внешним разделяемым библиотекам.

Теперь можно собрать разделяемую библиотеку, используя версионный сценарий:

$ gcc — g — c — fPIC — Wall vis_comm.c vis_f1.c vis_f2.c

$ gcc — g — shared — o vis.so vis_comm.o vis_f1.o vis_f2.o \

— Wl, — version-script,vis.map

При повторном вызове команды readelf можно увидеть, что функция vis_comm() больше не доступна извне:

$ readelf — syms — use-dynamic vis.so | grep vis_

25 0: 00000730 73 FUNC GLOBAL DEFAULT 11 vis_f2

29 16: 000006f0 59 FUNC GLOBAL DEFAULT 11 vis_f1

42.3.2. Версионирование символов

Перейти на страницу:

Похожие книги