我想知道在哪里可以找到os x上的mmap标志值。mmap的手册页上说要使用MAP_PRIVATE,MAP_...等等,但是如果你正在处理汇编,你必须知道实际的值来进行系统调用。我试图寻找定义这些常量的头文件,但找不到。有没有人能把它联系起来?
smdncfj31#
首先要找到正确的文件:两种选择:
mmap
sys/mman.h
ack
ack --hh MAP_PRIVATE /usr/include/ /usr/lib/gcc/x86_64-linux-gnu/5/将只搜索这两个目录下的.h文件(--hh),这是所有系统头文件所在的目录。为了找到你的系统把头文件放在哪里,cpp的输出(没有-dM)包含了current-line-number设置行,告诉你哪些头文件被包含了。例如# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
ack --hh MAP_PRIVATE /usr/include/ /usr/lib/gcc/x86_64-linux-gnu/5/
.h
--hh
-dM
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
如果有任何常量是八进制,比如asm-generic/fcntl.h中的#define O_CREAT 00000100,请注意NASM将0100视为十进制,因此您需要将其更改为0q100或0o100。GNU汇编器在解释整数文字方面与C相匹配,因此您应该能够直接使用宏定义,即使是open()标志。(如果你想使用像S_IRUSR这样的文件权限常量,而不是像普通的汇编语言程序员那样编写八进制常量,那么就可以使用这些常量。:P)
asm-generic/fcntl.h
#define O_CREAT 00000100
0100
0q100
0o100
open()
S_IRUSR
gcc -E -dM在处理结束时只打印 * #define行,其中包含所有宏的最终值,而不是预处理的源代码。-告诉它从标准输入中读取,因此您可以使用echo将代码片段通过管道传输到它。
gcc -E -dM
#define
-
echo
echo '#include <sys/mman.h>' | gcc -E - -dM | less
在less中,您当然可以使用/进行搜索。**您也可以使用&**进行过滤,隐藏与正则表达式不匹配的行。因此,您可以键入&MAP_来获取MAP_ macro定义。在x86-64 GNU/Linux上,我得到:
less
/
&
#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语法。
gcc -c foo.S
.S
typedef unsigned char __u_char;
最适合未来/可移植的方法可能是让您的构建脚本/ Makefile使用gcc -E -dM来创建您需要的系统头文件的本地宏版本。然后你的.S文件可以#include "system_macros/mman.h"等等。
#include "system_macros/mman.h"
但是,请注意MAP_FAILED的((void *) -1)定义:该语法不会汇编,因此这并不总是适用于编写可移植的asm,这些asm在具有相同ABI但具有不同常量和系统调用号的不同系统上工作。对于系统调用号,系统asm/unistd.h通常只有宏,没有原型或typedef。
MAP_FAILED
((void *) -1)
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定义:
$
$foo|bar
sed
.equ
mov r10d, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB
6kkfgxo02#
在gcc中使用-E选项可以让您看到源文件在预处理器之后的输出。在以下源文件中使用gcc -E test.c
-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。然而,并非所有系统都是如此。
MAP_PRIVATE
0x02
2条答案
按热度按时间smdncfj31#
首先要找到正确的文件:两种选择:
mmap
手册页只提到了sys/mman.h
。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
),这是所有系统头文件所在的目录。为了找到你的系统把头文件放在哪里,cpp的输出(没有
-dM
)包含了current-line-number设置行,告诉你哪些头文件被包含了。例如# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
注意NASM的八进制文字
如果有任何常量是八进制,比如
asm-generic/fcntl.h
中的#define O_CREAT 00000100
,请注意NASM将0100
视为十进制,因此您需要将其更改为0q100
或0o100
。GNU汇编器在解释整数文字方面与C相匹配,因此您应该能够直接使用宏定义,即使是
open()
标志。(如果你想使用像S_IRUSR
这样的文件权限常量,而不是像普通的汇编语言程序员那样编写八进制常量,那么就可以使用这些常量。:P)使用C预处理器转储宏值。
gcc -E -dM
在处理结束时只打印 *#define
行,其中包含所有宏的最终值,而不是预处理的源代码。-
告诉它从标准输入中读取,因此您可以使用echo
将代码片段通过管道传输到它。在
less
中,您当然可以使用/
进行搜索。**您也可以使用&
**进行过滤,隐藏与正则表达式不匹配的行。因此,您可以键入&MAP_来获取MAP_ macro定义。在x86-64 GNU/Linux上,我得到:
也许可以在构建系统中使用它,而不是硬编码搜索结果
如果您正在编写一些需要这些宏定义的实际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"
等等。但是,请注意
MAP_FAILED
的((void *) -1)
定义:该语法不会汇编,因此这并不总是适用于编写可移植的asm,这些asm在具有相同ABI但具有不同常量和系统调用号的不同系统上工作。对于系统调用号,系统
asm/unistd.h
通常只有宏,没有原型或typedef。您的asm源代码应该如下所示:
括号是不必要的:一个
$
使整个操作数成为像$foo|bar
一样的立即数。我想你可以把它看作是一个具有最低优先级的运算符。或者对于NASM,使用类似
sed
的东西将cpp宏转换为NASM.equ
定义:6kkfgxo02#
在gcc中使用
-E
选项可以让您看到源文件在预处理器之后的输出。在以下源文件中使用gcc -E test.c
输出
这表明在我的系统中
MAP_PRIVATE
等于0x02
。然而,并非所有系统都是如此。