Skip to content

Commit e62a5e0

Browse files
committed
API vs ABI slide/notes translated.
1 parent 150322c commit e62a5e0

File tree

1 file changed

+83
-117
lines changed

1 file changed

+83
-117
lines changed

intro.tex

Lines changed: 83 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,61 +1375,64 @@
13751375
\pdfbookmark[1]{API/ABI}{APIABI}
13761376

13771377
\begin{slide}
1378-
\sltitle{API versus ABI}
1378+
\sltitle{API vs ABI}
13791379

13801380
API -- Application Programming Interface
13811381

13821382
\begin{itemize}
1383-
\item rozhraní pou¾ité pouze ve zdrojovém kódu
1384-
\item rozhraní \emsl{zdrojáku} vùèi systému, knihovnì èi vlastnímu kódu, tj.
1385-
napø. \texttt{exit(1)}, \texttt{printf("hello\bs{}n")} nebo
1386-
\texttt{my\_function(1, 2)}
1387-
\item \dots{}aby se stejný \emsl{zdrojový kód} mohl pøelo¾it na v¹ech
1388-
systémech podporující dané API
1383+
\item interface used in the \emsl{source code} to use another software
1384+
component like a library, OS kernel, or your own code -- eg.
1385+
\texttt{exit(1)}, \texttt{printf("hello\bs{}n")} or \texttt{my\_function(1,
1386+
2)}
1387+
\item \dots{}so that the same source code could be compiled on all systems
1388+
supporting a given API
13891389
\end{itemize}
13901390

13911391
ABI -- Application Binary Interface
13921392

13931393
\begin{itemize}
1394-
\item low-level rozhraní \emsl{aplikace} vùèi systému, knihovnì èi jiné èásti
1395-
sama sebe
1396-
\item \dots{}aby se \emsl{objektový modul} mohl pou¾ít v¹ude tam, kde
1397-
je podporováno stejné ABI
1394+
\item low-level binary interface between \emsl{modules} (eg. \texttt{a.out}
1395+
and \texttt{libc.so.1} or even \texttt{a.out} and \texttt{a.out})
1396+
\item \dots{}so that the built module could be used wherever the same ABI is
1397+
supported
13981398
\end{itemize}
13991399
\end{slide}
14001400

14011401
\label{API_ABI}
14021402

14031403
\begin{itemize}
1404-
\item Pøíkladem API je tøeba API definované normou POSIX.1.
1405-
\item ABI definuje konvenci volání (to jak program pøedá parametry funkci
1406-
a jak od ní pøevezme návratovou hodnotu), jaká jsou èísla systémových volání,
1407-
jak se systémové volání provede èi formát objektového modulu
1408-
a pøijímaných argumentù, viz pøíklad dole.
1409-
\item API knihovny pak definuje mimo jiné mno¾inu volání která jsou knihovnou
1410-
definována, jejich parametry a typy tìchto parametrù.
1411-
\item následná ukázka je pøíklad na to, kdy vývojáø zmìní velikost argumentù v
1412-
bajtech (tj. zmìní ABI knihovny), a nahradí novou verzí tu starou. V¹imnìte
1413-
si, ¾e dynamický linker toto nezjistí; nemá toti¾ jak, øídí se podle jména
1414-
knihovny v dynamické sekci programu, a to se nezmìnilo. Uvedená zmìna je sice
1415-
i zmìna v API a problém by se odstranil, kdybychom \texttt{main.c} znovu
1416-
pøelo¾ili se zmìnìným øádkem deklarace funkce \texttt{add}. To je ale èasto
1417-
problém (pøe\-klá\-dej\-te celý systém jen kvùli tomu), proto je tak dùle¾ité
1418-
dodr¾ovat zpìtnou kompatibilitu v ABI u knihoven.
1419-
1420-
Výsledek následujícího pøekladu knihovny, programu a jeho spu¹tìní je jak
1421-
bychom oèekávali (pou¾it \texttt{cc} ze SunStudio, pro \texttt{gcc} pou¾ijte
1422-
místo \texttt{-G} volbu \texttt{-shared}; novìj¹í \texttt{gcc} navíc neznají
1423-
\texttt{-R} a je místo toho nutné pou¾ít \texttt{-Xlinker -R .}:
1404+
\item In short -- an API is source code based while an ABI is binary based.
1405+
\item An example of an API is one defined by POSIX.1 standard or the set of
1406+
system calls for a given system.
1407+
\item An example of an ABI is System V AMD64 ABI, the one followed on Solaris,
1408+
Linux, FreeBSD, macOS, and other systems.
1409+
\item ABI defines calling convention interface to the called machine code, eg.
1410+
how parameters are passed (pushed on the stack, placed in registers, or a mix
1411+
of both) or how return value is returned.
1412+
\item API defines a set of functions, its parameters and their types, and
1413+
function return values. Part of the API may be also global variables --
1414+
\texttt{errno}, for example.
1415+
\item The following example represents what happens if a library ABI is changed
1416+
and the new library replaces the old one. Note that the dynamic linker can not
1417+
detect that as the function symbol did not change. The given change is also an
1418+
API change and the problem would be fixed if \texttt{main.c} was recompiled
1419+
with the correct prototype for function \texttt{my\_add}. However,
1420+
recompiling is often not desirable as one might end up recompiling the whole
1421+
system. That is why keeping backward compatibility for library ABI is so
1422+
important.
1423+
1424+
The first result is expected, ie. \texttt{3}:
14241425

14251426
\begin{verbatim}
14261427
$ cat main.c
1428+
#include <stdio.h>
1429+
14271430
int my_add(int a, int b);
14281431
14291432
int
14301433
main(void)
14311434
{
1432-
printf("%d\n", my_add(1, 2));
1435+
(void) printf("%d\n", my_add(1, 2));
14331436
return (0);
14341437
}
14351438
@@ -1440,17 +1443,16 @@
14401443
return (a + b);
14411444
}
14421445
1443-
$ cc -G -o libadd.so add.c
1444-
$ cc -L. -ladd -R. main.c
1446+
$ gcc -shared -o libadd.so add.c
1447+
$ gcc -L. -ladd -Xlinker -R . main.c
14451448
$ ./a.out
14461449
3
14471450
\end{verbatim}
14481451

