Невозможно связать объектный файл с помощью 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 на i386
    • sycall на x86-64
    • svc в режиме большого пальца на 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 здесь:

https://github.com/jaredsburrows/Assembly

Стандартный 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
Другие вопросы по тегам