qemu-linux-user ELF vs XCOFF 1

2023-10-30

最后更新2021/12/14

注:以下及以后本系列都是个人对相关技术在此时此刻的理解和研究,会根据学习深入,不断修正,但过去历史文章不见得会被(及时)修改订正,见谅。当然欢迎读者批评指正,本人虚心接受,但什么时候把文章修改正确,不好说。

============================================
qemu-linux-use利用linux binfmt执行机制(或者说代码)实现了对ELF的解析和加载。

判断文件类型的机制是统一的,binfmt提供了两个方案:扩展名和MAGIC魔数。扩展名很简单,文件命名就代表了自身格式,例如exe, com;魔数其实跟文件名扩展名方案没啥大区别,只是将类型放到了文件头,确切来说,是最开始的若干个字节,例如0x1df是xcoff32格式,'ELF’是elf格式。至于为啥有的是hex数,有的是字母?其实,本质上都是hex,只是这个hex对应到ascii码表恰好是有意义的字母而已。起名(魔数)的这些人也不是那么无趣或计算机呆子,自然会想一些有意义的数字以便让后人容易识别。

可以对比一下,扩展名在不打开文件就能看到,放在文件meta data里,文件复制的时候很容易被修改,一般是给“人”看的,不是给计算机用的。如果是魔数,则包含在文件数据之内,更改就不太容易,同样,读取也更麻烦,一般是给计算机处理用的。基于此点,对于二进制文件,魔数会优先于扩展名,或者更看重魔数;而文本文件类的,则更在意扩展名,因为文本文件的直接对象是人,而非计算机。一个普通文件,通常扩展名,魔数兼备,这样就皆大欢喜。如果不方便如此,那就最好采用适合它的直接使用者的一种方案。如果都没有呢?也不是不可以,那就要使用者“强迫”把它作为某种文件类型去解析、打开。

例如shell文件,一般起名xxx.ksh, xxx.sh等等,这就是扩展名方案。同时,也有魔数方案,就是我们熟知又大都不知所以的在shell文件第一行写上:#!/bin/ksh,这个东东其实就是魔数。由于设计者优势,魔数方案的创立者unix大神们总要有特权,先把方便实用的字母表达占据上。这个魔数一语三关:

  1. #! 表示我是个shell脚本
  2. #通常表示后面的是非执行信息,这样程序在解释执行的时候,就能自动跳过,处理方便
  3. /bin/ksh表示了解释本文件的shell是哪个。最终用一个解释器入口,就能自动处理任何shell

由于历史发展久了,shell也烂了大街,现在已经没人注意这个#!魔数了,没有它,其实OS省缺找到了对应的shell,然后执行,也都没啥事,隐含着,计算机帮你设定了省缺shell,省缺执行等等。

对任何可执行文件,Linux采用了统一的读magic和文件头(magic在文件头结构里面)方案,用一个bprm结构,把文件前128字节都读到buf里面,然后根据定义的魔数去判断是否付合,判断相符之后,就会转交给相应挂接的加载、解释程序。qemu中由linux_load/loader_exec()完成判断,然后去call load_xxx_binary()

  • ELF magic:0x7f 0x45 0x4c 0x46 —> 0x7f ‘ELF’
  • xcoff magic: 0x01 0xdf —> 32bit xcoff
  • xcoff magic: 0x01 0xf7 —> 64bit xcoff

