Автор: Пользователь скрыл имя, 03 Октября 2011 в 21:21, реферат
В практической деятельности большинства программистов рано или поздно возникают проблемы, для решения которых необходимо знать форматы исполняемых файлов. Если ассемблер является отражением архитектуры компьютера, то формат исполняемого файла является отражением архитектуры операционной системы.
Для 32-разрядных операционных систем фирма Microsoft разработала специальный формат исполняемого файла. Он получил название переносимый формат исполняемого файла (PE — Portable Executable). В нашем изложении мы будем называть его PE-форматом. Детальное рассмотрение PE-формата требует очень много места, но вряд ли это так необходимо. В большинстве случаев достаточно представлять общую структуру файла PE-формата («знать, что где лежит»). Для получения детальной информации всегда можно обратиться к документации. Необходимо отметить, что идеи, заложенные в PE-формат, не новы. Основы этого формата были заложены в операционной системе Unix, где аналогичный формат назывался COFF-формат (Common Object File Format — стандартный формат объектного файла). Почему формат файла в 32-разрядных операционных системах назван переносимым (portable)? Это сделано из-за стремления фирмы Microsoft создать единый формат исполняемого файла для реализаций операционной системы Windows NT на различных аппаратных платформах (что, конечно, не означает совместимости на уровне машинных команд).
Перечислим особенности данного формата:
m простота загрузки файла PE-формата. Если сравнивать этот процесс с загрузкой файла NE-формата, то для PE-исполняемого файла он значительно проще. Чтобы загрузить NE-файл, загрузчик должен создать рабочие структуры в памяти, найти информацию для их заполнения внутри NE-файла;
m поддержка сплошной модели памяти. Конструкция PE-файла максимально упрощена с точки зрения загрузки в память. Фактически он представляет собой слепок участка оперативной памяти;
m не требуется настраивать сегменты команд или данных, так как их нет в том виде, как это было в 16-разрядной среде;
m расположение многих полей в PE-файле задается с помощью относительного смещения от начала PE-файла — Относительного Адреса Поля (ОАП). Сам PE-файл располагается по Базовому Адресу Памяти (БАП) — физическому адресу памяти, с которого начинается загруженный в память модуль.
Информация в PE-файле является, в основном, высокоуровневой и используется системой или приложениями, чтобы определить правила обращения с конкретным исполняемым файлом.
Перед тем как углубиться в рассмотрение деталей PE-формата, давайте рассмотрим его общую структуру (рис. 5).
Рис. 5. Общая структура файла PE-формата
Из рис. 5 видно, что в структуре файла PE-формата выделяются следующие составные части:
m программа-заглушка MS-DOS с аналогичными, как в файлах NE-формата, функциями;
m заголовок PE-файла;
m раздел секций;
m область отладочной информации (необязательно).
Рассмотрим их подробнее.
Основные соображения, по которым в начале PE-файла находится программа-заглушка MS-DOS, те же, что и для NE-файла. Ее основная функция — при запуске в среде MS-DOS выдать сообщение типа «This program cannot be run in DOS mode». Сама программа-заглушка выполнена как полноценный MZ-файл, все поля которого обсуждались нами выше. Для нас интерес представляет 32-разрядное поле со смещением 3Ch. В нем содержится смещение, указывающее на начало PE-файла.
Заголовок PE-файла начинается с четырехбайтовой сигнатуры 50 45 00 00h, что соответствует строке «PE» с последующими двумя байтами нулей.
Заголовок PE-файла можно разбить на следующие части:
m сигнатура PE-файла;
m основной заголовок PE-файла (PE header);
m дополнительный заголовок PE-файла (PE optional header).
Формат основного заголовка представлен в табл. 22. Он содержит самую общую информацию о PE-файле.
Таблица 22. Структура основного заголовка PE-файла
Смещение Длина, Назначение
байт
00h 2 Тип компьютера,
для которого создавалась программа.
Некоторые возможные значения:
0000h — неизвестный тип компьютерной платформы;
014ch — Intel i80x86;
0160h 0162h, 166, 168 — MIPS;
0184h — DEC Alpha AXP;
01f0h — Power PC;
0268h — Motorola 68000.
Эти константы определены
во включаемом файле winnt.h
(Visual C++). Система использует их для организации
правильного обращения с файлом
02h 2 Количество секций в PE-файле
04h 4 Время
создания файла. Отсчет времени производится
в се-
кундах, прошедших с 16:00 31.12.69. (Как насчет
проблемы
Y2К?)
08h 4 0
0ch 4 0
10h 2 Размер
дополнительного заголовка PE-файла (PE
optional
header). Его размер обычно 224 байта
Смещение Длина, Назначение
байт
12h 2 Информационные
флаги:
0001h — информация о перемещении удалена
из файла;
0002h — файл представляет собой исполняемое
отображение, то
есть не имеет неразрешенных внешних ссылок;
0004h — информация о номерах строк удалена
из файла;
0008h — локальные символы удалены из файла;
0080h — расположение байт в машинном слове
обратное, то есть
соответствует принципу «младший байт
по младшему адресу»;
0100h — размер машинного слова 32 бита;
0200h — отладочная информация удалена из
исполняемого
файла в файл .dbg;
1000h — системный файл;
2000h —dll-библиотека;
и др. Полный перечень флагов приведен
во включаемом файле
winnt.h (Visual C++)
За основным заголовком PE-файла следует дополнительный заголовок. В табл. 23 представлены расположение и значения полей, представляющих наибольший интерес. Все смещения считаются от начала дополнительного заголовка.
Таблица 23. Структура дополнительного заголовка PE-файла
Смещение Размер, Назначение
байт
+00h 2 Сигнатура, определяющая
состояние PE-файла. Возможные
значения:
0107h — отображение постоянного запоминающего
устройства;
010bh — обычный исполняемый файл
+02h 2 Версия компоновщика, создавшего исполняемый файл
+04h 4 Размер секции кода (.text) в байтах
+08h 4 Размер секции инициализированных данных
+0ch 4 Размер секции неинициализированных данных
+10h 4 Адрес
(ОАП), с которого начинается выполнение
программы
модуля. Он находится в секции .text
+14h 4 ОАП,
с которого начинаются программные секции
PE-файла.
Если файл был создан компоновщиком Microsoft,
то про-
граммная секция начинается с адреса 1000h.
Компоновщик
Borland (Inprise) размещает секцию кода с ОАП
10000h
+18h 4 ОАП,
с которого начинаются секции данных PE-файла.
Обычно они расположены за секциями кода.
Все объекты
PE-файла, в том числе секции кода и данных
выравни-
ваются на кратную границу: компоновщик
Microsoft
выравнивает объекты на границу, кратную
4 Кбайт,
компоновщик Borland — на границу 64 Кбайт
Таблица 23 (продолжение)
Смещение Размер, Назначение
байт
+1Сh 4 Адрес
оперативной памяти, куда предполагается
загрузка
файла. Этот адрес формирует компоновщик.
Если файл
действительно загружается по этому адресу,
то загрузчику
не нужно делать больше никаких настроек,
поэтому процесс
загрузки происходит быстрее. Если загрузчик
не может раз-
местить файл по указанному адресу, то
он вынужден произ-
водить настройку адресов
+20h 4 Значение
выравнивания для секции. Каждая секция
в
PE-файле выравнивается на границу, численное
значение
которой кратно величине, указанной в
данном поле (см.
также описание поля 0018h)
+24h 4 Значение
кратности, в соответствии с которым выравнивают-
ся данные в PE-файле. Смысл этого поля аналогичен
полю
в NE-файле 0032h (см. табл. 3)
+28 4 Номер
самой старой версии (модификации) операционной
системы, в среде которой может работать
данный файл
(обычно 1.0)
+2ch 4 Определяется
пользователем с помощью ключа компонов-
щика /VERSION:n.m (для link.exe (MASM)) или /Vn.m
(для tlink32.exe (TASM)). Значения n
и m
заносятся в два
слова этого поля
30h 4 Номера
самой старой версии и (модификации) операцион-
ной системы Windows NT, в среде которой может
работать
данный файл (обычно 4.0)
34h 4 0
+38h 4 Размер
PE-файла, выровненный на ближайшую границу
секции
+3Сh 4 Общий
размер всех заголовков в PE-файле, включая
заголо-
вок MS-DOS, PE-заголовок, дополнительный PE-заголовок
и заголовки PE-секций
+40h 4 Для
исполняемых файлов поле равно 0. Для файлов
dll-биб-
лиотек поле содержит контрольную сумму
(crc)
+44h 2 Тип пользовательского
интерфейса, используемого PE-
файлом:
0000h — неизвестная подсистема;
0001h — подсистема не требуется (драйвер
устройства);
0002h — Windows GUI;
0003h — консольное приложение Windows;
0005h — OS/2;
0007h — Posix
+46h 2 0
+48h 4 Потребный объем памяти для стека
+4ch 4 Выделяемое количество памяти для стека
+50h 4 Потребный объем памяти для локальной кучи
+54h 4 Выделяемое количество памяти для локальной кучи
Смещение Размер, Назначение
байт
+58h 4 0
+5Сh 4 Количество
элементов массива структур, описывающих
местоположение и размер некоторых значимых
таблиц и
областей исполняемого файла. Значение
обычно равно 10h
+60h 10h*2*4 Массив
структур, каждая из которых состоит из
двух полей
(размерность каждого поля dword):
ОАП расположения данных
в PE-файле;
размер данных.
Реальное наполнение
имеют первые 12 структур в данном
массиве. Их перечень можно посмотреть
во включаемом
файле winnt.h (Visual
C++). Они описывают расположение
следующих данных в PE-файле:
0 — таблица экспортируемых
функций;
1 — таблица импортируемых функций;
2 — таблица ресурсов;
3 — таблица исключений;
4 — таблица безопасности;
5 — таблица настройки;
6 — таблица отладки;
7 — строки описания;
8 — характеристика скорости
компьютера, измеряемая в
MIPS (million of instructions per second — миллионов
инструкций в секунду);
9 — область TLS (Thread Local
Storage, локальная память це-
почки);
10 — область таблицы конфигурации;
11 — таблица адресов
импорта (Bound Import Directory in
headers)
За массивом структур, которым заканчивается заголовок PE-файла, начинается таблица секций.
Структура PE-файла проще, чем NE-файла. Если не считать программы-заглушки для MS-DOS и необязательной области отладочной информации, то PE-файл состоит из двух больших частей — заголовка и области общих объектов, называемых секциями. Cекцию можно сравнить с сегментом в структуре NE-файла. Основное отличие секции от сегмента в том, что в PE-файле в виде секции оформляется любой объект, а не только данные или код, как в NE-файле. По этой причине секции иногда называют объектами. Информация о всех секциях PE-файла хранится в таблице секций (таблице объектов). Таблица секций располагается сразу после заголовка PE-файла. Количество секций определяется по значению поля в начале основного заголовка +2h (см. табл. 22).