Mac OS X 上的 mmap 系统调用有什么问题?
What is wrong with mmap system-call on Mac OS X?
我正在尝试在 Mac OS X 上编写一个简单的应用程序,仅使用系统调用,不使用标准库。
main.c
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define MAP_ANONYMOUS 0x20
#define MAP_PRIVATE 0x02
#define PAGE_SIZE 4096
#define NULL 0
#define STDOUT 1
#define SYSCALL_BASE 0x2000000
#define SYSCALL_GET(num) SYSCALL_BASE + num
long long syscall(long long arg1, long long arg2, long long arg3, long long arg4, long long arg5, long long arg6, long long cn);
void exit(long long status) {
syscall(status, 0, 0, 0, 0, 0, SYSCALL_GET(1));
}
long long write(long long fd, char *buf, long long len) {
return syscall(fd, buf, len, 0, 0, 0, SYSCALL_GET(4));
}
void *mmap(void *addr, long long length, long long prot, long long flags, long long fd, long long offset) {
return syscall(addr, length, prot, flags, fd, offset, SYSCALL_GET(197));
}
long long munmap(void *addr, long long length) {
return syscall(addr, length, 0, 0, 0, 0, SYSCALL_GET(73));
}
int strlen(char *s) {
int len = 0;
while (*(s++) != '[=12=]') {
len++;
}
return len;
}
int putchar(char c) {
return write(STDOUT, &c, 1);
}
int main(int argc, char *argv[]) {
if (argc <= 1) {
return 0;
}
int *lengths = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
for (int i = 1; i < argc; i++) {
lengths[i] = strlen(argv[i]);
}
for (int i = 1; i < argc; i++) {
write(STDOUT, argv[i], lengths[i]);
putchar(' ');
}
putchar('\n');
munmap(lengths, PAGE_SIZE);
return 0;
}
start.s
.global start
.global _syscall
.text
start:
popq %rdi
movq %rsp, %rsi
andq [=13=]xfffffffffffffff0, %rsp
call _main
movq %rax, %rdi
call _exit
_syscall:
movq %rcx, %r10
movq 8(%rsp), %rax
pushq %rbx # alignment
syscall
popq %rbx
retq
如您所见,该应用程序基本上反映了简单echo
。当我 运行 没有参数的程序时,它成功完成,所以我假设 exit
调用有效。但是当我 运行 它带有任何参数时,它会因 Segmentation fault: 11
而崩溃。据我现在的理解,当调用 mmap
时,内核 returns 奇怪的值:9。我认为 9 不是正确的地址,但我无法理解我的错误,因为根据文档,传递给 syscall
的所有值都是正确的。系统调用编号取自 here.
我也想知道
我认为苹果使用 MAP_ANON,这是一个不同的数字。尝试
#define MAP_ANON 0x1000
https://github.com/nneonneo/osx-10.9-opensource/blob/master/xnu-2422.1.72/bsd/sys/mman.h#L150
我正在尝试在 Mac OS X 上编写一个简单的应用程序,仅使用系统调用,不使用标准库。
main.c
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define MAP_ANONYMOUS 0x20
#define MAP_PRIVATE 0x02
#define PAGE_SIZE 4096
#define NULL 0
#define STDOUT 1
#define SYSCALL_BASE 0x2000000
#define SYSCALL_GET(num) SYSCALL_BASE + num
long long syscall(long long arg1, long long arg2, long long arg3, long long arg4, long long arg5, long long arg6, long long cn);
void exit(long long status) {
syscall(status, 0, 0, 0, 0, 0, SYSCALL_GET(1));
}
long long write(long long fd, char *buf, long long len) {
return syscall(fd, buf, len, 0, 0, 0, SYSCALL_GET(4));
}
void *mmap(void *addr, long long length, long long prot, long long flags, long long fd, long long offset) {
return syscall(addr, length, prot, flags, fd, offset, SYSCALL_GET(197));
}
long long munmap(void *addr, long long length) {
return syscall(addr, length, 0, 0, 0, 0, SYSCALL_GET(73));
}
int strlen(char *s) {
int len = 0;
while (*(s++) != '[=12=]') {
len++;
}
return len;
}
int putchar(char c) {
return write(STDOUT, &c, 1);
}
int main(int argc, char *argv[]) {
if (argc <= 1) {
return 0;
}
int *lengths = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
for (int i = 1; i < argc; i++) {
lengths[i] = strlen(argv[i]);
}
for (int i = 1; i < argc; i++) {
write(STDOUT, argv[i], lengths[i]);
putchar(' ');
}
putchar('\n');
munmap(lengths, PAGE_SIZE);
return 0;
}
start.s
.global start
.global _syscall
.text
start:
popq %rdi
movq %rsp, %rsi
andq [=13=]xfffffffffffffff0, %rsp
call _main
movq %rax, %rdi
call _exit
_syscall:
movq %rcx, %r10
movq 8(%rsp), %rax
pushq %rbx # alignment
syscall
popq %rbx
retq
如您所见,该应用程序基本上反映了简单echo
。当我 运行 没有参数的程序时,它成功完成,所以我假设 exit
调用有效。但是当我 运行 它带有任何参数时,它会因 Segmentation fault: 11
而崩溃。据我现在的理解,当调用 mmap
时,内核 returns 奇怪的值:9。我认为 9 不是正确的地址,但我无法理解我的错误,因为根据文档,传递给 syscall
的所有值都是正确的。系统调用编号取自 here.
我也想知道
我认为苹果使用 MAP_ANON,这是一个不同的数字。尝试
#define MAP_ANON 0x1000
https://github.com/nneonneo/osx-10.9-opensource/blob/master/xnu-2422.1.72/bsd/sys/mman.h#L150