Linux 基础io_ELF_虚拟物理地址_动态库加载

news2024/10/26 17:57:34

1.可执行程序格式 ELF

[wws@hcss-ecs-178e myshell]$ ll
total 56
-rw-rw-r-- 1 wws wws    92 Oct 17 19:14 file
-rw-rw-r-- 1 wws wws    82 Oct 12 16:51 makefile
-rw-r--r-- 1 wws wws    90 Oct 17 19:13 myfile
-rwxrwxr-x 1 wws wws 20128 Oct 16 21:02 myshell
-rw-rw-r-- 1 wws wws  7627 Oct 16 21:16 myshell.cc
[wws@hcss-ecs-178e myshell]$ file myshell
myshell: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=285576a85c296a5f746e5570999a6c447128bd52, not stripped
[wws@hcss-ecs-178e myshell]$ size myshell
   text    data     bss     dec     hex filename
   9159     900    3192   13251    33c3 myshell

file 查看文件的基本情况 size查看可执行程序的结构情况,text数据段大小 data初始化数据大小 bss未初始化数据大小  dec10进制总大小 hex16进制总大小 filename名称

前两个部分是系统在加载时用到的,中间黄色部分Section 每一个小框就是一个节 不同的节存储不同的内容 比如

text节

存储程序的机器代码,也就是可执行指令。

data节

存储初始化的全局和静态变量。这些变量在程序启动时会被加载到内存中。

bss节

存储未初始化的全局和静态变量。

...

最后一个部分Section Header Table 它的作用是保存每个节的偏移量和大小...,通过节的偏移量和大小,可以计算出每个节在ELF文件中的范围。

2.重谈地址空间(可执行程序 加载)

我们知道每一个进程都有对应的mm_struct虚拟地址空间,它通过页表与物理内存建立映射关系。每次访问虚拟地址时,系统会通过页表查找相应的物理地址。

现在有几个问题

1.可执行性程序在加载到内存前有地址吗?

在加载到内存之前,可执行程序确实具有地址,但这些地址主要是虚拟地址,而非物理地址。我们在编译时就可以看到地址,但这些地址其实是虚拟地址。

从这张图就可以看出在加载到物理内存前,可执行程序就有程序自己生成的逻辑地址了,之前不说说虚拟地址吗?逻辑地址是什么?逻辑地址=起始地址+偏移量(平坦模式下起始地址==0)知道一条指令的地址+它的长度=下一个指令的地址  逻辑地址在数字层面上就和虚拟地址一样了  只不过在磁盘ELF中一般说逻辑地址 加载到内存时说虚拟地址

2.mm_struct由谁初始化的?

我们知道可执行程序加载到内存前就有虚拟地址,每个节的起始的虚拟地址也知道(节偏移+节大小) 

程序内部进行函数跳转也是用的虚拟地址。

每个节的虚拟地址的范围就是mm_struct中每个区域的起始范围。

3.现在可执行程序加载到内存,虚拟地址空间也通过页表跟内存建立映射关系,接下来CPU怎么开始调度呢?

将 PC 寄存器设置为入口点地址,要从ELF的ELF Header中读取

但这是一个虚拟地址,CPU怎么找对应的物理地址呢?

PC:程序计数器是一个指向下一条将要执行的指令的内存地址的寄存器

EIP:用于指向当前正在执行的指令。保存了下一条要执行的指令的地址,并且在程序执行过程中会自动更新。

MMU硬件:是负责虚拟地址到物理地址转换的硬件模块。

CR3:存储页表的物理地址

现在pc中有第一条指令的虚拟地址,再根据MUU+CR3找到对应的物理地址,再把该物理地址里面的内容(指令+虚拟地址)读入到EIP,最后根据读入的虚拟地址+指令长度=下一个指令的虚拟地址更新PC。形成闭环

所以虚拟地址是CPU 操作系统 编译器 共同协助下的产物。

为什么要有虚拟地址空间?

有了虚拟地址空间,编译器在编址的时候就不用考虑物理内存的情况,直接在平坦模式下从0000开始不断生成地址,完成编译器与操作系统的解耦。

3.重谈区域划分

现在我们知道了mm_struct里面代码段 数据段是根据可执行程序ELF格式中的Section(text节 data节...)的虚拟地址的范围划分的。但里面栈区 堆区 共享区的范围怎么划分的?又怎么对它们进行管理?

其实在mm_struct中有struct vm_area_struct结构体,vm_area_struct是 Linux 内核中用于管理虚拟内存区域的结构体。里面存有该区域的起始位置

