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

Haw*_*ken 5 macos 64-bit assembly 32bit-64bit att

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

.globl start

start:
    pushq $0x0 
    movq $0x1, %rax
    subq $0x8, %rsp
    int $0x80
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

dyld: no writable segment
Trace/BPT trap
Run Code Online (Sandbox Code Playgroud)

知道是什么原因引起的吗?32位汇编中的类似程序运行良好.

小智 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
Run Code Online (Sandbox Code Playgroud)

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