Я составил простую программу, например
int main()
{
return 0;
}
используя Clang в исполняемый файл, и попросил otool
сообщить о командах загрузки, сгенерированных компилятором. Меня интересует LC_SEGMENT_64
, в частности тот, который описывает сегмент __TEXT
в файле. Я получаю следующее описание:
$ otool -lV foo
foo:
Load command 0
cmd LC_SEGMENT_64
cmdsize 72
segname __PAGEZERO
vmaddr 0x0000000000000000
vmsize 0x0000000100000000
fileoff 0
filesize 0
maxprot ---
initprot ---
nsects 0
flags (none)
Load command 1
cmd LC_SEGMENT_64
cmdsize 312
segname __TEXT
vmaddr 0x0000000100000000
vmsize 0x0000000000001000
fileoff 0
filesize 4096
maxprot rwx
initprot r-x
nsects 3
flags (none)
Section
sectname __text
segname __TEXT
addr 0x0000000100000f90
size 0x000000000000000f
offset 3984
align 2^4 (16)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
Мой вопрос: почему поле fileoff
во второй команде загрузки установлено в ноль?
В документации Apple для этого поля указано, что
Файл сопоставляется, начиная с fileoff, с началом сегмента в памяти, vmaddr.
Сначала это натолкнуло меня на мысль, что это поле вместе с filesize
указывает загрузчику примерно так: «Возьмите содержимое файла с fileoff
по fileoff + filesize
, и это последовательность инструкций, которые вы собираетесь запросить у процессора. бежать". Но мое предположение, конечно, неверно, если это значение равно нулю.
Я думал, что, поскольку сегмент имеет по крайней мере один раздел, загрузчик будет использовать значение соответствующего смещения в описании раздела, чтобы найти код для запуска, и, следовательно, такое значение точно не нужно --- мы можем видеть, что , на самом деле первый раздел в этом сегменте имеет значение для поля offset
(в данном случае 3984, которое я проверил с помощью otool -s __TEXT __text -j foo
и действительно относится к смещению, по которому этот раздел находится в файле).
Но если я сделаю то же самое с объектным файлом, сгенерированным из того же исходного файла (т. е. файла с типом MH_OBJECT
вместо MH_EXECUTE
), я получу следующий результат:
$ otool -lV foo.o
foo.o:
Load command 0
cmd LC_SEGMENT_64
cmdsize 312
segname
vmaddr 0x0000000000000000
vmsize 0x0000000000000070
fileoff 464
filesize 112
maxprot rwx
initprot rwx
nsects 3
flags (none)
Section
sectname __text
segname __TEXT
addr 0x0000000000000000
size 0x000000000000000f
offset 464
align 2^4 (16)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
В этом случае команда загрузки имеет значение для своего поля fileoff
, которое совпадает со значением для ее первого раздела, __text
.