1449-
Nyní ale pøi¹la dal¹í verze knihovny se stejným jménem, a ve funkci
1450-
\texttt{my\_add}
1451-
nastala zmìna v typu argumentù, kde místo 4-bajtového integeru se pou¾ije
1452-
64-bitový celoèíselný typ. Program ale o nièem neví, nechá se spustit a vrátí
1453-
chybnou hodnotu:
1452+
Now imagine a new library came, one with a modified ABI in function
1453+
\texttt{my\_add}. Note that we replaced the old library with the new one.
1454+
Now, instead of 4 byte integers, 64-bit longs are used. When you run the
1455+
program again, you will get an incorrect return value:
14541456

14551457
\begin{verbatim}
14561458
$ cat add2.c
@@ -1460,90 +1462,54 @@
14601462
return (a + b);
14611463
}
14621464
1463-
$ cc -G -o libadd.so add2.c
1465+
$ gcc -shared -o libadd.so add2.c
14641466
$ ./a.out
14651467
-1077941135
14661468
\end{verbatim}
14671469

1468-
\item \label{ABI_MAIN} pøíklad: \example{lib-abi/abi-main.c} (komentáø v
1469-
souboru napoví jak pou¾ít os\-tat\-ní soubory ve stejném adresáøi)
1470-
1471-
1472-
\item zde pak pøichází ke slovu verzování knihoven, tj. je nutné ``nìco''
1473-
zmìnit tak, aby po instalaci nové knihovny ne¹lo program spustit bez jeho
1474-
rekompilace.
1475-
\item \label{OPENSSL} binární nekompatibilita je napøíklad problém u OpenSSL.
1476-
Vìtve 0.9.x a 0.9.y nejsou ABI kompatibilní. Konkrétnì verze 0.9.7 a 0.9.8,
1477-
v roce 2009 stále obì pou¾ívané. Verze rozli¹ené písmeny, tj. napøíklad 0.9.8a a
1478-
0.9.8g, jsou ABI kompatibilní. Nìkteré systémy stále pou¾ívají pouze 0.9.7
1479-
(FreeBSD 6.x, Solaris 10), jiné jen 0.9.8 (Solaris 11 Express), dal¹í integrují
1480-
obì vìtve (rùzné Linuxové distribuce). Problém je, máte-li napøíklad program pro
1481-
Solaris~10 pou¾ívající \texttt{libcrypto.so} knihovnu, který chcete pou¾ívat i
1482-
na Solaris 11 Express (to je jinak díky zpìtné binární kompatibilitì striktnì
1483-
dodr¾ované mezi "major" verzemi Solarisu mo¾né - napø. program který bì¾el
1484-
na Solarisu 2.6 z roku 1997 mù¾e bì¾et na Solarisu 10 z roku 2009 bez nutnosti
1485-
rekompilace - to se týká systému a knihoven s ním dodávaných).
1486-
Jediné správné re¹ení je zkompilovat pro nový systém, pøípadnì manuálnì
1487-
zkopírovat potøebné verze knihoven, co¾ ale zdaleka není ideální -- program
1488-
nebude fungovat s novì nainstalovaným systémem, ale nikdo najednou neví,
1489-
proè to funguje na stejném systému vedle, a kdy¾ se to zjistí tak je opìt
1490-
potøeba manuální zásah, a pochybuji o tom, ¾e autor ``øe¹ení'' bude instalovat
1491-
opravené verze pøi výskytu bezpeènostních chyb. Nekompatibilita 0.9.x verzí je
1492-
dùvodem, proè je v dynamické sekci knihovny i její celé èíslo (bez písmen, ta
1493-
jak ji¾ víme nejsou pro ABI kompatibilitu u OpenSSL dùle¾itá), a díky tomu je
1494-
pak toto èíslo uvedeno i v ka¾dém programu proti knihovnì slinkovanému:
1470+
\item \label{ABI_MAIN} Example: \example{lib-abi/abi-main.c} (see the block
1471+
comment in the file on how to use other files located in the same directory).
1472+
\item To change an ABI safely, you need library versioning -- if the library
1473+
ABI change is not backward compatible, a bumped up version needs to prevent to
1474+
run the program without rebuilding it. However, in that case you need to keep
1475+
the old library in the system. Note that having different versions of the same
1476+
library might become a problem by itself, for example if more versions of such
1477+
an library get loaded into the program address space.
1478+
\item The way how versioning works in ELF (see page \pageref{ELF}) is that the
1479+
library file name incorporates a version. The \texttt{SONAME} in the dynamic
1480+
section then lists the full name of the library, including the version. When
1481+
the loader searches for the libraries, it searches for the filename from the
1482+
\texttt{SONAME} field.
1483+
\item Example on what exact libraries and their versions are needed for the
1484+
Secure shell client on a Linux distribution. You see that, for example, the
1485+
OpenSSL library version used by the SSH client is 1.0.0.
1486+
14951487
\begin{verbatim}
1496-
$ elfdump -d /usr/sfw/lib/libcrypto.so.0.9.8 | grep SONAME
1497-
[7] SONAME 0x1 libcrypto.so.0.9.8
1498-
1499-
$ elfdump -d /usr/bin/ssh | grep NEEDED
1500-
[1] NEEDED 0x3c99 libsocket.so.1
1501-
[3] NEEDED 0x3cb1 libnsl.so.1
1502-
[5] NEEDED 0x3cc6 libz.so.1
1503-
[7] NEEDED 0x3d12 libcrypto.so.0.9.8
1504-
[9] NEEDED 0x3cd9 libgss.so.1
1505-
[10] NEEDED 0x3cfe libc.so.1
1488+
$ readelf -d /usr/bin/ssh
1489+
1490+
Dynamic section at offset 0xb0280 contains 34 entries:
1491+
Tag Type Name/Value
1492+
0x0000000000000001 (NEEDED) Shared library: [libsctp.so.1]
1493+
0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.1.0.0]
1494+
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
1495+
0x0000000000000001 (NEEDED) Shared library: [libz.so.1]
1496+
0x0000000000000001 (NEEDED) Shared library: [libresolv.so.2]
1497+
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
1498+
0x0000000000000001 (NEEDED) Shared library: [libgssapi.so.3]
1499+
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
1500+
1501+
$ openssl version
1502+
OpenSSL 1.0.2n 7 Dec 2017
1503+
1504+
$ ls /usr/lib/libcrypto.so.1.0.0
1505+
/usr/lib/libcrypto.so.1.0.0
15061506
\end{verbatim}
1507-
\begin{itemize}
1508-
\item pøíèinou zpìtné nekompatibility OpenSSL verzí je to, ¾e z historických
1509-
dùvodù jsou nìkteré pou¾ívané struktury v hlavièkových souborech. Tyto struktury
1510-
je ale nìkdy nutné roz¹íøit, napøíklad pøi vývoji nové funkcionality. Tím
1511-
nastane situace, ¾e program pøelo¾ený s verzí 0.9.7 by pøedal novìj¹í knihovnì
1512-
``men¹í'' strukturu, respektive nová knihovna by pøistupovala ve staré struktuøe
1513-
na polo¾ky, které neexistují -- a tedy by pøistupovala k pamìti, která programu
1514-
nebyla pøidìlena. To mù¾e zpùsobit pád programu (pøístup na nenamapovanou
1515-
stránku), mù¾e to fungovat dále (v dané pamìti je to, co se tam typicky oèekává,
1516-
napøíklad nula), nebo se to zaène chovat ``podivnì'' (v pamìti bylo nìco, co v
1517-
dané situaci oèekávané nebylo). Problém v OpenSSL je, ¾e nyní ji¾ není technicky
1518-
jednoduché z tìchto struktur udìlat interní a navenek pracovat jen s
1519-
transparentními referencemi objektovým pøístupem, co¾ by umo¾nilo dìlat
1520-
libovolné zmìny ve strukturách, ani¾ by to program ovlivnilo.
1521-
\item bì¾nì vidìné øe¹ení zpùsobené neznalostí vìci je vytvoøit symbolický link,
1522-
napøíklad na Solarisu 11 udìlat 0.9.7 symlink na existující knihovnu verze
1523-
0.9.8. Èastý výsledek je pak pád programu a údiv autora symlinku. Nìkdy to
1524-
naopak funguje, proto¾e program náhodou nepou¾ívá pøíslu¹né struktury, a to je
1525-
jasným dùkazem pro aktéra, ¾e øe¹ení musí být správné. Mù¾e se ale stát, ¾e
1526-
program struktury nepou¾ívá pøi konkrétním provedeném testu, ale zaène dìlat
1527-
problémy a¾ pøi ¾ivém nasazení. Tady je jediná rada -- pokud si opravdu nejste
1528-
jisti ¾e víte, co dìláte a nejste si jistí svoji detailní znalostí kódu programu
1529-
i knihoven, vyhnìte se tomu. Nebo riskujte, ale ji¾ víte jak to mù¾e skonèit.
1530-
\item zdánlivì jednoduché øe¹ení dodávat více verzí OpenSSL s jedním sys\-\-mem
1531-
pøiná¹í zase jiné problémy -- obtí¾nìj¹í vývoj systému, obtí¾nìj¹í správu
1532-
systému (pøi výskytu bezpeènostní chyby je èasto nutné patchovat v¹echny
1533-
instalované verze), problémy s nepøímými závislostmi obsahující více verzí dané
1534-
knihovny apod.
1535-
\item upgrade verze OpenSSL v existujícím systému je také vìc, které je dobré se
1536-
vyhnout, respektive toto tì¾ko vyøe¹íte vydáním patche pro existující systémy --
1537-
uva¾te ¾e zákazník pou¾ívá své nebo jím koupené programy, které závisí na
1538-
existující verzi. A tu byste mu najednou upgradovali na verzi vy¹¹í, ABI
1539-
nekompatibilní.
1540-
\item typickým pøíkladem, kdy se pou¾ívá transparentní typ jako reference, co¾
1541-
umo¾òuje dal¹í roz¹iøování pod ní le¾ící struktury bez rizika vý¹e uvedených
1542-
problémù, je typ POSIX vláken. Struktura typu \texttt{pthread\_t} (strana
1543-
\pageref{PTHREAD_T}) je interní zále¾itostí knihovny. Typicky je to integer, ale
1544-
to by programátora nemìlo vùbec zajímat. Samozøejmì souborový deskriptor èi
1545-
èíslo procesu jsou podobné pøípady, ale na pøíkladu vláken je to lépe vidìt.
1546-
\end{itemize}
1507+
1508+
\par The OpenSSL library version is kept 1.0.0 even that the real version is
1509+
actually 1.0.2n. That is because the micro versions (``z'' in x.y.z) do not
1510+
change the ABI binary compatibility (change in ``y'' does). So, such a number
1511+
must not be in the \texttt{SONAME} field otherwise you would need rebuilt
1512+
binaries that depend on OpenSSL even on a binary compatible micro upgrade.
15471513
\end{itemize}
15481514

15491515
%%%%%

0 commit comments

Comments
 (0)