【问题标题】:mmap does not return error nor valid pointermmap 不返回错误也不返回有效指针
【发布时间】:2019-06-21 23:22:57
【问题描述】:

我一直在尝试使用 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

我直接从 C 调用 mmap,一切都按预期工作,我调用了:

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

【问题讨论】:

  • 我认为 MacOS 有相当于 Linux strace 的功能,用于跟踪系统调用。使用它来了解您的 syscall 会发生什么。我怀疑 eax=197 是错误的电话号码;我认为 MacOS 系统调用设置了高位。不过,我发现它会让 RAX 保持不变,而不是返回 -ENOSYS,如果这是问题所在,我感到很惊讶。
  • 这是我们正在寻找的行,从 dtruss mmap(0x0, 0x1000, 0x3, 0x1001, 0xFFFFFFFFFFFFFFFF, 0x0) = 0x100783000 0转储
  • 那来自你的工作版本?我的意思是dtruss 你的非工作版本,看看你实际上用 asm 做了什么系统调用。
  • 您为什么操作系统编程?如果这是 macOS,那么您需要实际使用来自 macOS 的系统调用编号和常量,它们与 Linux 编号不同。调用约定也可能不同,但我不确定。
  • @PeterCordes 对不起!不,这不是来自大会的电话。我误解了。我找不到我打的电话。我正在使用来自站点的系统调用:sigsegv.pl/osx-bsd-syscalls。是的,我知道它们与 linux 中使用的不同。

标签: macos assembly x86-64 nasm


【解决方案1】:

mov rcx, 0x1000 | 0x0001 不可能是正确的:syscall instruction 本身会破坏 RCX(使用保存的 RIP)。

在 x86-64 Linux 上,系统调用的调用约定使用 R10 作为第四个参数,而不是函数调用约定 arg 顺序中的 RCX。 (What are the calling conventions for UNIX & Linux system calls on i386 and x86-64)

我认为 OS X 会做同样的事情(所以mov r10d, 0x1000 | 0x1),但内核实际上不可能读取syscall 之前用户空间RCX 中的内容,所以绝对不是那个寄存器。参见64-bit syscall documentation for MacOS assembly上的cmets


此外,x86-64 MacOS 使用的电话号码与 x86-64 Linux 不同。尽管根据https://sigsegv.pl/osx-bsd-syscalls/,197 是正确的,这似乎确实是关于 x86-64。 (而且 197 不是 Linux 系统调用号)

我想我记得需要设置更高位的实际 EAX 值,例如 0x2000xyz;也许这是您需要添加的内容。 更新:是的,macOS 64-bit System Call Table 解释说在电话号码中添加0x2000000 是正确的。


一般要调试这种东西

syscall 指令从已知良好的库实现中运行时,单步调用 C 库 mmap 调用以查看寄存器值。

还可以在您的手写 asm 程序中使用 dtruss (MacOS) 或 strace 以查看内核认为它实际上在做什么。

【讨论】:

  • 我已经进行了更改,但它仍然返回 197。我使用 sigsegv.pl/osx-bsd-syscallsopensource.apple.com/source/xnu/xnu-2782.20.48/bsd/kern/… 作为检查系统调用编号的参考
  • 我无法编辑我的评论,所以我将把解释放在这里。有效!!。我改变了两件事。我将 0x2000000 添加到 197 并使用 r10d 存储第 4 个参数。这个魔法的解释0x2000000。已经在另一个线程中指出这是必要的。链接:stackoverflow.com/a/53905561/6091011
  • @MateuszStompór:嘿,我记得你必须添加的十六进制常数差了一个零。很高兴你能找到参考资料。
猜你喜欢
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2015-04-04
  • 2015-10-05
  • 2014-04-12
  • 2015-12-08
相关资源
最近更新 更多