Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Pali 27. 02. 2011, 14:27:08

Název: ELF shared library vs ELF executable
Přispěvatel: Pali 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...
Název: Re: ELF shared library x ELF executable
Přispěvatel: František 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?
Název: Re: ELF shared library x ELF executable
Přispěvatel: Pali 27. 02. 2011, 15:20:19
Ano, zaujima ma spustanie so kniznice a pouzivam gcc.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Sten 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.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Pali 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)...
Název: Re: ELF shared library vs ELF executable
Přispěvatel: mf 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.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Ivan 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".
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Pali 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
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Pali 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"
Název: Re: ELF shared library x ELF executable
Přispěvatel: František 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.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Sten 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
Název: Re: ELF shared library vs ELF executable
Přispěvatel: jv 28. 02. 2011, 17:51:34
Ahoj Sten, mohol by si to aj trosku vysvetlit, ze preco nie "-shared" ? Vdaka.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Sten 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í.
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Pali 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?
Název: Re: ELF shared library vs ELF executable
Přispěvatel: Sten 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).