КаталогИндекс раздела
НазадОглавлениеВперед


Обычный формат объектных файлов

СОДЕРЖАНИЕ

1. Введение

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. Заголовок секции неинициализированных данных

6. Секции

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. Описание вспомогательного элемента

10. Таблица цепочек

11. Программы доступа к объектным файлам обычного формата


 

1. ВВЕДЕНИЕ

Ниже описывается обычный формат объектных файлов (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 символов.

Выполняемым считается объектный файл, не содержащий ошибок или неразрешенных внешних ссылок.

 

2. ОПРЕДЕЛЕНИЯ И СОГЛАШЕНИЯ

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

2.1. Секции

Секция есть наименьшая часть объектного файла, которая подвергается перемещению и рассматривается как нечто отдельное и различимое. Как правило, в объектном файле присутствуют три секции, именуемые .text, .data и .bss. Это секции команд, инициализированных и неинициализированных данных. В других секциях могут размещаться комментарии, дополнительные сегменты команд и данных, разделяемые сегменты данных. Допускаются секции, определенные пользователем. Однако в любом случае ОС UNIX при загрузке файла на выполнение помещает в память только секции .text, .data и .bss.

Примечание

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

2.2. Физические и виртуальные адреса

Физический адрес секции или имени есть смещение этой секции или данных, соответствующих этому имени, от начала (нулевого адреса) адресного пространства. Значение термина физический адрес, когда он используется для описания объектных файлов обычного формата, отличается от общепринятого. Физический адрес объекта не обязательно будет совпадать с адресом, по которому этот объект будет помещен во время выполнения. Так, в системах со страничной виртуальной памятью адрес берется относительно нулевого адреса виртуальной памяти, после чего операционная система выполняет дальнейшее преобразование адреса. Заголовок секции содержит два адресных поля, для физического и виртуального адресов; однако во всех версиях COFF-формата и ОС UNIX эти адреса совпадают.

2.3. Целевой компьютер

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

 

3. ЗАГОЛОВОК ФАЙЛА

Заголовок файла состоит из 20 байт; его формат показан в следующей таблице. Последние два байта содержат флаги, используемые редактором связей ld(1) и другими утилитами, обрабатывающими объектные файлы.

Байты Описание Имя Смысл
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 Флаги (см. следующую таблицу)

3.1. Магическое число

Магическое число определяет целевой компьютер, для которого предназначен объектный файл.

3.2. Флаги

Последние два байта заголовка файла содержат флаги, характеризующие тип объектного файла. Флаги определены во включаемом файле <filehdr.h>; используемые флаги приведены в следующей таблице:

Обозначение Значение Смысл
F_RELFLG 00001 Из файла удалена информация о настройке ссылок
F_EXEC 00002 Файл является выполняемым (в нем нет неразрешенных внешних ссылок)
F_LNNO 00004 Из файла удалена информация о номерах строк
F_LSYMS 00010 Из файла удалена информация о локальных именах
F_AR32W 0001000 32-битное слово

3.3. Описание заголовка файла

Ниже приведено описание 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)

 

4. ВСПОМОГАТЕЛЬНЫЙ ЗАГОЛОВОК СИСТЕМЫ UNIX

Структура вспомогательного заголовка файла зависит от конкретной системы, использующей обычный формат объектных файлов. Во вспомогательный заголовок помещается вся зависящая от системы информация, что дает возможность различным операционным системам получать доступ к только им необходимым данным, без того, чтобы в каждом объектном файле обычного формата для каждой операционной системы отводить место для таких данных. Утилиты общего назначения (например, дизассемблер, функции, работающие с таблицей имен, и т.д.) реализованы так, чтобы обеспечить правильную работу с любым объектным файлом. Это достигается использованием информации, расположенной за вспомогательным заголовком, длина которого хранится в поле f_opthdr заголовка файла.

4.1. a.out - стандартный заголовок системы UNIX

По умолчанию, вспомогательный заголовок файлов, создаваемых редактором внешних связей системы UNIX, имеет стандартную структуру файлов a.out. Размер этой структуры - 28 байт. Поля вспомогательного заголовка описаны в следующей таблице:

Байты Описание Имя Смысл
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 Данные располагаются с границы сегмента, следующего за сегментом текста. Сегмент текста защищен от записи

4.2. Описание вспомогательного заголовка

Ниже приведено описание 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;

 

5. ЗАГОЛОВКИ СЕКЦИЙ

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

Байты Описание Имя Смысл
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 (обрабатывается так же, как секция комментариев)

5.2. Описание заголовка секции

Ниже приведено описание 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;   /* Число элементов в таблице
                                      номеров строк */
                           как секция комментариев)                             

5.3. Заголовок секции неинициализированных данных

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

 

6. СЕКЦИИ

В объектном файле обычного формата за таблицей заголовков секций следует содержимое секций - соответствующее количество байт команд или данных. Содержимое начинается с границы, кратной четырем байтам.

