musl libc ldso 动态加载研究笔记:02

前言

  • 本篇继续研究 musl libc ldso 的动态加载过程中遇到的关键性的概念:到底要加载ELF 文件的哪些内容到 内存

  • 当前如果遇到 ELF 动态加载,当前系统需要有【文件系统】,并且有较大的内存,因为 ELF 文件是无法直接运行的,首先通过解析 ELF 头部 获取入口函数,把需要载入到内存中的文件内容复制到指定内存区域,然后执行ELF 的入口函数,通常不是 ELF的 main 函数,而是更早的执行函数,如 _start 或者 _dlstart 函数。此时 PC 指针指向 ELF 加载的基地址 + ELF 入口函数。

ELF 加载基地址

  • 一个 ELF 文件,是否可以随意的加载?

当前验证发现: ELF 文件包括我们通常见到的 可以执行的文件,以及 共享库(如 xx.so)。共享库没有连接地址,基址是 0,但入口函数不一定是 0,如果遇到入口函数也是 0 的,需要注意这个 偏移地址 为 0 的入口函数,是否只是个空的符号,无法执行

  • 为何有的 xxx.so 也称作 ELF 文件? 比如 musl libc.so,本身是个 库,但是它 有入口函数,并且可以执行。 当前 musl libc.so 确实如此,通常我们一般区分 执行文件与 库,库不用于执行。但是 musl libc.so 具备执行的功能,就像是我们见到的普通的执行文件,但是它依旧具备普通库的功能,为其他动态编译的应用程序提供共享库。

  • 作为 共享库与可执行 集成在一起的 musl libc.so,基地址:0,入口函数不为0,基地址为0 可以重定位加载,如手动把 libc.so 加载到 0x200000 地址, 那么 libc.so 的入口函数就是: 0x200000 + libc.so 入口地址

  • 普通静态或者动态链接的ELF 文件,由于基地址 不为0,就无法手动加载到 随意的地址。

  • 如下 ELF 文件:基地址 0x200000,这个基地址跟链接脚本中的链接地址有关系,可以查看这个 elf 的连接脚本配置

  • 入口点:入口地址,这个地址 已经是基于基地址 0x200000的,所以这个地址就不能随机加载了。如果想改变 这个 elf 的基地址,需要更改 相应的 链接脚本 链接地址的设置

在这里插入图片描述

动态加载需要加载哪些 ELF 内容到内存

  • 有的 ELF 文件特别的大,尤其是开启了 【DEBUG】的,比如编译时使用 -O0 -g, gdb 的调试信息都加入 ELF 文件了, ELF 文件不同于单片机的烧写文件 bin 文件,里面还有一些内容,如调试信息,是不需要加载到内存的,那么到底需要加载什么内容呢?

  • 这部分可以查看 Linux 内核代码 elf 加载部分,如 linux-6.3.8/fs/binfmt_elf.c 中的 load_elf_binary

  • Linux 系统由于默认支持 mmu,执行文件的 mmap 映射,所以没有文件没有使用常规的 内存分配,不过依旧是先把文件内容映射 到用户地址空间,之所以不填充,是因为 Linux文件mmap 有缺页异常机制,需要访问时才会真正载入文件内容到内存,这样有很多好处,开始只映射(占位子)不加载,这样节省了加载时间,一个 ELF 文件,不可能上来全部执行到,可能只会执行部分内容,这样采用 访问时再加载,将会节省数量可观的内存,节省大量的加载时间。加上文件 mmap 有 cache 功能,如果加载过后,缓存暂时不清掉,这样下次执行就不再重复加载了。Linux 这个文件mmap 映射加载机制,对于 ELF 加载非常的有用。

  • 经过熟悉 Linux 的 load_elf_binary ,发现只需要 加载 PT_LOAD

  • 那么 ELF 的 PT_LOAD 段,真的覆盖 ELF 的所有需要加载到内存中的内容范围吗?有没有漏下的?或者说 elf 不是还有 重定位、符号、.text.data、等等吗?这些包含在里面吗?

  • 通过 elf 查看工具,加上对实际加载到内存的内容进行反向 dump 出来,肯定的一点就是: ELF 的 PT_LOAD 段 包含了所有需要加载到内存的文件内容,是所有,如果在其他的系统上,发现动态加载后, 内存中的文件内容不正确,或者部分内容为0,需要查看文件加载部分是否有处理不当的地方。

查看 PT_LOAD

  • 可以使用 Die 这个工具,查看 ELF文件

