无法使用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生成目标文件。

然后我在我的Mac OS X 10.7上运行了以下“ld”命令,它有这些输出和警告,我试图在我的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 

获取程序链接很容易:

  • 改变_start start
  • $ nasm -f macho exit.asm
  • $ ld -arch i386 -o exiter exit.o

问题是exit.asm正在调用i386 Linux exit()系统调用( EAX = 1),并且程序不会以OS X上的预期状态退出。

系统调用

系统调用是对内核的请求。 与sqrt()不同, exit()必须向其实现中具有更高权限的软件组件发出请求,因为它终止正在运行的程序。 应用无法自行创建或终止进程。 系统调用为应用程序提供了一种让内核代表他们执行操作的方法。

制作系统调用是这样的:

  • 应用程序通过将数据放入CPU寄存器(或寄存器指向的存储器)来描述他们想要执行的操作,例如
    • EAX中的值1exit的系统调用号。
    • EBX中的值0EBXxor清除)是系统调用的第一个参数,即退出状态。
  • 应用程序发出一条指令,使控件转移到内核,例如
    • i386上的int 80
    • x86-64上的sycall
    • ARMv7上的Thumb模式下的svc
  • 内核检查请求并决定执行或拒绝它。
  • 内核将控制权转移回app,返回值在商定的位置,例如i386上的EAX

Linux和OS X都为C程序提供了一个void exit(int)函数,但是对于如何向内核描述这个请求的细节并不一致。 exit.asm的代码与libc _exit()函数的实现处于同一级别。

即使在运行Linux的不同架构之间,系统调用号和调用约定也不同。 例如,在x86-64 Linux上, exit(0)更常见,如下所示:

 xor rdi, rdi mov al, 60 syscall 

你可以通过在/lib64/libc.so.6反汇编_exit来看到这/lib64/libc.so.6

我们不能从libc调用exit()而不是吗?

您可以。 但是你必须将程序与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位输出,因此在链接时你也需要匹配该架构。

我还必须更改_startstart链接。

以下是您的代码的工作示例:

 $ 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”指定主标签。

对于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

有关更详细的解释,我在这里向我的Github解释:

https://github.com/jaredsburrows/Assembly

标准mac gcc不会链接elf对象。 对于需要坚持使用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