程序运行之ELF文件的段

更多精彩内容在公众号。

我们将之前的代码增加下变量来具体看下

在代码中增加了全局变量以及静态变量,还有一个简单的函数。

#include <stdio.h>

int global_var=1;

int global_init_var;

void func1(int i){

printf("%d\n",i);

}

int main(void){

static int static_var=8;

static int static_var2;

int a=1;

int b;

func1(static_var+a);

return 0;

}

使用gcc -c来编译这个文件:gcc -c main.c。 -c表示只编译不链接

然后通过objdump -h来查看生成的.o文件。从下面结果看到除了代码段,数据段和BSS段以外,还有.rodata(只读数据段), .comment(注释信息段),.note.GNU-stack(堆栈提示段)。 在File off中标识了每个段的偏移位置。比如.text段的偏移位置是0x40. 代表ELF的header占据的空间为0x00-0x40。.text的起始位置为0x40

main.o:     文件格式 elf64-x86-64

节:

Idx Name          Size      VMA               LMA               File off  Algn

  0 .text         0000004c  0000000000000000  0000000000000000  00000040  2**0

                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE

  1 .data         00000004  0000000000000000  0000000000000000  0000008c  2**2

                  CONTENTS, ALLOC, LOAD, DATA

  2 .bss          00000008  0000000000000000  0000000000000000  00000090  2**2

                  ALLOC

  3 .rodata       00000004  0000000000000000  0000000000000000  00000090  2**0

                  CONTENTS, ALLOC, LOAD, READONLY, DATA

  4 .comment      00000024  0000000000000000  0000000000000000  00000094  2**0

                  CONTENTS, READONLY

  5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000b8  2**0

                  CONTENTS, READONLY

  6 .eh_frame     00000058  0000000000000000  0000000000000000  000000b8  2**3

                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

另外有一个专门的命令size可以查看ELF文件的代码段,数据段和BSS段的长度。hex代表的是三个段的总长度。

root@zhf-maple:/home/zhf/c_prj# size main.o

   text    data     bss     dec     hex filename

168       8       8     180      b4 main.o

在.data段中保存是已经初始化了的全局静态变量和局部静态变量。上面的代码中global_var和static_var就是这样的数据,两个变量都是int类型,各占4个字节。一共刚好8个字节。所以.data这个段的大小为8个字节。

要想查看各个数据段中的具体内容可以通过objdump -s main.o的方式来查看

可以看到.data段中的数据为 01000000 和 08000000 各自占据4个字节,分别对应int global_var=1以及static int static_var=8;

那么为什么不是0x00000001和0x00000008呢,原因在于字节存放的顺序是大端序还是小端序的

大端序:数据的高位字节存放在地址的低端 低位字节存放在地址高端

小端序:数据的高位字节存放在地址的高端 低位字节存放在地址低端

具体的实现参考下面的这个帖子

https://www.cnblogs.com/flysnail/archive/2011/10/25/2223721.html

从上面的数据可以看出这个是小端序的

main.o:     文件格式 elf64-x86-64

Contents of section .text:

 0000 554889e5 4883ec10 897dfc8b 45fc89c6  UH..H....}..E...

 0010 488d3d00 000000b8 00000000 e8000000  H.=.............

 0020 0090c9c3 554889e5 4883ec10 c745fc01  ....UH..H....E..

 0030 000000be 04000000 488d3d00 000000b8  ........H.=.....

 0040 00000000 e8000000 008b1500 0000008b  ................

 0050 45fc01d0 89c7e800 000000b8 00000000  E...............

 0060 c9c3                                 ..              

Contents of section .data:

 0000 01000000 08000000                    ........        

Contents of section .rodata:

  0000 25640a00                             %d..        

Contents of section .comment:

 0000 00474343 3a202855 62756e74 7520372e  .GCC: (Ubuntu 7.

 0010 322e302d 38756275 6e747533 2920372e  2.0-8ubuntu3) 7.

 0020 322e3000                             2.0.            

Contents of section .eh_frame:

 0000 14000000 00000000 017a5200 01781001  .........zR..x..

 0010 1b0c0708 90010000 1c000000 1c000000  ................

 0020 00000000 24000000 00410e10 8602430d  ....$....A....C.

 0030 065f0c07 08000000 1c000000 3c000000  ._..........<...

 0040 00000000 3e000000 00410e10 8602430d  ....>....A....C.

 0050 06790c07 08000000                    .y...... 

另外我们看到在.rodata中也有数据。.rodata中是存储只读数据的。比如const修改的变量。在这里看到.rodata中的数据为%d。 这个是因为我们调用了printf的时候用到了字符串常量%d. 它是一种只读数据。所以被放到了.rodata中。

0000 25640a00                             %d.. 

