|
1243 | 1243 | \pdfbookmark[1]{dynamic linker}{ldso} |
1244 | 1244 |
|
1245 | 1245 | \begin{slide} |
1246 | | -\sltitle{Dynamický linker (loader)} |
| 1246 | +\sltitle{Dynamic linker (loader)} |
1247 | 1247 |
|
1248 | 1248 | \begin{itemize} |
1249 | | -\item pøeklad vy¾aduje v¹echny potøebné dynamické knihovny pro kontrolu |
1250 | | -dosa¾itelnosti pou¾itých symbolù |
1251 | | -\item \emsl{sestavení kompletního programu v pamìti se ale provede |
1252 | | -a¾ pøi spu¹tìní}. To je úkol pro \emsl{dynamický linker} |
1253 | | -(\emph{run-time linker}, \emph{loader}) |
1254 | | -\item seznam dynamických knihoven zjistí ze sekce \texttt{.dynamic} |
1255 | | -\item systém má nastaveno nìkolik cest, kde se automaticky tyto knihovny hledají |
1256 | | -\item v sekci \texttt{.dynamic} je mo¾né dal¹í cesty ke knihovnám pøidat pomocí |
1257 | | -tagù \texttt{RUNPATH}/\texttt{RPATH} |
1258 | | -\item nalezené knihovny se pøipojí do pamì»ového procesu pomocí volání |
1259 | | -\funnm{mmap}() (bude pozdìji) |
| 1249 | +\item the compilation phase requires all needed dynamic libraries to check |
| 1250 | +accessibility of used symbols |
| 1251 | +\item \emsl{loading external shared libraries into a running process happens on |
| 1252 | +program execution}. That is what a \emsl{dynamic linker} does (\emph{run-time |
| 1253 | +linker}, \emph{loader}). |
| 1254 | +\item list of required dynamic libraries is in the \texttt{.dynamic} section of |
| 1255 | +an ELF object |
| 1256 | +\item system by default looks for shared libs in certain locations |
| 1257 | +\item located libraries are mapped to the process address space via |
| 1258 | +\funnm{mmap}() (will be later) |
1260 | 1259 | \end{itemize} |
1261 | 1260 | \end{slide} |
1262 | 1261 |
|
1263 | 1262 | \label{RUNTIMELINKER} |
1264 | 1263 |
|
1265 | 1264 | \begin{itemize} |
1266 | | -\item proces spu¹tìní dynamicky slinkovaného programu probíhá takto: |
1267 | | - |
1268 | | -\begin{itemize} |
1269 | | -\item kernel ve volání \texttt{exec} namapuje program do pamìti a zjistí, jaký |
1270 | | -dynamický linker se má pou¾ít (viz dále) |
1271 | | -\item kernel namapuje linker do pamì»ového prostoru spou¹tìného programu a pak |
1272 | | -linkeru pøedá kontrolu. Linker je program sám o sobì -- na Solarisu je ho mo¾né |
1273 | | -normálnì spustit (má tedy funkci \texttt{main}) a jako parametr mu dát jméno |
1274 | | -programu. Mo¾nost spou¹tìt dynamický linker z pøíkazového øádku je ale hlavnì |
1275 | | -pro experimentovaní s linkerem pøi jeho vývoji. |
1276 | | -\item linker z hlavièky programu zjistí, jaké dynamické knihovny program |
1277 | | -pou¾ívá, namapuje je do pamìti a zavolá jejich inicializaèní funkce, pokud |
1278 | | -existují. Mapují se v¹echny nalezené závislosti které nejsou nastavené jako |
1279 | | -\emph{lazy} (strana \pageref{DLOPEN}), rekurzívnì prohledáváním do ¹íøky. V |
1280 | | -tomto poøadí se pak také objekty prohledávají pøi hledání jednotlivých symbolù. |
1281 | | -\item linker programu pøedá øízení (tj. zavolá funkci \texttt{main}) |
1282 | | -\item proces mù¾e i za bìhu dále vyu¾ívat dynamický linker pomocí volání |
1283 | | -\texttt{dlopen} a spol.; k tomu se dostaneme na stranì \pageref{DLOPEN} |
1284 | | -\end{itemize} |
1285 | | - |
1286 | | -\item je potøeba si uvìdomit, ¾e dynamický linker zde nepracuje jako samostatný |
1287 | | -proces pøesto¾e má svoji vlastní \texttt{main} funkci, jeho kód se pou¾ívá v |
1288 | | -rámci pamì»ového prostoru procesu; \emsl{program, linker a knihovny dohromady |
1289 | | -tvoøí jeden proces}. |
1290 | | - |
1291 | | -\item \emsl{následující pøíkazy a pøíklady se týkají Solarisu}. Pokud to nebude |
1292 | | -fungovat na jiných systémech, tak mají ekvivaletní nástroje s podobnou |
1293 | | -funkcionalitou. |
1294 | | - |
1295 | | -\begin{itemize} |
1296 | | -\item seznam sekcí se zjistí pomocí \texttt{elfdump -c} (GNU má pøíkazy |
1297 | | -\texttt{objdump} a \texttt{readelf}). O programových sekcích bude více na stranì |
| 1265 | +\item An ELF object format is explained on page \pageref{ELF}. |
| 1266 | +\item In the ELF \texttt{.dynamic} section, you can add additional paths to |
| 1267 | +search for the libraries using tags \texttt{RUNPATH}/\texttt{RPATH}. |
| 1268 | +\item The process of an execution of a dynamically linked program works like |
| 1269 | +this: |
| 1270 | +\begin{itemize} |
| 1271 | +\item The kernel in \texttt{exec()} maps the program to a newly created process |
| 1272 | +address space and finds out what a dynamic linker is used (see \texttt{.interp} |
| 1273 | +below). |
| 1274 | +\item The kernel maps the dynamic linker to the process address space as well |
| 1275 | +and calls the linker's \texttt{main()} function. As a dynamic linker is an |
| 1276 | +executable program by itself, it has \texttt{main()}. You can usually also run |
| 1277 | +a dynamic linker on a command line if you want to, that is mostly useful for |
| 1278 | +debugging and experimenting with a dynamic linker. |
| 1279 | +\item The linker gets the list of required libraries from the program ELF header, |
| 1280 | +maps those libraries to the process address space, and calls their initialization |
| 1281 | +functions if those exist. All dependencies not set as |
| 1282 | +\emph{lazy} (see page \pageref{DLOPEN}) are mapped recursively via breadth |
| 1283 | +search. |
| 1284 | +\item The linker's job is done at that point and calls the program |
| 1285 | +\texttt{main()} function. |
| 1286 | +\item A process may continue to use the dynamic linker during program execution |
| 1287 | +via calls like \texttt{dlopen()} etc. See page \pageref{DLOPEN} for more |
| 1288 | +information. |
| 1289 | +\end{itemize} |
| 1290 | +\item Note that the dynamic linker does not run as a separate process (unless |
| 1291 | +you run it like that) even that it has its own \texttt{main()} function. It is |
| 1292 | +used within an address space of an executed program. The program, dynamic |
| 1293 | +linker, and dynamic libraries constitute a single process. |
| 1294 | + |
| 1295 | +\item The following examples \emsl{are from Solaris}. Finding equivalent |
| 1296 | +commands and/or options on Linux is left as an excercise to the reader. |
| 1297 | +\begin{itemize} |
| 1298 | +\item ELF sections are listed via \texttt{elfdump -c} (GNU has |
| 1299 | +\texttt{objdump} and \texttt{readelf}). More on program sections on page |
1298 | 1300 | \pageref{ELF}. |
1299 | | -\item to, jaký dynamický linker se pou¾ije, kernel zjistí ze sekce |
1300 | | -\texttt{.interp}, viz ''\texttt{elf\-dump -i}'' a ``\texttt{ld -I}''. To |
1301 | | -znamená, ¾e si mù¾ete napsat vlastní linker a pomocí \texttt{-I} pro \texttt{ld} |
1302 | | -ho pak nastavit jako dynamický linker pro vá¹ program. |
1303 | | -\item dynamická sekce se vypí¹e pomocí \texttt{elfdump -d}, dynamické knihovny |
1304 | | -jsou o\-zna\-èe\-né tagem \texttt{NEEDED} |
| 1301 | +\item What a dynamic linker is used is in section \texttt{.interp}, see |
| 1302 | +''\texttt{elf\-dump -i}'' and ``\texttt{ld -I}''. It means you could write your |
| 1303 | +own dynamic linker and set it via the \texttt{-I} option for \texttt{ld} to your |
| 1304 | +program. It is needed to say such an enterprise would not be an easy feat at |
| 1305 | +all. |
| 1306 | +\item To list the dynamic section, use \texttt{elfdump -d}, dynamic libraries |
| 1307 | +are set as \texttt{NEEDED}. |
1305 | 1308 | \item Finding out shared object dependencies is very easy via the |
1306 | | -\texttt{ldd} command (Solaris, Linux, BSD). It displays paths to the libraries |
1307 | | -that will be used if the program is run in the same environment (see right |
1308 | | -below for more information). The command resolves the depencides recursively so |
1309 | | -you will also see dynamic libraries that are used by other libraries and not |
1310 | | -directly by the program. To find out what exactly depends on what, use the |
1311 | | -\texttt{-v} option. macOS does not have \texttt{ldd}, use \texttt{otool -L} |
1312 | | -instead. |
1313 | | -\item jaké knihovny byly pøi spu¹tìní nakonec pou¾ity mù¾e být jiné ne¾ co uká¾e |
1314 | | -pøíkaz \texttt{ldd}, a to tøeba díky mechanismu \texttt{LD\_PRELOAD}. Na |
1315 | | -Solarisu proto existuje pøíkaz \texttt{pldd}, který pomocí èísla procesu uká¾e |
1316 | | -závislosti konkrétního procesu. Pøíklad na \texttt{LD\_PRELOAD}: pou¾ijte ji¾ |
1317 | | -zmínìný \texttt{Ma\-ke\-file01}, a pøelo¾te \example{basic-utils/preload.c} |
1318 | | -takto: |
1319 | | -``\texttt{cc -shared -o lib\-pre\-load.so preload.c}''. Pak spus»te |
1320 | | -program, který zachytí |
1321 | | -systémové volání \texttt{close}: ``\verb#LD_PRELOAD=./libpreload.so ./a.out#''. |
1322 | | -\item vìt¹inu zde uvedených informací naleznete v manuálové stránce pro |
1323 | | -dynamický linker v Solarisu, \texttt{ld.so.1(1)}, a více pak v \emph{Linkers |
1324 | | -and Libraries Guide} na \texttt{docs.oracle.com}. Na FreeBSD se dynamický |
1325 | | -linker nazývá \texttt{ld-elf.so.1}, v linuxových distribucích vìt¹inou |
1326 | | -\texttt{ld-linux.so.1}, na IRIXu \texttt{rld} atd. |
1327 | | -\item dynamický linker se typicky dá konfigurovat pomocí nastavení |
1328 | | -pro\-mìn\-ných, napøíklad si zkuste na Solarisu spustit toto: |
| 1309 | +\texttt{ldd} command (Solaris, Linux, BSD). It displays paths to the specific |
| 1310 | +libraries (ie. full paths) that will be used if the program is run in the |
| 1311 | +same environment (see right below for more information). The command resolves |
| 1312 | +the dependencies recursively so you will also see dynamic libraries that are used |
| 1313 | +by other libraries and not directly by the program. To find out what exactly |
| 1314 | +depends on what, use the \texttt{-v} option. macOS does not have \texttt{ldd}, |
| 1315 | +use \texttt{otool -L} instead. |
| 1316 | +\item What libraries are eventually used when running the program could be |
| 1317 | +different from what \texttt{ldd} shows. For example, |
| 1318 | +one could use the \texttt{LD\_PRELOAD} mechanism. For that reasons, |
| 1319 | +Solarisu has a \texttt{pldd} command which provides for a running process |
| 1320 | +library dependencies. Example on \texttt{LD\_PRELOAD} with \texttt{gcc}: use |
| 1321 | +already mentioned \texttt{Ma\-ke\-file01}, and compile |
| 1322 | +\example{basic-utils/preload.c} like this: ``\texttt{gcc -shared -o |
| 1323 | +lib\-pre\-load.so preload.c}''. Run the program then which interposes a system |
| 1324 | +call \texttt{close()}: ``\verb#LD_PRELOAD=./libpreload.so ./a.out#''. |
| 1325 | +\item Most of the information listed here can be found in a manual page for the |
| 1326 | +Solaris dynamic linker, \texttt{ld.so.1(1)}, and much more then in an excellent |
| 1327 | +\emph{Linkers and Libraries Guide} on \texttt{docs.oracle.com}. If you use |
| 1328 | +FreeBSD, its dynamic linker is \texttt{ld-elf.so.1}, on Linux distros it is |
| 1329 | +usually \texttt{ld-linux.so.1}, it is \texttt{rld} on SGI IRIX etc. |
| 1330 | +\item You can also configure the dynamic linker via setting environment |
| 1331 | +variables. For example, try this on Solaris: |
1329 | 1332 | \begin{verbatim} |
1330 | 1333 | LD_LIBRARY_PATH=/tmp LD_DEBUG=libs,detail date |
1331 | 1334 | \end{verbatim} |
1332 | | -a pro zji¹tìní v¹ech mo¾ností jak debugovat dynamický linker pou¾ijte: |
| 1335 | +and to find out what options you have to debug the dynamic linker there: |
1333 | 1336 | \begin{verbatim} |
1334 | 1337 | LD_DEBUG=help date |
1335 | 1338 | \end{verbatim} |
1336 | | -\item pøíklad na to, kdy je potøeba, aby linker hledal knihovny i jinde ne¾ v |
1337 | | -defaultních adresáøích (adresáøe specifikované promìnnou |
1338 | | -\texttt{LD\_LIBRARY\_PA\-TH} se prohledávají jako první): |
| 1339 | +\item To tell the linker to look for dynamic libraries also in directories other |
| 1340 | +than the default ones (paths from \texttt{LD\_LIBRARY\_PA\-TH} are searched |
| 1341 | +first), use it like the following: |
1339 | 1342 | \begin{verbatim} |
1340 | 1343 | $ cp /lib/libc.so.1 /tmp |
1341 | 1344 | $ LD_LIBRARY_PATH=/tmp sleep 100 & |
|
1345 | 1348 | /tmp/libc.so.1 |
1346 | 1349 | /usr/lib/locale/cs_CZ.ISO8859-2/cs_CZ.ISO8859-2.so.3 |
1347 | 1350 | \end{verbatim} |
1348 | | -\item Solaris má velmi zajímavý pøíkaz \texttt{elfedit(1)}, pomocí kterého |
1349 | | -mù¾ete editovat metadata ELF objektu, napøíklad pøepsat jméno závislé |
1350 | | -kni\-hov\-ny, zmìnit nastavení \texttt{RUNPATH} atd. |
1351 | | -\end{itemize} |
1352 | | -\item \label{EVIL_LDLIBPATH} Obecnì platí, ¾e pou¾ívat |
1353 | | -\texttt{LD\_LIBRARY\_PATH} k ovlivnìní bìhu dynamického linkeru pro nìco |
1354 | | -jiného ne¾ ladìní dynamických knihoven pøi vývoji nebo pøesunech knihoven |
1355 | | -mezi adresáøi není dobrý nápad. Na internetu lze najít mno¾ství èlánkù |
1356 | | -typu "why is \texttt{LD\_LIBRARY\_PATH} evil ?" apod., napø. |
| 1351 | +\item You can also edit ELF objects via \texttt{elfedit(1)} on Solaris. You can |
| 1352 | +change \texttt{RUNPATH}, for example. |
| 1353 | +\end{itemize} |
| 1354 | +\item \label{EVIL_LDLIBPATH} In general, you should not use |
| 1355 | +\texttt{LD\_LIBRARY\_PATH} for anything else then debugging during the |
| 1356 | +development or when moving libraries between directories. You can find lots of |
| 1357 | +articles on ``why is \texttt{LD\_LIBRARY\_PATH} evil?'' etc. For example, |
1357 | 1358 | \url{http://xahlee.org/UnixResource\_dir/\_/ldpath.html}. |
| 1359 | + |
1358 | 1360 | \par |
1359 | | -Tato promìnná je typicky zneu¾ívaná ve startovacích skriptech programù, aby |
1360 | | -pøedsunuly alternativní seznam adresáøù kde hledat dynamické knihovny na |
1361 | | -kterých program závisí. To vìt¹inou proto, ¾e byl program nesprávnì |
1362 | | -slinkován a dynamický linker by podle informací v ELFu nedokázal jinak |
1363 | | -knihovny najít. Typický nechtìný side effect je, ¾e program dále spustí |
1364 | | -jiný program, který pou¾ívá knihovnu stejného jména, ale "díky" tomu, ¾e |
1365 | | -se promìnné prostøedí dìdí, tak dynamický linker najde tuto knihovnu |
1366 | | -jako první v aresáøi specifikovaném pomocí \texttt{LD\_LIBRARY\_PATH}. |
1367 | | -Tato knihovna mù¾e být ale jiné verze, ne¾ ten druhý program oèekává, a |
1368 | | -pak snadno mù¾e dojít k nìèemu, co se vìt¹inou nazývá "nedefinované |
1369 | | -chování" (viz pøíklad u dal¹ího slide o ABI). |
| 1361 | +This varible is often misused in the start-up scripts because the command(s) |
| 1362 | +is/are incorrectly linked and the dynamic linker would not otherwise find the |
| 1363 | +correct libraries. The typical side effect, however, is that the program(s) |
| 1364 | +subsequently start(s) additional programs that use the same libraries but as all |
| 1365 | +children inherit the environment, those programs are forced to use libraries |
| 1366 | +from non-default directories, and possibly those contain libraries of different |
| 1367 | +versions from those that the programs were initially built with. Quite often |
| 1368 | +this might be hard to find when something goes bad and you start seeing |
| 1369 | +unexpected behavior. Commands like \texttt{pldd} come in handy in such |
| 1370 | +situation. |
1370 | 1371 | \end{itemize} |
1371 | 1372 |
|
1372 | | - |
1373 | 1373 | %%%%% |
1374 | 1374 |
|
1375 | 1375 | \pdfbookmark[1]{API/ABI}{APIABI} |
|
0 commit comments