struct vm_area_struct {
    struct mm_struct *vm_mm;        // 指向该虚拟内存区域所属的内存管理结构
    unsigned long vm_start;          // 虚拟内存区域的起始地址
    unsigned long vm_end;            // 虚拟内存区域的结束地址
    struct vm_area_struct *vm_next;  // 指向下一个虚拟内存区域的指针
    pgprot_t vm_page_prot;           // 页的保护属性
    unsigned long vm_flags;          // 该虚拟内存区域的标志
    struct file *vm_file;            // 如果是映射文件,该指针指向文件结构
    unsigned long vm_pgoff;          // 在映射文件时的偏移
    // 可能还有其他字段
};

每一个区域都有自己的vm_area_struct,并通过链表的形式相互连接。

4.加载动态库

我们知道动态库也是ELF结构,对里面函数方式进行编址,也是按照基址0+偏移量 进行的。(库名:偏移量 库名会变成地址)

库加载到内存也需要被管理,struct libso 里面记录了加载到内存中的库的信息,引用计数,指针

#include <stddef.h>  // for size_t

// 定义共享库结构体
struct libso {
    char *name;               // 库的名称
    char *path;               // 库的路径
    void *handle;             // 库的句柄
    size_t size;              // 库的大小
    int ref_count;            // 引用计数
    struct libso *next;       // 指向下一个 libso 结构体的指针
};

库映射到mm_struct。知道库在物理内存占据的空间大小,以及物理地址起始位置。通过页表建立映射关系,映射到mm_struct的位置由系统找等大小的虚拟地址空间。并在vm_area_struct的链表中链接自己的vm_area_struct(虚拟地址的起始位置)

所以正文代码中怎么找到库函数呢?

库名:偏移量 库名会变成地址 当系统找到等大的虚拟地址空间分配给库,库就有了虚拟起始地址,此时把库名改成 库的虚拟起始地址 再加上偏移量,就能找到库函数的虚拟地址了。

正文代码段是不能修改的,也就不能把库名该为 库的虚拟起始地址。

其实在ELF中的节有一个是GOT全局偏移表,它里面存放的就是库函数的虚拟地址(库名:偏移量)。

代码区找库函数时是这样写的 call GOT虚拟地址:目标库函数的下标

GOT的虚拟地址在加载到内存前就已经编址好了。通过call GOT虚拟地址:目标库函数的下标 就可以找到目标库函数的虚拟地址需要等系统分配好虚拟地址 才能找到库的虚拟起始地址 进而通过偏移量找到库函数虚拟地址)

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

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

相关文章

005:航空力学基础、无人机操纵、飞机性能

摘要&#xff1a;本文详细介绍无人机稳定性、操控性、飞机性能等概念。 一、飞机的稳定性 概念&#xff1a; 飞机的稳定性&#xff08;安定性&#xff09;&#xff0c;是指在飞机受到扰动后&#xff0c;不经飞行员操纵&#xff0c;能恢复到受扰动前的原始状态&#xff08;即原…

萤石设备视频接入平台EasyCVR私有化视频平台变电站如何实现远程集中监控?

一、方案背景 随着城市经济的发展和电力系统的改造&#xff0c;变电站的数量和规模逐渐增加&#xff0c;对变电站的安全管理和监控需求也越来越高。视频监控系统作为重要的安全管理手段&#xff0c;在变电站中起到了关键的作用。 目前青犀视频研发的萤石设备视频接入平台EasyC…

刷题 - 图论

1 | bfs/dfs | 网格染色 200. 岛屿数量 访问到马上就染色&#xff08;将visited标为 true)auto [cur_x, cur_y] que.front(); 结构化绑定&#xff08;C17&#xff09;也可以不使用 visited数组&#xff0c;直接修改原始数组时间复杂度: O(n * m)&#xff0c;最多将 visited 数…

生信软件39 - GATK最佳实践流程重构,提高17倍分析速度的LUSH流程

1. LUSH流程简介 基因组测序通常用于分子诊断、分期和预后&#xff0c;而大量测序数据在分析时间方面提出了挑战。 对于从FASTQ到VCF的整个流程&#xff0c;LUSH流程在非GVCF和GVCF模式下都大大降低了运行时间&#xff0c;30 X WGS数据耗时不到2 h&#xff0c;从BAM到VCF约需…

力扣143:重排链表

给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示…

【已解决】C# NPOI如何在Excel文本中增加下拉框