.bss段存放的是未初始化的全局变量以及局部静态变量。也就是global_init_var和static_var2变量,但是.bss段只有4个字节大小,2个int的变量应该是8个字节才对。我们通过objdump -x main.o来查看符号表。可以看到.bss段中只有static_var2变量,global_init_var并没有在里面。这和编译器有关,global_init_var是一个未定义的COMMON符号,有些编译器会将其放入.bss段中

SYMBOL TABLE:

0000000000000000 l    df *ABS* 0000000000000000 main.c

0000000000000000 l    d  .text 0000000000000000 .text

0000000000000000 l    d  .data 0000000000000000 .data

0000000000000000 l    d  .bss 0000000000000000 .bss

0000000000000000 l    d  .rodata 0000000000000000 .rodata

0000000000000004 l     O .data 0000000000000004 static_var.2256

0000000000000000 l     O .bss 0000000000000004 static_var2.2257

0000000000000000 l    d  .note.GNU-stack 0000000000000000 .note.GNU-stack

0000000000000000 l    d  .eh_frame 0000000000000000 .eh_frame

0000000000000000 l    d  .comment 0000000000000000 .comment

0000000000000000 g     O .data 0000000000000004 global_var

0000000000000004       O *COM* 0000000000000004 global_init_var

0000000000000000 g     F .text 0000000000000024 func1

0000000000000000         *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_

0000000000000000         *UND* 0000000000000000 printf

0000000000000024 g     F .text 0000000000000028 main

除了之前介绍的这些段,ELF文件还有如下的段

.strtab : String Table 字符串表,用于存储 ELF 文件中用到的各种字符串。

.symtab : Symbol Table 符号表,从这里可以所以文件中的各个符号。

.shstrtab : 是各个段的名称表,实际上是由各个段的名字组成的一个字符串数组。

.hash : 符号哈希表。

.line : 调试时的行号表,即源代码行号与编译后指令的对应表。

.dynamic : 动态链接信息。

.debug : 调试信息。

.comment : 存放编译器版本信息,比如 "GCC:(GNU)4.2.0"。

.plt 和 .got : 动态链接的跳转表和全局入口表。

.init 和 .fini : 程序初始化和终结代码段

另外GCC还提供了自定义段,比如你可能希望变量或者某些部分代码能够放到你指定的段中去实现特定的功能,比如满足硬件内存和I/O的地址布局。

我们在全局变量和函数之前加上”__attribute__((section(“name”)))”属性就可以把相应的变量或者函数放到以”name”为段名的段中去。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++入门(一)

目录 命名空间&#xff1a; 为什么要提出命名空间&#xff1f; 命名空间的定义&#xff1a; 命名空间的使用&#xff1a; 加命名空间名称及作用域限定符&#xff1a; 使用using将命名空间中某个成员引入&#xff1a; 使用using namespace命名空间名称引用&#xff1a; C…

【c++】类和对象(四)深入了解拷贝构造函数

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好啊&#xff0c;本篇内容带大家深入了解拷贝构造函数 目录 1.拷贝构造函数1.1传值调用的无限调用1.2浅拷贝1.3深拷贝1.4深拷贝的实现 1.拷贝构造函数 拷贝构造函数是一种特殊的…

yolov5+pyside6+登录+用户管理目标检测可视化源码

一、软件简介 这是基于yolov5目标检测实现的源码&#xff0c;提供了用户登录功能界面&#xff1b; 用户需要输入正确的用户名和密码才可以登录。如果是超级管理员&#xff0c;可以修改普通用户的信息&#xff0c;并且在检测界面的右上角显示【管理用户】按钮。 支持图片、视频、…

访问二维数组本质

