Создаем ELF-файл с отладочной информацией (DWARF) вручную (для микроконтроллеров ARM). Расширение файла ELF Elf файл что

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

Любой файл формата ELF (в том числе и объектные модули этого формата) состоит из следующих частей:

  • Заголовок ELF файла;
  • Таблица программных секций (в объектных модулях может отсутствовать);
  • Секции ELF файла;
  • Таблица секций (в выполняемом модуле может отсутствовать);
  • Ради производительности в формате ELF не используются битовые поля. И все структуры обычно выравниваются на 4 байта.

Теперь рассмотрим типы, используемые в заголовках ELF файлов:

Теперь рассмотрим заголовок файла:

#define EI_NIDENT 16 struct elf32_hdr { unsigned char e_ident; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; };

Массив e_ident содержит в себе информацию о системе и состоит из нескольких подполей.

Struct { unsigned char ei_magic; unsigned char ei_class; unsigned char ei_data; unsigned char ei_version; unsigned char ei_pad; }

  • ei_magic - постоянное значение для всех ELF файлов, равное { 0x7f, "E", "L", "F"}
  • ei_class - класс ELF файла (1 - 32 бита, 2 - 64 бита который мы не рассматриваем)
  • ei_data - определяет порядок следования байт для данного файла (этот порядок зависит от платформы и может быть прямым (LSB или 1) или обратным (MSB или 2)) Для процессоров Intel допустимо только значение 1.
  • ei_version - достаточно бесполезное поле, и если не равно 1 (EV_CURRENT) то файл считается некорректным.

В поле ei_pad операционные системы хранят свою идентификационную информацию. Это поле может быть пустым. Для нас оно тоже не важно.

Поле заголовка e_type может содержать несколько значений, для выполняемых файлов оно должно быть ET_EXEC равное 2

e_machine - определяет процессор на котором может работать данный выполняемый файл (Для нас допустимо значение EM_386 равное 3)

Поле e_version соответствует полю ei_version из заголовка.

Поле e_entry определяет стартовый адрес программы, который перед стартом программы размещается в eip.

Поле e_phoff определяет смещение от начала файла, по которому располагается таблица программных секций, используемая для загрузки программ в память.

Не буду перечислять назначение всех полей, не все нужны для загрузки. Лишь еще два опишу.

Поле e_phentsize определяет размер записи в таблице программных секций.

И поле e_phnum определяет количество записей в таблице программных секций.

Таблица секций (не программных) используется для линковки программ. мы ее рассматривать не будем. Так же мы не будем рассматривать динамически линкуемые модули. Тема эта достаточно сложная, для первого знакомства не подходящая. :)

Теперь про программные секции. Формат записи таблицы программных секций таков:

Struct elf32_phdr { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; };

Подробнее о полях.

  • p_type - определяет тип программной секции. Может принимать несколько значений, но нас интересует только одно. PT_LOAD (1). Если секция именно этого типа, то она предназначена для загрузки в память.
  • p_offset - определяет смещение в файле, с которого начинается данная секция.
  • p_vaddr - определяет виртуальный адрес, по которому эта секция должна быть загружена в память.
  • p_paddr - определяет физический адрес, по которому необходимо загружать данную секцию. Это поле не обязательно должно использоваться и имеет смысл лишь для некоторых платформ.
  • p_filesz - определяет размер секции в файле.
  • p_memsz - определяет размер секции в памяти. Это значение может быть больше предыдущего. Поле p_flag определяет тип доступа к секциям в памяти. Некоторые секции допускается выполнять, некоторые записывать. Для чтения в существующих системах доступны все.

Загрузка формата ELF.

С заголовком мы немного разобрались. Теперь я приведу алгоритм загрузки бинарного файла формата ELF. Алгоритм схематический, не стоит рассматривать его как работающую программу.

