程序编译链接的过程

让我们通过一个简单的C程序来进行分析。

  1. 原始demo如下
#include<stdio.h>
//int  printf(const char* format, ...);
extern int gdata10;
extern int sum(int,int);
int gdata1 = 84;
int gdata2 = 0;
int gdata3;
static int gdata4 = 11;
static int gdata5 = 0;
static int gdata6;

int main(){
    int a =1;
    int b =0;
    int c;
    sum(a,b);    
    static int static_var =85;
    static int static_var1 =0;
    static int static_var2;
    getchar();
    return 0;
}

程序就是指令加数据。
操作系统将程序加载到内存中,产生进程。
对于每个程序,操作系统会分配虚拟地址空间(32位系统虚拟内存大小为2的32次方)
2. 程序的内存分布
如下图所示
内存空间分为用户空间(3G)和内核空间(1G)
从0地址开始的128字节不可访问
栈的增长方向是从高到低
在这里插入图片描述
3. 编译
编译期间做的工作:代码优化,汇总所有的符号
符号:数据产生符号,指令产生函数名符号

ELF文件的组成
文件头加各个段组成
文件头:
记录段表的起始位置为208,即d0.
段表里面记录了各个段的起始位置和偏移。在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

通过objdump -t 打印符号表的内容(obj文件还未进行虚拟地址空间的分配)
在这里插入图片描述
引用外部变量和函数
对于外部引用的变量和函数,符号表的状态均为UND(undefine)。需要在链接期进行符号解析, 对符号引用的地方都要找到该符号对应的地方
在这里插入图片描述
在这里插入图片描述

  1. 链接
    链接做的工作:
    将所有相同属性的段进行合并,并调整段偏移和段长度,合并符号表,并进行符号解析
    链接的核心就是符号的重定位
    链接完成后完成虚拟内存的地址分配
    在这里插入图片描述
    通过查看汇编信息,我们可以看到sum和gdata均设置为有效地址
    在这里插入图片描述
    可执行文件和obj文件的区别
    在这里插入图片描述
    可执行文件以页面方式进行组织
    相比obj文件,多一个program header段,用于指示操作系统将哪些东西加载到内存里面去
    52+ 32*3
    在这里插入图片描述
    load2个页面。
    在这里插入图片描述
    虚拟地址空间和物理地址都是按照页面进行组织。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值