次のアセンブリプログラムを実行しようとした場合:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
次のエラーが発生します。
dyld: no writable segment
Trace/BPT trap
これを引き起こしている可能性のあるアイデアはありますか?32ビットアセンブリの類似プログラムは正常に実行されます。
次のアセンブリプログラムを実行しようとした場合:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
次のエラーが発生します。
dyld: no writable segment
Trace/BPT trap
これを引き起こしている可能性のあるアイデアはありますか?32ビットアセンブリの類似プログラムは正常に実行されます。
OSXでは、実行可能ファイルにコンテンツを含む書き込み可能なデータセグメントが必要になるため、コードを動的に再配置およびリンクできます。なぜ、おそらくセキュリティ上の理由で、おそらく新しいRIPレジスタが原因です。そこに.dataセグメントを(偽のコンテンツを含めて)配置すると、「書き込み可能なセグメントがありません」というエラーを回避できます。IMOこれはld
バグです。
64ビットのシステムコールに関しては、2つの方法で実行できます。libSystem.dylib
、またはrawからの_syscallPROCEDUREを使用するGCCスタイル。Rawは、トラップsyscall
ではなく命令を使用します。64ビットでの不正な命令です。int 0x80
int 0x80
「GCCメソッド」がsyscallの分類を処理するため、sys/syscall.hにあるのと同じ32ビットの数値を使用できます。ただし、生の場合は、タイプIDとORをとって、どのようなシステムコールであるかを分類する必要があります。これが両方の例です。呼び出し規約が異なることに注意してください!(これは私を悩ませるNASM
ので構文です)gas
; 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を確認してください。
システムコールインターフェイスは、32ビットと64ビットで異なります。まず、int $80
に置き換えられsyscall
、システムコール番号が異なります。システムコールの64ビットバージョンのドキュメントを検索する必要があります。これは、64ビットプログラムがどのように見えるかの例です。