Как линковщик находит в статической библиотеке функции?

Модератор: Модераторы разделов

Аватара пользователя
жучара
Сообщения: 950
ОС: астралинукс

Как линковщик находит в статической библиотеке функции?

Сообщение жучара »

Друзья! То есть если у нас есть статическая библиотека (libhello.a), например, с двумя функциями (foo() и bar()), и исходник main.c исполнимого файла, в котором две эти функции вызываются:

Код: Выделить всё

/* main.c */
#include "hello.h"
int main(void)
{
        foo();
        bar();
        return 0;
}
Всё, теперь если мы кропаем исходный файл вот так вот:

Shell

$ gcc -o main main.o -L. -lhello
$
То если libhello.a скропан без ошибок, то на выходе- исполняемый файл main, в котором две эти функции вызываются.
Так, а теперь вот в последней команде, кропается исполняемый файл main, в котором должны быть два безусловных перехода (или прыжка, как угодно), на адреса (смещения, как угодно), где эти функции лежат. Но эти функции в файле libhello.a непонятно где, их там просто не найти.

Shell

$ nm libhello.a

file_foo.o:
0000000000000000 T foo
0000000000000000 r __FUNCTION__.0
U _GLOBAL_OFFSET_TABLE_
U printf
U putchar

file_bar.o:
0000000000000000 T bar
0000000000000000 r __FUNCTION__.0
U _GLOBAL_OFFSET_TABLE_
U printf
U putchar
$
Что foo, что bar лежат по одному и тому же адресу, что асбурдно. То есть непонятно, где их там тела находится, в чём, собсно и состоит вопрос.

На всякий случай исходники file_foo.c и file_bar.c и хидер:

Код: Выделить всё

/* file_foo.c */
#include <stdio.h>
#include "hello.h"

void foo (void)
{
        printf (__FUNCTION__);
        printf ("\n");
}

Код: Выделить всё

/* file_bar.c */
#include <stdio.h>
#include "hello.h"

void bar (void)
{
        printf (__FUNCTION__);
        printf ("\n");
}

Код: Выделить всё

/* hello.h */

void foo();
void bar();
И полный набор команд:

Shell

$ gcc -c file_foo.c
$ gcc -c file_bar.c
$ ar crs libhello.a file_foo.o file_bar.o
$ gcc -o main main.c -L. -lhello
$ ./main
foo
bar
$
─────────────────────────────

И просто такое наблюдение: если функции будут определены в одном файле, и из него будет скропан объектный файл, то там уже адреса есть, пожалуйста, как, по логике вещей и должно быть:

Код: Выделить всё

/* file_foo_bar.c */
#include <stdio.h>
#include "hello.h"

void foo (void)
{
        printf (__FUNCTION__);
        printf ("\n");
}
void bar (void)
{
        printf (__FUNCTION__);
        printf ("\n");
}

Shell

$ gcc -c file_foo_bar.c
$ nm file_foo_bar.o
0000000000000022 T bar
0000000000000000 T foo
0000000000000004 r __FUNCTION__.0
0000000000000000 r __FUNCTION__.1
U _GLOBAL_OFFSET_TABLE_
U printf
U putchar
$
В общем, странно всё это. Есть, конечно, глупое предположение, что оно всё подряд перебирает в файле libhello.a, символ за символом и тело нужной функции, лежит, например, по фиксированному смещению за соответствующим символом. То есть нашли символ (например, bar) ТУПЫМ перебором, отсчитали от него фиксированное количество байт и получаем адрес- в нашем случае, адрес, куда должен осуществляться безусловный переход при вызове функции bar(). Да не может такого быть. В общем, спасибо, кто откликнется.
Последний раз редактировалось Bizdelnick 08.08.2022 23:39, всего редактировалось 1 раз.
Причина: тег code
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20834
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Как линковщик находит в статической библиотеке функции?

Сообщение Bizdelnick »

Применительно к архиву смещение символа не имеет смысла. Оно указывается относительно объектных файлов, которых в архиве несколько. Имеет смысл только пара файл внутри архива + смещение в нём. Линковщик сначала находит файл, содержащий символ, по индексу архива, а потом — смещение символа в самом файле.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 950
ОС: астралинукс

Re: Как линковщик находит в статической библиотеке функции?

Сообщение жучара »

Bizdelnick писал:
08.08.2022 23:48
Применительно к архиву смещение символа не имеет смысла. Оно указывается относительно объектных файлов, которых в архиве несколько. Имеет смысл только пара файл внутри архива + смещение в нём. Линковщик сначала находит файл, содержащий символ, по индексу архива, а потом — смещение символа в самом файле.
а как он находит файл? Простым перебором содержимого архива?
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20834
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Как линковщик находит в статической библиотеке функции?

Сообщение Bizdelnick »

жучара писал(а):
09.08.2022 00:11
а как он находит файл?
Bizdelnick писал:
08.08.2022 23:48
по индексу архива
Если индекса нет, то перебором, конечно.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 950
ОС: астралинукс

Re: Как линковщик находит в статической библиотеке функции?

Сообщение жучара »

Bizdelnick писал:
09.08.2022 00:35
жучара писал(а):
09.08.2022 00:11
а как он находит файл?
Bizdelnick писал:
08.08.2022 23:48
по индексу архива
я так понимаю, по индексу архива он может найти имя файла, содержащего нужный символ- в нашем случае имя функции. А сам-то файл как?

Shell

$ nm -s libhello.a

Индекс архива:
foo in file_foo.o
bar in file_bar.o

file_foo.o:
0000000000000000 T foo
0000000000000000 r __FUNCTION__.0
U _GLOBAL_OFFSET_TABLE_
U printf
U putchar

file_bar.o:
0000000000000000 T bar
0000000000000000 r __FUNCTION__.0
U _GLOBAL_OFFSET_TABLE_
U printf
U putchar
$
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20834
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Как линковщик находит в статической библиотеке функции?

Сообщение Bizdelnick »

жучара писал(а):
09.08.2022 00:39
я так понимаю, по индексу архива он может найти имя файла, содержащего нужный символ- в нашем случае имя функции. А сам-то файл как?
Сам файл — да, перебором. Это же потоковый архив. Но файлов обычно не так много, так что это не проблема.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 950
ОС: астралинукс

Re: Как линковщик находит в статической библиотеке функции?

Сообщение жучара »

Bizdelnick писал:
09.08.2022 00:56
жучара писал(а):
09.08.2022 00:39
я так понимаю, по индексу архива он может найти имя файла, содержащего нужный символ- в нашем случае имя функции. А сам-то файл как?
Сам файл — да, перебором. Это же потоковый архив. Но файлов обычно не так много, так что это не проблема.
ясно. А потом он может просто-напросто обратиться к объектному файлу, используя его официальную структуру, и все нужные символы в нём найти.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 901
ОС: debian, fedora (i3-wm)

Re: Как линковщик находит в статической библиотеке функции?

Сообщение olecya »

жучара
Не обращайте внимание на сам архив, это дело организации доступа и хранения. Представьте что у вас просто набор объектных файлов (nm *.o). Или для чистоты эксперимента создавайте архив из файлов с двумя функциями (или создайте архив из одного объектного файла file_foo_bar.o) и вы увидите что адрес (смещение для линковщика) по каждой функции относительно объектного файла в архиве есть. Даже в вашем варианте, где функции представлены с нулевым смещением в каждом из файлов это и есть адрес, а не его отсутствие.
Спасибо сказали: