PB173 - Binární programování Linux V. DWARF Jiri Slabý ITI, Fakulta informatiky 15. 10. 2013 J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 1 /16 DWARF • Strukturované ladicí informace • Zápis komplikovaných výrazů 9 Vytvářené překladačem • Nezávislost na jazyku a formátu souborů a Dokumentace • Introduction to the DWARF Debugging Format • DWARF Debugging Information Format (Version 4) J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 2/ 16 DWARF formát • Ladicí informace v lese skoro-stromů • Pro každý zdrojový soubor jeden skoro-strom • Uzly stromů jsou Debugging Information Entry(D\E) • Jeden DIE může odkazovat na kterýkoliv jiný DIE type = compilationjjnit dir = /tmp/test name = test.c producer = GCC DIE type = subprogram name = fun type = int DIE DIE type = subprogram type = base.type name = mam name = int type = int size = 4 J. Slaby (ITI, Fl) PB173/07 15. 10. 2013 3/ 16 DWARF a ELF O DWARF je v ELFu uložený v .debug_* sekcích • .debug_inf o: všechny DIE z lesa stromů • .debug_abbrev: formát .debug_inf o (Figure 48 V DWARF) 9 .debug_types: popis datových typů • .debug_str: řetězce odkazované z .debug_info • .debug_iine: překlad instrukce -o- řádek kódu Q Výpis DWARFu v ELFu • readelf —debug-dump • objdump —dwarf • dwarf dump (z libdwarf) J. Slaby (ITI, Fl) PB173/07 15. 10. 2013 4/ 16 Knihovny na práci s DWARF Dvě různé implementace knihoven O libdwarf • Starší • Hůř se s ní pracuje • Obsahuje méně chyb • Lépe dokumentovaná • libdwarf/libdwarf.h O libdw alibdwf1 • Podpora nových standardů DWARF • Lepší rozhraní • Základní: libdw (elfutils/libdw.h) • Nadstavba: libdwfi (eifutils/libdwfí.h) 9 Tuto budeme používat J. Slabý (ITI, Fl) PB173/07 15.10.2013 5/ 16 libdw a libdwf 1 • Knihovny jsou součástí elfutils a Lze je používat střídavě (jako elf a gelf) a Inicializace: Dwfl *dwf l_begin(const Dwf l_Callbacks *cb) O .section_address = dwfl_offline_section_address • Ukončení: void dwf 1_ end (Dwfl *dwfl) • Poslední chyba: dwf i_errmsg(-i) a Dokumentace • V hlavičkových souborech • Knihovny při překladu: gcc ... -ldw J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 6/ 16 Úkol Inicializace libdwf i O Nainstalujte si libdw (a libdwf i) O Vytvořte si main O Definujte si statické háčky • Struktura const Dwf l_Callbacks • .section_address = dwfl_offline_section_address O Zavolejte dwf l_begin O Zavolejte dwf l_end O Ověřujte návratové hodnoty a vypisujte chyby O Přeložte a spusťte J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 7/ 16 libdw a libdwf 1 - soubory Načtení ELFu s DWARFem uvnitř • Dwfl_Module *dwfl_report_offline(Dwf1 *dwfl, const char *name, const char *file_name, int fd) • dwf l: návratová hodnota z dwf l_begin 9 name: cokoliv (např. "") • f ile_name: jméno souboru • f d:-1 (nebo souborový deskriptor, pak f iie_name == "") Průchod stromů (jednotlivých Compilation Unit) • Dwarf_Die *dwfl_nextcu(Dwf1 *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias) • dwf l: návratová hodnota z dwf l_begin • lastcu: poslední CU • bias: přičítá se k adresám, které vrací libdw mod = dwfLreporLoffline (dwfl, "", argv[1], -1); while ((die = dwfl.nextcu(dwfl, die, &bias))) { ... } J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 8/ 16 Úkol Otevření ELFu pomocí libdwf i O Přidávejte kód mezi dwf i_begin a dwf i_end O Zavolejte dwfl_report_offline O Iterujte přes CU DIE dwf l_nextcu • Spočítejte z kolika souborů je objekt přeložen O Ověřujte návratové hodnoty a vypisujte chyby O Přeložte a spusťte J. Slabý (ITI, Fl) DIE Debugging Information Entry • Typ/tag DW_TAG_* • Z DIE: int dwarf_tag (Dwarf_Die *die) • DW_TAG_compile_unit:0 SOUboru • DW_TAG_subprogram: 0 funkci • DW_TAG_base_type: 0typu DIE type = compilationjjnit dir = /tmp/test name = test.c producer = GCC • Seznam dvojic • Typ hodnoty: DW_AT_* • DW_AT_name: jméno (proměnné, souboru, o DW_AT_deci_f ile: soubor s deklarací • DW_AT_deci_iine: řádek s deklarací 9 DW_AT_type: typ proměnné Hodnota J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 10/16 Hlavní DIE DW.TAG.compile.unit DW_AT_producer DW_AT_language DW-AT-name DW_AT_comp_dir DW-ATJow-pc DW_AT_entry_pc DW_AT_stmtJist DW.TAG.subprogram DW-AT-extemal DW_AT_name DW-AT-decLfile DW_AT_declJine DW-AT-prototyped DW_AT_type DW_AT_low_pc DW_AT_high_pc DW_AT_frame-base DW-AT.GNU-alLcall-Sites DW_AT_sibling GNU C 4.7.2 20130108 [gcc-4_7-branch revision 195012] DW.LANG.C89 test. c /tmp/test 0x00000000 0x00000000 0x00000000 yes(1) main 0x00000001 /tmp/test/test.c 0x00000019 yes(1) <0x0000005b> 0x00000000 0x0000011 d yes(1) <0x00000770> J. Slaby (ITI, Fl) PB173/07 15. 10. 2013 11/16 Atributy DIE Iterace přes všechny atributy v jednom DIE • ptrdiff_t dwarf_getattrs(Dwarf_Die *die, int (*callback)(Dwarf_Attribute *, void *), void *arg, ptrdiff_t offset) • die: Z dwf l_nextcu • callback: vaše funkce, která se zavolá pro každý atribut v DIE • arg: něco, co se předá do callback jako 2. parametr • offset:0 Operace nad atributem • Typ: dwarf_whatattr • Vrací DW_AT_* (DW_AT_name apod.) « Typ obsahu: dwarf _ what form a Vrací DW_F0RM_* (DW_FORM_string apod.) • Obsah: dwarf_form* O Např. dwarf _f ormstring J. Slaby (ITI, Fl) PB173/07 15.10.2013 12/ 16 Atributy DIE - příklad static int cb(DwarLAttribute *attr, void *ptr) { printf ("AT=%x FORM=%x\n", dwarf.whatattr(attr), dwarf.whatform(attr)); if (dwarf.whatform(attr) == DW.FORM.strp) printf ("name=%s\n", dwarf.formstring(attr)); return DWARF.CB.OK; } while ((die = dwfl.nextcu(dwfl, die, &bias))) { dwarf.getattrs(die, cb, NULL, 0); } J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 13/16 Úkol Výpis atributů O Definujte funkci (háček) pro dwarf _getattrs O V ní vypište informace • Typ atributu (dwarf _whatattr(attr)) • Typ obsahu atributu (dwarf _whatf orm(attr)) • Adresu, pokud se jedná o typ DW_at_iow_pc • Řetězec a typ atributu dw_at_*, pokud se jedná o typ hodnoty DW_FORM_string nebo DW_FORM_strp O V těle cyklu dwf l_nextcu zavolejte dwarf _getattrs O Přeložte a spusťte J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 14/16 Průchod skoro-stromem Iterace přes všechny atributy v jednom DIE • int dwarf_child(Dwarf_Die *die, Dwarf_Die *result) • Do result vloží potomka die • Vrací 0 (OK), 1 (žádný potomek), -1 (chyba) • result musí být ukazatel na lokální proměnnou • int dwarf_siblingof(Dwarf_Die *die, Dwarf_Die *result) • Do result vloží sourozence die • Vrací 0 (OK), 1 (žádný sourozenec), -1 (chyba) J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 15/16 Úkol Výpis potomků CU O Vezměte 1. potomka od CU (dwarf_chiid) 0 Iterujte přes sourozence potomka (dwarf _sibiingof) O Pro všechny potomky vypište typ DIE (dwarf _tag) • Nejprve zjistěte, které tam jsou • Potom vypisujte v textové podobě O Rozšiřte na celý podstrom, nejen první úroveň O Přeložte a spusťte J. Slabý (ITI, Fl) PB173/07 15. 10. 2013 16/16