寻找 mmap 标志值

Looking for mmap flag values

我想知道在哪里可以找到 os x 上的 mmap 标志值。 mmap 的联机帮助页说要使用 MAP_PRIVATE、MAP_... 等等,但是如果您正在处理程序集,则必须知道进行系统调用的实际值。我试图寻找定义这些常量的头文件,但找不到。有人 link 可以 possibly 吗?

在 gcc 中使用 -E 选项可以让您看到预处理器后源文件的输出。在以下源文件上使用 gcc -E test.c

#include <sys/mman.h>

int main() {
        return MAP_PRIVATE;
}

输出

...
# 2 "asdf.c" 2

int main() {

 return 0x02;
}

这表明 MAP_PRIVATE 在我的系统上等于 0x02。然而,并非所有系统都如此。

首先找到正确的文件:两个选项:

  • google 宏,并查看文档以了解它说要包含的 header 内容。例如mmap 手册页仅提及 sys/mman.h.
  • 或者:了解您的系统在哪里保存 header 文件,recursive-grep 在那里。 (或使用 ack, because it knows not to search binary files and is generally good for this sort of thing)。例如在我的 GNU/Linux 系统上,
    ack --hh MAP_PRIVATE /usr/include/ /usr/lib/gcc/x86_64-linux-gnu/5/ 将仅搜索这两个目录下的 .h 个文件 (--hh),这是所有系统 header 所在的目录。

要首先找到系统保留 headers 的位置,cpp 输出(不带 -dM)包括 current-line-number 设置行,告诉您哪些 headers包括在内。例如
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4


使用 C 预处理器转储宏值。

gcc -E -dM 在处理结束时打印 #define 行所有宏的最终值,而不是预处理源。 - 告诉它从 stdin 读取,因此您可以使用 echo.

将代码片段输入其中
echo '#include <sys/mman.h>' | gcc -E - -dM | less

less中当然可以用/搜索。 您还可以使用 & 进行过滤,隐藏与正则表达式不匹配的行。因此,您可以键入 &MAP_ 以仅获取 MAP_ 宏定义。


在 x86-64 GNU/Linux 上,我得到:

#define MAP_32BIT 0x40
#define MAP_TYPE 0x0f
#define MAP_EXECUTABLE 0x01000
#define MAP_FAILED ((void *) -1)
#define MAP_PRIVATE 0x02
...

也许在构建系统中使用它而不是 hard-coding 您的搜索结果

如果您正在编写一些需要这些宏定义的实际 asm 代码,请记住 gcc -c foo.S 在汇编之前通过 C 预处理器运行 .S 文件。但是,sys/mman.h 包含宏定义以外的行(如 typedef unsigned char __u_char;),这些行不是有效的 asm 语法。

最future-proof/可移植的方法可能是您的构建脚本/Makefile 使用gcc -E -dM创建本地macro-only你需要的系统版本headers。然后你的 .S 文件可以 #include "system_macros/mman.h" 等等。

但是,请注意 MAP_FAILED((void *) -1) 定义:该语法不会 assemble,因此这并不总是适用于编写可在不同系统上运行的可移植 asm相同的 ABI 但不同的常量和系统调用编号。

对于系统调用号,系统asm/unistd.h通常只有宏,没有原型或typedef。


你的 asm 源应该是这样的:

# 4th arg (flags) goes in r10 for the syscall ABI, vs. rcx for function calls
mov   $(MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB), %r10d

或者对于 NASM,使用类似 sed 的东西将 cpp 宏转换为 NASM .equ 定义:

mov   r10d,  MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB