Разбор ELF-файла.

Тема в разделе "WASM.UNIX", создана пользователем Vasilii, 2 апр 2010.

  1. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    Доброго времени суток участникам форума!

    Хочу разобраться в ELF-формате для того, чтобы написат дизассемблер. Разбираюсь на примере простой программы "Hello, world!", написанной на с++, скомпилированной gcc. Нашёл секции с кодом. Теперь возникает такая проблема: некоторые части секций именованы. Не могу понять, как найти информацию об этих именах (метках, насколько я понимаю).

    Ещё одна проблема в том, что встречаются пустые части в файле (как многоточие перед второй меткой -- см. ниже). Сложность в том, что пустые два байта, как в приведённом фрагменте, неправильно дизассемблируются. Решается эта сложность, как я представляю, нахождением информации о метках.

    Но как и где найти эту информацию?

    Вот кусок того, что выдаёт objdump:

    Disassembly of section .plt:

    08048580 <__cxa_atexit@plt-0x10>:
    8048580: ff 35 f8 9f 04 08 pushl 0x8049ff8
    8048586: ff 25 fc 9f 04 08 jmp *0x8049ffc
    804858c: 00 00 add %al,(%eax)
    ...

    08048590 <__cxa_atexit@plt>:
    8048590: ff 25 00 a0 04 08 jmp *0x804a000
    8048596: 68 00 00 00 00 push $0x0
    804859b: e9 e0 ff ff ff jmp 8048580 <_init+0x30>
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Странно.. этож опенсурс.
     
  3. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    Да, документацию нашёл без проблем. Но она на английском. Наверное, я что-то пропустил в ней, связанное с конкретно этой частью. Кто-нибудь может подсказать, как находить каждый раз длину участка файла, заполненного кодом, и его месторасположение?
     
  4. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Vasilii
    Нет, тут надо просто conrtol-flow отслеживать: видим команду безусловного перехода, значит следующие байты вовсе не обязательно будут командами. ELF не содержит информации о том, где заканчивается код, есть записи лишь о том, где он начинается -- это как раз выясняется метками. Кстати в *nix их вроде принято называть словом symbol, по-крайней мере мой опыт общения с libbfd, подсказывает что это так.
     
  5. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    r90, спасибо! Я как раз думал, что информация об этом либо содержится в файле, либо выясняется переходами.

    Но, в таком случае, возникает резонный вопрос: откуда в таком случае тот же objdump знает имена меток? Здесь:

    08048590 <__cxa_atexit@plt>:

    то, что в угловых скобках -- это имя метки. И такие имена по всему дизассемблированному файлу. В самом исполняемом файле эти имена присутствуют. Только непонятно, как их связать с адресами.
     
  6. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Имена находятся в таблице символов (.symtab). Находим секцию с типом SHT_SYMTAB, разбираем ее и получаем символы. Секция .symtab состоит из записей в формате:

    Код (Text):
    1. typedef struct
    2. {
    3.   Elf64_Word    st_name;                /* Symbol name (string tbl index) */
    4.   unsigned char st_info;                /* Symbol type and binding */
    5.   unsigned char st_other;               /* Symbol visibility */
    6.   Elf64_Section st_shndx;               /* Section index */
    7.   Elf64_Addr    st_value;               /* Symbol value */
    8.   Elf64_Xword   st_size;                /* Symbol size */
    9. } Elf64_Sym;
    Количество записей в секции определяется с помощью размера секции и размера записи секции (sh_size / sh_entsize) из заголовка секции. Это для получения символов, которые определены в файле.

    Для получения символов, которые используются, но не определены надо разобрать SHT_REL и SHT_RELA:
    Код (Text):
    1. typedef struct
    2. {
    3.   Elf64_Addr    r_offset;               /* Address */
    4.   Elf64_Xword   r_info;                 /* Relocation type and symbol index */
    5. } Elf64_Rel;
    6.  
    7. typedef struct
    8. {
    9.   Elf64_Addr    r_offset;               /* Address */
    10.   Elf64_Xword   r_info;                 /* Relocation type and symbol index */
    11.   Elf64_Sxword  r_addend;               /* Addend */
    12. } Elf64_Rela;
    Секции SHT_REL и SHT_RELA связаны с таблицей символов (SHT_SYMTAB) и описывают связь неопределенного в файле символа с адресами, где этот символ используется. Т.е. если мы вызываем ф-ию printf, по адресу 0х0:

    0x0: 0xE8 0x0 0x0 0x0 0x0 call printf

    то релокация опишет, что байты по адресу 0x1 должны быть скорректированы, чтобы указывать на символ printf, когда он будет найден.

    Вкратце примерно так.

    P.S. Рекомендую все же заняться английским и заглянуть в файл /usr/include/elf.h
     
  7. black_hole

    black_hole New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2006
    Сообщения:
    44
    Код (Text):
    1. 804858c:    00 00                    add    %al,(%eax)
    Если об этом, то всё согласно мануалам и практике
     
  8. black_hole

    black_hole New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2006
    Сообщения:
    44
    хотя очень расстроен, думал на nasm можно положиться:dntknw:
     
  9. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    Mika0x65, спасибо большое!!!

    Теперь всё ясно, вроде. Попробую написать. И английским тоже займусь :)
     
  10. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    black_hole, да, именно это и смущает... Ладно, будем дизассемблировать коряво.
     
  11. Vasilii

    Vasilii New Member

    Публикаций:
    0
    Регистрация:
    7 мар 2010
    Сообщения:
    8
    Это не nasm, это под gcc компилировалось.