ELF加载内存

news/2024/9/19 20:55:11/文章来源:https://www.cnblogs.com/lihaoxiang/p/18418022

当一个 ELF(Executable and Linkable Format)文件加载到内存后,它的各个段会根据文件中的描述被映射到内存的不同区域。ELF 文件被广泛用于 Unix/Linux 系统中的可执行文件、共享库和目标文件。典型的 ELF 文件包含多个段(sections),这些段被加载到内存中用于不同的目的,例如代码、数据、堆栈等。

ELF 文件的段(Section)与内存布局

ELF 文件在磁盘上有多个段,这些段在被加载到内存后,操作系统将它们映射到不同的虚拟内存区域。不同的段有不同的功能,它们通常包括代码段、数据段和其他需要加载的内容。

ELF 文件的主要段和内存中的分布

在内存中,ELF 文件通常会被分为以下几个关键段:

  1. .text 段(代码段)

    • 功能:该段存放可执行的程序代码,即编译后的指令。
    • 权限:一般标记为只读和可执行r-x)。
    • 内存位置:通常位于程序映射的最低虚拟地址附近,且通常是页面对齐的(比如 4KB 对齐)。
    • 映射到内存后:该段加载到内存后,系统将其标记为可执行的内存区域,而不会允许写入操作。

    内存布局示意图:

    0x08048000: (低地址)↓.text 段(代码段)存储程序的可执行代码[r-x] (只读 + 可执行)↑
    
  2. .rodata 段(只读数据段)

    • 功能:该段存储程序的只读数据,如字符串常量、全局常量等。
    • 权限:标记为只读r--),防止运行时修改。
    • 内存位置:通常紧随 .text 段之后加载到内存中。

    内存布局示意图:

    0x08049000: ↓.rodata 段(只读数据段)存储只读数据(例如字符串常量)[r--] (只读)↑
    
  3. .data 段(数据段)

    • 功能:该段存储初始化的全局变量和静态变量。
    • 权限:标记为可读和可写rw-),因为这些变量在程序运行过程中可能会被修改。
    • 内存位置:通常位于 .rodata 段之后。

    内存布局示意图:

    0x0804A000: ↓.data 段(数据段)存储初始化的全局变量[rw-] (可读 + 可写)↑
    
  4. .bss 段(未初始化数据段)

    • 功能:该段存储未初始化的全局变量和静态变量。在 ELF 文件中,.bss 段并不占据磁盘空间(只在内存中分配),其大小在 ELF 文件头中描述。
    • 权限:标记为可读和可写rw-),因为这些变量可能会被修改。
    • 内存位置:通常位于 .data 段之后。

    内存布局示意图:

    0x0804B000: ↓.bss 段(未初始化数据段)存储未初始化的全局变量[rw-] (可读 + 可写)↑
    
  5. 堆(Heap)

    • 功能:堆是动态分配内存的区域,用于程序在运行时通过 malloc 等动态分配函数申请的内存。
    • 权限:标记为可读和可写rw-)。
    • 内存位置:堆区域位于 .bss 段之后,通常会随着程序的运行动态增长,操作系统通过系统调用(如 brksbrk)来调整堆的大小。

    内存布局示意图:

    0x0804C000:↓堆动态内存分配区域[rw-] (可读 + 可写)↑
    
  6. 栈(Stack)

    • 功能:栈是用于函数调用时存储局部变量、返回地址等信息的区域。
    • 权限:标记为可读和可写rw-),并具有自动增长的特点(通常栈向下增长)。
    • 内存位置:栈通常位于虚拟地址空间的高地址处,并向低地址方向增长。

    内存布局示意图:

    高地址:↓栈(Stack)[rw-] (可读 + 可写)↑
    

ELF 文件的段加载和布局示意图

内存中 ELF 文件加载后的典型布局示例如下:

内存高地址
+----------------------------+ 
|         栈段 (Stack)        |  ← 栈从高地址向低地址增长
+----------------------------+
|            ...              |
+----------------------------+
|         堆段 (Heap)         |  ← 堆从低地址向高地址增长
+----------------------------+
|         .bss 段             |  ← 未初始化数据
+----------------------------+
|         .data 段            |  ← 已初始化的全局变量
+----------------------------+
|        .rodata 段           |  ← 只读数据
+----------------------------+
|         .text 段            |  ← 可执行代码
+----------------------------+
内存低地址
  • :位于高地址,向低地址方向增长。栈用于存储函数调用的局部变量和返回地址等信息。
  • :位于 .bss 段之后,随着动态内存分配不断增长。堆用于存储运行时动态分配的内存。
  • .bss 段:存储未初始化的全局变量和静态变量。
  • .data 段:存储已初始化的全局变量和静态变量。
  • .rodata 段:存储只读数据(如常量字符串、常量数组等)。
  • .text 段:存储程序的可执行代码。

各个段的权限说明

  • .text 段:只读且可执行,存放程序的指令。
  • .rodata 段:只读,存放只读数据。
  • .data 段:可读可写,存放已初始化的全局变量和静态变量。
  • .bss 段:可读可写,存放未初始化的全局变量和静态变量。
  • :可读可写,用于动态内存分配。
  • :可读可写,用于函数调用时存储局部变量、返回地址等。

