Автор Тема: Къде се намира so?  (Прочетена 8655 пъти)

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8768
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Къде се намира so?
« -: May 14, 2016, 18:43 »
Здравейте,

На който бог на Ц не му се четат дрънканици, да иде направо на последното изречение. Goto END; (любимият ми оператор)

=*=

Напоследък не съм наминавал, но то е и защото освен експерименти с bash, си правя такива с Ц. Трябва да кажа, че опити с Ц и Ц++ си правя от мно-о-ого години с го-о-о-олеми прекъсвания. Все още много неща ми звучат като черна магия.

Днешният казус. Просто ме гложди.

Ако искам да ползвам някаква  библиотека трябва да вкарам заглавката ѝ. Например:

Код
GeSHi (C):
  1. #include <X11/Xlib.h>

Т'ва например е за Xlib. Обаче Ц не знае де трябва да го търси. При цомпилиране трябва да кажем. Например:

Код
GeSHi (Bash):
  1. gcc -g -Wall -o intro intro.c $(pkg-config --libs --cflags x11)

Всъщност изхода от подкомандата е „-lX11“. Който и pc да отворите отдолу пише само -l*.

Разглеждал съм и много заглавки (*.h), но вътре са описани само, какви неща са изнесени от библиотеката за ползване. Не пише, къде да се търсят.

Добре де, въпроса е как точно вече транслираната програма знае, къде точно се намира споделената библиотека? Аз например знам къде е, защото съм я инсталирал от пакет или от изходен код. Знам, къде, какво е сложено.

Така, аз през годините съм разбрал (май първо от Гейт го чух) за митична програма наречена linker. Това име се споменава и в много други езици. Аз не съм го срещал като понятие в динамично-типизираните езици (на които пиша предимно), но изглежда е много важно нещо за неща като Ц и Жаба. Така нареченият linker в *nix за Ц изглежда се нарича ld. Много често ми е гърмял.

Изглежда също, че той е отговорната програма, която казва на нашата програма, къде се намира съответното so, което да ползва за правилното си изпълнение. Обаче никой, никъде не му е задал нещо различно от „-l*“, в нашият пример „-lX11“.

Е добре де, как под ягодите се разбира точното име на споделената библиотека и къде се намира?

Второто е до някъде много ясно. Има променливи на средата, които оказват това. Най-използвана е LD_LIBRARY_PATH, но има всякакви други откачени, например LD_RUN_PATH, LTDL_LIBRARY_PATH. Както и да е. Ако в ГНУ/Линукс няма поне по три неща правещи едно и също едновременно, няма да е ГНУ/Линукс. Такива променливи не всеки път са зададени, пък все пак програмите си намират библиотеките. Например в Дебиан 8 те са на много олигофренично място (подкаталози на /usr/lib/i386-linux-gnu/). А ld някак си ги намира¹.

Някъде съм срещал да се „изяснява“, че ако искам да знам, какво точно *.so се ползва и къде е то, трябвало да се допитам до libtool. Четох му документацията на това нещо, дори изходният код (някакъв bash), за да разбера, че това е някакво нещо, правещо нещо си, което не се отнася до мен и изобщо за нищо не служи, освен да обслужва само себе си.

Та успях ли да попитам ясно?

=*=

END:

Обобщавам: В Ц е пълно с черна магия. Сигурно скоро пак ще попитам за нещо, но в момента изгарям от любопитство да разбера как при транслиране на една програма, тя после разбира как се казват нейните споделени библиотеки, като това никъде и по никакъв начин не е оказано??? Програмата някак си пита ld за това, но и на самото ld, никой, никога и никак не му е казвал подобно нещо и все пак, той го знае?!?

Благодаря!


¹Според разни изходи от транслиране, чете някакъв малоумен /etc/ld.so.conf. Не знам за другите дистрибуции, но в Дебиан 8 е ужасен. Поне в 5 до 7 помня, че не беше нацепен на частички в /etc/ld.so.conf.d/, а си беше цял. Както и да е, като насъбере пътищата от всички места описани там, почва да намира библиотеките. Но техните имена все още ги няма.
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear

Odido

  • Напреднали
  • *****
  • Публикации: 627
  • Distribution: Arch Linux
  • Window Manager: Gnome
    • Профил
