我正在学习关于x86_64系统上Linux用户空间内存布局,并希望打印一些部分的地址。我使用了以下Rust代码:
fn main() {
let x = 3; // should be stored on stack
let s = "hello"; // should be in the .data section
println!("stack ≈ {:p}", &x);
println!(".text ≈ {:p}", main as *const ());
println!(".data ≈ {:p}", s);
use std::io;
let mut f = std::fs::File::open("/proc/self/maps").unwrap();
let out = io::stdout();
io::copy(&mut f, &mut out.lock()).unwrap();
}
这段代码还会将文件/proc/self/maps
打印到标准输出。我只是使用rustc mem.rs
编译了这个名为mem.rs
的文件。它输出了:
stack ≈ 0x7ffffbf82f2c
.text ≈ 0x7f45b7c0a2b0
.data ≈ 0x7f45b7c4d35b
7f45b6800000-7f45b6c00000 rw-- 00000000 00:00 0
7f45b6de0000-7f45b6f9a000 r-x- 00000000 00:00 664435 /lib/x86_64-linux-gnu/libc-2.19.so
7f45b6f9a000-7f45b6fa2000 ---- 001ba000 00:00 664435 /lib/x86_64-linux-gnu/libc-2.19.so
[ ... more .so files]
7f45b7a22000-7f45b7a23000 r--- 00022000 00:00 663920 /lib/x86_64-linux-gnu/ld-2.19.so
7f45b7a23000-7f45b7a24000 rw-- 00023000 00:00 663920 /lib/x86_64-linux-gnu/ld-2.19.so
7f45b7a24000-7f45b7a25000 rw-- 00000000 00:00 0
7f45b7aa0000-7f45b7aa2000 rw-- 00000000 00:00 0
7f45b7ab0000-7f45b7ab2000 rw-- 00000000 00:00 0
7f45b7ac0000-7f45b7ac1000 rw-- 00000000 00:00 0
7f45b7ad0000-7f45b7ad1000 rw-- 00000000 00:00 0
7f45b7ae0000-7f45b7ae2000 rw-- 00000000 00:00 0
7f45b7c00000-7f45b7c5f000 r-x- 00000000 00:00 1134580 /home/lukas/tmp/mem
7f45b7e5e000-7f45b7e62000 r--- 0005e000 00:00 1134580 /home/lukas/tmp/mem
7f45b7e62000-7f45b7e63000 rw-- 00062000 00:00 1134580 /home/lukas/tmp/mem
7f45b7e63000-7f45b7e64000 rw-- 00000000 00:00 0
7ffffb784000-7ffffb785000 ---- 00000000 00:00 0 [stack]
7ffffb785000-7ffffbf84000 rw-- 00000000 00:00 0
7ffffc263000-7ffffc264000 r-x- 00000000 00:00 0 [vdso]
至少我自己打印的地址似乎与“地图”所说的匹配。但是当我在终端中执行cat /proc/self/maps
时,会得到以下输出:
00400000-0040b000 r-x- 00000000 00:00 107117 /bin/cat
0060a000-0060b000 r--- 0000a000 00:00 107117 /bin/cat
0060b000-0060c000 rw-- 0000b000 00:00 107117 /bin/cat
0071c000-0073d000 rw-- 00000000 00:00 0 [heap]
7f7deb933000-7f7debc30000 r--- 00000000 00:00 758714 /usr/lib/locale/locale-archive
7f7debc30000-7f7debdea000 r-x- 00000000 00:00 664435 /lib/x86_64-linux-gnu/libc-2.19.so
7f7debdea000-7f7debdf2000 ---- 001ba000 00:00 664435 /lib/x86_64-linux-gnu/libc-2.19.so
[ ... more .so files ...]
7f7dec222000-7f7dec223000 r--- 00022000 00:00 663920 /lib/x86_64-linux-gnu/ld-2.19.so
7f7dec223000-7f7dec224000 rw-- 00023000 00:00 663920 /lib/x86_64-linux-gnu/ld-2.19.so
7f7dec224000-7f7dec225000 rw-- 00000000 00:00 0
7f7dec250000-7f7dec252000 rw-- 00000000 00:00 0
7f7dec260000-7f7dec261000 rw-- 00000000 00:00 0
7f7dec270000-7f7dec272000 rw-- 00000000 00:00 0
7ffff09e8000-7ffff11e8000 rw-- 00000000 00:00 0 [stack]
7ffff1689000-7ffff168a000 r-x- 00000000 00:00 0 [vdso]
后面的结果与我所读到的有关此主题的所有内容都匹配:可执行文件的部分被映射在虚拟地址空间的较低端(大约从0x400000开始)。
我在Windows的Linux子系统(基本上是Ubuntu 14.04)中执行和编译了所有内容。我知道,这很新颖,但我相当确定这不是子系统的问题(如果是,请告诉我!)。Rust 1.14很重要(我怀疑),
我还尝试了一个C程序(请原谅我的可能不好的C语言):
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
FILE *test_file;
char buf[4096];
if ((test_file = fopen ("/proc/self/maps", "r")) != NULL) {
while (!feof (test_file)) {
fgets (buf, sizeof (buf), test_file);
puts (buf);
}
}
return 0;
}
它会输出类似于
cat
的内容:00400000-00401000 r-x- 00000000 00:00 1325490 /home/lukas/tmp/a.out
00600000-00601000 r--- 00000000 00:00 1325490 /home/lukas/tmp/a.out
00601000-00602000 rw-- 00001000 00:00 1325490 /home/lukas/tmp/a.out
为什么Rust可执行文件在堆栈附近被映射到大地址?
stack ≈ 0x7ffc2a01636c
;.text ≈ 0x559f58ae4270
;.data ≈ 0x559f58b2735b
。 这与栈并不接近。 - Shepmaster