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 ответа:
После некоторого поиска я не нашел способа выполнить 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>