Mac OS X运行时错误的64位汇编:“dyld:无可写段”和“Trace / BPT陷阱”

时间:2012-03-27 01:39:15

标签: macos assembly 64-bit 32bit-64bit att

尝试运行以下程序集程序时:

.globl start

start:
    pushq $0x0 
    movq $0x1, %rax
    subq $0x8, %rsp
    int $0x80

我收到以下错误:

dyld: no writable segment
Trace/BPT trap

知道可能导致这种情况的原因是什么? 32位汇编中的类似程序运行良好。

2 个答案:

答案 0 :(得分:9)

OSX现在要求您的可执行文件具有包含内容的可写数据段,因此它可以动态地重定位和链接您的代码。 Dunno为什么,可能是安全原因,可能是由于新的RIP寄存器。如果你在那里放一个.data段(有一些虚假的内容),你将避免“无可写段”错误。 IMO这是一个ld bug。

关于64位系统调用,您可以通过2种方式完成。 GCC风格,使用libSystem.dylib中的_syscall PROCEDURE或raw。 Raw使用syscall指令,而不是int 0x80陷阱。 “int 0x80”是64位的非法指令。

“GCC方法”将为您分类系统调用,因此您可以使用sys / syscall.h中的相同32位数字。但是如果你是原始的,你将不得不通过ORing它与类型id来分类它是什么样的系统调用。这是两者的一个例子。请注意,调用约定是不同的! (为NASM语法道歉;气体让我烦恼)

; assemble with
; nasm -f macho64 -o syscall64.o syscall64.asm && ld -lc -ldylib1.o -e start -o syscall64 syscall64.o
extern _syscall
global start

[section .text align=16]
start:
    ; do it gcc-style
    mov rdi, 0x4 ; sys_write
    mov rsi, 1 ; file descriptor
    mov rdx, hello
    mov rcx, size
    call _syscall ; we're calling a procedure, not trapping.

    ;now let's do it raw
    mov rax, 0x2000001 ; SYS_exit = 1 and is type 2 (bsd call)
    mov rdi, 0 ; Exit success = 0
    syscall ; faster than int 0x80, and legal!


[section .data align=16]
hello: db "hello 64-bit syscall!", 0x0a
size: equ $-hello

查看http://www.opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/syscall_sw.h以获取有关如何键入系统调用的更多信息。

答案 1 :(得分:2)

系统调用接口在32位和64位之间不同。首先,int $80替换为syscall,系统调用号码不同。您需要查找64位版本系统调用的文档。 Here是64位程序的示例。