Re: Къде се намира so?
« Отговор #1 -: May 14, 2016, 20:30 »
http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

Или 3-та точка ако съм разбрал правилно дългия въпрос;

3.Linking: Here is where all of the object files and any libraries are linked together to make your final program. Note that for static libraries, the actual library is placed in your final program, while for shared libraries, only a reference to the library is placed inside. Now you have a complete program that is ready to run. You launch it from the shell, and the program is handed off to the loader.
4.Loading: This stage happens when your program starts up. Your program is scanned for references to shared libraries. Any references found are resolved and the libraries are mapped into your program.

Steps 3 and 4 are where the magic (and confusion) happens with shared libraries.

И по-надолу в линка има интересни неща : GCC has a list of places it looks by default, but our directory is not in that list.2 We need to tell GCC where to find libfoo.so. We will do that with the -L option. In this example, we will use the current directory, /home/username/foo:

$ gcc -L/home/username/foo -Wall -o test main.c -lfoo
« Последна редакция: May 14, 2016, 20:37 от Odido »
Активен

"Congratulations, you broke the Internet
Look at what you did! Are you happy now?"

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8768
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #2 -: May 14, 2016, 20:52 »
Благодаря Дидо,

Т'ва горе-долу го схващам. Явно въпросният „свързочник“ е необходим, защото това е език, който не се интерпретира директно, а се докарва първо до двоичен код. Така например, в нормален език, казваш:

включи /целият/път/до/кода;

използвай едиКоеси();

Тук казваш:

включи <това_описание_на_някакви_неща>;

използвай еди_коe_си();

И после стават някакви вуду-ритуали.

Това, което не схващам е как `-lfoo` се превръща някак си до:

/…/libfoo1.so

Разглеждал съм неща със strace и там е възможно най-тъпашката история. Взима се libfoo1.so и се търси във всеки възможен път докато изкочи. След това се отваря, прочита, прави-нещо, затваря.

Е добре въпросните пътища ги доставя ld. Но как така ld знае, че криптираното заглавие „-lfoo“ се отнася за библиотеката libfoo1.so, като нито <Foo.h>, нито lfoo прилича по някакъв начин на действителното име libfoo1.so, което истинско име никъде не се подава — нито го има при писане (Foo.h), нито го има при транслиране (-lfoo), a то е libfoo1.so.

Ей това ми е големият въпрос.
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #3 -: May 14, 2016, 21:10 »
man ld-linux.so

P.S и другите въпроси са хубави - на първо време забрави за хедърите, защото те нямат много общо.

Под "линкер" се разбират две неща - на gcc линкера с който линкваш крайния изпълним файл и "динамичния" такъв (ld-linux.so) който знае в runtime къде и какво да търси на базата на разни неща в ELF хедъра.

Едното и другото от различни неща зависи къде ще си търсят библиотеките - опции на командния ред, променливи от обкръжението и т.н. Дори в link-time можеш да го направиш срещу една библиотека, а при изпълнението - срещу друга.

Що се отнася до -lfoo и libfoo.so, това е по-скоро именна конвенция....shared библиотеките трябва да се казват libнещото.so и да могат да се открият в директориите където се търсят.
« Последна редакция: May 14, 2016, 21:15 от gat3way »
Активен

"Knowledge is power" - France is Bacon

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8768
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #4 -: May 14, 2016, 22:02 »
О ле-ле, мъглата е дори по-дебела, отколкото предполагах.

Приложих --list на една моя „програма“, която всичко на всичко  взима две библиотеки и използва две-три функции.  Ами изкара ми над двадесет реда. Някой  от нещата разпознах като основни библиотеки (напр. libm.so.6, нещо математическо е, ползвал съм го в други опити), други неща разпознах като зависимости на вложените библиотеки. То и libm.so.6 трябва да е такава, защото не съм подавал -lm .

Мислех, че Foo.h трябва да има отношение, защото това е единственото в кода, имащо някаква връзка. Искаш да кажеш, че като казвам -lfoo то се разширява по подразбиране до libfoo.so? В горният пример това е libxcb.so. Забелязал съм, че винаги тези кратки (без номерация) имена са символни връзки.

