Невозможно связать объектный файл с помощью 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
4 ответа
Получить ссылку на программу легко:
- + Изменить
_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()
, должен сделать запрос к программному компоненту с более высокими привилегиями в своей реализации, так как он завершает работающую программу. Приложения не могут создавать или завершать процессы самостоятельно. Системные вызовы позволяют приложениям запрашивать ядро о выполнении действий от их имени.
Создание системного вызова выглядит примерно так:
- Приложения описывают операцию, которую они хотят выполнить, помещая данные в регистры ЦП (или память, на которую указывают регистры), например
- Значение
1
в EAX это номер системного вызоваexit
, - Значение
0
в EBX (EBX был очищенxor
) является первым аргументом системного вызова, статусом выхода.
- Значение
- Приложения выдают инструкцию, которая приводит к передаче управления ядру, например
int 80
на i386sycall
на x86-64svc
в режиме большого пальца на ARMv7
- Ядро проверяет запрос и решает выполнить или отклонить его.
- Ядро передает управление обратно приложению с возвращаемым значением в согласованном месте, например, EAX на i386.
Linux и OS X оба обеспечивают void exit(int)
функция для программ на C, но не согласны с деталями о том, как описать этот запрос ядру. Код в exit.asm
находится на том же уровне, что и реализация _exit()
функция в libc
,
Даже между различными архитектурами под управлением Linux номера системных вызовов и соглашение о вызовах различаются. например, на Linux x86-64, 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
Попробуйте это и посмотрите на размер файла.
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.
Большую часть времени, когда вы получаете эту ошибку:
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".
Для носа:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
Для лд:
-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
Для Shell:
./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
Для более подробного объяснения я объяснил на своем Github здесь:
Стандартный mac gcc не будет связывать эльфийские объекты. Для людей, которым нужно придерживаться формата elf и разрабатывать на 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