Обычный формат объектных файлов Обычный формат объектных файлов СОДЕРЖАНИЕ 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. Таблицу заголовков секций. Содержимое соответствующих секций. Информацию о настройке ссылок. Информацию о номерах строк. Таблицу имен. Таблицу цепочек. Общая структура объектного файла обычного формата приведена в следующей таблице: ~-------------------------------------------- │ ЗАГОЛОВОК ФАЙЛА │ -------------------------------------------- │ Вспомогательный заголовок системы UNIX │ -------------------------------------------- │ Заголовок секции 1 │ -------------------------------------------- │ . . . │ -------------------------------------------- │ Заголовок секции n │ -------------------------------------------- │ Содержимое секции 1 │ -------------------------------------------- │ . . . │ -------------------------------------------- │ Содержимое секции n │ -------------------------------------------- │ Информация о настройке ссылок секции 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. Флаги Последние два байта заголовка файла содержат флаги, характери- зующие тип объектного файла. Флаги определены во включаемом файле ; используемые флаги приведены в следующей таблице: ~------------- ---------- ------------------------------------- │ Обозначение │ Значение │ Смысл │ ------------- ---------- ------------------------------------- │ F_RELFLG │ 00001 │ Из файла удалена информация о │ │ │ │ настройке ссылок │ ------------- ---------- ------------------------------------- │ F_EXEC │ 00002 │ Файл является выполняемым (в нем нет│ │ │ │ неразрешенных внешних ссылок) │ ------------- ---------- ------------------------------------- │ F_LNNO │ 00004 │ Из файла удалена информация о номе- │ │ │ │ рах строк │ ------------- ---------- ------------------------------------- │ F_LSYMS │ 00010 │ Из файла удалена информация о ло-│ │ │ │ кальных именах │ ------------- ---------- ------------------------------------- │ F_AR32W │ 0001000 │ 32-битное слово │ ------------- ---------- ------------------------------------- 3.3. Описание заголовка файла Ниже приведено описание C-структуры, соответствующей заголовку файла. Для включения описания в программу следует использовать файл . 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. Для включения описания в программу следует использовать файл . 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 │ 0Х08 │ Секция-заполнитель (неразмещаемая, │ │ │ │ ненастраиваемая, загружаемая) │ ------------- ---------- ------------------------------------- │ STYP_COPY │ 0Х10 │Секция типа COPY (рабочий признак для│ │ │ │редактора связей; неразмещаемая, не-│ │ │ │настраиваемая, загружаемая; таблицы│ │ │ │настройки ссылок и номеров строк об- │ │ │ │рабатываются обычным образом) │ ------------- ---------- ------------------------------------- │ STYP_TEXT │ 0Х20 │ Секция содержит выполняемые команды│ ------------- ---------- ------------------------------------- │ STYP_DATA │ 0x40 │ Секция содержит инициализированные│ │ │ │ данные │ ------------- ---------- ------------------------------------- │ STYP_BSS │ 0x80 │ Секция содержит только неинициализи-│ │ │ │ рованные данные │ ------------- ---------- ------------------------------------- │ STYP_INFO │ 0x200 │ Секция комментариев (неразмещаемая, │ │ │ │ ненастраиваемая, незагружаемая) │ ------------- ---------- ------------------------------------- │ STYP_OVER │ 0x400 │ Оверлейная секция (неразмещаемая, │ │ │ │ настраиваемая, незагружаемая) │ ------------- ---------- ------------------------------------- │ STYP_LIB │ 0Х800 │Библиотечная секция .lib (обрабатыва-│ │ │ │ется так же, как секция комментариев)│ ------------- ---------- ------------------------------------- 5.2. Описание заголовка секции Ниже приведено описание C-структуры, соответствующей заголовку секции. Для включения описания в программу следует использовать файл . 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; /* Число элементов в таблице номеров строк */ long s_flags; /* Флаги */ }; #define SCNHDR struct scnhdr #define SCNHSZ sizeof (SCNHDR) 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-структуры, соответствующей элементу таблицы настройки ссылок. Для включения описания в программу следует использовать файл . 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-структуры, соответствующей элементу таблицы номеров строк. Для включения описания в программу сле- дует использовать файл . 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 │ --------------------- │ . . . │ --------------------- 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. Классы памяти В поле, указывающем класс памяти, хранится одно из перечислен- ных ниже значений. Именованные константы определены во включае- мом файле . ~------------- ---------- ------------------------------------ │ Обозначение │ Значение │ Смысл класса памяти │ ------------- ---------- ------------------------------------ │ │ │ │ │ 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_LON NG │ 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-структуры, соответствующей элементу таблицы имен. Для включения описания в программу следует ис- пользовать файл . #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, │C_STAT │DT_NON│T_NULL │Секция │ │.bss │ │ │ │ │ ---------------- --------- ------ ----------- ---------------- │ Имя структуры, │C_STRTAG,│DT_NON│T_NULL │Начало структуры│ │ объединения или│C_UNTAG, │ │ │объединения или │ │ перечисления │C_ENTAG │ │ │перечисления │ ---------------- --------- ------ ----------- ---------------- │.eos │C_EOS │DT_NON│T_NULL │Конец структуры │ ---------------- --------- ------ ----------- ---------------- │ Имя функции │C_EXT, │DT_FCN│Кроме T_MOE│Функция │ │ │C_STAT │ │ │ │ ---------------- --------- ------ ----------- ---------------- │ Имя массива │C_AUTO, │DT_ARR│Кроме T_MOE│Массив │ │ │C_STAT, │ │ │ │ │ │C_MOS, │ │ │ │ │ │C_MOU, │ │ │ │ │ │C_TPDEF │ │ │ │ ---------------- --------- ------ ----------- ---------------- │.bb, .eb │C_BLOCK │DT_NON│T_NULL │Начало и конец │ │ │ │ │ │блока │ ---------------- --------- ------ ----------- ---------------- │.bf, .ef │C_FCN │DT_NON│T_NULL │Начало и конец │ │ │ │ │ │функции │ ---------------- --------- ------ ----------- ---------------- │Имя, связанное │C_AUTO, │DT_PTR│T_STRUCT, │Имя, связанное │ │со структурой, │C_STAT, │DT_ARR│T_UNION, │со структурой, │ │объединеним или│C_MOS, │DT_NON│T_ENUM │объединением или│ │перечислением │C_MOU, │ │ │перечислением │ │ │C_TPDEF │ │ │ │ ---------------- --------- ------ ----------- ---------------- Здесь имя структуры, объединения или перечисления включает так- же специальные имена .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-структуры, соответствующей вспомога- тельному элементу таблицы имен. Для включения описания в прог- рамму следует использовать файл . #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).