段加载的过程

  1. 解析 ELF 文件头:加载器首先读取 ELF 文件头,了解文件的格式、段的数量和位置等信息。

  2. 加载各个段:根据程序头表(Program Header Table)中描述的段信息,加载器将各个段(如 .text.data.bss)从磁盘加载到内存,并设置相应的访问权限。

  3. 内核映射内存区域:操作系统的加载器为 ELF 文件中的各个段分配虚拟地址空间,并通过页表将虚拟地址映射到实际的物理内存。还会为堆和栈分配内存。

  4. 权限设置:根据段的类型和需求,加载器为每个段设置合适的权限。例如,.text 段被标记为可执行但不可写,.data 段可读可写等。

总结

ELF 文件加载到内存后,各个段的分布和权限如下:

  • .text 段:存放可执行代码,通常位于内存低地址,具有只读和可执行权限。
  • .rodata 段:存放只读数据,具有只读权限。
  • .data 段:存放初始化的全局变量,具有读写权限。
  • .bss 段:存放未初始化的全局变量,

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

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

相关文章

Vue3.5中解构props,让父子组件通信更加丝滑

前言 在Vue3.5版本中响应式 Props 解构终于正式转正了,这个功能之前一直是试验性的。这篇文章来带你搞清楚,一个String类型的props经过解构后明明应该是一个常量了,为什么还没丢失响应式呢?本文中使用的Vue版本为欧阳写文章时的最新版Vue3.5.5 关注公众号:【前端欧阳】,给…

【python爬虫案例】利用python爬取豆瓣电影TOP250评分排行数据!

【python爬虫案例】利用python爬取豆瓣电影TOP250评分排行数据,并导出为excel文档一、爬取对象-豆瓣电影TOP250 今天给大家分享一期豆瓣读书TOP排行榜250的python爬虫案例 爬取的目标网址是:https://movie.douban.com/top250咱们以目标为驱动,以兴趣为导向,先来看下爬虫程序…

Ros2 - Moveit2 - DeepGrasp(深度抓握)

MoveIt 深度把握 本教程演示了如何在 MoveIt 任务构造器中使用抓握姿势检测 (GPD)和 Dex-Net 。 GPD(左)和 Dex-Net(右)用于生成拾取圆柱体的抓取姿势。 https://moveit.picknik.ai/main/_images/mtc_gpd_panda.gif 入门 如果您还没有这样做,请确保您已经完成入门指南中…

(装)K8s 总体架构及目录结构

原文:https://www.guoshaohe.com/cloud-computing/kubernetes-source-read/12491. kubernetes 总体架构目前想对kubernetes 1.21 的源码进行一次阅读分析,本篇文章是对k8s的整体架构进行一个大致分析,先要搞清楚每个组件的功能和任务,在根据不同的组件进行深度的源码分析。…

[C++ Daily] calloc 与 malloc

转载 C++ 面试突破 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台 Kind BorglQI的评论

贼好用!五分钟搭建一个美观且易用的导航页面!

Pintree 是一个开源项目,旨在将浏览器书签导出成导航网站。通过简单的几步操作,就可以将书签转换成一个美观且易用的导航页面。大家好,我是 Java陈序员。 今天,给大家介绍一个贼好用的导航网站搭建工具,只需通过几步操作,就能搭建出个性化导航网站!关注微信公众号:【Ja…

26.删除有序数组中的重复项 Golang实现

题目描述:给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以…

Hadoop(十一)HDFS 读写数据流程

HDFS读写数据流程 一、写数据流程1、客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在 2、NameNode返回是否可以上传 3、客户端请求第一个Block上传到哪几个DataNode服务器上 4、NameNode返回3个DataNode节点,分…

产品经理的日常工作

杜工库 声明 欢迎转载,但请保留文章原始出处:) 博客园:https://www.cnblogs.com/chenxiaomeng/ 如出现转载未声明 将追究法律责任~谢谢合作

Hadoop(十一)HDFS 写数据流程

HDFS写数据流程 一、写数据流程1、客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在 2、NameNode返回是否可以上传 3、客户端请求第一个Block上传到哪几个DataNode服务器上 4、NameNode返回3个DataNode节点,分别…

windows定时执行python程序

先写个 bat 脚本,执行 Python 程序 :: 根据实际情况修改 Python 解释器的路径 set PYTHON=D:\python\python.exe set CODE_DIR=D:\code\projectcd /d "%CODE_DIR%" :: 启动 Python 程序 echo Running main.py... %PYTHON% main.py > nohup.log 2>&1echo A…

Prometheus修改数据存储位置

Prometheus修改数据存储位置 Prometheus的数据存储位置可以通过配置文件中的 --storage.tsdb.path 参数来指定。默认情况下,数据存储在Prometheus安装目录下的 data 文件夹中。要修改数据存储位置,可以在Prometheus启动命令中添加或修改该参数。 步骤 1:修改 Prometheus 启动…