前言 上图&#xff01; 解决方法 直接上代码&#xff01;&#xff01;&#xff01;&#xff01;综合了各个大佬的自己修改了一下&#xff01;可以直接规定在任意单元格进行设置。 核心代码方法块 #region Excel增加下拉框/// <summary>/// 增加下拉框选项/// </s…

在 Ubuntu 上安装 OpenCV 3.2.0 的详细指南

以下步骤将指导您如何在 Ubuntu 系统上从源码编译并安装 OpenCV 3.2.0。 步骤 1&#xff1a;更新系统并安装必备工具 首先&#xff0c;更新您的系统并安装编译 OpenCV 所需的基本工具和库。 sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential…

docker 可用镜像服务地址(2024.10.25亲测可用)

1.错误 Error response from daemon: Get “https://registry-1.docker.io/v2/” 原因&#xff1a;镜像服务器地址不可用。 2.可用地址 编辑daemon.json&#xff1a; vi /etc/docker/daemon.json内容修改如下&#xff1a; {"registry-mirrors": ["https://…

C++进阶之路:日期类的实现、const成员(类与对象_中篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

Qt之QCamera的简单使用

文章目录 一、相机操作相关示例1.摄像头操作内容使用示例2.摄像头信息展示使用示例3.摄像头设置切换、预览操作示例 二、相机使用个人操作理解1.相机类支持信息获取2.相机类曝光、焦点、图像处理控制信息获取3.快速启动相机设置&#xff08;各个设备处于理想状态&#xff09; 三…

内网穿透:如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)

内网穿透&#xff1a;如何借助Cloudflare连接没有公网的电脑的远程桌面(RDP)-含详细原理配置说明介绍 前言 远程桌面协议(RDP, Remote Desktop Protocol)可用于远程桌面连接&#xff0c;Windows系统&#xff08;家庭版除外&#xff09;也是支持这种协议的&#xff0c;无需安装…

基础数据结构——队列(链表实现,数组实现)

1.概述 计算机科学中&#xff0c;queue 是以顺序的方式维护的一组数据集合&#xff0c;在一端添加数据&#xff0c;从另一端移除数据。习惯来说&#xff0c;添加的一端称为尾&#xff0c;移除的一端称为头&#xff0c;就如同生活中的排队买商品 接口信息如下 public interfa…

Java如何实现PDF转高质量图片

大家好&#xff0c;我是 V 哥。在Java中&#xff0c;将PDF文件转换为高质量的图片可以使用不同的库&#xff0c;其中最常用的库之一是 Apache PDFBox。通过该库&#xff0c;你可以读取PDF文件&#xff0c;并将每一页转换为图像文件。为了提高图像的质量&#xff0c;你可以指定分…

卷积神经网络评价指标

1.评价指标的作用 1. 性能评估&#xff1a;评价指标提供了一种量化的方式来衡量CNN模型的性能。通过这些指标&#xff0c;我们可以了解模型在特定任务上的表现&#xff0c;比如图像分类、目标检测或图像分割等。 2. 模型比较&#xff1a;不同的模型架构或训练策略可能会产生不…

Pytest-Bdd-Playwright 系列教程(2):支持在多浏览器、多环境中执行测试

Pytest-Bdd-Playwright 系列教程&#xff08;2&#xff09;&#xff1a;支持在多浏览器、多环境中执行测试 前言一、 修改 conftest.py 文件二、创建配置文件三、修改search_steps.py文件四、运行测试 前言 学会本文教程内容后&#xff0c;你将掌握&#xff1a; 通过本文的学…

重构案例:将纯HTML/JS项目迁移到Webpack

我们已经了解了许多关于 Webpack 的知识&#xff0c;但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后&#xff0c;就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构&#xff0c;项目位于 GitH…

深度学习案例:带有一个隐藏层的平面数据分类

该案例来自吴恩达深度学习系列课程一《神经网络和深度学习》第三周编程作业&#xff0c;作业内容是设计带有一个隐藏层的平面数据分类。作业提供的资料包括测试实例&#xff08;testCases.py&#xff09;和任务功能包&#xff08;planar_utils.py&#xff09;&#xff0c;下载请…

Jetpack架构组件_LiveData组件

1.LiveData初识 LiveData:ViewModel管理要展示的数据&#xff08;VM层类似于原MVP中的P层&#xff09;&#xff0c;处理业务逻辑&#xff0c;比如调用服务器的登陆接口业务。通过LiveData观察者模式&#xff0c;只要数据的值发生了改变&#xff0c;就会自动通知VIEW层&#xf…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中&#xff0c;我们…

【Python爬虫系列】_031.Scrapy_模拟登陆中间件

课 程 推 荐我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)教程合集 👈👈…