Но например ми се е случвало да внасям заглавки към неща (например в xcb има нещо наречено atom, необходимо за манипулиране на свойства на прозорци, хакерствам, хи-хи), които не водят към никакво so. Да се чудиш за какво са. Казваш обаче, че едното  няма общо с другото.

А ве, откачена език. Да не повярваш, че това е най-важният език на света. Явно наистина има вуду в цялата история.

Благодаря за отделеното внимание на всички!

Като има нещо, ще питам пак.
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #5 -: May 14, 2016, 22:15 »
То ти и -lc не указваш за да се линкнеш с libc, става автоматично (същото и за още няколко библиотеки част от libc - математическата, тази за posix нишките и т.н.)

Иначе няма значение какво include-ваш, има значение какво викаш из кода обаче - после при линкване което се намери из object файловете се включва, каквото не - влиза в една таблица, тази въпросната накрая е определяща при динамичното линкване. Предполагам readelf/objdump може да ти изкара въпросната.
Активен

"Knowledge is power" - France is Bacon

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8768
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #6 -: May 14, 2016, 22:32 »
Брей, че мощно дуо са тези readelf/objdump! Сефте ги чувам, ама не вярвам на очите си. Че те на практика ти изкарват (почти) целият изходен код. Да се чудиш, как е възможно да има closed source при такива инструменти. Няма скрито покрито.

Но в моя случай излезе напълно прав. Всички функции, които съм използвал от заглавки, не водещи към so, ми ги показаха и двете като „недефинирани“. А другите им показа кое е so-то.
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #7 -: May 15, 2016, 00:32 »
Ъммм много оптимистично е това, дори binary-то да е компилирано с debug символи и да не е strip-нато, не мисля че можеш да възтановиш source кода. Това че с gdb примерно можеш да видиш точно на кой ред гърми нещо и какъв е реда се дължи просто на факта че имаш и сорса, а иначе не мисля че можеш да "извадиш" сорса от debug символите...може би все пак може във вид на някаква междинна интерпретация, но оригиналния C сорс - абсурд. Освен което много рядко ще ти попадне нещо с debug символи, особено нещо със затворен код.

Също така тук говорим за чисто C....при C++ нещата стават леееко различни, тези същите символи изглеждат съвсем различно (и много грозно и неразбираемо) ако са методи на класове примерно. Та това дето го говориш че C било тъмна Индия и вуду магия, ха!
Активен

"Knowledge is power" - France is Bacon

spec1a

  • Напреднали
  • *****
  • Публикации: 3837
    • Профил
Re: Къде се намира so?
« Отговор #8 -: May 18, 2016, 08:44 »
"при C++ нещата стават леееко различни, тези същите символи изглеждат съвсем различно (и много грозно и неразбираемо)"
   Една лека забележка. Могат да се "пооправят" нещата например с:
#ifdef __cplusplus
extern "C" {
#endif
Активен

laskov

  • Напреднали
  • *****
  • Публикации: 3166
    • Профил
Re: Къде се намира so?
« Отговор #9 -: May 18, 2016, 09:42 »

3.Linking: Here is where all of the object files and any libraries are linked together to make your final program. Note that for static libraries, the actual library is placed in your final program, while for shared libraries, only a reference to the library is placed inside. Now you have a complete program that is ready to run. You launch it from the shell, and the program is handed off to the loader.
4.Loading: This stage happens when your program starts up. Your program is scanned for references to shared libraries. Any references found are resolved and the libraries are mapped into your program.

Steps 3 and 4 are where the magic (and confusion) happens with shared libraries.

И по-надолу в линка има интересни неща : GCC has a list of places it looks by default, but our directory is not in that list.2 We need to tell GCC where to find libfoo.so. We will do that with the -L option. In this example, we will use the current directory, /home/username/foo:

$ gcc -L/home/username/foo -Wall -o test main.c -lfoo

И после стават някакви вуду-ритуали.

Това, което не схващам е как `-lfoo` се превръща някак си до:

/…/libfoo1.so

Разглеждал съм неща със strace и там е възможно най-тъпашката история. Взима се libfoo1.so и се търси във всеки възможен път докато изкочи. След това се отваря, прочита, прави-нещо, затваря.

Е добре въпросните пътища ги доставя ld. Но как така ld знае, че криптираното заглавие „-lfoo“ се отнася за библиотеката libfoo1.so, като нито <Foo.h>, нито lfoo прилича по някакъв начин на действителното име libfoo1.so, което истинско име никъде не се подава — нито го има при писане (Foo.h), нито го има при транслиране (-lfoo), a то е libfoo1.so.

Ей това ми е големият въпрос.
Нещата около големия ти въпрос се случват при стартирането на програмата. Не би трябвало да търсиш пътища в програмата, още повече, че в различните дистрибуции пътят до so-тата може да е различен ... мисля :)
Активен