Предложение SECTIONS управляющего языка редактора связей (см. Руководство по редактору связей) предоставляет, помимо прочих, следующие возможности:

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

 

7. ИНФОРМАЦИЯ О НАСТРОЙКЕ ССЫЛОК

Таблица настройки содержит по одному элементу для каждой ссылки (среди команд или данных), требующей настройки. Элементы имеют следующий формат:

Байты Описание Имя Смысл
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-битный виртуальный адрес имени

7.1. Описание элемента таблицы настройки ссылок

Ниже приведено описание C-структуры, соответствующей элементу таблицы настройки ссылок. Для включения описания в программу следует использовать файл <reloc.h>.

       struct reloc {
         long           r_vaddr;  /* Виртуальный адрес ссылки */
         long           r_symndx; /* Номер в таблице имен */
         unsigned short r_type;   /* Тип ссылки */
       };
       #define RELOC  struct reloc
       #define RELSZ  10      /* sizeof(RELOC) */

 

8. ИНФОРМАЦИЯ О НОМЕРАХ СТРОК

Использование команд cc -g и svs +d приводит к тому, что для каждой строки исходного текста, на которую можно установить точка прерывания, в объектный файл помещается элемент с информацией о строке. Эту информацию используют символьные отладчики, такие как sdb(1) и КРОТ. В пределах секции элементы сгруппированы по функциям, как показано в следующей таблице:

Номер в таблице имен 0
физический адрес номер строки
физический адрес номер строки
. . . . . .
Номер в таблице имен 0
физический адрес номер строки
физический адрес номер строки

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

8.1. Описание элемента таблицы номеров строк

Ниже приведено описание C-структуры, соответствующей элементу таблицы номеров строк. Для включения описания в программу следует использовать файл <linenum.h>.

       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 вне всех функций. Таблица содержит по меньшей мере один элемент фиксированной длины для каждого имени, однако для некоторых имен за этим элементом может следовать несколько вспомогательных элементов той же длины. Элемент таблицы хранит значение имени, тип и другую информацию.

9.1. Специальные имена

В таблицу имен помещаются некоторые специальные имена, генерируемые ассемблером as(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. В основном элементе таблицы хра- нится различная информация для различных видов имен. За основным элементом могут следовать вспомогательные.

9.2. Внутренние блоки

В языке C блок определяется как составной оператор, заключенный в фигурные скобки, { и }. Внутренний блок определяется как блок, находящийся внутри функции. Сама функция также является блоком.

Если в некотором внутреннем блоке определены локальные имена, то в таблицу имен, непосредственно перед элементом для первого такого имени, будет помещен элемент для специального имени .bb. Равным образом, специальное имя .eb помещается сразу после элемента для последнего в этом блоке локального имени. Пример такой последовательности изображен изображен в следующей таблице:

.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
. . .

9.3. Имена и функции

В таблице имен между элементами для имени каждой функции и для первого локального имени помещается элемент, соответствующий специальному имени .bf. После последнего элемента для локального в данной функции имени помещается элемент, соответствующий имени .ef. Эта последовательность показана ниже:

Имя функции
.bf
Локальные имена
.ef

9.4. Элементы таблицы имен

Структура элементов таблицы имен одинакова для всех имен и не зависит от их типа или класса памяти. Размер каждого элемента - 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 Число вспомогательных элементов

9.4.1. Тексты имен

Первые 8 байт элемента таблицы имен представляют собой объединение массива символов и двух четырехбайтных целых чисел. Если длина текста имени не превышает восьми символов, то здесь хранится сам текст, дополненный нулевыми байтами. Если же его длина больше восьми символов, то текст хранится в таблице цепочек. В этом случае в первых восьми байтах элемента таблицы имен находятся два целых числа, первое из которых равно нулю, а второе есть смещение соответствующего элемента таблицы цепочек относительно начала этой таблицы. Нули в первых четырех байтах позволяют отличить текст от ссылки на него, поскольку никакое имя не может начинаться с нулевых байт:

Байты Описание Имя Смысл
0-7 char n_name 8-символьный текст имени, дополненный нулевыми байтами
0-3 long n_zeroes Нули в этом поле указывают, что текст имени находится в таблице цепочек
4-7 long n_offset Смещение текста имени относительно начала таблицы цепочек
Специальные имена, генерируемые C-компилятором, описаны выше в разделе Специальные имена.

9.4.2. Классы памяти

В поле, указывающем класс памяти, хранится одно из перечисленных ниже значений. Именованные константы определены во включаемом файле <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

9.4.4. Поле значения имени

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

 
Класс памяти Смысл значения имени
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

9.4.7. Поле типа

Поле типа элемента таблицы имен содержит информацию о базовом и производных типах соответствующего имени. Компилятор языка C заполняет эти поля только при указании опции -g. Производных типов может быть несколько, но каждое имя имеет ровно один базовый тип. Формат 16-битного поля типа таков:

d6 d5 d4 d3 d2 d1 базовый тип
Биты с 0-го по 3-й кодируют базовый тип:

Обозначение Значение Базовый тип
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 с тем исключением, что не может быть двух последовательных производных типов функция.

Хотя аргументы функции и могут быть объявлены как массивы, они все равно трактуются как указатели. Поэтому аргумент функции не может иметь массив в качестве своего первого производного типа.

9.4.9. Описание элемента таблицы имен

Ниже приведено описание C-структуры, соответствующей элементу таблицы имен. Для включения описания в программу следует использовать файл lt;syms.h>.

       #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. Если имя удовлетворяет нескольким из перечисленных условий, то его вспомогательный элемент должен иметь формат объединения.

Примечание

Было бы ошибкой полагаться на какие-либо априорные предположения о числе вспомогательных элементов. Число вспомогательных элементов для имени хранится в поле n_numaux соответствующего основного элемента и должно извлекаться только оттуда.

В следующих пунктах описывается структура вспомогательных элементов.

9.5.1. Имя файла

Вспомогательный элемент для имени файла в байтах с 0-го по 13-й содержит 14-символьное имя файла, дополненное нулями.

9.5.2. Секция

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

Байты Описание Имя Смысл
0-3 long int x_scnlen Длина секции
4-5 unsigned short x_nreloc Число элементов в таблице настройки ссылок
6-7 unsigned short x_nlinno Число элементов в таблице номеров строк
8-17 - - Не используются (заполнены нулями)

9.5.3. Начало структуры, объединения или перечисления

Вспомогательные элементы для таких имен имеют следующий формат:

Байты Описание Имя Смысл
0-5 - - Не используются (заполнены нулями)
6-7 unsigned short x_size Размер структуры, объединения или перечисления
8-11 - - Не используются (заполнены нулями)
12-15 long int x_endndx Номер элемента, следующего за элементами для этой структуры, объединения, или перечисления
16-17 - - Не используются (заполнены нулями)

9.5.4. Конец структуры

Формат вспомогательного элемента для конца структуры изображен в следующей таблице:

Байты Описание Имя Смысл
0-3 long int x_tagndx Номер элемента для начала структуры
4-5 - - Не используются (заполнены нулями)
6-7 unsigned short x_size Размер структуры, объединения или перечисления
8-17 - - Не используются (заполнены нулями)

9.5.5. Функция

Вспомогательные элементы для функций имеют следующий формат:

Байты Описание Имя Смысл
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 не используется)

