64-битная сборка в Mac OS X: ошибки времени выполнения: «dyld: нет записываемого сегмента» и «Trap / BPT trap» - PullRequest
5 голосов
/ 27 марта 2012

При попытке запустить следующую программу сборки:

.globl start

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

Я получаю следующие ошибки:

dyld: no writable segment
Trace/BPT trap

Есть идеи, что может быть причиной этого? Аналогичная программа в 32-битной сборке работает нормально.

Ответы [ 2 ]

9 голосов
/ 28 марта 2012

OSX теперь требует, чтобы ваш исполняемый файл имел доступный для записи сегмент данных с содержимым, чтобы он мог перемещать и связывать ваш код динамически. Не знаю почему, может быть, из-за соображений безопасности, может быть из-за нового регистра RIP. Если вы поместите туда сегмент .data (с некоторым поддельным содержимым), вы избежите ошибки «нет доступного для записи сегмента». ИМО это ошибка ld.

Что касается 64-битного системного вызова, вы можете сделать это двумя способами. GCC-стиль, который использует _syscall PROCEDURE из libSystem.dylib или raw. Raw использует инструкцию syscall, а не ловушку int 0x80. "int 0x80" - недопустимая инструкция в 64-битной версии.

«Метод GCC» позаботится о классификации системного вызова для вас, поэтому вы можете использовать те же 32-битные числа, что и в sys / syscall.h. Но если вы пойдете по-сырому, вам придется классифицировать, какой это системный вызов, ИЛИ с помощью идентификатора типа. Вот пример того и другого. Обратите внимание, что соглашение о вызовах отличается! (извинения за синтаксис 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 для получения дополнительной информации о том, как набирается системный вызов.

2 голосов
/ 27 марта 2012

Интерфейс системного вызова отличается от 32 до 64 бит.Во-первых, int $80 заменяется на syscall, и номера системных вызовов отличаются.Вам нужно будет найти документацию для 64-битной версии вашего системного вызова. Здесь - пример того, как может выглядеть 64-битная программа.

...