Mac 64-разрядный syscall


Как выполнить 64-битную версию syscall на Mac в C++.

Мне нужно следующее, чтобы работать:

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

int main() {
  long* addr = (long*) syscall(SYS_mmap, 0, 100, 1 | 2, 2 | 4096, -1, 0);
}

Проблема в том, что addr ниже должен быть 64-разрядным, поскольку это указатель, но он усекает результат до 32-разрядного значения.

Я компилирую с:

g++ ./mmap.cc -o ./mmap 
P.S. Я знаю, что существует функция mmap, выше приведен только пример, мне нужно заставить функцию syscall работать.

P. P. S. проблема в том, что на 64-битных системах syscall должно возвращать 64-битное значение, но в Mac unistd.h определяется как int:

int  syscall(int, ...);

Это ошибка? Системный вызов mmap возвращает корректно void*:

void *  mmap(void *, size_t, int, int, int, off_t) __DARWIN_ALIAS(mmap);

Как на самом деле реализуется mmap?

P. P. P. S.

В Linux он определяется правильно как long:

long syscall(long number, ...);
2 4

2 ответа:

После некоторого поиска я не нашел способа выполнить 64-битные системные вызовы на Mac.

Итак, я реализовал их сам, вы можете найти функции здесь.

Кроме того, если вы используете эти функции, не забудьте добавить 0x2000000 Unix system call class shift к вашим номерам системных вызовов:

int SYS_write = 4;
int STDOUT = 1;
char* str = "Hello world\n";

syscall3(0x2000000 + SYS_write, STDOUT, str, 12);

Функция syscall устарела в OS X, как указал Кен Томасс.

Для вашего конкретного примера, вы должны использовать mmap вместо syscall. Функция mmap реализуется не в терминах функции syscall, а в терминах __mmap:

libsystem_kernel.dylib`mmap:
    0x7fff643fa69e <+87>:  callq  0x7fff643fe998            ; __mmap

Который, в свою очередь, делает фактический syscall и, вероятно, реализован в сборке:

libsystem_kernel.dylib`__mmap:
    0x7fff643fe998 <+0>:  movl   $0x20000c5, %eax          ; imm = 0x20000C5
    0x7fff643fe99d <+5>:  movq   %rcx, %r10
    0x7fff643fe9a0 <+8>:  syscall
    0x7fff643fe9a2 <+10>: jae    0x7fff643fe9ac            ; <+20>