在这里插入图片描述

  • 这里了解到, PT_LOAD 段 第一个段 文件偏移是 0,也就是把 ELF 文件头部也加入了内存

  • 两个 PT_LOAD 段 的大小:Program 中的 p_filesz 就是当前的段大小,总大小: 0x23528 + 0x9f8 = 0x23f20,之所以这么计算,是因为 当前的两个段 是连在一起的。

  • 由于段有多个节(section),可以查看 节 信息,

在这里插入图片描述

  • 通过 计算 PT_LOAD 段的总大小,知道 这个 elf 文件 前面 0 ~ (0x23f20 -1) ,也就是 0x23f20 个字节已经加载到内存,剩下 的节,.bss 没有实际内容,但内存中需要留位置,并且清 0。其他的节全部是 调试信息 debug 相关的。

  • 所以通过加载 PT_LOAD 段,确实实现了整个 ELF 必需文件内容的全部加载

加载大小

  • 这里需要提一下:段的加载大小,不是 段的 p_filesz,而是 段的 p_memsz, p_memsz 一般等于或者大于 p_filesz,超出的大小,就是 .bss section 的大小,这部分大小需要手动清零,不清零,可能引发程序启动后的异常,比如定义了一个变量,但是没有初始化就使用,而程序员默认没有初始化的变量会被初始化 为 0。 清零 .bss 就是清零 PT_LOAD 段 中 p_memsz - p_filesz 大小的区域,这个区域的起始地址应该是: base +elf_ppnt->p_vaddr + elf_ppnt->p_filesz,如果是静态连接编译的 elf 程序, base 是0,也就是 elf_ppnt->p_vaddr + elf_ppnt->p_fileszelf_ppnt->p_vaddr 是这个文件段的起始地址。

  • 这里需要提一下: 段的 p_offset,这个是相对文件本身的偏移,通过情况下, p_offsetp_vaddr 是相同的,但也有不相同的。所以在文件填充时,需要把 文件内容 偏移 p_offset 后,读取到内存地址 p_vaddr 的位置,也就是说: 文件内容的存放位置 与 文件映射到内存的地址,并非一一对应。

在这里插入图片描述

小结

  • 本篇注意讲解一下 ELF文件在 动态加载时需要加载哪些内容到内存,注意这里的动态加载,是动态加载 ELF 文件,这个 ELF文件,不单是 动态编译链接的 ELF,也包括静态编译链接的 ELF 以及 经常遇到的 动态共享库 (xx.so)

  • 需要熟悉 ELF 的 头部、Program Header、了解 各个 Segment 段,了解 Section 节信息,这样对理解 动态加载程序,熟悉 动态加载非常有用。

  • 需要了解操作系统的进程、线程机制,文件映射 mmap 机制。注意需要反复确认 内存的文件内容是否正确、完整。可以同 dump 的方式,把内存中的文件内容 dump 成一个文件,然后与实际的文件进行内容对比。

  • 需要深刻了解 文件段的本身的偏移 :p_offset 与 内存地址 p_vaddr 的关系,也需要了解 段真实文件大小 p_filesz 与 p_memsz 的关系,也就是 .bss 节的存在

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

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

相关文章

IDEA两种方法修改生成的jar包名字

方法一&#xff1a; 直接修改pom文件中的如下部分 <artifactId>excelreport</artifactId> <version>0.0.1-SNAPSHOT</version> <name>excelreport</name> <description>excelreport</description> 修改完成后&#xff0c;点…

SpringBoot3集成Kafka

标签&#xff1a;Kafka3.Kafka-eagle3&#xff1b; 一、简介 Kafka是一个开源的分布式事件流平台&#xff0c;常被用于高性能数据管道、流分析、数据集成和关键任务应用&#xff0c;基于Zookeeper协调的处理平台&#xff0c;也是一种消息系统&#xff0c;具有更好的吞吐量、内…

跟着美团学设计模式(感处)

读了着篇文章之后发现真的是&#xff0c;你的思想&#xff0c;你的思维是真的比比你拥有什么技术要强的。 注 开闭原则 开闭原则&#xff08;Open-Closed Principle&#xff09;是面向对象设计中的基本原则之一&#xff0c;它的定义是&#xff1a;一个软件实体应该对扩展开放…

python爬虫7:实战1

python爬虫7&#xff1a;实战1 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

carla中lka实现(二)

前言&#xff1a; 首先计算之前检测出来的车道线的中线与输入图像的中线进行计算距离&#xff0c;&#xff0c;并设置不同的阈值对于不同的方向进行相关的调整。 一、车辆中心线 一般而言将摄像头架设在车辆的正中心轴上&#xff0c;所获得的图像的中间线极为车辆的中心。 …

QGraphicsView 实例3地图浏览器

