linux – 为什么我的Rust可执行文件映射到这样的高地址(靠近堆栈)而不是0x400000?

linux – 为什么我的Rust可执行文件映射到这样的高地址(靠近堆栈)而不是0x400000?,第1张

概述我正在学习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 ≈ 我正在学习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打印到stdout.我用rustc mem.rs编译了这个文件mem.rs.它打印:

stack ≈ 0x7ffffbf82f2c.text ≈ 0x7f45b7c0a2b0.data ≈ 0x7f45b7c4d35b7f45b6800000-7f45b6c00000 rw-- 00000000 00:00 07f45b6de0000-7f45b6f9a000 r-x- 00000000 00:00 664435             /lib/x86_64-linux-gnu/libc-2.19.so7f45b6f9a000-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.so7f45b7a23000-7f45b7a24000 rw-- 00023000 00:00 663920             /lib/x86_64-linux-gnu/ld-2.19.so7f45b7a24000-7f45b7a25000 rw-- 00000000 00:00 07f45b7aa0000-7f45b7aa2000 rw-- 00000000 00:00 07f45b7ab0000-7f45b7ab2000 rw-- 00000000 00:00 07f45b7ac0000-7f45b7ac1000 rw-- 00000000 00:00 07f45b7ad0000-7f45b7ad1000 rw-- 00000000 00:00 07f45b7ae0000-7f45b7ae2000 rw-- 00000000 00:00 07f45b7c00000-7f45b7c5f000 r-x- 00000000 00:00 1134580            /home/lukas/tmp/mem7f45b7e5e000-7f45b7e62000 r--- 0005e000 00:00 1134580            /home/lukas/tmp/mem7f45b7e62000-7f45b7e63000 rw-- 00062000 00:00 1134580            /home/lukas/tmp/mem7f45b7e63000-7f45b7e64000 rw-- 00000000 00:00 07ffffb784000-7ffffb785000 ---- 00000000 00:00 0                  [stack]7ffffb785000-7ffffbf84000 rw-- 00000000 00:00 07ffffc263000-7ffffc264000 r-x- 00000000 00:00 0                  [vdso]

至少我自己打印的地址似乎与地图所说的相符.但是当我在终端中执行cat / proc / self / maps时,我得到了这个输出:

00400000-0040b000 r-x- 00000000 00:00 107117                     /bin/cat0060a000-0060b000 r--- 0000a000 00:00 107117                     /bin/cat0060b000-0060c000 rw-- 0000b000 00:00 107117                     /bin/cat0071c000-0073d000 rw-- 00000000 00:00 0                          [heap]7f7deb933000-7f7debc30000 r--- 00000000 00:00 758714             /usr/lib/locale/locale-archive7f7debc30000-7f7debdea000 r-x- 00000000 00:00 664435             /lib/x86_64-linux-gnu/libc-2.19.so7f7debdea000-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.so7f7dec223000-7f7dec224000 rw-- 00023000 00:00 663920             /lib/x86_64-linux-gnu/ld-2.19.so7f7dec224000-7f7dec225000 rw-- 00000000 00:00 07f7dec250000-7f7dec252000 rw-- 00000000 00:00 07f7dec260000-7f7dec261000 rw-- 00000000 00:00 07f7dec270000-7f7dec272000 rw-- 00000000 00:00 07ffff09e8000-7ffff11e8000 rw-- 00000000 00:00 0                  [stack]7ffff1689000-7ffff168a000 r-x- 00000000 00:00 0                  [vdso]

后一个结果与我读到的关于此主题的所有内容相匹配:可执行文件中的部分映射在虚拟地址空间的下端(从0x400000开始).

我执行并编译了linux子系统windows(基本上是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的东西:

为什么Rust可执行文件映射到堆栈附近的大地址?

00400000-00401000 r-x- 00000000 00:00 1325490 /home/lukas/tmp/a.out0
fn main() {    let x = 3;        // should be stored on stack    let s = "hello";  // should be in the .data section    println!("stack ≈ {:p}",&mut out.lock()).unwrap();}
fn main() { let x = 3; // should be stored on stack let s = "hello"; // should be in the .data section println!("stack ≈ {:p}",&mut out.lock()).unwrap();}00-00601000 r--- 00000000 00:00 1325490 /home/lukas/tmp/a.out
00601000-00602000 rw-- 00001000 00:00 1325490 /home/lukas/tmp/a.out
解决方法 使用rustc -Z print-link-args addr.rs,您可以看到Rust编译器将使用哪个链接器调用.由于当前链接器恰好是cc,我们可以直接为C程序重用这些选项.忽略不重要的参数并逐个删除其他参数,我留下了这个编译器调用:

gcc -fPIC -pIE addr.c -o addr-c

像这样编译C代码产生与Rust编译的可执行文件类似的地址,表明这些选项中的一个或两个可能是罪魁祸首.这会将问题更改为“为什么-fPIC和/或-pIE映射到这样的高地址?”

我发现另一个问题and answer似乎可以说明这一点:

The PIE binary is linked just as a shared library,and so its default load address (the .p_vaddr of the first LOAD segment) is zero. The expectation is that something will relocate this binary away from zero page,and load it at some random address.

在Rust可执行文件上使用readelf -e,我们可以看到第一个LOAD段的虚拟地址为零:

Program headers:  Type           Offset             VirtAddr           PhysAddr                 fileSiz            MemSiz              Flags  Align  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000                 0x000000000005e6b4 0x000000000005e6b4  R E    200000  LOAD           0x000000000005ead0 0x000000000025ead0 0x000000000025ead0                 0x00000000000039d1 0x00000000000049e8  RW     200000

我想这会将问题改为“为什么选择这些随机地址”,但我不确定答案. ^ _ ^预感告诉我ASLR发挥作用.这个other answer似乎证实了这一点:

PIE is to support 07002 in executable files.

ASLR是一种安全技术,可以帮助强化程序以防止某些类型的攻击,因此有意义的是,Rust以其安全的方法,会默认尝试启用此类功能.实际上,地址每次调用都会改变一小部分:

root@97bcff9a925c:/# ./addr | grep 'r-xp' | grep 'addr'5587cea9d000-5587ceafc000 r-xp 00000000 00:21 206                        /addr561d8aae2000-561d8ab41000 r-xp 00000000 00:21 206                        /addr555c30ffd000-555c3105c000 r-xp 00000000 00:21 206                        /addr55db249d5000-55db24a34000 r-xp 00000000 00:21 206                        /addr55e988572000-55e9885d1000 r-xp 00000000 00:21 206                        /addr560400e1b000-560400e7a000 r-xp 00000000 00:21 206                        /addr
总结

以上是内存溢出为你收集整理的linux – 为什么我的Rust可执行文件映射到这样的高地址(靠近堆栈)而不是0x400000?全部内容,希望文章能够帮你解决linux – 为什么我的Rust可执行文件映射到这样的高地址(靠近堆栈)而不是0x400000?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/1026115.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存