9.5.6. Массив

Формат вспомогательного элемента для массива изображен в следующей таблице. Попытка определения массива с количеством измерений, превышающим 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 - - Не используются (заполнены нулями)

9.5.7. Конец блока или функции

Вспомогательные элементы для конца блока или функции имеют следующий формат:

Байты Описание Имя Смысл
0-3 - - Не используются (заполнены нулями)
4-5 unsigned short x_lnno Номер строки исходного текста
6-17 - - Не используются (заполнены нулями)

9.5.8. Начало блока или функции

Формат вспомогательных элементов для начала блока или функции изображен ниже:

Байты Описание Имя Смысл
0-3 - - Не используются (заполнены нулями)
4-5 unsigned short x_lnno Номер строки исходного текста
6-11 - - Не используются (заполнены нулями)
12-15 long int x_endndx Номер элемента, следующего за элементами для этого блока
16-17 - - Не используются (заполнены нулями)

9.5.9. Имена, связанные со структурой, объединением или перечислением

Формат вспомогательных элементов для имен, связанных со структурой, объединением или перечислением, приведен в следующей таблице:

Байты Описание Имя Смысл
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 - нет, поскольку его описание предшествует описанию структуры.

9.5.10. Описание вспомогательного элемента

Ниже приведено описание C-структуры, соответствующей вспомогательному элементу таблицы имен. Для включения описания в программу следует использовать файл <syms.h>.

       #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. ТАБЛИЦА ЦЕПОЧЕК

Тексты имен, состоящие более чем из восьми символов, размещаются последовательно в таблице цепочек, причем каждый текст завершается нулевым байтом. Первые четыре байта таблицы цепочек содержат размер этой таблицы в байтах; таким образом, смещения всех имен из этой таблицы больше или равны 4.

 

11. ПРОГРАММЫ ДОСТУПА К ОБЪЕКТНЫМ ФАЙЛАМ ОБЫЧНОГО ФОРМАТА

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

Средства доступа можно разделить на четыре категории:

Функции доступа хранятся в библиотеке libld.a и описаны в разделе 3 Справочника программиста. Статья с обзором этих функций помещена в разделе 4 Справочника программиста, см. ldfcn(4).


НазадОглавлениеВперед
КаталогИндекс раздела