Невозможно связать файл объекта с помощью ld - Mac OS X
/*********
exit.asm
*/
[SECTION .text]
global _start
_start:
xor eax, eax
xor ebx, ebx
mov al, 1
int 0x80
//****************************
Сначала я использовал nasm -f elf exit.asm для создания объектного файла.
тогда я выполнил следующую команду "ld" на моей Mac OS X 10.7, у нее есть эти выходы и предупреждение, я попытался запустить ее на моей 32-битной Linux-машине, все прошло отлично,
Не могли бы вы объяснить, почему бы линкер не работал на моем Mac?
Спасибо!
Alfred says: ld -o exiter exit.o
ld: warning: -arch not specified
ld: warning: -macosx_version_min not specified, assuming 10.7
ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45 0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the architecture being linked (x86_64): exit.o
Undefined symbols for architecture x86_64:
"start", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for inferred architecture x86_64
после того, как я укажу свою арку и версию, я получил:
Alfred says: ld -arch x86_64 -macosx_version_min 10.7 -o exiter exit.o
ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45 0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the architecture being linked (x86_64): exit.o
Undefined symbols for architecture x86_64:
"start", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
Ответы
Ответ 1
Получение ссылки на программу - это легкая часть:
- Измените
_start
на start
-
$ nasm -f macho exit.asm
-
$ ld -arch i386 -o exiter exit.o
Проблема заключается в том, что exit.asm
вызывает системный вызов i386 Linux exit()
( EAX= 1), и программа НЕ выйдет с нулевым статусом, как предполагалось в OS X.
Системные вызовы
Системный вызов - это запрос к ядру. exit()
, в отличие от sqrt()
, должен сделать запрос к программному компоненту с более высокими привилегиями в его реализации, поскольку он завершает запущенную программу. Приложения не могут самостоятельно создавать или завершать процессы. Системные вызовы предоставляют приложениям возможность просить ядро выполнять действия от их имени.
Создание syscall происходит примерно так:
- Приложения описывают операцию, которую они хотят выполнить, помещая данные в регистры процессора (или память, на которую указывают регистры), например.
- Значение
1
в EAX - это номер системного вызова exit
.
- Значение
0
в EBX ( EBX было очищено xor
) - это первый аргумент для syscall, статус выхода.
- Приложения выдают команду, которая заставляет управление передавать в ядро, например.
-
int 80
на i386
-
sycall
на x86-64
-
svc
в режиме Thumb на ARMv7
- Ядро проверяет запрос и решает его выполнить или отклонить.
- Ядро передает управление обратно в приложение с возвращаемым значением в согласованном местоположении, например. EAX на i386.
Linux и OS X предоставляют функцию void exit(int)
для программ C, но не согласны с подробностями о том, как описать этот запрос ядру. Код в exit.asm
находится на том же уровне, что и реализация функции _exit()
в libc
.
Даже между различными архитектурами, работающими под управлением Linux, номера системных вызовов и соглашения о вызовах различаются. например В x86-64 Linux exit(0)
чаще всего выдается следующим образом:
xor rdi, rdi
mov al, 60
syscall
Это можно увидеть, разобрав _exit
в /lib64/libc.so.6
.
Не может ли мы просто вызвать exit() из libc Вместо?
Вы можете. Но вам нужно связать программу с libc
. Это разница между ссылкой exit.asm
выше:
$ cc -m32 -nostdlib exit.o -o exiter
и
выход-libc.asm
extern exit
global main
main:
push 0
call exit
который должен быть связан с:
$ cc -m32 exit-libc.o -o exit-libc
Попробуйте это и посмотрите размер файла.
Ответ 2
Mac OS X не использует ELF, поэтому вы захотите создать объект Mach-O для связи с этой системой. На моей машине nasm
появляется только поддержка 32-битного вывода, поэтому вам также нужно будет сопоставить эту архитектуру при компоновке.
Мне также пришлось изменить _start
на start
, чтобы связать его.
Вот рабочий пример с вашим кодом:
$ cat exit.asm
[SECTION .text]
global start
start:
xor eax, eax
xor ebx, ebx
mov al, 1
int 0x80
$ nasm -f macho exit.asm
$ ld -arch i386 -macosx_version_min 10.7 -o exiter exit.o
$ ./exiter
$ echo $?
236
Обратите внимание, что программа, вероятно, не делает то, что вы хотите в Mac OS X, поскольку она не выполняет системные вызовы так же, как Linux.
Ответ 3
В большинстве случаев, когда вы получаете эту ошибку:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not
allowed in code signed PIE, but used in _start from hello.o. To fix this
warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
Это потому, что он ищет вашу функцию "main()" (метку) мне ярлык "start:". Всегда лучше указывать основную метку с помощью "ld -e".
Для nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
Для ld:
-arch i386 - specify architecture (32 bit assembly)
-macosx_version_min 10.6 (Mac OSX - complains about default specification)
-no_pie (Mac OSX - removes ld warning)
-e main - specify main symbol name (Mac OSX - default is start)
-o hello.o - outfile
Для оболочки:
./hello.o - execution
Однострочник:
nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o
Сообщите мне, если это поможет!
Я написал, как это сделать в моем блоге:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
Для более подробного объяснения я объяснил здесь свой Гитуб:
https://github.com/jaredsburrows/Assembly
Ответ 4
Стандартный mac gcc не будет связывать объекты эльфа. Для людей, которым нужно придерживаться формата эльфа и разрабатывать на Mac, вам нужен кросс-компилятор...
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Затем вы можете продолжить что-то похожее на это...
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o