模仿实现Linux下readelf工具部分功能
模仿实现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工具部分功能相关推荐
- 详解linux下auto工具制作Makefile源码包(制作篇)
2019独角兽企业重金招聘Python工程师标准>>> 详解linux下auto工具制作Makefile源码包(制作篇) 水木杨 一. 概述 为了更好的制作configure ...
- 实验 Linux下C工具应用
实验报告 实 验(一) 题 目 Linux下C工具应用 专 业 计算机科学与技术 计算机科学与技术学院 目 录 第1章 实验基本信息... - 4 - 1.1 实验目的... - ...
- 万得终端 linux安装,Linux下常用工具
Linux下常用工具: yuv rgba playerubuntu 18.04 wps1 2sudo dpkg -i wps-office_10.1.0.5672~a21_amd64.deb sudo ...
- Linux下抓图工具shutter
Linux下抓图工具shutter 转载于:https://www.cnblogs.com/zhangze/archive/2013/06/07/3123558.html
- 利用Linux下DDOS工具tfn2k进行DDOS攻击试验
"Tribe Flood Network 2000 (TFN2K)是一款分布式拒绝服务(DDOS)的攻击工具.TFN2K是由德国著名黑客Mixter编写的同类攻击工具TFN的后续版本.本文将 ...
- Linux下基本工具及彩色进度条程序
1.vim配置 Vim是从 vi 发展出来的一个功能强大.高度可定制的文本编辑器.代码补全.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和Emacs并列成为类Unix系统用户最喜欢的 ...
- Linux下同步工具inotify+rsync使用详解
1. rsync 1.1 什么是rsync rsync是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.它使用所谓的"Rsync演算法"来使本地和远程两个主机之 ...
- linux 卸载ninja,Linux下数据库管理工具:DbNinja
以前一直在Windows下进行开发,转而使用Linux反而有许多不适应,以前使用Navicate数据库管理工具,但是这个只能在Windows下使用,一直没有找到使用顺手的Linux下可以使用的数据库管 ...
- linux串口工具 kermit,Linux下串口工具kermit的安装使用攻略
终端(计算机显示终端)是用户使用系统的入口,是计算机系统的输入输出设备,终端的发展也经历了字符哑终端.图形终端和网络终端三种形式:而console更强调是控制系统的地方,其使用者主要是管理员,从概念上 ...
最新文章
- 按照这步骤来刷题,两个月你亦能成为王者
- 额外篇 | basemap(上)
- linux空间管理,教你玩转Linux—磁盘管理
- 将COM+ Events进行到底[转]
- Linux学习之01_基础命令介绍
- python中的文件处理_python学习——python中的文件处理
- 经典编程问题之:选择排序、冒泡排序、汉诺塔游戏,均用js代码实现
- 程序关闭是总是出异常解决方法
- remote collaboration on physical tasks 应用
- Vue中如何导入并读取Excel数据
- 区块链零知识证明:Zcash 基础知识普及帖,Zcash 技术分析
- 为啥Hibernate的HQL查询要使用别名呢?
- JavaScript中this的使用(四种情况下this的指向)
- jquery实现回到顶部和回到底部
- 注册时添加学号Idnumber
- mocha-only和skip的用法
- 华为运营商级路由器配置示例 | 配置BGP方式VPLS示例
- 伪全息老婆制作1(Shader入门1)
- 基于FFmpeg 实现RTSP, 音视频编解码,视频流添加文字,音视频合成MP4
- H5游戏开发:一笔画