【发布时间】:2016-05-23 06:29:30
【问题描述】:
我正在使用系统调用实现 mmap 功能。(由于某些原因,我正在手动实现 mmap。)
但是我得到了返回值 -14(-EFAULT,我用 GDB 进行了检查)这个消息:
WARN Nar::Mmap: Memory allocation failed.
这里是函数:
void *Mmap(void *Address, size_t Length, int Prot, int Flags, int Fd, off_t Offset) {
MmapArgument ma;
ma.Address = (unsigned long)Address;
ma.Length = (unsigned long)Length;
ma.Prot = (unsigned long)Prot;
ma.Flags = (unsigned long)Flags;
ma.Fd = (unsigned long)Fd;
ma.Offset = (unsigned long)Offset;
void *ptr = (void *)CallSystem(SysMmap, (uint64_t)&ma, Unused, Unused, Unused, Unused);
int errCode = (int)ptr;
if(errCode < 0) {
Print("WARN Nar::Mmap: Memory allocation failed.\n");
return NULL;
}
return ptr;
}
我写了一个宏(使用类似 malloc() 函数):
#define Malloc(x) Mmap(0, x, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
我是这样使用的:
Malloc(45);
我查看了手册页。我在 mmap 手册页上找不到有关 EFAULT 的信息,但我在 mmap2 手册页上找到了有关 EFAULT 的信息。
EFAULT 从用户空间获取数据时出现问题。
我认为这意味着将结构传递给系统调用有问题。 但我相信我的结构没有任何问题:
struct MmapArgument {
unsigned long Address;
unsigned long Length;
unsigned long Prot;
unsigned long Flags;
unsigned long Fd;
unsigned long Offset;
};
处理结果值可能有问题? 使用 CallSystem 打开一个文件(不存在)给了我 -2(-ENOENT),这是正确的。
编辑:CallSystem 的完整来源。打开、写入、关闭工作,但 mmap(或 old_mmap)不起作用。 所有的参数都通过了。
section .text
global CallSystem
CallSystem:
mov rax, rdi ;RAX
mov rbx, rsi ;RBX
mov r10, rdx
mov r11, rcx
mov rcx, r10 ;RCX
mov rdx, r11 ;RDX
mov rsi, r8 ;RSI
mov rdi, r9 ;RDI
int 0x80
mov rdx, 0 ;Upper 64bit
ret ;Return
【问题讨论】:
-
发布
CallSystem的源代码。 -
请提供最少但完整的示例代码。此外,删除所有宏(它们是邪恶的,考虑内联函数或常量)和所有不必要的强制转换。然后,如果您使用
mmap()使用strace运行最小示例和等效示例,会发生什么?哦,请选择 C 和 C++ 之一。 -
没有代码可以将
MmapArgument的格式转换为系统调用所期望的格式。这段代码只能靠魔法工作。 -
我看到的另一个重大错误是您使用的是
int 0x80。这不处理 64 位地址,并且由于您的指针参数之一似乎是堆栈上的对象 - 地址将不正确(64 位代码使用无法以 32 位表示的堆栈地址) .在开发 64 位代码时,您确实需要使用syscall而不是int 0x80(这也将涉及将参数重新排列为系统调用)。这可能是int 0x80失败的原因 - 它使用了错误的地址ma -
int 0x80仅使用 64 位寄存器的低 32 位,因此它们被有效截断。sycall使用整个 64 位寄存器。
标签: c++ linux assembly x86-64 system-calls