PB173 - Binární programování Linux VI. Linker skripty Jiri Slabý Fakulta informatiky Masarykova univerzita 21. 10. 2014 Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 1/16 Q Linker skripty Q Verzování funkcí Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 2/ 16 Linker skripty • ldscripts • Linker se jimi řídí při linkování objektů • Tj. vždy se nějaký použije • Udávají a Kde která sekce leží • Např. pro embedded, kód musí být na adrese X a data na adrese Y • Výstupní formát • Kam skočit po načtení • A další • Může přidávat i symboly • Např. „toto" je adresa začátku sekce Z « Dokumentace • pinfo ld • (http://sourceware.org/binutils/) Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 3/ 16 Formát skriptu • Textové soubory • Příkazy • Pozice první instrukce, kterou spustit: entry • Výstupní formát: qutput_fqrmat • Seznam sekcí a jejich obsah: sections • Verzování: versi on «... • Komentáře • /**/jako v C • Linkeru se předává při linkování • gcc -T skript.x ... • ld -T skript.x ... • Demo: výchozí skript Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 4/ 16 Základní příkazy • entry o Udává, kam se má skočit po zavedení Např. ENTRY (main) O 0UTPUT_F0RMAT r Výstupní BFD formát • QUTPUT_FQRMAT("elf64-x86-64") (popř. elf32-i386) Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 5/ 16 Úkol Základní skript O Vytvořte si linker skript O Bude obsahovat pouze entry a output_format Q Vytvořte zdrojový soubor s jednou funkcí • Bude obsahovat nekonečný cyklus • Jméno bude stejné jako v entry O Přeložte a slinkujte skriptem • gcc -Wl,--build-id=none -nostdlib -t skript.x ... O Podívejte se na rozložení sekcí • Měly by začínat okolo adresy 0 0 Spusťte program • Bude fungovat jen pokud sysctl vm.mmap_min_addr je 0 Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 6/ 16 Sekce • sections • Záznamy typu .vystupni_sekce : { *(.vstupni_sekce)} • /discard/ je speciální výstupní sekce SECTIONS { .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } /DISCARD/: { *(.debug*) *(.comment*) *(.eh_frame*)} } Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 7/ 16 Úkol Skript se sekcemi O Rozšiřte skript, aby výsledek obsahoval pouze sekci .text Q Přeložte 0 Ověřte pomocí objdump -h O Spusťte Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 8/ 16 Sekce - adresování • Každému bodu ve skriptu lze přiřadit adresu • Aktuální adresa je . (tečka) • . = 0x10000; • Každou sekci lze: • Vložit na nějakou adresu: . sekce Oxioooo :{...} • Zarovnat: .sekce ALIGN(...): { ... } • Pro každou adresu lze vložit symbol • symbol = .; • V kódu pak extern void *symbol; SECTIONS { . = 0x40000; my_start = .; .text : { *(.text) } .data 0x50000 : { *(.data) } } Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 9/ 16 Úkol Skript se sekcemi a adresami O Rozšiřte zdrojový soubor o další 2 funkce, tedy: • 1 (původní): s nekonečným cyklem, dejte ji do sekce .text.t2 • 2: bude volat extern void my_fun(void), do sekce .text.ti • 3: bude volat adresu 0x401000 (bude entry) O Rozšiřte skript • Aby všechny sekce začínaly za hranicí 0x400000 • . = ... na začátku bloku sections • Přidejte novou výstupní sekci .text.t na adresu 0x401000 • Obsah .text. 11 • Nový symbol my_fun na aktuální adrese » Obsah .text.t2 (tedy my_fun ukazuje na začátek .text.t2) O Přeložte O Ověřte pomocí objdump -haobjdump -t 0 Spusťte Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 10/16 Sekce 2 Verzování funkcí Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 11/16 Verzování funkcí • Pro zachování zpětné kompatibility knihovních funkcí • Knihovny, které jsou udržované opravují chyby • Ale někteří uživatelé spoléhali na „chyby" • Jak zachovat zpětnou kompatibilitu nějaké funkce? • Chceme 2 funkce s týmž názvem, ale s jinou funkcionalitou Před opravou chyby Po opravě chyby void fun() void fun() putsfX"); puts("Y"); Řešením jsou linker skripty s verzováním Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 12/16 Verzování funkcí • Každé funkci lze ve skriptu: • Přiřadit verzi • Určit její viditelnost • Blok version { . . . } a Obsah version lze předat i samostatně na příkazové řádce • Odpadá nutnost psaní celého linker skriptu • ld --version-script=verze.x ... • gcc -Wl,--version-script=verze.x ... • Zobrazení pomocí readelf -v a Dokumentace • pinfo ld » U. Drepper: How To Write Shared Libraries, kap. 3 Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 13/16 Verze ve skriptu Obsah sekce version ve skriptech • Strom verzí • Uzly obsahují funkce • Uzly mohou obsahovat i označení viditelnosti • global: • local: VERS_1.1 { global: fun; local: old_fun*; }; VERS_1.2 { new_functionality_fun; } VERS_1.1; /* inheritance */ Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 14/16 Verze ve zdrojovém souboru • Ve zdrojových souborech je třeba přiřadit verze • Globální asm direktiva • Neverzovaná: asm(".symver fun_oldl,fun@"); • Pro určitou verzi: asm(" . symver fun_old2,fun@VERS_l") ; • Výchozí: asm(".symver fun_new,fun@@VERS_2"); void fun_old() { puts("OLD"); } asm(".symver fun_old,fun@"); void fun_new() { puts("NEW"); } asm(".symver fun_new,fun@@VERS_2"); Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 15/16 Úkol Verzování O Otevřete Si pbl73-bin/06/ O Projděte 3 verze knihovny versí1,2,3}. c • Definuje funkci bubák • bubák v nich má 3 různé sémantiky O Projděte soubor, který ji používá x. c • Volá funkci bubák O Přeložte o Standardně pomocí make Q Spusťte x{ 1,2,3} 0 Projděte verze v x{ 1,2,3} za pomoci readelf -v O Pokračujte domácím úkolem, částí 2 Jiri Slabý (Fakulta informatiky, MU) PB173/03 21.10.2014 16/16