-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathObject Code Format_ru.txt
321 lines (257 loc) · 25.7 KB
/
Object Code Format_ru.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
> Я был бы признателен за описание формата объектного файла и вывод
> 'dump.exe' для любого пакета компилятора Hi-Tech C (для любой архитекту-
> ры), датированного примерно 1990 - 1991 годами.
Я наткнулся на описание в архиве, относящееся к файлам символов. Я разме-
щаю его здесь для дальнейшего использования, поскольку архивы Usenet бо-
лее постоянны, чем большинство других веб-ресурсов:
Формат объектного кода программного обеспечения HI-TECH
1. Введение
Здесь описан формат объектного кода, распознаваемый компоновщиком
"link". Обратите внимание, что более поздние версии объектного кода имеют
идентификационные номера версий в записях IDENT. Ранняя версия объект-
ного кода не имела этих номеров версий. Наличие номера версии можно
определить по длине идентификационной записи. Определенные функции
будут идентифицированы как присутствующие в версиях, превышающих не-
которое значение, с помощью записи (>=mn), где m - основной номер версии, а
n - дополнительный номер версии, например (>=2.1).
2. Структура объектного кода
Объектный код (OCODE) по существу является двоичным, состоящим из по-
следовательности записей, каждая из которых имеет внешний конверт, таким
образом:
| Длина (16 бит) | Тип записи (8 бит) | Данные (длина * 8 бит) |
то есть длина 16 бит, затем тип 8 бит, затем последовательность байтов 8 бит.
Длина - это количество байтов, исключая длину и тип. На практике длина ча-
сти данных любой записи не превышает 512 байт. Это устанавливает верхний
предел размера буфера, необходимого для хранения любой записи.
2.1. Запись TEXT
Основной тип записи - TEXT (= 1). Ее формат (т.е. часть данных основного кон-
верта записи) выглядит следующим образом:
| Смещение (32 бита) | Имя psect (завершается нулем) | байты данных |
Смещение - это смещение (в байтах) внутри именованного psect (т.е. раздела
программы), в которую должны быть помещены байты данных. Имя, как и все
имена в этом OCODE, заканчивается нулем. Количество байтов данных опреде-
ляется путем вычитания длины имени + 4 из длины записи во внешнем кон-
верте.
2.2. Запись PSECT
Запись PSECT (= 2) используется для определения разделов программы. Каж-
дая запись PSECT описывает один psect.
| Флаги psect (16 бит) | Имя psect (завершается нулем) |
Обратите внимание, что в качестве проверки согласованности нулевой байт,
завершающий имя, должен быть последним байтом в записи.
Биты флага:
GLOBAL 020 psect является глобальной
PURE 040 psect предназначена только для чтения.
OVRLD 0100 Данные каждого модуля для этой psect начинаются с отно-
сительной позиции 0. По умолчанию используется конкате-
нация.
ABS 0200 Этот psect загружается с абсолютным 0.
BIGSEG 0400 Означает, что перемещаемость этого psect умножается на
65535.
BPAGE 01000 Это psect базовой страницы - игнорировать переполнения
при перемещениях.
2.3. Запись RELOC
Запись типа RELOC (= 3) содержит информацию о перемещении, относящуюся
к последней записи TEXT. Она состоит из последовательности пар смеще-
ние/дескриптор, причем смещение представляет собой 16-битное смещение в
последней записи TEXT, и дескриптор, предоставляющий информацию о пе-
ремещении. Типом перемещения может быть простое перемещение внутри
psect, перемещение по значению внешнего имени или что-то еще. Могут
также появляться сложные перемещения, которые представляют собой по-
следовательность операторов и операндов, которые должны быть оценены
стековой машиной. Каждая простая запись о перемещении будет выглядеть
так:
| Смещение (16 бит) | Тип перемещения(8 бит) | psect или внешнее имя |
Имя, как обычно, заканчивается нулем. Фактическая запись RELOC состоит из
произвольного количества этих записей.
Байт типа перемещения интерпретируется следующим образом:
биты | 7 4 | 3 0 |
| тип | размер |
Размер - это размер в байтах перемещаемого количества.
Тип может быть одним из:
RABS 0 Абсолютный - без перемещения (т.е. без изменений)
RPSECT 1 Перемещение внутри именованной psect
RNAME 2 Перемещение по значению имени
RRPSECT 5 Перемещение внутри psect за вычетом текущего pc. Он
требуется для машин, использующих относительную адре-
сацию. val = val + psect.base - code.location.
RRNAME 6 То же, что и RRPSECT, но относительно символа, а не psect.
RSPSECT 9 Перемещение по значению сегмента для psect
RSNAME 10 Перемещение по значению сегмента для символа
RCPLX 48 Далее следует сложное перемещение
Запись о сложном перемещении имеет вместо имени по-
следовательность байтов оператора и байтов операнда с
дополнительной информацией. При выполнении бинар-
ных операций запись верхнего стека является левым опе-
рандом, а значение стека, следующим за верхним, является
правым операндом. Оба значения удаляются из стека, а ре-
зультат возвращается. Унарные операторы действуют на
верхнее значение стека. Такие операнды, как RC_VAL и
RPSECT, помещают свое значение в стек. Возможны следу-
ющие байты типа:
RC_END 0 Конец сложных перемещений
RC_LOW 1 and с 0xFF
RC_HI 2 Сдвиг вправо 8 бит, and с 0xFF
RC_VAL 3 Следует 32-битная константа
RC_ADD 4 Сложение
RC_SUB 5 Вычитание
RC_MUL 6 Умножение
RC_DIV 7 Деление
RC_SHL 8 Сдвиг влево
RC_SHR 9 Сдвиг вправо
RC_AND 10 Побитовое И
RC_OR 11 Побитовое ИЛИ
RC_XOR 12 Побитовое исключающее ИЛИ
RC_CPL 13 Побитовое дополнение
RC_NEG 14 смена знака
RC_BITF 15 Извлечение битового поля - операнды -
- это значение, битовое смещение и длина
RPSECT 16 Значение psect - следует имя с завершающим нулем
RC_MOD 17 модуль значения
RNAME 32 Значение символа - следует имя с за-
вершающим нулем
RSPSECT 144 Селектор сегмента psect
RSNAME 160 Селектор сегмента символа
2.4. Запись SYM
Запись SYM (= 4) определяет внешние и внутренние имена. Она состоит из по-
следовательности определений имен. Обратите внимание, что здесь не обяза-
тельно упоминать внешнее имя, если на него есть ссылка в записи RELOC.
Каждая запись выглядит следующим образом:
| Значение (32 бита) | флаги (16 бит) | имя psect | имя символа |
Обратите внимание, что имя psect будет нулевым, если символ не определен.
То есть имя psect будет одним нулевым байтом. Слово флага содержит такие
же флаги, как определено выше для записей PSECT. В младших 4-х битах нахо-
дится одно из следующих значений:
NULL 0 Обычный случай определения локальных или глобальных символов
STACK 1 Символ - это символ стека (автоматическая переменная)
COMM 2 Символ является обычным символом - если он определен
где-либо еще, то это то же самое, что и EXTERN, в против-
ном случае компоновщик выделит пространство в назван-
ном psect размером, равным максимальному значению
любого обнаруженного экземпляра этого символа.
REGNAM 3 Символ ссылается на регистр
LINENO 4 Это номер строки в исходном коде.
FILNAM 5 Это имя исходного файла.
EXTERN 6 Это ссылка на внешне определенный символ
Имя psect должно быть пустым.
Символы STACK, REGNAM, FILNAM и LINENO предназначены исключительно для
использования отладчиком. Эти символы вообще не обрабатываются компо-
новщиком (кроме как для правильного перемещения их значений), но будут
переданы в таблицу символов, если не подавлены с помощью опции -x.
2.5. Запись START
Запись START (= 5) определяет начальный адрес. В модуле может появиться
только одна запись START.
| смещение (32 бита) | имя psect (нулевой термин) |
Она определяет, что начальный адрес находится по указанному смещению в
названном psect.
2.6. Запись END
Запись END (==6) выглядит следующим образом:
| флаги (16 бит) |
Значение флага в настоящее время не используется.
2.7. Запись IDENT
Запись IDENT (= 7) идентифицирует целевой компьютер и определяет поря-
док байтов в 32- и 16-битных количествах. Он влияет как на значения смеще-
ния, так и на значения символов, а также на перемещаемые значения в запи-
сях TEXT. Запись IDENT является необязательной, и по умолчанию использует-
ся строго младший байт в начале. Если запись IDENT присутствует, она долж-
на быть первой записью в файле. Поле длины во внешнем конверте каждой
записи всегда сохраняется первым младшим байтом, независимо от содержи-
мого любой записи IDENT.
| порядок байтов (32 бита) | порядок байтов (16 бит) | имя машины |
| номер версии (16 бит) |
В полях порядка байтов указывается относительное положение последова-
тельно более значимых байтов в полях размером 32 и 16 бит соответственно.
Например, идентификационная запись для PDP11 будет выглядеть так:
| 02 03 00 01 | 00 01 | PDP11 |
Имя машины заканчивается нулем. Идентификационная запись может не
присутствовать, если встречается более одной идентификационной записи,
все записи должны иметь одинаковый порядок байтов. Номер версии (>=2.0)
занимает 2 байта после имени машины. Он присутствует только в том случае,
если длина записи достаточно велика, чтобы содержать эти дополнительные
2 байта. Если он отсутствует, можно принять номер версии 1.0. Если присут-
ствует, первый байт - это основной номер версии, а второй - дополнительный
номер версии.
2.8. Запись XPSECT
Запись XPSECT (= 8) содержит дополнительную информацию о psect. Некото-
рые объектные файлы могут не содержать записей XPSECT.
Макет выглядит следующим образом:
| максимальный размер (32 бита) | перемещаемость (16 бит) |
| селектор (16 бит) | зарезервировано (24 бита) | тип (8 бит) | имя psect |
Поле максимального размера - длинное целое число, определяющее макси-
мальный размер этой psect. Поле перемещаемости, если оно не равно нулю,
указывает границу, на которой должен начинаться psect, например, для 8086
это поле обычно 16, так как сегмент 8086 должен начинаться на 16-байтовой
границе. В зарезервированном поле должны быть все нули. Имя psect - это
имя psect с завершающим нулем. Селектор (>=2.0) не равен нулю, если есть
селектор сегмента, который должен быть связан с этой psect. Эта функция
обычно используется только с процессорами с сегментированной архитекту-
рой, такими как 8086. В версиях объектного кода до 2.0 это поле всегда было
нулевым.
Поле типа (>=2.1) позволяет компоновщику проверять, что все вклады моду-
ля в данную psect имеют один и тот же тип. Это поле должно совпадать во
всех модулях этой psect. Обычно это используется ассемблером 8086 для ко-
дирования состояния флага USE32 для psect.
2.9. Запись SEGMENT
Запись SEGMENT (= 9) (>=2.0) присутствует только в полностью связанных
объектных файлах, т.е. созданных компоновщиком. Она определяет сегмент,
который представляет собой непрерывный набор psect. Структура записи
следующая:
| размер (32 бита) | базовый адрес (32 бита) | селектор (16 бит) |
| зарезервировано (16 бит) | происхождение (32 бита) | название сегмента |
Поле размера - это размер сегмента в байтах. Базовый адрес - это физический
базовый адрес сегмента. Это не обязательно то же самое, что и источник, ко-
торый является адресом, используемым при перемещении ссылок на этот
сегмент. Они соответствуют адресам загрузки и ссылки соответственно псев-
донимов, составляющих сегмент. Селектор - это значение селектора сегмента,
используемое для ссылки на этот сегмент. Это актуально в основном для про-
цессоров семейства 8086. Имя сегмента - это имя первого псевдонима, состав-
ляющего этот сегмент.
2.10. Запись XSYM
Запись XSYM (= 10) (>=2.1) аналогична записи SYM, но также определяет зна-
чение селектора для символа. Формат записи следующий:
| значение (32 бита) | флаги (16 бит) | селектор (16 бит) | имя |
Значение селектора - это селектор сегмента, в котором расположен символ.
2.11. Запись SIGNAT
Запись SIGNAT (= 11) (>=2.1) определяет подпись для символа. Во время свя-
зывания все подписи для символа сравниваются и должны быть идентичны-
ми. Если подпись не совпадает, выдается сообщение об ошибке. Формат запи-
си следующий:
| подпись (16 бит) | имя символа |
2.12. Запись FNINFO
Запись FNINFO (= 12) (>=2.3) предоставляет информацию, необходимую для
построения графиков вызовов и распределения локальных данных для
нереентерабельных функций. В записи объединены один или несколько эк-
земпляров следующих макетов. Каждый экземпляр имеет переменную длину
в зависимости от длины имени.
| FNCALL (1) | caller name | callee name |
| FNARG (2) | caller name | callee name |
| FNINDIR (3) | caller name | callee signature (16 bits) |
| FNADDR (4) | function name | signature (16 bits) |
| FNSIZE (5) | func name | local size (32 bits) | arg size (32 bits) |
| FNROOT (6) | func name |
Экземпляр FNCALL указывает, что одна функция напрямую вызывает другую.
Экземпляр FNARG указывает, что одна функция будет иметь аргументы, пока
вызывается другой. Экземпляр FNINDIR указывает, что функция косвенно вы-
зывает другую (неизвестную) функцию, подпись которой указана. Экземпляр
FNADDR указывает, что у функции уже занят адрес (и, таким образом, она яв-
ляется кандидатом на косвенный вызов) и ее подпись. Экземпляр FNSIZE
определяет размер блока локальной переменной и размер блока аргументов
для функции. Экземпляр FNROOT указывает, что эта функция является корнем
графа вызовов (либо основная функция, либо функция прерывания).
2.13. Запись FNCONF
Запись FNCONF (= 13) (>=2.3) предоставляет информацию о среде для постро-
ения графиков вызовов и распределения локальных данных. Макет состоит из
трех строк с завершающим нулем, а именно:
| имя psect | префикс локальных данных | префикс аргумента |
Имя psect - это имя psect, в котором локальные блоки данных и аргументов
должны быть выделены компоновщиком. Префиксы локальных данных и ар-
гументов - это строки, которые должны быть добавлены к имени функции,
чтобы получить имена для локальных данных и блоков аргументов для дан-
ной функции.
3. Примечания
В объектном файле не хранятся байты заполнения или дополнения, т. е. вы-
равнивание записей не выполняется. Не пытайтесь читать или записывать
объектные файлы с использованием структур, т.е. все записи должны быть
построены побайтно в массиве символов.
-----------------------------------------------------------------------
С уважением,
Майкл