ELF shared library vs ELF executable

Pali

ELF shared library vs ELF executable
« kdy: 27. 02. 2011, 14:27:08 »
1. Aky je medzi nimi rozdiel?
2. Da sa v C-cku pre ELF shared so library nastavit _start entry point (resp. aby sa spustil int main()) ? Ak skompilujem v C-ku jednoduchy program "int main() { printf("Hello\n"); }" ako shared library dostavam Segmentation fault...

Moje pozorovanie v asm:
Skusal som experimentovat s tymto jednoduchym programom (vypise "Hello 1\n", potom "Hello 2\n" a skonci):

Kód: [Vybrat]
.text
.global _start
_start:

movl $len, %edx
movl $msg, %ecx
movl $1, %ebx
movl $4, %eax
int $0x80

subl $8, %esp
movl $0x6C6C6548, 0(%esp) # "Hell"
movl $0x0A32206F, 4(%esp) # "o 2\n"
movl %esp, %ecx
addl $8, %esp

movl $8, %edx
movl $1, %ebx
movl $4, %eax
int $0x80

movl $0, %ebx
movl $1, %eax
int $0x80

.data
msg:
.ascii "Hello 1\n"
len = . - msg

Ak ho skompilujem ako ELF executable, tak ide vsetko ok:
Kód: [Vybrat]
$ as test.s -o test.o && ld test.o -o a.out
$ ./a.out
Hello 1
Hello 2

Avsak ak ho skompilujem ako ELF shared library, tak je tu daco divne a nechapem tomu uz vobec...
Kód: [Vybrat]
$ as test.s -o test.o && ld -shared test.o -o a.out
$ ./a.out
Hello 2
Kde sa stratil vypis "Hello 1"?? Skusal som aj presunut msg do sekcie .text (namiesto .data) ale spravanie bolo v oboch pripadoch rovnake...
« Poslední změna: 27. 02. 2011, 20:30:38 od Petr Krčmář »


František

Re: ELF shared library x ELF executable
« Odpověď #1 kdy: 27. 02. 2011, 14:53:32 »
Hlavní rozdíl je, že u shared library nevíte kam se zavede do paměti. Takže se musí jednat o pozičně nezávislý kód (position-independent code). Kód v C sdílené knihovny se musí kompilovat jako pozičně nezávislý (v gcc přepínač -fPIC).

V druhé otázce jde asi o spouštění sdílené knihovny. Proč chcete spouštět sdílené knihovny? Rozumím dobře druhé otázce? Definice C-čka nic takového samozřejmě neupravuje. Neptáte se spíše na GCC a binutils?

Pali

Re: ELF shared library x ELF executable
« Odpověď #2 kdy: 27. 02. 2011, 15:20:19 »
Ano, zaujima ma spustanie so kniznice a pouzivam gcc.

Sten

Re: ELF shared library vs ELF executable
« Odpověď #3 kdy: 28. 02. 2011, 00:03:38 »
Jediný rozdíl je v tom, že shared library je PIE, takže nevíte, kde se bude nacházet v paměti. Jinak může obsahovat cokoliv včetně funkce main (kterou potom executable, který s ní bude slinkovaný, obsahovat nemusí) — dokonce můžete takové shared library používat jak jako shared library tak jako executable.

Pali

Re: ELF shared library vs ELF executable
« Odpověď #4 kdy: 28. 02. 2011, 00:56:28 »
Ok, takze teoreticky shared library mozem pouzivat aj ako kniznicu aj ako executable. Ale prakticky to akosi nefunguje.

Ako som uz pisal, ak skompilujem
Kód: [Vybrat]
int main() { printf("Hello\n"); }
ako shared library tak dostavam iba Segmentation fault a ziaden vystup.

A ak skompilujem ten asm kod, tak sa chova akosi divne (co som uz pisal)...


mf

Re: ELF shared library vs ELF executable
« Odpověď #5 kdy: 28. 02. 2011, 08:57:28 »
Nechce se mi s tím teď hrát, ale mam tip. Doporučil bych se podívat na glibc. To je příklad sdílené knihovny, která se dá spustit. Není to zrova hello world example, ale z build logu by se možná dalo vyčíst s jakými přepínači se to kompiluje.

Jediné co mě zrovna napadá, je že sdílené knihovny neobsahují .interp sekci obsahující ukazatel na string, který představuje cestu k dynamickému linkeru (kernel to musí vědět, protože mu předává řízení při exec, ne binárce) a jak už bylo zmíněno, bylo by zahadno je kompilovat jako position independent code aby mohli být opravdu sdílené (kvůli relokacím, aby byly na jednom místě a nebylo všechno copy-on-writenuté ;-)). Taky k binárkám obvykle linker přivařuje něco jako crt?.o modul který řeší nějakou inicializaci před vstupem do fce main. Jestli během dne dostanu chuť to zkusit, tak sem postnu výsledek. Ale fakt bych se podíval na tu glibc.

Ivan

Re: ELF shared library vs ELF executable
« Odpověď #6 kdy: 28. 02. 2011, 10:24:12 »
Nektere knihovny spoustet jdou:
Kód: [Vybrat]
$ /lib/libc.so.6
GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) stable release version 2.11.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.3.
Compiled on a Linux >>2.6.24-27-server<< system on 2011-01-21.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.


Dokonce je to tak, ze kernel vsechny ne-staticky binarky sousti tak, ze v tom .ELFu najde
loader, a ten spusti jako:
Kód: [Vybrat]
"/lib/ld-2.11.1.so /bin/bash".

Pali