Не си мислете, че понеже Вие мислите правилно, всички мислят като Вас! Затова, когато има избори, идете и гласувайте, за да не сте изненадани после от резултата, и за да не твърди всяка партия, че тя е спечелила, а Б.Б. (С.С., ...) е загубил, а трети да управлява.  Наздраве!  [_]3

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #10 -: May 18, 2016, 10:28 »
"при C++ нещата стават леееко различни, тези същите символи изглеждат съвсем различно (и много грозно и неразбираемо)"
   Една лека забележка. Могат да се "пооправят" нещата например с:
#ifdef __cplusplus
extern "C" {
#endif

Може и така, обаче тогава ще трябва да си пишеш C функции, wrap-ващи C++ методите, не мисля че ще минеш без това.
Активен

"Knowledge is power" - France is Bacon

growchie

  • Напреднали
  • *****
  • Публикации: 623
    • Профил
Re: Къде се намира so?
« Отговор #11 -: May 18, 2016, 10:59 »
Това което говорите е за линкус, за mac е ептен различно, за бодза да не говорим. Имам в предвид намирането на рънтайм библиотеките. Иначе може да си поиграеш с ldd да видиш кое от къде зарежда както и с ldconfig.  Ако си виждал съобщение от типа updating ld.so.cache след инсталация на пакет заради това е. Виж си и /etc/ld.so.conf и ще си обясниш част от нещата.
« Последна редакция: May 18, 2016, 11:27 от growchie »
Активен

spec1a

  • Напреднали
  • *****
  • Публикации: 3837
    • Профил
Re: Къде се намира so?
« Отговор #12 -: May 18, 2016, 11:33 »
"Може и така, обаче тогава ще трябва да си пишеш C функции, wrap-ващи C++ методите, не мисля че ще минеш без това. "
   Не е задължително.
   Може да се "изнесе" част от функционалността на С++ проект
(където се използват класове)напр.  в отделен "под-проект".Компилира се,
(указва се на компилатора да се генерират libraries) и готово.
   Използват се тези libraries само когато трябва.
   Все пак в С++ НЕ Е задължително да се използват класове...
Активен

growchie

  • Напреднали
  • *****
  • Публикации: 623
    • Профил
Re: Къде се намира so?
« Отговор #13 -: May 18, 2016, 11:38 »
Ми то аз съм викал мой с++ код от фортран с това extern "C" и работи. Вътре си ползвам активно класове, но данните ги прехвърлям със структури. М-у другото с++ изхода на ld съм чувал, че е бинарно несъвместим с този който линкера на меките генерира. Ако ще се полза компилирана библиотека под боза с VStudio трябва да е чисто С компилирана.
« Последна редакция: May 18, 2016, 11:51 от growchie »
Активен

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: Къде се намира so?
« Отговор #14 -: May 18, 2016, 12:11 »
Между другото, вероятно индиректно могат да се викат и методи на обекти, през function pointer-и. Тя calling конвенцията е почти същата с това изключение че първият параметър към функцията трябва да е this, демек указател към обекта. Не че някога съм пробвал (почти никакво вземане-даване с изпълнение на C++ код от C нямам ако трябва да съм честен), но не мисля че би имало някакъв проблем. Обаче не мисля че C кода би могъл да създаде нов обект като хората, да му викне конструктора и т.н. А може и да може, знам ли. От друга страна, може да има и някакъв фундаментален проблем с викането на методи през function pointer-и, въпреки че поне в момента не се сещам.

П.П type safety-то е интересен въпрос разбира се, ако методите вземат някакви по-"C++ специфични" аргументи може да се случи неприятна авария.
« Последна редакция: May 18, 2016, 12:13 от gat3way »
Активен

"Knowledge is power" - France is Bacon