| Каталог | Индекс раздела |
| Назад | Оглавление | Вперед |
2. Определения и соглашения
2.1. Секции
2.2. Физические и виртуальные адреса
2.3. Целевой компьютер
3. Заголовок файла
3.1. Магическое число
3.2. Флаги
3.3. Описание заголовка файла
4. Вспомогательный заголовок системы UNIX
4.1. a.out - стандартный заголовок системы UNIX
4.2. Описание вспомогательного заголовка
5. Заголовки секций
5.1. Флаги
5.2. Описание заголовка секции
5.3. Заголовок секции неинициализированных данных
7. Информация о настройке ссылок
7.1. Описание элемента таблицы настройки ссылок
8. Информация о номерах строк
8.1. Описание элемента таблицы номеров строк
9. Таблица имен
9.1. Специальные имена
9.2. Внутренние блоки
9.3. Имена и функции
9.4. Элементы таблицы имен
9.4.1. Тексты имен
9.4.2. Классы памяти
9.4.3. Классы памяти специальных имен
9.4.4. Поле значения имени
9.4.5. Поле номера секции
9.4.6. Номера секций и классы памяти
9.4.7. Поле типа
9.4.8. Связь между типом и классом памяти
9.4.9. Описание элемента таблицы имен
9.5. Вспомогательные элементы таблицы имен
9.5.1. Имя файла
9.5.2. Секция
9.5.3. Начало структуры, объединения или перечисления
9.5.4. Конец структуры
9.5.5. Функция
9.5.6. Массив
9.5.7. Конец блока или функции
9.5.8. Начало блока или функции
9.5.9. Имена, связанные со структурой, объединением или перечислением
9.5.10. Описание вспомогательного элемента
11. Программы доступа к объектным файлам обычного формата
Ниже описывается обычный формат объектных файлов (common object file format, COFF), принятый в ОС UNIX. Ассемблер, as(1), и редактор внешних связей, ld(1), генерируют объектные файлы обычного формата.
Основные особенности этого формата таковы:
Объектный файл поддерживает определяемые пользователем секции и содержит избыточную информацию, необходимую для работы символьных отладчиков. Объектный файл содержит:
Общая структура объектного файла обычного формата приведена в следующей таблице:
| ЗАГОЛОВОК ФАЙЛА |
| Вспомогательный заголовок системы UNIX |
| Заголовок секции 1 |
| . . . |
| Заголовок секции n |
| Содержимое секции 1 |
| . . . |
| Содержимое секции 1 |
| Информация о настройке ссылок секции 1 |
| . . . |
| Информация о настройке ссылок секции n |
| Информация о номерах строк секции 1 |
| . . . |
| Информация о номерах строк секции n |
| ТАБЛИЦА ИМЕН |
| ТАБЛИЦА ЦЕПОЧЕК |
Последние четыре части (информация о настройке ссылок, информация о номерах строк, таблица имен и таблица цепочек) могут отсутствовать, если внешние связи редактировались с помощью команды ld -s, или если таблицы номеров строк, имен и цепочек были удалены командой strip(1). Информация о номерах строк генерируется только по командам cc -g или svs +d. Кроме того, если после редактирования связей не осталось неразрешенных внешних ссылок, то информация о настройке отсутствует за ненадобностью. Таблица цепочек отсутствует, если исходный текст не содержит имен, длина которых больше 8 символов.
Выполняемым считается объектный файл, не содержащий ошибок или неразрешенных внешних ссылок.
Дадим определения и оговорим соглашения, которые будут использоваться в дальнейшем изложении.
Секция есть наименьшая часть объектного файла, которая подвергается
перемещению и рассматривается как нечто отдельное и различимое. Как правило,
в объектном файле присутствуют три секции, именуемые .text,
.data и .bss.
Это секции команд, инициализированных и неинициализированных данных. В
других секциях
могут размещаться комментарии, дополнительные сегменты команд и
данных, разделяемые сегменты данных. Допускаются секции, определенные
пользователем. Однако в любом случае ОС UNIX при загрузке файла на
выполнение помещает в память только секции
.text, .data и .bss.
Примечание
Физический адрес секции или имени есть смещение этой секции или
данных, соответствующих этому имени, от начала (нулевого адреса)
адресного пространства. Значение термина физический адрес,
когда он используется для описания объектных файлов обычного
формата, отличается от общепринятого. Физический адрес объекта
не обязательно будет совпадать с адресом, по которому этот объект
будет помещен во время выполнения. Так, в системах со страничной
виртуальной памятью адрес берется относительно нулевого
адреса виртуальной памяти, после чего операционная система выполняет
дальнейшее преобразование адреса. Заголовок секции содержит
два адресных поля, для физического и виртуального
адресов; однако во всех версиях COFF-формата и ОС UNIX эти адреса
совпадают.
Компиляторы и редакторы внешних связей создают выполняемые объектные
файлы, предназначенные для запуска на определенных
компьютерах. В случае использования кросс-компиляторов, на одном
компьютере компилируются и редактируются объектные файлы,
предназначенные для выполнения на другом компьютере. Термин целевой
компьютер обозначает тот компьютер, на котором предполагается
выполнять объектный файл. За редким исключением целевой
компьютер - это в точности тот же компьютер, на котором создается
объектный файл.
Заголовок файла состоит из 20 байт; его формат показан в следующей
таблице. Последние два байта содержат флаги, используемые
редактором связей ld(1) и другими утилитами, обрабатывающими
объектные файлы.
2.1. Секции
2.2. Физические и виртуальные адреса
2.3. Целевой компьютер
3. ЗАГОЛОВОК ФАЙЛА
| Байты | Описание | Имя | Смысл |
| 0-1 | unsigned short | f_magic | Магическое число |
| 2-3 | unsigned short | f_nscns | Количество секций в файле |
| 4-7 | long int | f_timdat | Дата/время создания файла. Выражается количеством секунд, прошедших с 00:00:00 1 января 1970г. (по Гринвичу) |
| 8-11 | long int | f_symptr | Указатель в файле. Содержит адрес начала таблицы имен |
| 12-15 | long int | f_nsyms | Число элементов в таблице имен |
| 16-17 | unsigned short | f_opthdr | Размер вспомогательного заголовка в байтах |
| 18-19 | unsigned short | f_flags | Флаги (см. следующую таблицу) |
Магическое число определяет целевой компьютер, для которого
предназначен объектный файл.
Последние два байта заголовка файла содержат флаги, характеризующие
тип объектного файла. Флаги определены во включаемом
файле <filehdr.h>; используемые флаги приведены в следующей
таблице:
3.2. Флаги
| Обозначение | Значение | Смысл |
| F_RELFLG | 00001 | Из файла удалена информация о настройке ссылок |
| F_EXEC | 00002 | Файл является выполняемым (в нем нет неразрешенных внешних ссылок) |
| F_LNNO | 00004 | Из файла удалена информация о номерах строк |
| F_LSYMS | 00010 | Из файла удалена информация о локальных именах |
| F_AR32W | 0001000 | 32-битное слово |
Ниже приведено описание C-структуры, соответствующей заголовку файла. Для включения описания в программу следует использовать файл <filehdr.h>.
struct filehdr {
unsigned short f_magic; /* Магическое число */
unsigned short f_nscns; /* Количество секций */
long f_timdat; /* Время и дата создания */
long f_symptr; /* Указатель в файле на
таблицу имен */
long f_nsyms; /* Число элементов в таблице
имен */
unsigned short f_opthdr; /* Размер вспомогательного
заголовка */
unsigned short f_flags; /* Флаги */
};
#define FILHDR struct filehdr
#define FILHSZ sizeof (FILHDR)
Структура вспомогательного заголовка файла зависит от конкретной
системы, использующей обычный формат объектных файлов. Во
вспомогательный заголовок помещается вся зависящая от системы
информация, что дает возможность различным операционным системам
получать доступ к только им необходимым данным, без того,
чтобы в каждом объектном файле обычного формата для каждой операционной
системы отводить место для таких данных. Утилиты общего
назначения (например, дизассемблер, функции, работающие с
таблицей имен, и т.д.) реализованы так, чтобы обеспечить правильную
работу с любым объектным файлом. Это достигается использованием
информации, расположенной за вспомогательным заголовком, длина
которого хранится в поле f_opthdr заголовка файла.
По умолчанию, вспомогательный заголовок файлов, создаваемых редактором
внешних связей системы UNIX, имеет стандартную структуру файлов a.out.
Размер этой структуры - 28 байт. Поля вспомогательного заголовка описаны в следующей таблице:
4.1. a.out - стандартный заголовок системы UNIX
| Байты | Описание | Имя | Смысл |
| 0-1 | short | magic | Магическое число |
| 2-3 | short | vstamp | Метка версии |
| 4-7 | long int | tsize | Размер секции команд в байтах |
| 8-11 | long int | dsize | Размер секции инициализированных данных в байтах |
| 12-15 | long int | bsize | Размер секции неинициализированных данных в байтах |
| 16-19 | long int | entry | Точка входа |
| 20-23 | long int | text_start | Адрес начала команд |
| 24-27 | long int | data_start | Адрес начала данных |
В то время как магическое число в заголовке файла указывает целевой компьютер, магическое число во вспомогательном заголовке содержит информацию о том, как операционная система на этом компьютере должна выполнять файл. В следующей таблице показаны магические числа, распознаваемые ОС UNIX.
| Значение | Смысл |
| 0410 | Данные располагаются с границы сегмента, следующего за сегментом текста. Сегмент текста защищен от записи |
Ниже приведено описание C-структуры, соответствующей заголовку файла a.out. Такая структура вспомогательного заголовка используется в настоящее время системой UNIX. Для включения описания в программу следует использовать файл <aouthdr.h>.
typedef struct aouthdr {
short magic; /* Магическое число */
short vstamp; /* Метка версии */
long tsize; /* Размер сегмента команд в байтах
*/
long dsize; /* Размер секции .data (инициали-
зированные данные) */
long bsize; /* Размер секции .bss (неинициали-
зированные данные) */
long entry; /* Точка входа */
long text_start; /* Адрес, с которого размещается
сегмент команд */
long data_start; /* Адрес, с которого размещается
сегмент данных */
} AOUTHDR;
В каждом объектном файле есть таблица заголовков секций, определяющая расположение данных в файле. В этой таблице каждой секции соответствует один элемент. В следующей таблице описана информация, содержащаяся в заголовке секции.
| Байты | Описание | Имя | Смысл |
| 0-7 | char | s_name | 8-символьное имя секции, дополненное нулями |
| 8-11 | long int | s_paddr | Физический адрес секции |
| 12-15 | long int | s_vaddr | Виртуальный адрес секции |
| 16-19 | long int | s_size | Размер секции в байтах |
| 20-23 | long int | s_scnptr | Указатель в файле на содержимое секции |
| 24-27 | long int | s_relptr | Указатель в файле на информацию о настройке ссылок |
| 28-31 | long int | s_lnnoptr | Указатель в файле на информацию о номерах строк |
| 32-33 | unsigned short | s_nreloc | Число элементов в таблице настройки ссылок |
| 34-35 | unsigned short | s_nlnno | Число элементов в таблице номеров строк |
| 36-39 | long int | s_flags | Флаги (см. следующую таблицу) |
Размер секции увеличивается до ближайшего числа, кратного четырем.
Указатели в файле - это смещения в байтах, позволяющие определить
начало данных в этой секции и ее таблиц настройки ссылок
и номеров строк. Указатели могут использоваться функцией
fseek(3S) операционной системы UNIX.
Два младших байта поля флагов определяют тип секции. Флаги описаны
в следующей таблице:
5.1. Флаги
| Обозначение | Значение | Смысл |
| STYP_REG | 0x00 | Обычная секция (размещаемая, настраиваемая, загружаемая) |
| STYP_DSECT | 0x01 | Фиктивная секция (неразмещаемая, настраиваемая, незагружаемая) |
| STYP_NOLOAD | 0x02 | Незагружаемая секция (размещаемая, настраиваемая, незагружаемая) |
| STYP_GROUP | 0x04 | Групповая секция (формируется из входных секций) |
| STYP_PAD | 0x08 | Секция-заполнитель (неразмещаемая, ненастраиваемая, загружаемая) |
| STYP_COPY | 0x10 | Секция типа COPY (рабочий признак для редактора связей; неразмещаемая, ненастраиваемая, загружаемая; таблицы настройки ссылок и номеров строк обрабатываются обычным образом) |
| STYP_TEXT | 0x20 | Секция содержит выполняемые команды |
| STYP_DATA | 0x40 | Секция содержит инициализированные данные |
| STYP_BSS | 0x80 | Секция содержит только неинициализированные данные |
| STYP_INFO | 0x200 | Секция комментариев (неразмещаемая, ненастраиваемая, незагружаемая) |
| STYP_OVER | 0x400 | Оверлейная секция (неразмещаемая, настраиваемая, незагружаемая) |
| STYP_LIB | 0x800 | Библиотечная секция .lib (обрабатывается так же, как секция комментариев) |
Ниже приведено описание C-структуры, соответствующей заголовку секции. Для включения описания в программу следует использовать файл <scnhdr.h>.
struct scnhdr {
char s_name[8]; /* Имя секции */
long s_paddr; /* Физический адрес */
long s_vaddr; /* Виртуальный адрес */
long s_size; /* Размер секции */
long s_scnptr; /* Указатель в файле на
содержимое секции */
long s_relptr; /* Указатель в файле на
инф. о настр. ссылок */
long s_lnnoptr; /* Указатель в файле на
инф. о номерах строк */
unsigned short s_nreloc; /* Число ссылок, требующих
настройки */
unsigned short s_nlnno; /* Число элементов в таблице
номеров строк */
как секция комментариев)
Единственным отклонением от обычной структуры таблицы заголовков секций является заголовок для секции неинициализированных данных .bss. Секция .bss имеет размер, с ней связаны имена, которые ссылаются на нее, и имена, которые определены в ней. В то же время информация о настройке ссылок, таблица номеров строк и содержимое отсутствуют. Таким образом, секции .bss соответствует элемент таблицы заголовков секций, но сама она не занимает места где-либо еще в файле. В заголовке секции .bss значения числа элементов в таблицах настройки ссылок и номеров строк, а также значения всех указателей равны нулю. То же верно и для секций типа STYP_NOLOAD и STYP_DSECT.
В объектном файле обычного формата за таблицей заголовков секций следует содержимое секций - соответствующее количество байт команд или данных. Содержимое начинается с границы, кратной четырем байтам.
Предложение SECTIONS управляющего языка редактора связей (см. Руководство по редактору связей) предоставляет, помимо прочих, следующие возможности:
Если предложения SECTIONS отсутствуют, каждая входная секция размещается в одноименной выходной. Например, если редактируются связи набора объектных файлов, в каждом из которых имеется секция .text, то выходной объектный файл будет содержать единственную секцию .text, полученную путем объединения одноименных входных секций.
Таблица настройки содержит по одному элементу для каждой ссылки (среди команд или данных), требующей настройки. Элементы имеют следующий формат:
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | r_vaddr | (Виртуальный) адрес ссылки |
| 4-7 | long int | r_symndx | Номер в таблице имен |
| 8-9 | unsigned short | r_type | Тип ссылки |
Первые четыре байта элемента содержат виртуальный адрес ссылки среди команд или данных. В следующем поле находится номер (начиная с нуля) соответствующего элемента таблицы имен. Поле типа ссылки определяет, как именно ее нужно настраивать. Используются следующие типы:
| Обозначение | Значение | Смысл |
| R_ABS | 0 | Абсолютная ссылка, настройки не требуется. Элемент игнорируется |
| R_RELWORD | 020 | 16-битный виртуальный адрес имени |
| R_RELLONG | 022 | 32-битный виртуальный адрес имени |
Ниже приведено описание C-структуры, соответствующей элементу таблицы настройки ссылок. Для включения описания в программу следует использовать файл <reloc.h>.
struct reloc {
long r_vaddr; /* Виртуальный адрес ссылки */
long r_symndx; /* Номер в таблице имен */
unsigned short r_type; /* Тип ссылки */
};
#define RELOC struct reloc
#define RELSZ 10 /* sizeof(RELOC) */
Использование команд cc -g и svs +d приводит к тому, что для каждой строки исходного текста, на которую можно установить точка прерывания, в объектный файл помещается элемент с информацией о строке. Эту информацию используют символьные отладчики, такие как sdb(1) и КРОТ. В пределах секции элементы сгруппированы по функциям, как показано в следующей таблице:
| Номер в таблице имен | 0 |
| физический адрес | номер строки |
| физический адрес | номер строки |
| . . . | . . . |
| Номер в таблице имен | 0 |
| физический адрес | номер строки |
| физический адрес | номер строки |
Первый элемент в пределах каждой функции содержит 0 в поле номера
строки и вместо физического адреса хранит номер элемента
таблицы имен, содержащего имя этой функции. Последующие элементы
таблицы номеров строк содержат настоящие номера строк (относительно
начала функции) и адреса команд, соответствующих этим
строкам. В пределах функции элементы в таблице номеров строк
размещаются в порядке возрастания адресов.
Ниже приведено описание C-структуры, соответствующей элементу
таблицы номеров строк. Для включения описания в программу
следует использовать файл <linenum.h>.
Порядок имен в этой таблице очень важен для символьной отладки.
Имена размещаются в порядке, показанном в следующей таблице:
8.1. Описание элемента таблицы номеров строк
struct lineno {
union {
long l_symndx; /* Если l_lnno == 0, то номер элемента
табл. имен, описывающего функцию */
long l_paddr; /* Физический адрес команд, соответст-
вующих строке */
} l_addr;
unsigned short l_lnno; /* Номер строки */
};
#define LINENO struct lineno
#define LINESZ 6 /* sizeof(LINENO) */
9. ТАБЛИЦА ИМЕН
| Имя файла 1 |
| Функция 1 |
| Имена, локальные для функции 1 |
| Функция 2 |
| Имена, локальные для функции 2 |
| . . . |
| Статические имена |
| Имя файла 2 |
| Функция 1 |
| Имена, локальные для функции 1 |
| . . . |
| Статические имена |
| . . . |
| Определенные глобальные имена |
| Неопределенные глобальные имена |
Статическими в приведенной таблице называются имена, определенные
(в языке C) с классом памяти static вне всех функций. Таблица
содержит по меньшей мере один элемент фиксированной длины
для каждого имени, однако для некоторых имен за этим элементом
может следовать несколько вспомогательных элементов той же длины.
Элемент таблицы хранит значение имени, тип и другую информацию.
В таблицу имен помещаются некоторые специальные имена, генерируемые
ассемблером as(1) и другими инструментальными
средствами. Эти имена перечислены в следующей таблице:
9.1. Специальные имена
| Специальное имя | Смысл |
| .file | Имя файла |
| .text | Адрес секции команд |
| .data | Адрес секции инициализированных данных |
| .bss | Адрес секции неинициализированных данных |
| .bb | Адрес начала внутреннего блока |
| .eb | Адрес конца внутреннего блока |
| .bf | Адрес начала функции |
| .ef | Адрес конца функции |
| .target | Адрес структуры или объединения, возвращаемых функцией |
| .xfake | Фиктивное имя структуры, объединения или перечисления |
| .eos | Конец структуры, объединения или перечисления |
| etext | Ближайший доступный адрес после окончания выходной секции команд |
| edata | Ближайший доступный адрес после окончания выходной секции инициализированных данных |
| end | Ближайший доступный адрес после окончания выходной секции неинициализированных данных |
Из перечисленных специальных имен шесть появляются парами. Имена .bb и .eb отмечают границы внутренних блоков; пара .bf и .ef ограничивает каждую функцию. Пара .xfake и .eos именует и определяет границы непоименованных структур, объединений и перечислений. Имя .eos встречается также в конце поименованных структур, объединений и перечислений.
Для непоименованных структур, объединений и перечислений компилятор
генерирует служебные имена вида .xfake, где x есть целое
число. Так, если в исходном тексте встречаются три непоименованные
структуры, объединения или перечисления, то они получат
имена .0fake, .1fake и .2fake.
В основном элементе таблицы хра-
нится различная информация для различных видов имен. За основным
элементом могут следовать вспомогательные.
В языке C блок определяется как составной оператор, заключенный
в фигурные скобки, { и }. Внутренний
блок определяется как
блок, находящийся внутри функции. Сама функция также является
блоком.
Если в некотором внутреннем блоке определены локальные имена,
то в таблицу имен, непосредственно перед элементом для первого
такого имени, будет помещен элемент для специального имени .bb.
Равным образом, специальное имя .eb помещается сразу после элемента
для последнего в этом блоке локального имени. Пример такой
последовательности изображен изображен в следующей таблице:
9.2. Внутренние блоки
| .bb |
| Имена, локальные для этого блока |
| .eb |
Поскольку внутренние блоки могут быть вложенными, пары .bb и .eb и соответствующие им элементы таблицы имен также могут быть вложенными. Пусть исходный текст выглядит так:
{ /* Блок 1 */
int i;
char c;
. . .
{ /* Блок 2 */
long a;
. . .
{ /* Блок 3 */
int x;
. . .
} /* блок 3 */
. . .
} /* блок 2 */
. . .
{ /* Блок 4 */
long i;
. . .
} /* блок 4 */
. . .
} /* блок 1 */
Структура соответствующего фрагмента таблицы имен показана ниже:
| . . . |
| .bb для блока 1 |
| i |
| c |
| .bb для блока 2 |
| a |
| .bb для блока 3 |
| x |
| .eb для блока 3 |
| .eb для блока 2 |
| .bb для блока 4 |
| i |
| .eb для блока 4 |
| .eb для блока 1 |
| . . . |
В таблице имен между элементами для имени каждой функции и для первого локального имени помещается элемент, соответствующий специальному имени .bf. После последнего элемента для локального в данной функции имени помещается элемент, соответствующий имени .ef. Эта последовательность показана ниже:
| Имя функции |
| .bf |
| Локальные имена |
| .ef |
Структура элементов таблицы имен одинакова для всех имен и не зависит от их типа или класса памяти. Размер каждого элемента - 18 байт. Описание полей элемента таблицы имен приводится ниже. Следует отметить, что элементы таблицы имен (включая вспомогательные) нумеруются в возрастающем порядке, начиная с нуля.
| Байты | Описание | Имя | Смысл |
| 0-7 | см. текст ниже | _n | Эти восемь байт содержат либо текст имени, либо его смещение от начала таблицы цепочек |
| 8-11 | long int | n_value | Значение имени, зависящее от класса памяти |
| 12-13 | short | n_scnum | Номер секции, содержащей имя |
| 14-15 | unsigned short | n_type | Базовый и производные типы имени |
| 16 | char | n_sclass | Класс памяти |
| 17 | char | n_numaux | Число вспомогательных элементов |
Первые 8 байт элемента таблицы имен представляют собой объединение массива символов и двух четырехбайтных целых чисел. Если длина текста имени не превышает восьми символов, то здесь хранится сам текст, дополненный нулевыми байтами. Если же его длина больше восьми символов, то текст хранится в таблице цепочек. В этом случае в первых восьми байтах элемента таблицы имен находятся два целых числа, первое из которых равно нулю, а второе есть смещение соответствующего элемента таблицы цепочек относительно начала этой таблицы. Нули в первых четырех байтах позволяют отличить текст от ссылки на него, поскольку никакое имя не может начинаться с нулевых байт:
| Байты | Описание | Имя | Смысл |
| 0-7 | char | n_name | 8-символьный текст имени, дополненный нулевыми байтами |
| 0-3 | long | n_zeroes | Нули в этом поле указывают, что текст имени находится в таблице цепочек |
| 4-7 | long | n_offset | Смещение текста имени относительно начала таблицы цепочек |
В поле, указывающем класс памяти, хранится одно из перечисленных ниже значений. Именованные константы определены во включаемом файле <storclass.h>.
| Обозначение | Значение | Смысл класса памяти |
| C_EFCN | -1 | Физический конец функции |
| C_NULL | 0 | - |
| C_AUTO | 1 | Автоматическая переменная |
| C_EXT | 2 | Внешнее имя |
| C_STAT | 3 | Статический |
| C_REG | 4 | Регистровая переменная |
| C_EXTDEF | 5 | Внешнее определение |
| C_LABEL | 6 | Метка |
| C_ULABEL | 7 | Неопределенная метка |
| C_MOS | 8 | Элемент структуры |
| C_ARG | 9 | Аргумент функции |
| C_STRTAG | 10 | Начало структуры |
| C_MOU | 11 | Элемент объединения |
| C_UNTAG | 12 | Начало объединения |
| C_TPDEF | 13 | Определение типа |
| C_USTATIC | 14 | Неинициализированный статический |
| C_ENTAG | 15 | Начало перечисления |
| C_MOE | 16 | Элемент перечисления |
| C_REGPARM | 17 | Регистровый параметр |
| C_FIELD | 18 | Битное поле |
| Обозначение | Значение | Смысл класса памяти |
| C_BLOCK | 100 | Начало или конец блока |
| C_FCN | 101 | Начало или конец функции |
| C_EOS | 102 | Конец структуры |
| C_FILE | 103 | Имя файла |
| C_LINE | 104 | Только для внутреннего пользования |
| C_ALIAS | 105 | Синоним |
| C_HIDDEN | 106 | Аналог статического; используется, чтобы избежать конфликта имен |
Все перечисленные классы памяти, за исключением C_ALIAS и C_HIDDEN, генерируются при выполнении команд cc и as. Класс памяти C_HIDDEN никакими средствами системы UNIX не используется.
Некоторые из перечисленных классов памяти предназначены только
для внутреннего использования C-компилятором. Таковы C_EFCN,
C_EXTDEF, C_ULABEL, C_USTATIC и C_LINE.
Некоторым специальным именам соответствуют фиксированные классы
памяти. Это соответствие изображено в следующей таблице:
9.4.3. Классы памяти специальных имен
| Специальное имя | Класс памяти |
| .file | C_FILE |
| .bb | C_BLOCK |
| .eb | C_BLOCK |
| .bf | C_FCN |
| .ef | C_FCN |
| .target | C_AUTO |
| .xfake | C_STRTAG, C_UNTAG, C_ENTAG |
| .eos | C_EOS |
| .text | C_STAT |
| .data | C_STAT |
| .bss | C_STAT |
Обратно, существуют классы памяти, используемые исключительно для определенных специальных имен. Это соответствие изображено ниже:
| Класс памяти | Специальное имя |
| C_BLOCK | .bb, .eb |
| C_FCN | .bf, .ef |
| C_EOS | .eos |
| C_FILE | .file |
Смысл величины, хранящейся в поле значения, зависит от класса памяти соответствующего имени. Эту зависимость иллюстрирует следующая таблица:
| Класс памяти | Смысл значения имени |
| C_AUTO | Смещение в стеке (в байтах) |
| C_EXT | Настраиваемый адрес |
| C_STAT | Настраиваемый адрес |
| C_REG | Номер регистра |
| C_LABEL | Настраиваемый адрес |
| C_MOS | Смещение в байтах |
| C_ARG | Смещение в стеке (в байтах) |
| C_STRTAG | 0 |
| C_MOU | 0 |
| C_UNTAG | 0 |
| C_TPDEF | 0 |
| C_ENTAG | 0 |
| C_MOE | Значение элемента перечисления |
| C_REGPARM | Номер регистра |
| C_FIELD | Смещение в битах |
| C_BLOCK | Настраиваемый адрес |
| C_FCN | Настраиваемый адрес |
| C_EOS | Длина |
| C_FILE | См. текст ниже |
| C_ALIAS | Номер синонима |
| C_HIDDEN | Настраиваемый адрес |
Для имен с классом памяти C_FILE в поле значения указывается номер следующего элемента для специального имени .file. Таким образом, в таблице имен элементы .file образуют однонаправленный список. В поле значения последнего элемента .file хранится номер элемента таблицы имен, отвечающего первому глобальному имени.
Настраиваемые имена имеют значение, равное виртуальному адресу
соответствующих команд или данных. Эти значения изменяются при
обработке секции редактором связей.
Ниже перечислены допустимые номера секций:
9.4.5. Поле номера секции
| Обозначение | Номер секции | Смысл |
| N_DEBUG | -2 | Специальное имя для символьной отладки |
| N_ABS | -1 | Абсолютное имя |
| N_UNDEF | 0 | Неопределенное внешнее имя |
| N_SCNUM | 1-077777 | Номер той секции, в которой имя определяется |
Специальный номер секции -2 применяется для имен, используемых при символьной отладке. Таковы имена, отмечающие начало структуры, объединения или перечисления; определения типов; имена файлов. Номер секции -1 отмечает имена, имеющие ненастраиваемые значения. Такими именами являются, в частности, автоматические и регистровые переменные, аргументы функций и специальные имена .eos.
За единственным исключением, нулевой номер секции используется
для настраиваемых внешних имен, не определенных в данном файле.
Единственное же исключение - это повторно определяемое внешнее
имя (например, COMMON-блок Фортрана или же неинициализированная
переменная, определенная в функции языка C как внешняя). В таблице
имен каждого файла, в котором определено такое имя, в поле
номера секции соответствующего элемента помещается 0, а в поле
значения - положительное число, равное размеру данных для этого
имени. Когда же эти файлы объединяются для получения выполняемого
объектного файла, редактор внешних связей из всех таких
одинаковых входных имен строит одно имя, с номером секции
неинициализированных данных. Максимальный размер данных для всех
таких входных имен используется при отведении места под данные
для выходного имени. Значением выходного имени становится
соответствующий виртуальный адрес. Таков единственный случай, когда
имя имеет нулевой номер секции и ненулевое значение.
Существует соответствие между классами памяти и номерами
секций, возможными у имен с такими классами. Это соответствие
показано в следующей таблице:
9.4.6. Номера секций и классы памяти
| Класс памяти | Возможный номер секции |
| C_AUTO | N_ABS |
| C_EXT | N_ABS, N_UNDEF, N_SCNUM |
| C_STAT | N_SCNUM |
| C_REG | N_ABS |
| C_LABEL | N_UNDEF, N_SCNUM |
| C_MOS | N_ABS |
| C_ARG | N_ABS |
| C_STRTAG | N_DEBUG |
| C_MOU | N_ABS |
| C_UNTAG | N_DEBUG |
| C_TPDEF | N_DEBUG |
| C_ENTAG | N_DEBUG |
| C_MOE | N_ABS |
| C_REGPARM | N_ABS |
| C_FIELD | N_ABS |
| C_BLOCK | N_SCNUM |
| C_FCN | N_SCNUM |
| C_EOS | N_ABS |
| C_FILE | N_DEBUG |
| C_ALIAS | N_DEBUG |
Поле типа элемента таблицы имен содержит информацию о базовом и производных типах соответствующего имени. Компилятор языка C заполняет эти поля только при указании опции -g. Производных типов может быть несколько, но каждое имя имеет ровно один базовый тип. Формат 16-битного поля типа таков:
| d6 | d5 | d4 | d3 | d2 | d1 | базовый тип |
| Обозначение | Значение | Базовый тип |
| T_NULL | 0 | Тип не назначен |
| T_VOID | 1 | Пустой тип |
| T_CHAR | 2 | Символ |
| T_SHORT | 3 | Короткое целое |
| T_INT | 4 | Целое |
| T_LONG | 5 | Длинное целое |
| T_FLOAT | 6 | Вещественное одинарной точности |
| T_DOUBLE | 7 | Вещественное двойной точности |
| T_STRUCT | 8 | Структура |
| T_UNION | 9 | Объединение |
| T_ENUM | 10 | Перечисление |
| T_MOE | 11 | Элемент перечисления |
| T_UCHAR | 12 | Символ без знака |
| T_USHORT | 13 | Короткое целое без знака |
| T_UINT | 14 | Целое без знака |
| T_ULONG | 15 | Длинное целое без знака |
Биты с 4-го по 15-й разделены на шесть двухбитных полей, обозначаемых d1..d6. Эти поля представляют уровни производных типов, перечисленых ниже:
| Обозначение | Значение | Производный тип |
| DT_NON | 0 | Производный тип отсутствует |
| DT_PTR | 1 | Указатель |
| DT_FCN | 2 | Функция |
| DT_ARY | 3 | Массив |
В следующих примерах иллюстрируется представление типа в элементе таблицы имен.
char *func();
Здесь func есть имя функции, возвращающей указатель на символ. Базовый тип имени func есть 2 (символ), в поле d1 будет помещено число 2 (функция), а в поле d2 - 1 (указатель). Таким образом, в поле типа элемента func будет находиться шестнадцатеричное значение 0x62, которое и интерпретируется как функция, возвращающая указатель на символ.
short *tabptr [10] [25] [3];
Здесь tabptr есть трехмерный массив указателей на короткие
целые. Базовый тип для tabptr есть 3 (короткое целое); в каждое
из полей d1, d2, d3 будет помещено число 3 (массив), а в поле
d4 - 1 (указатель). Таким образом, для трехмерного массива
указателей на короткие целые в поле типа соответствующего элемента
таблицы имен будет храниться шестнадцатеричное значение 0xff3.
Ниже перечислены типы, допустимые для каждого класса памяти.
9.4.8. Связь между типом и классом памяти
| Класс памяти | d-поля | Базовый тип | ||
| Функция? | Массив? | Указатель? | ||
| C_AUTO | нет | да | да | Любой, кроме T_MOE |
| C_EXT | да | да | да | Любой, кроме T_MOE |
| C_STAT | да | да | да | Любой, кроме T_MOE |
| C_REG | нет | нет | да | Любой, кроме T_MOE |
| C_LABEL | нет | нет | нет | T_NULL |
| C_MOS | нет | да | да | Любой, кроме T_MOE |
| C_ARG | да | нет | да | Любой, кроме T_MOE |
| C_STRTAG | нет | нет | нет | T_STRUCT |
| C_MOU | нет | да | да | Любой, кроме T_MOE |
| C_UNTAG | нет | нет | нет | T_UNION |
| C_TPDEF | нет | да | да | Любой, кроме T_MOE |
| C_ENTAG | нет | нет | нет | T_ENUM |
| C_MOE | нет | нет | нет | T_MOE |
| C_REGPARM | нет | нет | да | Любой, кроме T_MOE |
| C_FIELD | нет | нет | нет | T_ENUM, T_UCHAR, T_USHORT, T_UINT, T_ULONG |
| C_BLOCK | нет | нет | нет | T_NULL |
| C_FCN | нет | нет | нет | T_NULL |
| C_EOS | нет | нет | нет | T_NULL |
| C_FILE | нет | нет | нет | T_NULL |
| C_ALIAS | нет | нет | нет | T_STRUCT, T_UNION, T_ENUM |
Условия относительно d-полей касаются всех полей d1..d6 с тем исключением, что не может быть двух последовательных производных типов функция.
Хотя аргументы функции и могут быть объявлены как массивы, они
все равно трактуются как указатели. Поэтому аргумент функции не
может иметь массив в качестве своего первого производного типа.
Ниже приведено описание C-структуры, соответствующей элементу
таблицы имен. Для включения описания в программу следует
использовать файл lt;syms.h>.
Вспомогательные элементы имеют тот же размер, что и основные,
однако их структура зависит от типа имени и класса памяти. Эта
зависимость показана в следующей таблице:
9.4.9. Описание элемента таблицы имен
#define SYMNMLEN 8 /* Максимальное количество символов
в тексте имени */
struct syment {
union { /* Все способы описать текст имени */
char _n_name [SYMNMLEN]; /* Текст имени */
struct {
long _n_zeroes; /* Если == 0, то в таблице цепочек */
long _n_offset; /* Смещение в табл. цепочек */
} _n_n;
char *_n_nptr [2];
} _n;
long n_value; /* Значение имени */
short n_scnum; /* Номер секции */
unsigned short n_type; /* Тип и производный тип */
char n_sclass; /* Класс памяти */
char n_numaux; /* Число вспомогательных
элементов */
};
#define n_name _n._n_name
#define n_zeroes _n._n_n._n_zeroes
#define n_offset _n._n_n._n_offset
#define n_nptr _n._n_nptr [1]
#define SYMENT struct syment
#define SYMESZ 18 /* sizeof(SYMENT) */
9.5. Вспомогательные элементы таблицы имен
| Имя | Класс памяти | Тип | Формат вспомогательного элемента | |
| d1 | Базовый тип | |||
| .file | C_FILE | DT_NON | T_NULL | Имя файла |
| .text, .data, .bss | C_STAT | DT_NON | T_NULL | Секция |
| Имя структуры,объединения или перечисления | C_STRTAG, C_UNTAG, C_ENTAG | DT_NON | T_NULL | Начало структуры, объединения или перечисления |
| .eos | C_EOS | DT_NON | T_NULL | Конец структуры |
| Имя функции | C_EXT, C_STAT | DT_FCN | Кроме T_MOE | Функция |
| Имя массива | C_AUTO, C_STAT, C_MOS, C_MOU, C_TPDEF | DT_ARR | Кроме T_MOE | Массив |
| .bb, .eb | C_BLOCK | DT_NON | T_NULL | Начало и конец блока |
| .bf, .ef | C_FCN | DT_NON | T_NULL | Начало и конец функции |
| Имя, связанное со структурой, объединением или перечислением | C_AUTO, C_STAT, C_MOS, C_MOU, C_TPDEF | DT_PTR, DT_ARR, DT_NON | T_STRUCT, T_UNION, T_ENUM | Имя, связанное со структурой, объединением или перечислением |
Здесь имя структуры, объединения или перечисления включает также специальные имена .xfake. Если имя удовлетворяет нескольким из перечисленных условий, то его вспомогательный элемент должен иметь формат объединения.
Примечание
В следующих пунктах описывается структура вспомогательных элементов.
Вспомогательный элемент для имени файла в байтах с 0-го по 13-й
содержит 14-символьное имя файла, дополненное нулями.
Вспомогательные элементы для секций имеют формат, изображенный
в следующей таблице:
9.5.1. Имя файла
9.5.2. Секция
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | x_scnlen | Длина секции |
| 4-5 | unsigned short | x_nreloc | Число элементов в таблице настройки ссылок |
| 6-7 | unsigned short | x_nlinno | Число элементов в таблице номеров строк |
| 8-17 | - | - | Не используются (заполнены нулями) |
Вспомогательные элементы для таких имен имеют следующий формат:
| Байты | Описание | Имя | Смысл |
| 0-5 | - | - | Не используются (заполнены нулями) |
| 6-7 | unsigned short | x_size | Размер структуры, объединения или перечисления |
| 8-11 | - | - | Не используются (заполнены нулями) |
| 12-15 | long int | x_endndx | Номер элемента, следующего за элементами для этой структуры, объединения, или перечисления |
| 16-17 | - | - | Не используются (заполнены нулями) |
Формат вспомогательного элемента для конца структуры изображен в следующей таблице:
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | x_tagndx | Номер элемента для начала структуры |
| 4-5 | - | - | Не используются (заполнены нулями) |
| 6-7 | unsigned short | x_size | Размер структуры, объединения или перечисления |
| 8-17 | - | - | Не используются (заполнены нулями) |
Вспомогательные элементы для функций имеют следующий формат:
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | x_tagndx | Номер основного элемента для функции |
| 4-7 | long int | x_fsize | Размер функции в байтах |
| 8-11 | long int | x_lnnoptr | Указатель в файле на соответствующий элемент таблицы номеров строк |
| 12-15 | long int | x_endndx | Номер элемента, следующего за элементами для этой функции |
| 16-17 | unsigned short | x_tvndx | Номер адреса функции в таблице адресов переходов (в ОС UNIX не используется) |
Формат вспомогательного элемента для массива изображен в следующей таблице. Попытка определения массива с количеством измерений, превышающим 4, приводит к выдаче предупреждения.
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | x_tagndx | Номер основного элемента для массива |
| 4-5 | unsigned short | x_lnno | Номер строки с описанием массива |
| 6-7 | unsigned short | x_size | Размер массива |
| 8-9 | unsigned short | x_dimen [0] | Первое измерение |
| 10-11 | unsigned short | x_dimen [1] | Второе измерение |
| 12-13 | unsigned short | x_dimen [2] | Третье измерение |
| 14-15 | unsigned short | x_dimen [3] | Четвертое измерение |
| 16-17 | - | - | Не используются (заполнены нулями) |
Вспомогательные элементы для конца блока или функции имеют следующий формат:
| Байты | Описание | Имя | Смысл
| 0-3 |
- |
- |
Не используются (заполнены нулями) |
4-5 |
unsigned short |
x_lnno |
Номер строки исходного текста |
6-17 |
- |
- |
Не используются (заполнены нулями) |
|
Формат вспомогательных элементов для начала блока или функции изображен ниже:
| Байты | Описание | Имя | Смысл |
| 0-3 | - | - | Не используются (заполнены нулями) |
| 4-5 | unsigned short | x_lnno | Номер строки исходного текста |
| 6-11 | - | - | Не используются (заполнены нулями) |
| 12-15 | long int | x_endndx | Номер элемента, следующего за элементами для этого блока |
| 16-17 | - | - | Не используются (заполнены нулями) |
Формат вспомогательных элементов для имен, связанных со структурой, объединением или перечислением, приведен в следующей таблице:
| Байты | Описание | Имя | Смысл |
| 0-3 | long int | x_tagndx | Номер элемента для начала структуры |
| 4-5 | - | - | Не используются (заполнены нулями) |
| 6-7 | unsigned short | x_size | Размер структуры, объединения или перечисления |
| 8-17 | - | - | Не используются (заполнены нулями) |
Имена, определенные в операторах typedef, могут иметь, но могут и не иметь вспомогательных элементов. Пример:
typedef struct people STUDENT;
struct people {
char name [20];
long id;
};
typedef struct people EMPLOYEE;
Имя EMPLOYEE будет иметь вспомогательный элемент в таблице
имен, а имя STUDENT - нет, поскольку его описание предшествует
описанию структуры.
Ниже приведено описание C-структуры, соответствующей вспомогательному
элементу таблицы имен. Для включения описания в программу
следует использовать файл <syms.h>.
Тексты имен, состоящие более чем из восьми символов, размещаются
последовательно в таблице цепочек, причем каждый текст завершается
нулевым байтом. Первые четыре байта таблицы цепочек
содержат размер этой таблицы в байтах; таким образом, смещения
всех имен из этой таблицы больше или равны 4.
Операционная система UNIX предоставляет набор инструментальных
средств для доступа к различным частям объектных файлов. Эти
средства избавляют использующую их программу от необходимости
знать общую структуру объектного файла, хотя строение обрабатываемых
частей программа должна знать в деталях.
Средства доступа можно разделить на четыре категории:
Функции доступа хранятся в библиотеке libld.a и описаны в
разделе 3 Справочника программиста. Статья с обзором этих функций
помещена в разделе 4 Справочника программиста, см. ldfcn(4).
9.5.10. Описание вспомогательного элемента
#define SYMNMLEN 8 /* Максимальное количество символов
в тексте имени */
#define FILNMLEN 14 /* Максимальное количество символов
в имени файла */
#define DIMNUM 4 /* Размерность массива во вспомога-
тельном элементе */
union auxent {
struct {
long x_tagndx; /* Номер в таблице имен начала структуры,
объединения или перечисления */
union {
struct {
unsigned short x_lnno; /* Номер строки
определения */
unsigned short x_size; /* Размер массива, структуры
или объединения */
} x_lnsz;
long x_fsize; /* Размер функции */
} x_misc;
union {
struct {
long x_lnnoptr;
long x_endndx;
} x_fcn;
struct { /* Если массив, то его размерности (до 4) */
unsigned short x_dimen [DIMNUM];
} x_ary;
} x_fcnary;
unsigned short x_tvndx;
} x_sym;
struct {
char x_fname [FILNMLEN]; /* Имя файла (занимает весь
элемент) */
} x_file;
struct {
long x_scnlen; /* Длина секции */
unsigned short x_nreloc; /* Число элем. с инф. о
настройке ссылок */
unsigned short x_nlinno; /* Число элем. с инф. о
номерах строк */
} x_scn;
struct {
long x_tvfill;
unsigned short x_tvlen;
unsigned short x_tvran[2];
} x_tv;
};
#define AUXENT union auxent
10. ТАБЛИЦА ЦЕПОЧЕК
11. ПРОГРАММЫ ДОСТУПА
К ОБЪЕКТНЫМ ФАЙЛАМ ОБЫЧНОГО ФОРМАТА
| Назад | Оглавление | Вперед |
| Каталог | Индекс раздела |