模仿实现Linux下 readelfreadelfreadelf 工具部分功能

完整实现:

https://github.com/JiaZhengJingXianSheng/ReadELF

ELF 目标文件格式的最前部是 ELF文件头 (ELF Header) ,它包含了描述整个文件的基本属性,比如 ELF 文件版本、目标机器型号、程序入口地址等。紧接是 ELF 文件各个段。其中ELF 文件中与段有关的重要结构就是 段表 (Section Header Table) ,该表描述了ELF 文件包含的所有段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。

linux 下elf的定义存放在 /usr/include/usr/include/usr/include 下, 我们可以用 readelf−hreadelf -hreadelf−h 命令加上文件来查看ELF头文件。

vim /usr/include/elf.h

ELF 的文件头中定义了 ELF 魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF 重定位类型、硬件平台、硬件平台版本,入口地址、程序头入口和长度、段表的位置和长度及段的数量等。

详细请参照: https://mp.weixin.qq.com/s/ZOvHG_ofiU6iWtoSR9bFow

头文件 -h功能

我们拿 ELF 文件头结构跟前面readelf输出的 ELF 文件头信息相比照,可以看到输出的信息与 ELF 文件头中的结构很多都一一对应。有点例外的是 “Elf64_ Ehdr” 中的e_ident这个成员对应了readelf 输出结果中的“Class”、Data”、“Version”、“OS/ABI”和“ABI Version”这5个参数。剩下的参数与“EIf64_ Ehdr”中的成员都一一对应。

细节请参照:https://www.cnblogs.com/jiqingwu/p/elf_explore_2.html

所以我们在c语言实现时,只需要按照结构体定义依次取值,并判断输出。下面提供简单部分代码,完整代码会附在文章开头。其中reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expression)有完全相同的比特位。

     const Elf64_Ehdr *header;header = reinterpret_cast<Elf64_Ehdr *>(programMMap);printf("Magic:\t\t\t\t\t");for (int i = 0; i < 16; ++i){printf("%02x ", header->e_ident[i]);}printf("\n");printf("类型:\t\t\t\t\t");switch (header->e_ident[4]){case 0:printf("无效\n");break;case 1:printf("ELF32\n");break;case 2:printf("Elf64\n");break;default:printf("错误\n");break;}printf("数据存储方式:\t\t\t\t");switch (header->e_ident[5]){case 0:printf("未知格式\n");break;case 1:printf("二进制补码 小端存储\n");break;case 2:printf("二进制补码 大端存储\n");break;default:printf("错误\n");break;}printf("版本:\t\t\t\t\t");printf("%d\n", (int)header->e_ident[8]);//部分代码

段表 -S功能

ELF 文件中有很多各种各样的段,这个段表 (Section Header Table)就是保存这些段的基本属性的结构。段表是 ELF 文件中除了文件头以外最重要的结构,它描述了ELF 的各个段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。也就是说,ELF 文件的段结构就是由段表决定的,编译器、链接器和装载器都是依靠段表来定位和访问各个段的属性的。

lyz@ubuntu:~/Desktop/LinuxHomework1/build$ readelf -S print
There are 31 section headers, starting at offset 0x3978:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.propert NOTE             0000000000000338  000003380000000000000020  0000000000000000   A       0     0     8[ 3] .note.gnu.build-i NOTE             0000000000000358  000003580000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000037c  0000037c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003a0  000003a00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003c8  000003c800000000000000a8  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000470  0000047000000000000000b7  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           0000000000000528  00000528000000000000000e  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000538  000005380000000000000020  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000558  0000055800000000000000c0  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000618  000006180000000000000018  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000020  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001040  000010400000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001060  000010600000000000000185  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         00000000000011e8  000011e8000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000004  0000000000000004  AM       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002004  000020040000000000000044  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         0000000000002048  000020480000000000000108  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003d98  00002d980000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003da0  00002da00000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003da8  00002da80000000000000210  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb8  00002fb80000000000000048  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000010  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004010  000030100000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003010000000000000002a  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB           0000000000000000  000030400000000000000618  0000000000000018          29    46     8[29] .strtab           STRTAB           0000000000000000  000036580000000000000203  0000000000000000           0     0     1[30] .shstrtab         STRTAB           0000000000000000  0000385b000000000000011a  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),l (large), p (processor specific)

我们通过起始地址加上e_shoff来指向我们的段表,并根据具体细节判断输出。

sTable = reinterpret_cast<Elf64_Shdr *>(programMMap + header->e_shoff);

-s 功能

ELF符号表定义如下

接下来我们用段表的段偏移当作索引去找拿出他的symbol_table,并判断是否为 .dynamic和.symtab.dynamic和.symtab.dynamic和.symtab 根据具体对应值输出即可。

详细对应关系在 /usr/include/elf.h/usr/include/elf.h/usr/include/elf.h 宏定义的备注。