主要介绍Graphics View框架&#xff0c;实现地图的浏览、放大、缩小&#xff0c;以及显示各个位置的视图、场景和地图坐标 效果图: mapwidget.h #ifndef MAPWIDGET_H #define MAPWIDGET_H #include <QLabel> #include <QMouseEvent> #include <QGraphicsView&…

WSL2 ubuntu子系统OpenCV调用本机摄像头的RTSP视频流做开发测试

文章目录 前言一、Ubuntu安装opencv库二、启动 Windows 本机的 RTSP 视频流下载解压 EasyDarwin查看本机摄像头设备开始推流 三、在ubuntu 终端编写代码创建目录及文件创建CMakeLists.txt文件启动 cmake 配置并构建 四、结果展示启动图形界面在图形界面打开终端找到 rtsp_demo运…

linux系统服务学习(二)linux下yum源配置实战

文章目录 Linux下yum源配置实战一、Linux下软件包的管理1、软件安装方式2、源码安装的配置过程3、详解源码安装的配置过程&#xff08;定制&#xff09;4、详解编译过程5、安装过程6、axel多线程下载软件源码安装7、使用软链接解决command not found8、使用环境变量解决command…

软考A计划-系统集成项目管理工程师-收尾管理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

中间件(二)dubbo负载均衡介绍

一、负载均衡概述 支持轮询、随机、一致性hash和最小活跃数等。 1、轮询 ① sequences&#xff1a;内部的序列计数器 ② 服务器接口方法权重一样&#xff1a;&#xff08;sequences1&#xff09;%服务器的数量&#xff08;决定调用&#xff09;哪个服务器的服务。 ③ 服务器…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…

Spring中Bean的生命周期以及Bean的单例与多例模式

一. Bean的生命周期 bean的生命周期可以表达为&#xff1a;bean的定义➡bean的初始化➡bean的使用➡bean的销毁 Bean的初始化过程 1&#xff09;通过XML、Java annotation&#xff08;注解&#xff09;以及Java Configuration&#xff08;配置类&#xff09; 等方式加载Bea…

2023+HuggingGPT: Solving AI Tasks with ChatGPT and itsFriends in Hugging Face

摘要&#xff1a; 语言是llm(例如ChatGPT)连接众多AI模型(例如hugs Face)的接口&#xff0c;用于解决复杂的AI任务。在这个概念中&#xff0c;llms作为一个控制器&#xff0c;管理和组织专家模型的合作。LLM首先根据用户请求规划任务列表&#xff0c;然后为每个任务分配专家模…

Unity 鼠标实现对物体的移动、缩放、旋转

文章目录 1. 代码2. 测试场景 1. 代码 using UnityEngine;public class ObjectManipulation : MonoBehaviour {// 缩放比例限制public float MinScale 0.2f;public float MaxScale 3.0f;// 缩放速率private float scaleRate 1f;// 新尺寸private float newScale;// 射线pri…

【Windows系统编程】03.远线程注入ShellCode

shellcode&#xff1a;本质上也是一段普通的代码&#xff0c;只不过特殊的编程手法&#xff0c;可以在任意环境下&#xff0c;不依赖于原有的依赖库执行。 远程线程 #include <iostream> #include <windows.h> #include <TlHelp32.h>int main(){HANDLE hPr…

Educational Codeforces Round 153 (Rated for Div. 2)ABC

Educational Codeforces Round 153 (Rated for Div. 2) 目录 A. Not a Substring题目大意思路核心代码 B. Fancy Coins题目大意思想核心代码 C. Game on Permutation题目大意思想核心代码 A. Not a Substring 题目大意 给定一个只包含“&#xff08;”和“&#xff09;”这两…

react-native-webview RN和html双向通信

rn登录后得到的token需要传递给网页&#xff0c;js获取到的浏览器信息需要传递给rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

iPhone删除的照片能恢复吗?不小心误删了照片怎么找回?

iPhone最近删除清空了照片还能恢复吗&#xff1f;大家都知道&#xff0c;照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活&#xff0c;也留住了我们的美好瞬间&#xff0c;具有极其重要的纪念价值。 照片不小心误删是一件非常难受的事&#xff0c;那么iP…

Centos7 配置Docker镜像加速器

docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六):docker 网络及数据卷设置 docker实战(七):docker 性质及版本选择 认知升…

CentOS系统环境搭建(五)——Centos7安装maven

centos系统环境搭建专栏&#x1f517;点击跳转 Centos7安装maven 下载压缩包 maven下载官网 解压 压缩包放置到/usr/local tar -xvf apache-maven-3.9.2-bin.tar.gz配置环境变量 vim /etc/profile在最下面追加 MAVEN_HOME/usr/local/apache-maven-3.9.2 export PATH${MAV…