PB173 - Binární programování Linux V. DWARF Jiri Slabý Fakulta informatiky Masarykova univerzita 15. 10. 2013 Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 1 /16 DWARF • Strukturované ladicí informace • Zápis komplikovaných výrazů • Vytvářené překladačem • Nezávislost na jazyku a formátu souborů • Dokumentace • Introduction to the DWARF Debugging Format • DWARF Debugging Information Format (Version 4) Jiri Slabý (Fakulta informatiky, MU) PB173/03 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 = compilejjnit comp_dir = /tmp/test name = test.c producer = GCC DIE type = subprogram name = fun type = int DIE DIE type = subprogram type = base_type name = main name = int type = int size = 4 Jiri Slabý (Fakulta informatiky, MU) PB173/03 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ů 9 .debug_abbrev: formát .debug_info (Figure 48 V DWARF) a .debug_types: popis datových typů • .debug_str: řetězce odkazované z .debug_info • . debug_iine: překlad instrukce -o- řádek kódu O Výpis DWARFu v ELFu • readelf --debug-dump • objdump --dwarf • dwarf dump (z libdwarf) Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 4/16 Knihovny na práci s DWARF Dvě různé implementace knihoven O libdwarf • Starší • Hůř se s ní pracuje o Obsahuje méně chyb • Lépe dokumentovaná • libdwarf/libdwarf.h Q libdw a libdwf1 • Podpora nových standardů DWARF • Lepší rozhraní • Základní: libdw (elfutils/libdw.h) • Nadstavba: libdwfi (eifutils/libdwfí.h) » Tuto budeme používat Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 5/16 libdw a libdwf 1 • Knihovny jsou součástí elfutils • Lze je používat střídavě (jako elf a gelf) • Inicializace: Dwfl *dwf l_begin(const Dwf l_Callbacks *cb) • .section_address = dwfl_offline_section_address » .find_debuginfo = dwfl_standard_find_debuginfo o Ukončení: void dwf l_end(Dwf 1 *dwf1) • Poslední chyba: dwf i_errmsg(-i) « Dokumentace o V hlavičkových souborech • PDF ze slajdů • Knihovny při překladu: gcc ... -ldw Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 6/16 Úkol Inicializace libdwf i Q Nainstalujte si libdw (a libdwf i) O Vytvořte si main 0 Definujte si statické háčky • Struktura const Dwfl_Callbacks • .section_address = dwfl_offline_section_address » .find_debuginfo = dwfl_standard_find_debuginfo O Zavolejte dwf l_begin 0 Zavolejte dwf l_end 0 Ověřujte návratové hodnoty a vypisujte chyby O Přeložte a spusťte Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 7/16 libdw alibdwfl - 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 • 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 = dwfl_report_offline(dwfl, "", argv[1], -1); while ((die = dwfl_nextcu(dwfl, die, &bias))) { ... } Jiri Slabý (Fakulta informatiky, MU) PB173/03 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 Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 9/16 DIE Debugging Information Entry • Typ/tag DW_TAG_* « Z DIE: int dwarf_tag (Dwarf_Die *die) • DW_TAG_compile_unit: DIE O souboru • DW_TAG_subprogram: DIE O funkci • DW_TAG_base_type: DIE O typu DIE type = compile_unit comp_dir = /tmp/test name = test.c producer = GCC Seznam trojic • O co jde:dw_at_* • DW_AT_comp_dir: adresář, kde se překládalo • DW_AT_name: jméno (proměnné, souboru, ...) • DW_AT_deci_f ile: soubor s deklarací • DW_AT_type: typ proměnné Typ/forma hodnoty (dw_form_*) o DW_FORM_addr • DW_FORM_string «... • Hodnota Jiri Slabý (Fakulta informatiky, MU) Hlavní DIE D W_TAG_co m p i I e_u n i t DW_AT_producer DW_AT_language DW_AT_name DW_AT_comp_dir DW_AT_low_pc DW_AT_entry_pc DW AT stmt list GNU C 4.7.2 20130108 [gcc- DW_LANG_C89 test. c /tmp/test 0x00000000 0x00000000 0x00000000 4_7-branch revision 195012] DW_TAG_subprogram DW_AT_external DW_AT_name DW_AT_decl_file DW_AT_decl_line DW_AT_prototyped DW_AT_type DW_AT_low_pc DW_AT_high_pc D W_AT_f ram e_base DW_AT_GNU_all_call_sites yes(1) DW_AT_sibling <0x00000770> yes(1) main 0x00000001 /tmp/test/test.c 0x00000019 yes(1) <0x0000005b> 0x00000000 0x0000011 d Jiri Slabý (Fakulta informatiky, MU) PB173/03 15. 10. 2013 11 /16 Atributy DIE Iterace přes všechny atributy v jednom DIE o ptrdiff_t dwarf_getattrs(Dwarf_Die *die, int (*callback)(Dwarf_Attribute *, void *), void *arg, ptrdiff_t offset) • die: Z dwfl_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 • O CO jde:dwarf_whatattr • Vrací DW_AT_* (DW_AT_name apod.) • Typ obsahu: dwarf _ what form o Vrací DW_F0RM_* (DW_FQRM_string apod.) • Obsah: dwarf _form* • Např. dwarf _f ormstring Jiri Slabý (Fakulta intormatiky, MU) PB173/03 15.10.2013 12/16 Atributy DIE - příklad static int cb(Dwarf_Attribute *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); } Jiri Slabý (Fakulta informatiky, MU) PB173/03 15.10.2013 13/16 Úkol Výpis atributů O Definujte funkci (háček) pro dwarf _getattrs @ V ní vypište informace • O jaký atribut jde (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_FQRM_string nebo DW_FQRM_strp Q V těle cyklu dwf l_nextcu zavolejte dwarf _getattrs O Přeložte a spusťte Jiri Slabý (Fakulta informatiky, MU) PB173/03 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) Jiri Slabý (Fakulta informatiky, MU) PB173/03 15.10.2013 15/16 Úkol Výpis potomků CU O Vezměte 1. potomka od CU (dwarf _chiid) O 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ň 0 Přeložte a spusťte Jiri Slabý (Fakulta informatiky, MU) PB173/03 15.10.2013 16/16