почему /lib32/libc.so.6 содержит два символа "fopen"? - PullRequest
4 голосов
/ 06 февраля 2012
nm -D /lib32/libc.so.6 | grep '\<fopen\>'
0005d0c0 T fopen
00109750 T fopen

readelf -s  /lib32/libc.so.6 | egrep '0005d0c0|00109750'
181: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 fopen@@GLIBC_2.1
182: 00109750   136 FUNC    GLOBAL DEFAULT   12 fopen@GLIBC_2.0
679: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 _IO_fopen@@GLIBC_2.1
680: 00109750   136 FUNC    GLOBAL DEFAULT   12 _IO_fopen@GLIBC_2.0

вот мой вопрос:

  1. почему в /lib32/libc.so.6 есть два символа fopen?идентичный символ в том же файле назначения должен быть запрещен, верно?

  2. почему readelf -s выдает fopen @@ GLIBC_2.1 и fopen@GLIBC_2.0 вместо fopen?

Спасибо

Ответы [ 2 ]

9 голосов
/ 06 февраля 2012

Чтобы понять, что здесь происходит, сначала нужно понять, как двоичная совместимость традиционно обрабатывается.

Механизм, используемый для «внешнего управления версиями». Вы начали с libfoo.so.1, и когда вам нужно было изменить ABI существующей функции, вы были вынуждены ввести libfoo.so.2.

Приложения, которые были связаны до libfoo.so.2, продолжали использовать libfoo.so.1 со старым ABI, а новые приложения использовали libfoo.so.2 с новым ABI.

Это все подробно описано здесь .

Но затем glibc представил расширение , где вместо введения совершенно новой библиотеки (которая разделяет 99% кода с предыдущей версоном), вы вводите новый символ в существующую библиотеку.

Это расширение позволяет libc.so.6 оставаться в версии 6 в течение лет , при этом позволяя старым двоичным файлам работать и развиваться ABI.

В частном случае fopen в версии 2.1 glibc было сделано несовместимое изменение на struct FILE. Двоичные файлы, которые были связаны в системах glibc-2.0, продолжают использовать старый struct FILE (единственный, который был доступен тогда) и продолжают вызывать _IO_old_fopen (для которого fopen@GLIBC_2.0 является псевдонимом). Двоичные файлы, связанные с glibc-2.1 и новее, используют новый struct FILE и вызывают _IO_new_fopen (для которого fopen@GLIBC_2.1 является псевдонимом).

@@ - это просто обозначение, показывающее текущую стандартную версию символа.

3 голосов
/ 06 февраля 2012

На самом деле множественные определения одного и того же символа хороши и могут происходить разными способами. Один из них (а это не так) - слабые символы.

Здесь происходит то, что динамический компоновщик glibc поддерживает управление версиями символов, а glibc использует это. Он экспортирует версию fopen из glibc 2.1 и обратно совместимую версию из glibc 2.0 с различными интерфейсами.

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

...