====================================
只检查magic就OK么?不,还有更多与ELF有关的参数要验证,都在_check_ident()里面,再次检查magic,类型(用于判断elf,目标cpu版本等等。

    return (ehdr->e_ident[EI_MAG0] == ELFMAG0
            && ehdr->e_ident[EI_MAG1] == ELFMAG1
            && ehdr->e_ident[EI_MAG2] == ELFMAG2
            && ehdr->e_ident[EI_MAG3] == ELFMAG3
            && ehdr->e_ident[EI_CLASS] == ELF_CLASS
            && ehdr->e_ident[EI_DATA] == ELF_DATA
            && ehdr->e_ident[EI_VERSION] == EV_CURRENT);

前4个字节是ELF的Magic Number,固定为7f 45 4c 46。
第5个字节指明ELF文件是32位还是64位的。
第6个字节指明了数据的编码方式,即我们通常说的little endian或是big endian。little endian小端低位字节在前,或者说低位字节在低位地址,比如0x7f454c46,存储顺序就是46 4c 45 7f。big endian大端高位字节在前,就是高位字节在低位地址,比如0x7f454c46,在文件中的存储顺序是7f 45 4c 46。
第7个字节指明了ELF header的版本号,目前值都是1。
第8-16个字节,都填充为0。

xcoff对应检查就比较简单,因为没有大小端标记,其源自AIX,都是大端的;xcoff用了两个magic标记32位还是64位格式,因此也不存在额外检测(到这个阶段,早就定好了是32位还是64位);最后版本,也没有。xcoff有一个类似作用的 f_timdat, f_flags。

f_timdat 是日期和时间戳,但一般都不用,总是0;
f_flags包含的内容比较多,其功能与ELF的ELF_CLASS差别比较大,暂且不分析;

基于这个分析,xcoff没有必要去分析ident(因为没这个结构),因此直接删掉、跳过:elf_check_ident(ehdr)。

由于ELF存在大端和小端两种,因此elf_check_ident被执行了两次,中间由bswap_ehdr做了交换,以便大小端不对而导致判断错误。都删掉!我删除,我快乐,我擅长。

由于bprm结构只预读了文件头128byte,而再下一步,需要分析更多的文件头数据,这些数据可能已经在128byte中,也许不够,要预先读进来,因此需要先计算空间要多大,读进来多少。

同理xcoff也要这么做,但有点不同,很多数据都是在auxiliary head里面,虽然auxiliary长度是变化的,但大概应该在128字节之内,所以计算上要根据filehdr和auxhdr两个结构计算总共需要多少空间。计算方案是(当前全部需求):
filehdr + auxhdr + sectionhdr * number of sections
由于预读的128字节可能已经包括filehdr + auxhdr +,因此做一些判断,还差多少,如果已经够了,那就不用申请空间,如果不够,那就只申请后面section header的空间(filehdr + auxhdr肯定小于128byte的);
其实,我们知道filehdr是20bytes,auxhdr是72bytes(均为32位,64位以后再考虑),因此就不用判断了,直接计算为section header准备空间,并读进来。

顺便说一句,由于有大小端问题,读进来的数据都要先经过swap_xxxs()走一遍,将其中必要的数据进行大小端转换,变得与目标机一致;有s结尾的指更改目的地址的数据,没s的,返回变化后的数据。tls看起来是和32位,64位有关,如果已知32位还是64位并且不想随宿主机自动变化,则可以直接用定义好的。

今天就到这里吧,收工。明天看map memory。

晚上睡不着,又加了会班,多看了两眼,发现此处ELF和XCOFF差别还是很大,例如xcoff没那么多section,map也相对简单一点,大部分为ELF做的map操作都要删掉。其实,代码变化越大,无论增删,都变得复杂了,看来memory map不是一两天能搞定的。再接再厉,自我催眠一下。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

qemu-linux-user ELF vs XCOFF 1 的相关文章

  • Linux 中的无缓冲 I/O

    我正在写入大量的数据 这些数据数周内都不会再次读取 由于我的程序运行 机器上的可用内存量 显示为 空闲 或 顶部 很快下降 我的内存量应用程序使用量不会增加 其他进程使用的内存量也不会增加 这让我相信内存正在被文件系统缓存消耗 因为我不打算
  • 如何在 Linux 中编写文本模式 GUI? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 当我编写脚本 程序时 我经常想弹出一个简单的文本 gui 来提示输入 我该怎么做 例如 来自 Shel
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • sendfile64 只复制约2GB

    我需要使用 sendfile64 复制大约 16GB 的文件 到目前为止我所取得的成就是 include
  • qemu 访客自动化

    我找不到任何文档说明存在可用于在 qemu guest 内部实现自动化操作的 API 例如 我想从主机启动来宾计算机内部的进程 Libvirt 似乎不包含此类功能 注意 无需使用任何虚拟化 API 即可实现自动化 从我的博客文章 http
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何有效截断文件头?

    大家都知道truncate file size 函数 通过截断文件尾部将文件大小更改为给定大小 但是如何做同样的事情 只截断文件的尾部和头部呢 通常 您必须重写整个文件 最简单的方法是跳过前几个字节 将其他所有内容复制到临时文件中 并在完成
  • 添加要在给定命令中运行的 .env 变量

    我有一个 env 文件 其中包含如下变量 HELLO world SOMETHING nothing 前几天我发现了这个很棒的脚本 它将这些变量放入当前会话中 所以当我运行这样的东西时 cat env grep v xargs node t
  • 尝试安装 LESS 时出现“请尝试以 root/管理员身份再次运行此命令”错误

    我正在尝试在我的计算机上安装 LESS 并且已经安装了节点 但是 当我输入 node install g less 时 出现以下错误 并且不知道该怎么办 FPaulMAC bin paul npm install g less npm ER
  • 将 PDF 转换为 600dpi 的 TIFF 和 jpg 96 dpi

    我想使用 ImageMagick 从 Python 脚本将 pdf 转换为 600 dpi 的 tiff 和 96 dpi 的 jpg 我使用 imagemagick 命令行完成了这项任务 但我想使用python中的Imagemagick将
  • NPTL 和 POSIX 线程有什么区别?

    NPTL 和 POSIX 线程之间的基本区别是什么 这两者是如何演变的 POSIX 线程 pthread 不是一个实现 它是几个函数的 API 规范 纸上的标准 英文 其名称以pthread 以及定义在
  • 如何在shell中输出返回码?

    我正在尝试通过调用自定义 shell 脚本sh bin sh c myscript sh gt log txt 2 gt 1 echo 该命令的输出是创建的后台进程的 PID 我想指导 bin sh保存返回码myscript sh到某个文件
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的
  • PHP 无法打开流:是一个目录

    非常简单的 PHP 脚本 我在我亲自设置的 Ubuntu Web 服务器上的 EE 模板中运行 我知道这与权限有关 并且我已经将我尝试写入的目录的所有者更改为 Apache 用户 我得到的错误是 遇到 PHP 错误 严重性 警告 消息 fi
  • SSE:跨页边界的未对齐加载和存储

    我在页面边界旁边执行未对齐加载或存储之前读过某处 例如使用 mm loadu si128 mm storeu si128内在函数 代码应首先检查整个向量 在本例中为 16 个字节 是否属于同一页 如果不属于同一页 则切换到非向量指令 我知道
  • 在我的 index.php 中加载 CSS 和 JS 等资源时出现错误 403

    我使用的是 Linux Elementary OS 并在 opt 中安装了 lampp My CSS and JS won t load When I inspect my page through browser The console
  • 如何通过ssh检查ubuntu服务器上是否存在php和apache

    如何通过ssh检查Ubuntu服务器上apache是 否安装了php和mysql 另外如果安装的话在哪个目录 如果安装了其他软件包 例如 lighttpd 那么它在哪里 确定程序是否已安装的另一种方法是使用which命令 它将显示您正在搜索
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 如何使用 GOPATH 的 Samba 服务器位置?

    我正在尝试将 GOPATH 设置为共享网络文件夹 当我进入 export GOPATH smb path to shared folder I get go GOPATH entry is relative must be absolute

随机推荐

  • 13天带你了解C++ ---DAY5 c++类中的6个默认成员函数

    快起床学习啦 你怎么睡的着哒 目录 1 6个默成员函数介绍 2 构造函数 2 1概念 2 2构造函数举例 2 3易错点 2 4举一反三 类中包含其它类对象 2 5扩展 c 11新特性 在成员变量中赋值 2 6补充 全缺省构造函数 3 析构函
  • 我的创作纪念日(个人感悟)

    昨天2023年5月10日是我成为创作者的第128天纪念日 感谢CSDN官方的纪念信让我铭记这特殊的一天 机缘 要说与CSDN的初次相遇 还是2022年的高考结束完的暑假 当时对于大学的学习没有什么概念 当初的高考志愿报的有计算机相关的专业
  • NameError: name 'islice' is not defined

    加个导包即可 from itertools import islice 这样就运行没有问题了
  • 《计算机网络》——第七章知识点

    防火墙 特殊编程的路由器 实施访问控制策略 分为网络级防火墙 防止网络出现非法入侵 和应用级防火墙 进行应用的访问控制 本次文章详细PDF请点击以下链接查看 https download csdn net download qq 53142
  • Linux中建立TCP网络通信,代码运行异常,[Errno 111] Connection refused

    代码如下 报错信息 原因 直接理解报错的意思就是 链接失败 Linux端作为客户端 Windows端作为服务端 排查服务端的本地地址 发现有误 所以引起链接失败
  • 电脑相机错误0x00f4288_如何解决电脑摄像头打不开问题

    很多人打开QQ视频时发现摄像头打开是全黑的 打开相机拍照也是全黑的 回跳出错误 还会出现代码0xA00F4292
  • Edge浏览器出现无法访问此页面,XXX已拒接链接,请尝试检查代理和防火墙

    针对这种情况有两种办法解决 方案一 针对部分人有效 方案二 针对所有人有效 且从根本上解决问题 如果方案二不成功 把方案一也配置一下 情况如下图所示 www bilibili com 已拒绝连接 请尝试 检查连接 检查代理和防火墙 ERR
  • 数字电路设计之低功耗设计方法五:门控

    Clock gating 在时钟频率加快的同时 有时候会产生不必要的跳转 有的时候输入并没有改变 但是由于时钟的跳转 寄存器的值会被一遍一遍的刷新 可能输入才更改一次 结果时钟已经跳了几万次 这样的差距是可怕的 每次时钟上升沿 输出就要重新
  • 如何实现物料的柔性“强预留”和“弱预留”占用

    一 占料场景 车间实际领料过程中 需要预先对物料进行占用 预先将特定的物料分配至特殊的工单 优先级较高 需要预先占用物料 物料占用存在多种混合的形态 1 承诺优先 已经承诺的需求 优先占用物料 未承诺的需求后占用物料 且后承诺的需求占用物料
  • HC05-ESP8266实现控制LED的闪烁

    蓝牙设备是不可或缺的一部分 在这里我们将用HC05 ESP8266实现控制LED的闪烁 在本篇文章中 将HC 05蓝牙模块与流行的Wi Fi模块ESP8266连接 并通过蓝牙发送命令无线控制LED 该LED可以由继电器和AC设备代替 以构建
  • sort函数源码分析(超详细)

    直接呈现源码 if IS CALLABLE comparefn comparefn function x y if x y return 0 如果x与y取值相同返回0 x与y位置不变 if IsSmi x IsSmi y return Sm
  • 从一个程序中启动和关闭另一个程序

    今天正在编写的程序是一个插件 PlugIn 插件其实就是一个动态链接库 可以被主程序装入内存中 并调用插件中按照主程序规定编写的函数 由于插件受制于主程序 因此我必须另外提供一个程序可以扩展插件的功能 于是乎 我就编写了一个更加复杂的程序来
  • JSTS学习(一) - 简介

    JSTS是一个符合OGC规范的简单要素空间位置判定函数JavaScript库 JSTS也是Java类库JTS的一个接口 且与OpenLayer3具有互操作性 目前原生的OpenLayers3并不支持空间拓扑关系查询 此类库可以作为重要的补充
  • 前端面试题汇总

    前端面试题汇总 一 Html css js 1 Html5新增的语义化标签有哪些 语义化标签的优点 提升可访问性 SEO 结构清晰 利于维护 header页面头部 main页面主要内容 footer页面底部 Nav导航栏 aside侧边栏
  • pyqt5弹出提示框

    弹窗的分类 1 软件关闭提示弹框 2 信息提示弹框 3 错误提示弹框 4 信息警告弹框 5 关于弹窗 模块导入 from PyQt5 QtWidgets import QMessageBox 1 软件关闭弹框 这类的弹框一般是在整个软件关闭
  • Shell脚本入门 03:字符串与数组

    文章目录 目的 字符串 获取字符串长度 拼接字符串 截取字符串 替换字符串 判断与默认值 内嵌文档与内嵌字符串 内嵌文档 Here Document 内嵌字符串 Here String 数组 数组定义与使用 获取数组长度 拼接数组 删除数组
  • UBUNTU20.04配置qt+vtk+pcl+libtorch+cuda+cudnn+tensorrt开发环境

    总目录 1 环境及版本说明 2 下载并安装Qt 3 下载并编译vtk 4 下载并编译PCL依赖库 4 1 metslib 4 2 libpng 4 3 libpcap 5 编译PCL 6 cuda cudnn tensorrt安装与测试 6
  • 关于js导出excel的标题日期问题

    注意 获取日期放入标题和sheet中 不能用空格 否则不好使 var startTime startTime val substring 0 10 var endTime endTime val substring 0 10 var tit
  • STM32系统学习——TIM(基本定时器)

    一 定时器分类 STM32F1 系列中 除了互联型的产品 共有 8 个定时器 分为基本定时器 通用定时器和高级定时器 基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器 只能定时 没有外部 IO 通用定时器 TIM2
  • qemu-linux-user ELF vs XCOFF 1

    最后更新2021 12 14 注 以下及以后本系列都是个人对相关技术在此时此刻的理解和研究 会根据学习深入 不断修正 但过去历史文章不见得会被 及时 修改订正 见谅 当然欢迎读者批评指正 本人虚心接受 但什么时候把文章修改正确 不好说 qe