细节可参考:https://bbs.pediy.com/thread-255670.htm

参考链接:

https://mp.weixin.qq.com/s/ZOvHG_ofiU6iWtoSR9bFow

https://bbs.pediy.com/thread-255670.htm

https://github.com/cyyzero/readelf

https://www.cnblogs.com/jiqingwu/p/elf_explore_2.html

参考书目:

《程序员的自我修养》 俞甲子、石凡、潘爱民著

模仿实现Linux下readelf工具部分功能相关推荐

  1. 详解linux下auto工具制作Makefile源码包(制作篇)

    2019独角兽企业重金招聘Python工程师标准>>> 详解linux下auto工具制作Makefile源码包(制作篇) 水木杨 一.     概述 为了更好的制作configure ...

  2. 实验 Linux下C工具应用

    实验报告 实 验(一) 题     目 Linux下C工具应用 专       业 计算机科学与技术 计算机科学与技术学院 目  录 第1章 实验基本信息... - 4 - 1.1 实验目的... - ...

  3. 万得终端 linux安装,Linux下常用工具

    Linux下常用工具: yuv rgba playerubuntu 18.04 wps1 2sudo dpkg -i wps-office_10.1.0.5672~a21_amd64.deb sudo ...

  4. Linux下抓图工具shutter

    Linux下抓图工具shutter 转载于:https://www.cnblogs.com/zhangze/archive/2013/06/07/3123558.html

  5. 利用Linux下DDOS工具tfn2k进行DDOS攻击试验

    "Tribe Flood Network 2000 (TFN2K)是一款分布式拒绝服务(DDOS)的攻击工具.TFN2K是由德国著名黑客Mixter编写的同类攻击工具TFN的后续版本.本文将 ...

  6. Linux下基本工具及彩色进度条程序

    1.vim配置 Vim是从 vi 发展出来的一个功能强大.高度可定制的文本编辑器.代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和Emacs并列成为类Unix系统用户最喜欢的 ...

  7. Linux下同步工具inotify+rsync使用详解

    1. rsync 1.1 什么是rsync rsync是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.它使用所谓的"Rsync演算法"来使本地和远程两个主机之 ...

  8. linux 卸载ninja,Linux下数据库管理工具:DbNinja

    以前一直在Windows下进行开发,转而使用Linux反而有许多不适应,以前使用Navicate数据库管理工具,但是这个只能在Windows下使用,一直没有找到使用顺手的Linux下可以使用的数据库管 ...

  9. linux串口工具 kermit,Linux下串口工具kermit的安装使用攻略

    终端(计算机显示终端)是用户使用系统的入口,是计算机系统的输入输出设备,终端的发展也经历了字符哑终端.图形终端和网络终端三种形式:而console更强调是控制系统的地方,其使用者主要是管理员,从概念上 ...

最新文章

  1. 按照这步骤来刷题,两个月你亦能成为王者
  2. 额外篇 | basemap(上)
  3. linux空间管理,教你玩转Linux—磁盘管理
  4. 将COM+ Events进行到底[转]
  5. Linux学习之01_基础命令介绍
  6. python中的文件处理_python学习——python中的文件处理
  7. 经典编程问题之:选择排序、冒泡排序、汉诺塔游戏,均用js代码实现
  8. 程序关闭是总是出异常解决方法
  9. remote collaboration on physical tasks 应用
  10. Vue中如何导入并读取Excel数据
  11. 区块链零知识证明:Zcash 基础知识普及帖,Zcash 技术分析
  12. 为啥Hibernate的HQL查询要使用别名呢?
  13. JavaScript中this的使用(四种情况下this的指向)
  14. jquery实现回到顶部和回到底部
  15. 注册时添加学号Idnumber
  16. mocha-only和skip的用法
  17. 华为运营商级路由器配置示例 | 配置BGP方式VPLS示例
  18. 伪全息老婆制作1(Shader入门1)
  19. 基于FFmpeg 实现RTSP, 音视频编解码,视频流添加文字,音视频合成MP4
  20. H5游戏开发:一笔画

热门文章

  1. 阿里云物联实现不同设备间的通信
  2. 小明学java基础系列——Java 类加载
  3. 一次实战 WIFI 渗透小米4A千兆路由器提权开 telnet
  4. 浏览器是怎么工作的(前端必读)
  5. 13.Django中几大常用模板标签讲解及实战使用 【for循环;if判断;页面跳转;开启关闭自动转义;url携带参数传递;注释】
  6. 我是谁:没有绝对安全的系统
  7. 看东南亚年末双节爆品图鉴,抢占旺季流量
  8. GCC | GCC编译器
  9. Python自学笔记9:实操案例六(千年虫,购物流程)
  10. Calendar类常用方法,获取每月最大天数