【OS】Linux Process Memory的探究

【OS】Linux Process Memory的探究

前言

刷B站刷到了南大OS的课程,不得不说酒吧舞的教育水平真滴高,狠狠的看了一些关于进程地址相关的课程。

进程地址空间

1.导言

先导入两个问题:

  • 如下的程序会输出什么?

    #include<stdio.h>
    
    int main() {
         
        printf("%p\n", main);
    }
    
  • 如果生成一个随机指针,什么情况会segmentation fault?

    chat *ptr = random();
    *p;
    

要解决上述两个问题,我们可以向进程空间中尝试了解。

那么,在Linux中,一个进程的地址空间是如何映射的?可以使用什么样的手段去查看某个进程的地址分配呢?

2.手动解决第一个问题

实践是检验真理的唯一标准,我们可以通过编译的方式来查看第一个问题的答案。

  • 动态编译

    gcc -o libc_ main.c
    
  • 静态编译

    gcc --static -o static_ main.c
    
  • 写成一个Makefile

    all: clean static libc
    clean:
    	rm -rf static_ libc_
    static:
    	gcc --static -o static_ main.c
    libc:
    	gcc -o libc_ main.c
    

运行两个程序,静态编译的结果每次都是相同的0x401745,而动态编译出来的结果是0x55ff1b6ff149,并且每次除了后3位不变其他都是会变的。

(之所以动态编译的main函数地址会变,是因为gcc编译的选项默认开启了PIE的保护手段,会将代码段的函数地址给随机化)

3.尝试分析结果

上述的实验结果已经看到了,那么为什么会这样呢?同时0x40开头的地址和0x55开头的地址分别是什么?

这些问题的答案我们不妨使用gdb来调试查看

针对静态编译的文件,进行starti的操作,来到起点函数,随后执行vmmap进行查看

我这里可以执行vmmap是因为安装了gdb的插件pwndbg

image-20230424161815295

可以非常鲜明的看到当前的内存状态。vmmap函数的底层是通过读取/proc/[pid]/maps这个文件来进行内存的查看的,我们直接cat这个文件来看看

image-20230424162150342

通过ps来读取static_这个文件的pid,随后进行maps的查看

我们的main函数地址就在0x401000~0x498000这一段代码段中,具有可执行权限。

main函数的位置打个断点,然后continue到main函数的开始部分,查看maps

image-20230424162449563

我们发现0x4c5000这个具有可读可写的段存放的其实是got表,同时0x4c8000开始的一段heap内存在经历_start函数之后被扩容了

随后就是0x7f开头的地址了,那么这里的vvar、vdso分别是什么呢?

(stack我们知道就是执行函数调用栈的一个内存数据结构)

看玩静态编译的程序后,我们再来看看动态编译的程序!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值