寻找 mmap 标志值

问题描述 投票:0回答:2

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

c assembly x86 x86-64 mmap
2个回答
6
投票

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

  • google 宏,并查看文档以查看它所说的包含哪些标头。例如
    mmap
    手册页仅提及
    sys/mman.h
  • 或者:了解系统保存头文件的位置,以及那里的 recursive-grep。 (或者使用
    ack
    ,因为它知道不搜索二进制文件,并且通常适合此类事情
    )。例如在我的 GNU/Linux 系统上,
    ack --hh MAP_PRIVATE /usr/include/ /usr/lib/gcc/x86_64-linux-gnu/5/
    将仅搜索这两个目录下的
    .h
    文件 (
    --hh
    ),这是所有系统标头所在的位置。

为了找到系统首先保存标题的位置,cpp 输出(不带

-dM
)包含当前行号设置行,告诉您包含了哪些标题。例如
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4


注意 NASM 的八进制文字

如果任何常量采用 八进制 格式,例如

#define O_CREAT 00000100
中的
asm-generic/fcntl.h
,请注意 NASM 将
0100
视为十进制,因此您需要将其更改为
0q100
0o100

GNU 汇编器在整数文字的解释上与 C 匹配,因此即使对于

open()
标志,您也应该能够直接使用宏定义。 (如果您想使用像
S_IRUSR
这样的文件权限常量,而不是像普通汇编语言程序员那样编写八进制常量。:P)

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

gcc -E -dM
在处理结束时打印 only
#define
行以及所有宏的最终值,而不是预处理的源。
-
告诉它从标准输入读取,因此您可以使用
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
...

也许可以在构建系统中使用它,而不是对搜索结果进行硬编码

如果您正在编写一些需要这些宏定义的实际 asm 代码,请记住

gcc -c foo.S
在汇编之前通过 C 预处理器运行
.S
文件。但是,
sys/mman.h
包含宏定义以外的行(如
typedef unsigned char __u_char;
),这些行不是有效的 asm 语法。

最面向未来/可移植的方法可能是让您的构建脚本/Makefile使用

gcc -E -dM
来创建您需要的系统标头的本地仅宏版本。然后您的
.S
文件可以
#include "system_macros/mman.h"
等等。

但是,请注意

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

对于系统调用号,系统

asm/unistd.h
通常只有宏,没有原型或类型定义。


你的asm源代码应该是这样的:

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

括号不是必需的:一个

$
使整个操作数成为立即数,如
$foo|bar
。我想您可以将其视为优先级最低的运算符。

或者对于 NASM,使用类似

sed
的内容将 cpp 宏转换为 NASM
.equ
定义:

mov   r10d,  MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB

4
投票

在 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
。然而,这可能不适用于所有系统。

© www.soinside.com 2019 - 2024. All rights reserved.