Int LoadELF (unsigned char *bin) { struct elf32_hdr *EH = (struct elf32_hdr *)bin; struct elf32_phdr *EPH; if (EH->e_ident != 0x7f || // Контролируем MAGIC EH->e_ident != "E" || EH->e_ident != "L" || EH->e_ident != "F" || EH->e_ident != ELFCLASS32 || // Контролируем класс EH->e_ident != ELFDATA2LSB || // порядок байт EH->e_ident != EV_CURRENT || // версию EH->e_type != ET_EXEC || // тип EH->e_machine != EM_386 || // платформу EH->e_version != EV_CURRENT) // и снова версию, на всякий случай return ELF_WRONG; EPH = (struct elf32_phdr *)(bin + EH->e_phoff); while (EH->e_phnum--) { if (EPH->p_type == PT_LOAD) memcpy (EPH->p_vaddr, bin + EPH->p_offset, EPH->p_filesz); EPH = (struct elf32_phdr *)((unsigned char *)EPH + EH->e_phentsize)); } return ELF_OK; }

По серьезному стоит еще проанализировать поля EPH->p_flags, и расставить на соответствующие страницы права доступа, да и просто копирование здесь не подойдет, но это уже не относится к формату, а к распределению памяти. Поэтому сейчас об этом не будем говорить.

Формат PE.

Во многом он аналогичен формату ELF, ну и не удивительно, там так же должны быть секции, доступные для загрузки.

Как и все в Microsoft:) формат PE базируется на формате EXE. Структура файла такова:

  • 00h - EXE заголовок (не буду его рассматривать, он стар как Дос. :)
  • 20h - OEM заголовок (ничего существенного в нем нет);
  • 3сh - смещение реального PE заголовка в файле (dword).
  • таблица перемещения stub;
  • stub;
  • PE заголовок;
  • таблица объектов;
  • объекты файла;

stub - это программа, выполняющаяся в реальном режиме и производящая какие-либо предварительные действия. Может и отсутствовать, но иногда может быть нужна.

Нас интересует немного другое, заголовок PE.

Структура его такая:

Struct pe_hdr { unsigned long pe_sign; unsigned short pe_cputype; unsigned short pe_objnum; unsigned long pe_time; unsigned long pe_cofftbl_off; unsigned long pe_cofftbl_size; unsigned short pe_nthdr_size; unsigned short pe_flags; unsigned short pe_magic; unsigned short pe_link_ver; unsigned long pe_code_size; unsigned long pe_idata_size; unsigned long pe_udata_size; unsigned long pe_entry; unsigned long pe_code_base; unsigned long pe_data_base; unsigned long pe_image_base; unsigned long pe_obj_align; unsigned long pe_file_align; // ... ну и еще много всякого, неважного. };

Много всякого там находится. Достаточно сказать, что размер этого заголовка - 248 байт.

И главное что большинство из этих полей не используется. (Кто так строит?) Нет, они, конечно, имеют назначение, вполне известное, но моя тестовая программа, например, в полях pe_code_base, pe_code_size и тд содержит нули но при этом прекрасно работает. Напрашивается вывод, что загрузка файла осуществляется на основе таблицы объектов. Вот о ней то мы и поговорим.

Таблица объектов следует непосредственно после PE заголовка. Записи в этой таблице имеют следующий формат:

Struct pe_ohdr { unsigned char o_name; unsigned long o_vsize; unsigned long o_vaddr; unsigned long o_psize; unsigned long o_poff; unsigned char o_reserved; unsigned long o_flags; };

  • o_name - имя секции, для загрузки абсолютно безразлично;
  • o_vsize - размер секции в памяти;
  • o_vaddr - адрес в памяти относительно ImageBase;
  • o_psize - размер секции в файле;
  • o_poff - смещение секции в файле;
  • o_flags - флаги секции;

Вот на флагах стоит остановиться поподробнее.

  • 00000004h - используется для кода с 16 битными смещениями
  • 00000020h - секция кода
  • 00000040h - секция инициализированных данных
  • 00000080h - секция неинициализированных данных
  • 00000200h - комментарии или любой другой тип информации
  • 00000400h - оверлейная секция
  • 00000800h - не будет являться частью образа программы
  • 00001000h - общие данные
  • 00500000h - выравнивание по умолчанию, если не указано иное
  • 02000000h - может быть выгружен из памяти
  • 04000000h - не кэшируется
  • 08000000h - не подвергается страничному преобразованию
  • 10000000h - разделяемый
  • 20000000h - выполнимый
  • 40000000h - можно читать
  • 80000000h - можно писать

Опять таки не буду с разделяемыми и оверлейными секциями, нас интересуют код, данные и права доступа.

В общем, этой информации уже достаточно для загрузки бинарного файла.

Загрузка формата PE.

int LoadPE (unsigned char *bin) { struct elf32_hdr *PH = (struct pe_hdr *) (bin + *((unsigned long *)&bin)); // Конечно комбинация не из понятных... просто берем dword по смещению 0x3c // И вычисляем адрес PE заголовка в образе файла struct elf32_phdr *POH; if (PH == NULL || // Контролируем указатель PH->pe_sign != 0x4550 || // сигнатура PE {"P", "E", 0, 0} PH->pe_cputype != 0x14c || // i386 (PH->pe_flags & 2) == 0) // файл нельзя запускать! return PE_WRONG; POH = (struct pe_ohdr *)((unsigned char *)PH + 0xf8); while (PH->pe_obj_num--) { if ((POH->p_flags & 0x60) != 0) // либо код либо инициализированные данные memcpy (PE->pe_image_base + POH->o_vaddr, bin + POH->o_poff, POH->o_psize); POH = (struct pe_ohdr *)((unsigned char *)POH + sizeof (struct pe_ohdr)); } return PE_OK; }

Это опять таки не готовая программа, а алгоритм загрузки.

И опять таки многие моменты не освещаются, так как выходят за пределы темы.

Но теперь стоит немного поговорить про существующие системные особенности.

Системные особенности.

Не смотря на гибкость средств защиты, имеющихся в процессорах (защита на уровне таблиц дескрипторов, защита на уровне сегментов, защита на уровне страниц) в существующих системах (как в Windows, так и в Unix) полноценено используется только страничная защита, которая хотя и может уберечь код от записи, но не может уберечь данные от выполнения. (Может быть, с этим и связано изобилие уязвимостей систем?)

Все сегменты адресуются с нулевого линейного адреса и простираются до конца линейной памяти. Разграничение процессов производится только на уровне страничных таблиц.

В связи с этим все модули линкуются не с начальных адресов, а с достаточно большим смещением в сегменте. В Windows используется базовый адрес в сегменте - 0x400000, в юникс (Linux или FreeBSD) - 0x8048000.

Некоторые особенности так же связаны со страничной организацией памяти.

ELF файлы линкуются таким образом, что границы и размеры секций приходятся на 4-х килобайтные блоки файла.

А в PE формате, не смотря на то, что сам формат позволяет выравнивать секции на 512 байт, используется выравнивание секций на 4к, меньшее выравнивание в Windows не считается корректным.

При наличии на компьютере установленной антивирусной программы можносканировать все файлы на компьютере, а также каждый файл в отдельности . Можно выполнить сканирование любого файла, щелкнув правой кнопкой мыши на файл и выбрав соответствующую опцию для выполнения проверки файла на наличие вирусов.

Например, на данном рисунке выделен файл my-file.elf , далее необходимо щелкнуть правой кнопкой мыши по этому файлу, и в меню файла выбрать опцию «сканировать с помощью AVG» . При выборе данного параметра откроется AVG Antivirus, который выполнит проверку данного файла на наличие вирусов.


Иногда ошибка может возникнуть в результате неверной установки программного обеспечения , что может быть связано с проблемой, возникшей в процессе установки. Это может помешать вашей операционной системе связать ваш файл ELF с правильным прикладным программным средством , оказывая влияние на так называемые «ассоциации расширений файлов» .

Иногда простая переустановка Dolphin (emulator) может решить вашу проблему, правильно связав ELF с Dolphin (emulator). В других случаях проблемы с файловыми ассоциациями могут возникнуть в результате плохого программирования программного обеспечения разработчиком, и вам может потребоваться связаться с разработчиком для получения дополнительной помощи.


Совет: Попробуйте обновить Dolphin (emulator) до последней версии, чтобы убедиться, что установлены последние исправления и обновления.


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


Осторожно: Поврежденный файл может повлечь за собой возникновение сопутствующего ущерба предыдущей или уже существующей вредоносной программы на вашем ПК, поэтому очень важно, чтобы на вашем компьютере постоянно работал обновленный антивирус.


Если ваш файл ELF связан с аппаратным обеспечением на вашем компьютере , чтобы открыть файл вам может потребоваться обновить драйверы устройств , связанных с этим оборудованием.

Эта проблема обычно связана с типами мультимедийных файлов , которые зависят от успешного открытия аппаратного обеспечения внутри компьютера, например, звуковой карты или видеокарты . Например, если вы пытаетесь открыть аудиофайл, но не можете его открыть, вам может потребоваться обновить драйверы звуковой карты .


Совет: Если при попытке открыть файл ELF вы получаете сообщение об ошибке, связанной с.SYS file , проблема, вероятно, может быть связана с поврежденными или устаревшими драйверами устройств , которые необходимо обновить. Данный процесс можно облегчить посредством использования программного обеспечения для обновления драйверов, такого как DriverDoc .


Если шаги не решили проблему , и у вас все еще возникают проблемы с открытием файлов ELF, это может быть связано с отсутствием доступных системных ресурсов . Для некоторых версий файлов ELF могут потребоваться значительный объем ресурсов (например, память/ОЗУ, вычислительная мощность) для надлежащего открытия на вашем компьютере. Такая проблема встречается достаточно часто, если вы используете достаточно старое компьютерное аппаратное обеспечение и одновременно гораздо более новую операционную систему.

Такая проблема может возникнуть, когда компьютеру трудно справиться с заданием, так как операционная система (и другие службы, работающие в фоновом режиме) могут потреблять слишком много ресурсов для открытия файла ELF . Попробуйте закрыть все приложения на вашем ПК, прежде чем открывать Nintendo Wii Game File. Освободив все доступные ресурсы на вашем компьютере вы обеспечите налучшие условия для попытки открыть файл ELF.


Если вы выполнили все описанные выше шаги , а ваш файл ELF по-прежнему не открывается, может потребоваться выполнить обновление оборудования . В большинстве случаев, даже при использовании старых версий оборудования, вычислительная мощность может по-прежнему быть более чем достаточной для большинства пользовательских приложений (если вы не выполняете много ресурсоемкой работы процессора, такой как 3D-рендеринг, финансовое/научное моделирование или интенсивная мультимедийная работа). Таким образом, вполне вероятно, что вашему компьютеру не хватает необходимого объема памяти (чаще называемой «ОЗУ», или оперативной памятью) для выполнения задачи открытия файла.

Версия этого ответа с хорошим TOC и большим количеством контента: http://www.cirosantilli.com/elf-hello-world (нажмите здесь ограничение 30k char)

Стандарты

ELF задается LSB:

  • core generic: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/elf-generic.html
  • core AMD64: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/book1.html

LSB в основном ссылается на другие стандарты с незначительными расширениями, в частности:

    generic (оба по SCO):

    • System V ABI 4.1 (1997) http://www.sco.com/developers/devspecs/gabi41.pdf , не 64 бит, хотя для него зарезервировано магическое число. То же самое для основных файлов.
    • System V ABI Update DRAFT 17 (2003) http://www.sco.com/developers/gabi/2003-12-17/contents.html добавляет 64 бит. Только обновляет главы 4 и 5 предыдущего документа: остальные остаются в силе и по-прежнему ссылаются.
  • специфическая архитектура:

    • IA-32: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-IA32/LSB-Core-IA32/elf-ia32.html указывает в основном на http://www.sco.com/developers/devspecs/abi386-4.pdf
    • AMD64: http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/elf-amd64.html , в основном указывает на http://www.x86-64.org/documentation/abi.pdf

Удобное резюме можно найти по адресу:

Его структура может быть рассмотрена с помощью удобных для пользователя способов, таких как readelf и objdump .

Создать пример

Позвольте сломать минимальный исполняемый пример Linux x86-64:

Section .data hello_world db "Hello world!", 10 hello_world_len equ $ - hello_world section .text global _start _start: mov rax, 1 mov rdi, 1 mov rsi, hello_world mov rdx, hello_world_len syscall mov rax, 60 mov rdi, 0 syscall

Скомпилировано с помощью

Nasm -w+all -f elf64 -o "hello_world.o" "hello_world.asm" ld -o "hello_world.out" "hello_world.o"

  • NASM 2.10.09
  • Binutils версия 2.24 (содержит ld)
  • Ubuntu 14.04

Мы не используем программу на C, так как это осложнит анализ, который будет уровнем 2: -)

шестнадцатеричных представлений бинарных

hd hello_world.o hd hello_world.out

Глобальная файловая структура

Файл ELF содержит следующие части:

  • Заголовок ELF. Указывает на позицию таблицы заголовка раздела и таблицы заголовков программ.

    Таблица заголовков разделов (необязательно в исполняемом файле). Каждый из них имеет заголовки секций e_shnum , каждый из которых указывает на положение раздела.

    N разделов с N <= e_shnum (необязательно в исполняемом файле)

    Таблица заголовков программ (только для исполняемых файлов). Каждый из них имеет e_phnum заголовки программ, каждый из которых указывает на положение сегмента.

    N сегментов, с N <= e_phnum (необязательно в исполняемом файле)

Порядок этих частей не фиксирован: единственная фиксированная вещь - это заголовок ELF, который должен быть первым в файле: Общие документы говорят:

Заголовок ELF

Самый простой способ наблюдать за заголовком:

Readelf -h hello_world.o readelf -h hello_world.out

Байт в объектном файле:

00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 01 00 3e 00 01 00 00 00 00 00 00 00 00 00 00 00 |..>.............| 00000020 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......| 00000030 00 00 00 00 40 00 00 00 00 00 40 00 07 00 03 00 |....@.....@.....|

00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 3e 00 01 00 00 00 b0 00 40 00 00 00 00 00 |..>.......@.....| 00000020 40 00 00 00 00 00 00 00 10 01 00 00 00 00 00 00 |@...............| 00000030 00 00 00 00 40 00 38 00 02 00 40 00 06 00 03 00 |[email protected]...@.....|

Представленная структура:

Typedef struct { unsigned char e_ident; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;

Распад вручную:

    0 0: EI_MAG = 7f 45 4c 46 = 0x7f "E", "L", "F" : магическое число ELF

    0 4: EI_CLASS = 02 = ELFCLASS64: 64-разрядный эльф

    0 5: EI_DATA = 01 = ELFDATA2LSB: данные большого конца

    0 6: EI_VERSION = 01: версия формата

    0 7: EI_OSABI (только в 2003 году) = 00 = ELFOSABI_NONE: нет расширений.

    0 8: EI_PAD = 8x 00: зарезервированные байты. Должно быть установлено в 0.

    1 0: e_type = 01 00 = 1 (big endian) = ET_REl: перемещаемый формат

    В исполняемом файле 02 00 для ET_EXEC .

    1 2: e_machine = 3e 00 = 62 = EM_X86_64: архитектура AMD64

    1 4: e_version = 01 00 00 00: должно быть 1

    1 8: e_entry = 8x 00: точка ввода адреса выполнения, или 0, если не применимо, как для объектного файла, так как нет точки входа.

    В исполняемом файле это b0 00 40 00 00 00 00 00 . TODO: что еще мы можем установить? Ядро, кажется, помещает IP непосредственно в это значение, оно не является жестко запрограммированным.

    2 0: e_phoff = 8x 00: смещение таблицы заголовка программы, 0, если нет.

    40 00 00 00 в исполняемом файле, то есть он начинается сразу после заголовка ELF.

    2 8: e_shoff = 40 7x 00 = 0x40: смещение файла таблицы заголовка раздела, 0, если нет.

    3 0: e_flags = 00 00 00 00 TODO. Специально для Arch.

    3 4: e_ehsize = 40 00: размер этого заголовка эльфа. Почему это поле? Как это может измениться?

    3 6: e_phentsize = 00 00: размер каждого заголовка программы, 0, если нет.

    38 00 в исполняемом файле: длина файла составляет 56 байтов

    3 8: e_phnum = 00 00: количество записей заголовка программы, 0, если нет.

    02 00 в исполняемом файле: есть 2 записи.

    3 A: e_shentsize и e_shnum = 40 00 07 00: размер заголовка раздела и количество записей

Таблица заголовков разделов

Массив структур Elf64_Shdr .

Каждая запись содержит метаданные о данном разделе.

e_shoff заголовка ELF дает здесь начальную позицию, 0x40.

e_shentsize и e_shnum из заголовка ELF говорят, что у нас есть 7 записей, каждый длиной 0x40 .

Таким образом, таблица берет байты от 0x40 до 0x40 + 7 + 0x40 - 1 = 0x1FF.

Названия некоторых разделов зарезервированы для определенных типов разделов: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#special_sections , например. .text требуется тип SHT_PROGBITS и SHF_ALLOC + SHF_EXECINSTR

readelf -S hello_world.o:

There are 7 section headers, starting at offset 0x40: Section Headers: Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .data PROGBITS 0000000000000000 00000200 000000000000000d 0000000000000000 WA 0 0 4 [ 2] .text PROGBITS 0000000000000000 00000210 0000000000000027 0000000000000000 AX 0 0 16 [ 3] .shstrtab STRTAB 0000000000000000 00000240 0000000000000032 0000000000000000 0 0 1 [ 4] .symtab SYMTAB 0000000000000000 00000280 00000000000000a8 0000000000000018 5 6 4 [ 5] .strtab STRTAB 0000000000000000 00000330 0000000000000034 0000000000000000 0 0 1 [ 6] .rela.text RELA 0000000000000000 00000370 0000000000000018 0000000000000018 4 2 4 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)

struct , представленный каждой записью:

Typedef struct { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; } Elf64_Shdr;

Разделы

Раздел индекса 0

Содержится в байтах от 0x40 до 0x7F.

Первый раздел всегда волшебный: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html говорит:

Если количество секций больше или равно SHN_LORESERVE (0xff00), e_shnum имеет значение SHN_UNDEF (0), а фактическое количество записей таблицы заголовков разделов содержится в поле sh_size заголовка раздела с индексом 0 (в противном случае член sh_size начальной записи содержит 0).

В разделе Figure 4-7: Special Section Indexes есть другие магические разделы.

В индексе 0, SHT_NULL является обязательным. Существуют ли для этого другие виды использования: Какая польза от раздела SHT_NULL в ELF? ?

.data раздел

Data - это раздел 1:

00000080 01 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 |................| 000000a0 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|

    Здесь 1 говорит, что имя этого раздела начинается с первого символа этого раздела и заканчивается на первом символе NUL, составляя строку.data .

    Data - одно из имен разделов, которое имеет предопределенное значение http://www.sco.com/developers/gabi/2003-12-17/ch4.strtab.html

    В этих разделах хранятся инициализированные данные, которые вносят вклад в образ памяти программы.

  • 80 4: sh_type = 01 00 00 00: SHT_PROGBITS: содержимое раздела не задано ELF, только тем, как программа интерпретирует его. Нормально, так как a .data .

    80 8: sh_flags = 03 7x 00: SHF_ALLOC и SHF_EXECINSTR: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#sh_flags , как требуется из раздела.data

    90 0: sh_addr = 8x 00: в каком виртуальном адресе раздел будет помещен во время выполнения, 0 если не помещен

    90 8: sh_offset = 00 02 00 00 00 00 00 00 = 0x200: количество байт от начала программы до первого байта в этом разделе

    a0 0: sh_size = 0d 00 00 00 00 00 00 00

    Если взять 0xD байт, начиная с sh_offset 200, мы видим:

    00000200 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 0a 00 |Hello world!.. |

    AHA! Итак, наша строка "Hello world!" находится в разделе данных, как мы сказали, это на NASM.

    Как только мы закончим hd , мы рассмотрим это как:

    Readelf -x .data hello_world.o

    который выводит:

    Hex dump of section ".data": 0x00000000 48656c6c 6f20776f 726c6421 0a Hello world!.

    NASM устанавливает достойные свойства для этого раздела, потому что он магически относится к.data: http://www.nasm.us/doc/nasmdoc7.html#section-7.9.2

    Также обратите внимание, что это был неправильный выбор раздела: хороший компилятор C поместил бы строку в.rodata вместо этого, потому что он доступен только для чтения, и это позволит продолжить оптимизацию ОС.

    a0 8: sh_link и sh_info = 8x 0: не применяются к типу этого раздела. http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html#special_sections

    b0 0: sh_addralign = 04 = TODO: зачем это выравнивание необходимо? Это только для sh_addr , а также для символов внутри sh_addr ?

    b0 8: sh_entsize = 00 = раздел не содержит таблицы. Если!= 0, это означает, что раздел содержит таблицу записей фиксированного размера. В этом файле мы видим из вывода readelf , что это имеет место для разделов.symtab и.rela.text .

.text раздел

Теперь, когда мы сделали один раздел вручную, дайте выпускнику и используйте readelf -S других разделов.

Name Type Address Offset Size EntSize Flags Link Info Align [ 2] .text PROGBITS 0000000000000000 00000210 0000000000000027 0000000000000000 AX 0 0 16

Text является исполняемым, но не доступен для записи: если мы попытаемся написать ему Linux segfaults. Посмотрим, действительно ли у нас есть код:

Objdump -d hello_world.o

Hello_world.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <_start>: 0: b8 01 00 00 00 mov $0x1,%eax 5: bf 01 00 00 00 mov $0x1,%edi a: 48 be 00 00 00 00 00 movabs $0x0,%rsi 11: 00 00 00 14: ba 0d 00 00 00 mov $0xd,%edx 19: 0f 05 syscall 1b: b8 3c 00 00 00 mov $0x3c,%eax 20: bf 00 00 00 00 mov $0x0,%edi 25: 0f 05 syscall

Если мы имеем grep b8 01 00 00 на hd , мы видим, что это происходит только в 00000210 , что и говорится в этом разделе. И размер равен 27, что также соответствует. Поэтому мы должны говорить о правильном разделе.

Это выглядит как правильный код: a write , за которым следует exit .

Самая интересная часть - это строка a , которая делает:

Movabs $0x0,%rsi

передать адрес строки в системный вызов. В настоящее время 0x0 является просто заполнителем. После связывания произойдет его изменение:

4000ba: 48 be d8 00 60 00 00 movabs $0x6000d8,%rsi

Эта модификация возможна из-за данных раздела.rela.text .

SHT_STRTAB

Разделы с sh_type == SHT_STRTAB называются строковыми таблицами.

Такие разделы используются другими разделами, когда имена строк должны использоваться. В разделе "Использование" говорится:

  • какую строку они используют
  • что такое индекс в таблице целевых строк, где начинается строка

Так, например, мы могли бы иметь строковую таблицу, содержащую: TODO: нужно ли начинать с \0 ?

Data: \0 a b c \0 d e f \0 Index: 0 1 2 3 4 5 6 7 8

И если другой раздел хочет использовать строку d e f , они должны указывать на индекс 5 этого раздела (буква d).

Известные строковые таблицы:

  • .shstrtab
  • .strtab

.shstrtab

Тип раздела: sh_type == SHT_STRTAB .

Общее имя: строка заголовка заголовка раздела.

Имя раздела.shstrtab зарезервировано. В стандарте говорится:

В этом разделе содержатся имена разделов.

В этом разделе указывается поле e_shstrnd самого заголовка ELF.

Индексы строк этого раздела указываются полем sh_name заголовков разделов, которые обозначают строки.

В этом разделе не указано SHF_ALLOC , поэтому оно не будет отображаться в исполняемой программе.

Readelf -x .shstrtab hello_world.o

Hex dump of section ".shstrtab": 0x00000000 002e6461 7461002e 74657874 002e7368 ..data..text..sh 0x00000010 73747274 6162002e 73796d74 6162002e strtab..symtab.. 0x00000020 73747274 6162002e 72656c61 2e746578 strtab..rela.tex 0x00000030 7400 t.

Данные в этом разделе имеют фиксированный формат: http://www.sco.com/developers/gabi/2003-12-17/ch4.strtab.html

Если мы посмотрим на имена других разделов, мы увидим, что все они содержат числа, например. секция.text имеет номер 7 .

Затем каждая строка заканчивается, когда найден первый символ NUL, например. символ 12 \0 сразу после.text\0 .

.symtab

Тип раздела: sh_type == SHT_SYMTAB .

Общее имя: таблица символов.

Сначала отметим, что:

  • sh_link = 5
  • sh_info = 6

В разделе SHT_SYMTAB эти числа означают, что:

  • Строки
  • которые дают имена символов, находятся в разделе 5, .strtab
  • данные перемещения находятся в разделе 6, .rela.text

Хороший инструмент высокого уровня для разборки этого раздела:

Nm hello_world.o

который дает:

0000000000000000 T _start 0000000000000000 d hello_world 000000000000000d a hello_world_len

Это, однако, представление высокого уровня, в котором опускаются некоторые типы символов и в которых обозначаются символы. Более детальную разборку можно получить с помощью:

Readelf -s hello_world.o

который дает:

Symbol table ".symtab" contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello_world.asm 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 2 4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 1 hello_world 5: 000000000000000d 0 NOTYPE LOCAL DEFAULT ABS hello_world_len 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 _start

Бинарный формат таблицы документируется на http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html

Readelf -x .symtab hello_world.o

Что дает:

Hex dump of section ".symtab": 0x00000000 00000000 00000000 00000000 00000000 ................ 0x00000010 00000000 00000000 01000000 0400f1ff ................ 0x00000020 00000000 00000000 00000000 00000000 ................ 0x00000030 00000000 03000100 00000000 00000000 ................ 0x00000040 00000000 00000000 00000000 03000200 ................ 0x00000050 00000000 00000000 00000000 00000000 ................ 0x00000060 11000000 00000100 00000000 00000000 ................ 0x00000070 00000000 00000000 1d000000 0000f1ff ................ 0x00000080 0d000000 00000000 00000000 00000000 ................ 0x00000090 2d000000 10000200 00000000 00000000 -............... 0x000000a0 00000000 00000000 ........

Записи имеют тип:

Typedef struct { Elf64_Word st_name; unsigned char st_info; unsigned char st_other; Elf64_Half st_shndx; Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym;

Как и в таблице разделов, первая запись волшебна и задана фиксированными бессмысленными значениями.

Запись 1 имеет ELF64_R_TYPE == STT_FILE . ELF64_R_TYPE продолжается внутри st_info .

Байт-анализ:

    10 8: st_name = 01000000 = символ 1 в.strtab , который до следующего \0 делает hello_world.asm

    Этот фрагмент информационного файла может использоваться компоновщиком для определения того, какие сегменты сегмента идут.

    10 12: st_info = 04

    Bits 0-3 = ELF64_R_TYPE = Type = 4 = STT_FILE: основная цель этой записи - использовать st_name для указания имени файла, сгенерированного этим объектным файлом.

    Биты 4-7 = ELF64_ST_BIND = Binding = 0 = STB_LOCAL . Требуемое значение для STT_FILE .

    10 13: st_shndx = Таблица символов Таблица заголовков Индекс = f1ff = SHN_ABS . Требуется для STT_FILE .

    20 0: st_value = 8x 00: требуется для значения для STT_FILE

    20 8: st_size = 8x 00: нет выделенного размера

Теперь из readelf мы быстро интерпретируем остальные.

STT_SECTION

Есть два таких элемента, один указывает на.data , а другой на.text (индексы раздела 1 и 2).

Num: Value Size Type Bind Vis Ndx Name 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 3: 0000000000000000 0 SECTION LOCAL DEFAULT 2

TODO, какова их цель?

STT_NOTYPE

Затем введите наиболее важные символы:

Num: Value Size Type Bind Vis Ndx Name 4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 1 hello_world 5: 000000000000000d 0 NOTYPE LOCAL DEFAULT ABS hello_world_len 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 _start Строка

hello_world находится в разделе.data (индекс 1). Это значение равно 0: он указывает на первый байт этого раздела.

Start отмечен видимостью GLOBAL , так как мы написали:

Global _start

в NASM. Это необходимо, так как оно должно рассматриваться как точка входа. В отличие от C, по умолчанию метки NASM являются локальными.

hello_world_len указывает на специальный st_shndx == SHN_ABS == 0xF1FF .

0xF1FF выбирается так, чтобы не противоречить другим разделам.

st_value == 0xD == 13 , который является значением, которое мы сохранили там на сборке: длина строки Hello World! .

Это означает, что перемещение не повлияет на это значение: оно является константой.

Это небольшая оптимизация, которую делает наш ассемблер для нас и имеет поддержку ELF.

Если бы мы использовали адрес hello_world_len в любом месте, ассемблер не смог бы пометить его как SHN_ABS , и позже у компоновщика будет дополнительное перемещение.

SHT_SYMTAB в исполняемом файле

По умолчанию NASM размещает.symtab в исполняемом файле.

Это используется только для отладки. Без символов мы полностью слепы и должны все перепроектировать.

Вы можете удалить его с помощью objcopy , и исполняемый файл все равно будет работать. Такие исполняемые файлы называются разделенными исполняемыми файлами.

.strtab

Удерживает строки для таблицы символов.

В этом разделе sh_type == SHT_STRTAB .

Указывается на sh_link == 5 раздела.symtab .

Readelf -x .strtab hello_world.o

Hex dump of section ".strtab": 0x00000000 0068656c 6c6f5f77 6f726c64 2e61736d .hello_world.asm 0x00000010 0068656c 6c6f5f77 6f726c64 0068656c .hello_world.hel 0x00000020 6c6f5f77 6f726c64 5f6c656e 005f7374 lo_world_len._st 0x00000030 61727400 art.

Это означает, что это ограничение уровня ELF, что глобальные переменные не могут содержать символы NUL.

.rela.text

Тип раздела: sh_type == SHT_RELA .

Общее имя: раздел перемещения.

Rela.text содержит данные перемещения, в которых указано, как адрес должен быть изменен, когда последний исполняемый файл связан. Это указывает на байты текстовой области, которые должны быть изменены, когда связывание происходит с указанием правильных мест памяти.

В основном, он преобразует текст объекта, содержащий адрес заполнителя 0x0:

A: 48 be 00 00 00 00 00 movabs $0x0,%rsi 11: 00 00 00

к фактическому исполняемому коду, содержащему окончательный 0x6000d8:

4000ba: 48 be d8 00 60 00 00 movabs $0x6000d8,%rsi 4000c1: 00 00 00

Указывалось sh_info = 6 раздела.symtab .

readelf -r hello_world.o дает:

Relocation section ".rela.text" at offset 0x3b0 contains 1 entries: Offset Info Type Sym. Value Sym. Name + Addend 00000000000c 000200000001 R_X86_64_64 0000000000000000 .data + 0

Раздел не существует в исполняемом файле.

Фактические байты:

00000370 0c 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................| 00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|

Представленный struct:

Typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; Elf64_Sxword r_addend; } Elf64_Rela;

    370 0: r_offset = 0xC: адрес в адрес.text , адрес которого будет изменен

    370 8: r_info = 0x200000001. Содержит 2 поля:

    • ELF64_R_TYPE = 0x1: значение зависит от точной архитектуры.
    • ELF64_R_SYM = 0x2: индекс раздела, на который указывает адрес, поэтому.data , который находится в индексе 2.

    AMD64 ABI говорит, что тип 1 называется R_X86_64_64 и что он представляет операцию S + A где:

    • S: значение символа в объектном файле, здесь 0 , потому что мы указываем на 00 00 00 00 00 00 00 00 из movabs $0x0,%rsi
    • a: добавление, присутствующее в поле r_added

    Этот адрес добавляется в раздел, в котором работает перемещение.

    Эта операция перемещения действует на 8 байтов.

    380 0: r_addend = 0

Таким образом, в нашем примере мы заключаем, что новый адрес будет: S + A = .data + 0 , и, таким образом, первое в разделе данных.

Таблица заголовков программ

Отображается только в исполняемом файле.

Содержит информацию о том, как исполняемый файл должен быть помещен в виртуальную память процесса.

Исполняемый файл создается объектным файлом компоновщиком. Основные задания, которые выполняет компоновщик:

    определите, какие разделы объектных файлов войдут в какие сегменты исполняемого файла.

    В Binutils это сводится к анализу компоновщика script и работе с множеством значений по умолчанию.

    Вы можете получить компоновщик script, используемый с ld --verbose , и установить пользовательский с ld -T .

    выполнять перемещение по текстовым разделам. Это зависит от того, как несколько разделов помещаются в память.

readelf -l hello_world.out дает:

Elf file type is EXEC (Executable file) Entry point 0x4000b0 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000000d7 0x00000000000000d7 R E 200000 LOAD 0x00000000000000d8 0x00000000006000d8 0x00000000006000d8 0x000000000000000d 0x000000000000000d RW 200000 Section to Segment mapping: Segment Sections... 00 .text 01 .data

В заголовке ELF e_phoff , e_phnum и e_phentsize сказали нам, что есть 2 заголовка программы, которые начинаются с 0x40 и длиной 0x38 байтов каждый, поэтому они:

00000040 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 |..@.......@.....| 00000060 d7 00 00 00 00 00 00 00 d7 00 00 00 00 00 00 00 |................| 00000070 00 00 20 00 00 00 00 00 |.. ..... |

00000070 01 00 00 00 06 00 00 00 | ........| 00000080 d8 00 00 00 00 00 00 00 d8 00 60 00 00 00 00 00 |..........`.....| 00000090 d8 00 60 00 00 00 00 00 0d 00 00 00 00 00 00 00 |..`.............| 000000a0 0d 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 |.......... .....| typedef struct { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_Xword p_align; } Elf64_Phdr;

Пробой первого:

  • 40 0: p_type = 01 00 00 00 = PT_LOAD: TODO. Я думаю, это означает, что он будет загружен в память. Другие типы могут не обязательно быть.
  • 40 4: p_flags = 05 00 00 00 = выполнять и читать разрешения, не писать TODO
  • 40 8: p_offset = 8x 00 TODO: что это? Похоже на смещения от начала сегментов. Но это будет означать, что некоторые сегменты переплетаются? С ним можно немного поиграть: gcc -Wl,-Ttext-segment=0x400030 hello_world.c
  • 50 0: p_vaddr = 00 00 40 00 00 00 00 00: начальный адрес виртуальной памяти для загрузки этого сегмента в
  • 50 8: p_paddr = 00 00 40 00 00 00 00 00: начальный физический адрес для загрузки в память. Только вопросы для систем, в которых программа может установить физический адрес. В противном случае, как и в системах System V, может быть что угодно. Кажется, что NASM просто скопирует p_vaddrr
  • 60 0: p_filesz = d7 00 00 00 00 00 00 00: TODO vs p_memsz
  • 60 8: p_memsz = d7 00 00 00 00 00 00 00: TODO
  • 70 0: p_align = 00 00 20 00 00 00 00 00: 0 или 1 означает, что никакого выравнивания не требуется TODO, что это значит? в противном случае избыточно с другими полями

Вторая аналогична.

Section to Segment mapping:

раздела readelf говорит нам, что:

  • 0 - сегмент.text . Ага, поэтому он является исполняемым и не доступен для записи.
  • 1 - сегмент.data .

Формат ELF

Формат ELF имеет файлы нескольких типов, которые до сих пор мы называли по-разному, например, исполняемый файл или объектный файл. Тем не менее стандарт ELF различает следующие типы:

1. Перемещаемый файл (relocatable file), хранящий инструкции и данные, которые могут быть связаны с другими объектными файлами. Результатом такого связывания может быть исполняемый файл или разделяемый объектный файл.

2. Разделяемый объектный файл (shared object file) также содержит инструкции и данные, но может быть использован двумя способами. В первом случае, он может быть связан с другими перемещаемыми файлами и разделяемыми объектными файлами, в результате будет создан новый объектный файл. Во втором случае, при запуске программы на выполнение операционная система может динамически связать его с исполняемым файлом программы, в результате чего будет создан исполняемый образ программы. В последнем случае речь идет о разделяемых библиотеках.

3. Исполняемый файл хранит полное описание, позволяющее системе создать образ процесса. Он содержит инструкции, данные, описание необходимых разделяемых объектных файлов, а также необходимую символьную и отладочную информацию.

На рис. 2.4 приведена структура исполняемого файла, с помощью которого операционная система может создать образ программы и запустить программу на выполнение.

Рис. 2.4 . Структура исполняемого файла в формате ELF

Заголовок имеет фиксированное расположение в файле. Остальные компоненты размещаются в соответствии с информацией, хранящейся в заголовке. Таким образом заголовок содержит общее описание структуры файла, расположение отдельных компонентов и их размеры.

Поскольку заголовок ELF-файла определяет его структуру, рассмотрим его более подробно (табл. 2.4).

Таблица 2.3 . Поля заголовка ELF-файла

Поле Описание
е_ident Массив байт, каждый из которых определяет некоторую общую характеристику файла: формат файла (ELF), номер версии, архитектуру системы (32-разрядная или 64-разрядная) и т.д.
e_type Тип файла, поскольку формат ELF поддерживает несколько типов
e_machine Архитектура аппаратной платформы, для которой создан данный файл. В табл. 2.4 приведены возможные значения этого поля
e_version Номер версии ELF-формата. Обычно определяется как EV_CURRENC (текущая), что означает последнюю версию
e_entry Виртуальный адрес, по которому системой будет передано управление после загрузки программы (точка входа)
e_phoff Расположение (смещение от начала файла) таблицы заголовков программы
е_shoff Расположение таблицы заголовков секций
е_ehsize Размер заголовка
e_phentsize Размер каждого заголовка программы
e_phnum Число заголовков программы
e_shentsize Размер каждого заголовка сегмента (секции)
е_shnum Число заголовков сегментов (секций)
e_shstrndx Расположение сегмента, содержащего таблицу строк

Таблица 2.4 . Значения поля e_machine заголовка ELF-файла

Значение Аппаратная платформа
ЕМ_М32 AT&T WE 32100
ЕМ_SPARC Sun SPARC
ЕМ_386 Intel 80386
ЕМ_68K Motorola 68000
EM_88K Motorola 88000
ЕМ_486 Intel 80486
ЕМ_860 Intel i860
ЕМ_MIPS MIPS RS3000 Big-Endian
EM_MIPS_RS3_LE MIPS RS3000 Little-Endian
EM_RS6000 RS6000
EM_PA_RISC PA-RISC
EM_nCUBE nCUBE
EM_VPP500 Fujitsu VPP500
EM_SPARC32PLUS Sun SPARC 32+

Информация, содержащаяся в таблице заголовков программы, указывает ядру, как создать образ процесса из сегментов. Большинство сегментов копируются (отображаются) в память и представляют собой соответствующие сегменты процесса при его выполнении, например, сегменты кода или данных.

Каждый заголовок сегмента программы описывает один сегмент и содержит следующую информацию:

Тип сегмента и действия операционной системы с данным сегментом

Расположение сегмента в файле

Стартовый адрес сегмента в виртуальной памяти процесса

Размер сегмента в файле

Размер сегмента в памяти

Флаги доступа к сегменту (запись, чтение, выполнение)

Часть сегментов имеет тип LOAD, предписывающий ядру при запуске программы на выполнение создать соответствующие этим сегментам структуры данных, называемые областями , определяющие непрерывные участки виртуальной памяти процесса и связанные с ними атрибуты. Сегмент, расположение которого в ELF-файле указано в соответствующем заголовке программы, будет отображен в созданную область, виртуальный адрес начала которой также указан в заголовке программы. К сегментам такого типа относятся, например, сегменты, содержащие инструкции программы (код) и ее данные. Если размер сегмента меньше размера области, неиспользованное пространство может быть заполнено нулями. Такой механизм, в частности используется при создании неинициализированных данных процесса (BSS). Подробнее об областях мы поговорим в главе 3.

В сегменте типа INTERP хранится программный интерпретатор. Данный тип сегмента используется для программ, которым необходимо динамическое связывание. Суть динамического связывания заключается в том, что отдельные компоненты исполняемого файла (разделяемые объектные файлы) подключаются не на этапе компиляции, а на этапе запуска программы на выполнение. Имя файла, являющегося динамическим редактором связей , хранится в данном сегменте. В процессе запуска программы на выполнение ядро создает образ процесса, используя указанный редактор связей. Таким образом, первоначально в память загружается не исходная программа, а динамический редактор связей. На следующем этапе динамический редактор связей совместно с ядром UNIX создают полный образ исполняемого файла. Динамический редактор загружает необходимые разделяемые объектные файлы, имена которых хранятся в отдельных сегментах исходного исполняемого файла, и производит требуемое размещение и связывание. В заключение управление передается исходной программе.

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

Мы еще вернемся к формату ELF в главе 3 при обсуждении организации виртуальной памяти процесса, а пока перейдем к следующему распространенному формату - COFF.

Из книги Искусство программирования для Unix автора Реймонд Эрик Стивен

Из книги Самоучитель работы на компьютере автора Колисниченко Денис Николаевич

Из книги Реферат, курсовая, диплом на компьютере автора Баловсяк Надежда Васильевна

5.2.6. Формат Windows INI Многие программы в Microsoft Windows используют текстовый формат данных, подобный фрагменту, приведенному в примере 5.6. В данном примере необязательные ресурсы с именами account, directory, numeric_id и developer связываются с именованными проектами python, sng, f etchmail и py-howto. В записи

Из книги Новейший самоучитель работы на компьютере автора Белунцов Валерий

14.5.3. Формат ячейки Формат задает, как будет отображаться значение ячейки. Формат тесно связан с типом данных ячейки. Тип задаете вы сами. Если вы ввели число, то это числовой тип данных. Excel сама старается определить формат по типу данных. Например, если вы ввели текст, то

Из книги Искусство программирования для Unix автора Реймонд Эрик Стивен

Формат PDF PDF расшифровывается как Portable Document Format (портативный формат документа). Этот формат был создан специально для ликвидации проблем с отображением информации в файлах. Его преимущество состоит в том, что, во-первых, документ, сохраненный в формате PDF, будет одинаково

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

Формат файлов Когда пользователь начинает работу с каким-либо файлом, системе необходимо знать, в каком формате он записан и с помощью какой программы его нужно открывать. Например, если файл содержит обычный текст, то он может быть прочитан в любой текстовой программе

Из книги Яндекс для всех автора Абрамзон М. Г.

5.2.2. Формат RFC 822 Метаформат RFC 822 происходит от текстового формата сообщений электронной почты в Internet. RFC 822 является основным Internet RFC-стандартом, описывающим данный формат (впоследствии заменен RFC 2822). Формат MIME (Multipurpose Internet Media Extension - многоцелевые расширения Internet)

Из книги Macromedia Flash Professional 8. Графика и анимация автора Дронов В. А.

5.2.3. Формат Cookie-Jar Формат cookie-jar используется программой fortune(1) для собственной базы данных случайных цитат. Он подходит для записей, которые представляют собой просто блоки неструктурированного текста. В качестве разделителя записей в данном формате применяется символ

Из книги Компьютерная обработка звука автора Загуменнов Александр Петрович

5.2.4. Формат record-jar Разделители записей формата cookie-jar хорошо сочетаются с метаформатом RFC 822 для записей, образующих формат, который в данной книге называется "record-jar". Иногда требуется текстовый формат, поддерживающий множественные записи с различным набором явных имен

Из книги Операционная система UNIX автора Робачевский Андрей М.

5.2.6. Формат Windows INI Многие программы в Microsoft Windows используют текстовый формат данных, подобный фрагменту, приведенному в примере 5.6. В данном примере необязательные ресурсы с именами account, directory, numeric_id и developer связываются с именованными проектами python, sng, fetchmail и py-howto. В записи

Из книги Офисный компьютер для женщин автора Пастернак Евгения

19.5 Обобщенный формат URL Обобщая вышесказанное, отметим, что:? URL начинается с указания используемого протокола доступа.? Для всех приложений, кроме сетевых новостей и электронной почты, далее следует разделитель://.? Затем указывается имя хоста сервера.? Наконец

Из книги автора

3.3.1. Формат RSS Читать новости сайтов можно по-разному. Самый простой способ - заходить время от времени на сайт и просматривать новые сообщения. Можно поставить программу, которая подключается к новостному каналу и сама получает заголовки или аннотации новостей, по

Из книги автора

Формат MP3 Формат MP3 был создан для распространения музыкальных файлов, сжатых кодеком MPEG 1 level 3. В настоящее время - самый популярный формат распространения музыки через Интернет, и не только. Поддерживается абсолютно всеми программами записи и обработки звука, за

Из книги автора

Формат MP3 Метод сжатия звука, а также формат сжатых звуковых файлов, предложенный международной организацией MPEG (Moving Pictures Experts Group – Экспертная группа по видеозаписи), основан на перцептуальном кодировании звука. Работы по созданию эффективных алгоритмов кодирования

Из книги автора

Формат ELF Формат ELF имеет файлы нескольких типов, которые до сих пор мы называли по-разному, например, исполняемый файл или объектный файл. Тем не менее стандарт ELF различает следующие типы:1. Перемещаемый файл (relocatable file), хранящий инструкции и данные, которые могут быть

Из книги автора

Формат чисел Наконец-то добрались до формата чисел. Я уже не раз о нем упоминала, теперь разложу все по полочкам (хотя общий смысл вы уже могли понять).Числа в Excel могут отображаться в различных форматах. В этом разделе мы поговорим о том, какие существуют форматы чисел и как

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

Посещение этой страницы должно помочь Вам ответить конкретно на эти, или похожие вопросы:

  • Как открыть файл с расширением ELF?
  • Как провести конвертирование файла ELF в другой формат?
  • Что такое расширение формата файлов ELF?
  • Какие программы обслуживают файл ELF?

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

Что еще может вызвать проблемы?

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

Вы хотите помочь?

Если у Вас есть дополнительная информация о расширение файла ELF мы будем признательны, если Вы поделитесь ею с пользователями нашего сайта. Воспользуйтесь формуляром, находящимся и отправьте нам свою информацию о файле ELF.

Плееры