当前位置:网站首页>C程序是如何跑起来的01 —— 普通可执行文件的构成
C程序是如何跑起来的01 —— 普通可执行文件的构成
2022-07-31 15:37:00 【Mculover666】
学习目的
- 程序烧到什么地方?
- 程序加载到内存什么地方?
- 程序如何执行?
一、编译环境搭建
ubuntu 20.04使用arm-linux-gnueabihf-gcc 7.5.0。
二、程序源码
main.c:
#include <stdio.h>
#include "calc.h"
int main(int argc, char *argv[])
{
int a, b;
static int local_val = 2;
static int uninit_local_val;
a = add(2, 3);
b = sub(5, 4);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
calc.h:
#ifndef _CALC_H_
#define _CALC_H_
int add(int a, int b);
int sub(int a, int b);
#endif
calc.c:
#include "calc.h"
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
编译:
arm-linux-gnueabihf-gcc main.c calc.c
交叉编译生成 a.out 可执行文件,文件类型是32位ARM平台可执行文件。
三、readelf工具
readelf工具由编译器提供,用来列出关于可执行文件的内容的相关信息。
使用格式如下:
Usage: readelf <option(s)> elf-file(s)
(1)查看可执行文件的头部 信息
-h:用于列出ELF文件的头部信息,包括可执行文件运行的平台、软件版本、程序入口地址,以及program headers、section header等信息;

(2)查看section header
-S:用于列出程序中section的头部信息

四、可执行文件的组成结构
一个可执行文件由一系列section构成,section称为段,包括:代码段text、只读数据段rodata、数据段data、bss段等。

每个section用一个section header描述,包括段名、段的类型、段的起始地址、段的偏移、段的大小等。
将可执行文件的所有section header集合到一起就是section header table,使用readelf 的 -S 参数查看的就是该表。
在程序编译的时候,对C语言代码中定义的函数、变量、未初始化的全局变量进行编译分类,放置在不同的段中:
- 普通代码翻译成二进制放到代码段(text)中
- 常量放在只读数据段(rodata)中
- 初始化的全局变量和静态局部变量放在数据段(data)中
BSS段比较特殊,未初始化的全局变量和静态变量都会放置到bss段中,但因为这些变量的值都是0,没有必要再开辟空间存储,所以在可执行文件中bss段是不占用空间的。
但是BSS段的大小、起始地址、各个变量的地址信息都会分别保存在section header table和符号表symtab中,当程序运行的时候,加载器会根据这些信息在内存中紧挨着数据段之后的空间,为BSS段开辟一片存储空间,为各个变量分配存储空间。
总而言之:BSS段在可执行文件中不占用空间,在程序运行的时候才分配对应的空间。
如果在编译时开启了调试选项,则可执行文件中还会有 .debug section,用来保存可执行文件中每一条二进制指令对应的源码位置信息,根据这些信息,GDB调试器就可以支持源码级的单步调试。
在最后环节,编译器还会在可执行文件中添加一些其它的section,比如 .init section,这些代码来自C语言运行库的一些汇编代码,用来初始化C程序所依赖的环境。

参考资料
边栏推荐
- 外媒所言非虚,苹果降价或许是真的在清库存
- Handling write conflicts under multi-master replication (4) - multi-master replication topology
- MySQL database operations
- JVM parameter analysis Xmx, Xms, Xmn, NewRatio, SurvivorRatio, PermSize, PrintGC "recommended collection"
- R language moves time series data forward or backward (custom lag or lead period): use the lag function in the dplyr package to move the time series data forward by one day (set the parameter n to a p
- Unity 之 图集属性详解和代码示例 -- 拓展一键自动打包图集工具
- 删除 状态良好(恢复分区)的磁盘
- 7. Summary of common interview questions
- Grafana安装后web打开报错
- 11 pinia使用
猜你喜欢

WeChat chat record search in a red envelope

.NET 20周年专访 - 张善友:.NET 技术是如何赋能并改变世界的

【Meetup预告】OpenMLDB+OneFlow:链接特征工程到模型训练,加速机器学习模型开发

TRACE32——基于SNOOPer的变量记录

Synchronized and volatile interview brief summary

TextBlock控件入门基础工具使用用法,取上法入门

Kubernetes原理剖析与实战应用手册,太全了

Grafana安装后web打开报错

Efficient use of RecyclerView Section 1

mongo enters error
随机推荐
做事软件开发-法的重要性所在以及合理结论的认识
外媒所言非虚,苹果降价或许是真的在清库存
BGP综合实验(建立对等体、路由反射器、联邦、路由宣告及聚合)
R language test whether the sample conforms to normality (test whether the sample comes from a normally distributed population): shapiro.test function tests whether the sample conforms to the normal d
数据表插入数据insert into
三、数组
7. Summary of common interview questions
button控件的使用
TRACE32——常用操作
工程水文学试卷
Emmet 语法
org.apache.jasperException(could not initialize class org)
MySQL基础篇【单行函数】
复制延迟案例(3)-单调读
[CUDA study notes] First acquaintance with CUDA
Matlab矩阵基本操作(定义,运算)
多主复制的适用场景(2)-需离线操作的客户端和协作编辑
R language ggplot2 visualization: use the ggmapplot function of the ggpubr package to visualize the MA plot (MA-plot), the font.legend parameter and the font.main parameter to set the title and legend
使用 GraphiQL 可视化 GraphQL 架构
Codeforces Round #796 (Div. 2) (A-D)