先从一维数组讲起 int main() {int arr[5] { 1,2,3,4,5 };for (int i 0; i < 5; i) {printf("%d",arr[i]); //对数组进行访问}return 0; } 其实 arr [ i ] * (arr i) 这两个是完全相等的&#xff0c;在c语言指针&#xff08;1&#xff09;8.数组名与 …

机器人深度学习IMU和图像数据实现焊接精细操作

在双电极气体保护金属弧焊 &#xff08;DE-GMAW&#xff09; 中&#xff0c;对焊枪和旁路电极位置的精确控制是至关重要的。为了这一过程&#xff0c;科研团队提出了安装微型惯性测量单元&#xff08;IMU&#xff09;传感器和摄像头&#xff0c;来记录焊工控制焊枪的移动和微调…

如何配置高质量的告警

运维工程师吐槽起告警问题&#xff0c;人人都是BBKing&#xff01; 每天应对花式告警问题&#xff0c; 无关紧要的、短时急剧爆发的 被疲劳告警淹没的重要告警 和每天崭新的太阳一样&#xff0c; 每次的告警也是独一无二的&#xff01; 想躺平&#xff0c;不可能 下一秒…

01背包(acwing闫氏DP分析法)

题目描述&#xff1a; 有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式&#xff1a…

MATLAB:微分方程(组)数值解

一、显式微分方程 clc,clear tspan [0:10]; y0 2; [t1,y1] ode23(odefun_1,tspan,y0); %求数值解&#xff0c;精度相对低 [t2,y2] ode113(odefun_1,tspan,y0); %求数值解&#xff0c;精度相对高 yt sqrt(tspan1)1; %求精确解 subplot(1,2,1) plot(t1,y1,bo,t2,y2,r*,tspa…

C语言:动态内存管理(malloc,calloc,realloc,free)

目录 前言 malloc函数 free函数 calloc函数 realloc函数 前言 在这一章节将讲解动态内存分配&#xff0c;它可以在程序的堆区创建一块内存&#xff0c;在这块内存中存什么值就是由自己决定的了 开辟的空间有两个特点&#xff1a; 1. 空间开辟的大小是固定的 2. 数组在…

线性数据结构----(数组,链表,栈,队列,哈希表)

线性数据结构 数组链表栈使用场景 队列应用场景 哈希表特点哈希函数&#xff0c;哈希值&#xff0c;哈希冲突键值对 Entry 开放寻址法和拉链法 参考文档 数组 数组(Array) 是一种很常见的数据结构。由相同类型的元素组成&#xff0c;并且是使用一块连续的内存来存储的。 在数组…

python django实战开发序列化器的一个应用心得分享

需求: 查询的时候返回不包括SharePasswd 字段, 但是新增操作需要用到该字段 再不写多个model模型和序列化器的前提下实现 如果您在查询&#xff08;GET 请求&#xff09;时不希望返回 SharePasswd 字段&#xff0c;但在新增&#xff08;POST 请求&#xff09;时需要用到该字段…

Java两地经纬度通过高德api获取两地距离(公里)

代码如下&#xff1a; String startLongitude entity.getLONGITUDE(); // 起点&#xff08;当前位置&#xff09;经度String startLatitude entity.getLATITUDE(); // 起点纬度String endLongitude entity.getLO(); // 终点经度String endLatitude entity.getLA(); …

Spring框架介绍及详细使用

前言 本篇文章将会对spring框架做出一个比较详细的讲解&#xff0c;并且每个知识点基本都会有例子演示&#xff0c;详细记录下了我在学习Spring时所了解到全部知识点。 在了解是什么spring之前&#xff0c;我们要先知道spring框架在开发时&#xff0c;服务器端采用三层架构的方…

ABNDP: Co-optimizing Data Access and Load Balance in Near-Data Processing——论文泛读

ASPLOS 2023 Paper 论文阅读笔记整理 问题 近数据处理&#xff08;NDP&#xff09;是一种很有前途的体系结构范式&#xff0c;可以解决数据密集型应用程序的内存墙挑战。基于3D堆叠存储器的典型NDP系统包含大量并行处理单元&#xff0c;每个并行处理单元都可以访问其本地存储…

HTML基础:8个常见表单元素的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端程序媛。 后台回复“前端工具”可免费获取开发工具&#xff0c;持续更新。 今天来说说 HTML 表单。它是用于收集用户输入信息的元素集合。例如文本框、单选按钮、复选框、下拉列表等。 用户经常填写的表…

2024智能EDM邮件营销系统使用攻略

在数字化营销领域&#xff0c;智能EDM&#xff08;Electronic Direct Mail&#xff09;邮件营销作为一种高效、精准的推广方式&#xff0c;正日益受到企业的高度重视。而要实现这一策略的成功落地&#xff0c;一个高可靠性和高稳定性的专业邮件发送平台则是不可或缺的关键环节。…

大数据分析案例-基于决策树算法构建大学毕业生薪资预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

前端发版上线出现白屏问题

目录 路由配置问题资源缓存问题首屏加载过慢 &#xff1a;喂&#xff0c;你的页面白啦&#xff01; 出现上线白屏的问题有很多&#xff0c;如&#xff1a;配置错误、缓存问题、浏览器兼容问题&#xff0c;根据不同情况去解决。 路由配置问题 问题描述&#xff1a; 在vue开发…

C语言中位运算介绍

在C语言中&#xff0c;位运算是一种对二进制位进行操作的运算方式&#xff0c;它可以对数据的二进制表示进行位级别的操作&#xff0c;包括按位与、按位或、按位异或、按位取反等。位运算常用于处理底层数据结构、优化代码性能以及实现各种算法。本文将深入介绍C语言中的位运算…

两区域二次调频风火机组,麻雀启发式算法改进simulink与matlab联合

区域1结果 区域2结果 红色曲线为优化后结果〔风火机组二次调频〕