Re: ELF shared library vs ELF executable
« Odpověď #7 kdy: 28. 02. 2011, 10:57:09 »
Nechce se mi s tím teď hrát, ale mam tip. Doporučil bych se podívat na glibc. To je příklad sdílené knihovny, která se dá spustit. Není to zrova hello world example, ale z build logu by se možná dalo vyčíst s jakými přepínači se to kompiluje.

Jediné co mě zrovna napadá, je že sdílené knihovny neobsahují .interp sekci obsahující ukazatel na string, který představuje cestu k dynamickému linkeru (kernel to musí vědět, protože mu předává řízení při exec, ne binárce) a jak už bylo zmíněno, bylo by zahadno je kompilovat jako position independent code aby mohli být opravdu sdílené (kvůli relokacím, aby byly na jednom místě a nebylo všechno copy-on-writenuté ;-)). Taky k binárkám obvykle linker přivařuje něco jako crt?.o modul který řeší nějakou inicializaci před vstupem do fce main. Jestli během dne dostanu chuť to zkusit, tak sem postnu výsledek. Ale fakt bych se podíval na tu glibc.

Ok, skusim sa na nieco pozriet... nedavam vsak velku nadej. Ale ak vsak budes mat cas, velmi ti budem vdacny

Pali

Re: ELF shared library vs ELF executable
« Odpověď #8 kdy: 28. 02. 2011, 10:58:35 »
Nektere knihovny spoustet jdou:
Kód: [Vybrat]
$ /lib/libc.so.6
GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) stable release version 2.11.1, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.3.
Compiled on a Linux >>2.6.24-27-server<< system on 2011-01-21.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.


Dokonce je to tak, ze kernel vsechny ne-staticky binarky sousti tak, ze v tom .ELFu najde
loader, a ten spusti jako:
Kód: [Vybrat]
"/lib/ld-2.11.1.so /bin/bash".

Jasne, toto viem. Spustit ide aj ta jednoducha kniznica napisana v asm... Avsak nevypisuje "Hello 1"

František

Re: ELF shared library x ELF executable
« Odpověď #9 kdy: 28. 02. 2011, 11:57:52 »
Ano, zaujima ma spustanie so kniznice a pouzivam gcc.

Nejsem si jistý a nerad bych mystifikoval, ale pravděpodobně stačí spustitelný soubor přejmenovat a přidat koncovku .so. Vstupní bod můžete nastavit v linkeru ld přepínačem -entry. Problém bude s pozičně nezávislým kódem.

Nejjednodušší způsob jak se dostat k řetězcům apod. bude, když spuštěná dynamická knihovna si přes rozhraní dlopen namapuje sama sebe jako dynamickou knihovnu. A pak ke svým pozičně nezávislým řetězcům přistupuje dlsym jako k symbolům běžné dynamické knihovny.

Další způsob mít všechno v instrukčním kódu a nevyužívat datové sekce, u kterých nelze určit polohu. Tedy řetězce alokovat v kódu na zásobníku jako pole.

Sten

Re: ELF shared library vs ELF executable
« Odpověď #10 kdy: 28. 02. 2011, 16:13:38 »
Je potřeba nepoužít „-shared“, ale „-pie -rdynamic“ ;)

Kód: [Vybrat]
sten@ell test $ ./test.sh
++ cat libtest.cc
#include <iostream>

const char *HELLO = "Hello";


int main()
{
        std::cout << HELLO << " from shared library" << std::endl;
        return 0;
}


++ g++ -o libtest.so -rdynamic -pie -fPIC libtest.cc
++ cat test.cc
#include <iostream>

extern const char *HELLO;


int main()
{
        std::cout << HELLO << " from executable" << std::endl;
        return 0;
}


++ g++ -o test -L. -ltest test.cc
++ ./libtest.so
Hello from shared library
++ LD_LIBRARY_PATH=.
++ ./test
Hello from executable

jv

Re: ELF shared library vs ELF executable
« Odpověď #11 kdy: 28. 02. 2011, 17:51:34 »
Ahoj Sten, mohol by si to aj trosku vysvetlit, ze preco nie "-shared" ? Vdaka.

Sten

Re: ELF shared library vs ELF executable
« Odpověď #12 kdy: 28. 02. 2011, 17:57:24 »
Linker v takovém případě odstraní inicializaci statických dat (resp. přesune ji mimo inicializaci ELF objektu, takže tu inicializaci musí udělat někdo jiný). Nevím ale, proč to dělá ani jestli se tím nějak mění dynamické linkování.

Pali

Re: ELF shared library vs ELF executable
« Odpověď #13 kdy: 01. 03. 2011, 18:46:44 »
no skusal som som to. -pie -rdynamic funguje pekne ako ocakavam. Da sa pouzit dlopen ako aj dynamicky dolinkovat k inemu programu.

Co vlastne robi -rdynamic? a co -shared?
Aky je rozdiel medzi -pie a -fpic?

Sten

Re: ELF shared library vs ELF executable
« Odpověď #14 kdy: 02. 03. 2011, 19:24:40 »
-fPIC se týká hlavně kódu jednotlivých funkcí a linkování (tedy pouze toho, co používají sdílené knihovny), -pie pak třeba i inicializace statických dat nebo funkce main (takový program můžete dát kamkoliv v paměti a on bude fungovat). Přesné rozdíly neznám, manuálové stránky to moc nerozebírají.

-rdynamic slouží k exportování všech symbolů, ne jen těch, které je potřeba linkovat zvenčí. To je potřeba, pokud chcete, aby ten program šel používat jako dynamická knihovna (slinkovat s ním nebo dlopen).