Mmap не возвращает ни ошибку, ни действительный указатель - PullRequest
1 голос
/ 22 июня 2019

Я пытался выделить память с помощью mmap , но пока не знаю, как это сделать правильно.Ниже вы можете увидеть написанную мной функцию, которая вызывается из C. Результат, который она выдает, всегда 197, что совпадает с номером системного вызова.

Объявление C:

extern "C" void * ll_alloc ();

Определение сборки:

_ll_alloc:
  sub rsp, 8
  mov r9, 0
  mov rdi, 0
  mov rax, 197         
  mov rsi, 4096          
  mov r8, -1            
  mov rdx, 0x02 | 0x01
  mov rcx, 0x1000 | 0x0001
  syscall
  add rsp, 8
  ret

Я вызвал mmap напрямую из C, и все работает, как и ожидалось, я позвонил:

void * mem = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_ANON | MAP_SHARED, -1, 0);

1 Ответ

1 голос
/ 22 июня 2019

mov rcx, 0x1000 | 0x0001 не может быть прав: инструкция syscall сама уничтожает RCX (с сохраненным RIP).

В x86-64 Linux соглашение о вызовах для системных вызовов использует R10 для 4-го аргумента вместо RCX в порядке аргументов соглашения о вызовах функций. ( Каковы соглашения о вызовах для системных вызовов UNIX и Linux на i386 и x86-64 )

Я думаю, что OS X делает то же самое (, поэтому mov r10d, 0x1000 | 0x1), но ядру буквально невозможно прочитать то, что было в пользовательском RCX до syscall, так что это определенно не так регистр. См. Также комментарии к 64-битной документации системного вызова для сборки MacOS


Кроме того, x86-64 MacOS использует номера вызовов, отличные от x86-64 Linux. Хотя 197 является правильным согласно https://sigsegv.pl/osx-bsd-syscalls/, который, кажется, составляет приблизительно x86-64. (А 197 не системный номер Linux)

Мне показалось, что я запомнил фактическое значение EAX, для которого требовалось установить больший бит, например 0x2000xyz; может быть, это то, что вам нужно добавить. Обновление: да, Таблица 64-битных системных вызовов macOS объясняет, что добавление 0x2000000 к номеру вызова является правильным.


В общем, для отладки такого рода вещей

Один шаг к вызову библиотеки C mmap вызов для просмотра значений регистров, когда инструкция syscall запускается из зарекомендовавшей себя реализации библиотеки.

Также используйте dtruss (MacOS) или strace в своей рукописной программе asm , чтобы увидеть, что ядро ​​думает, что оно на самом деле делает.

...