当前位置: 首页 > article >正文

SOC Boot学习(一)——ELF文件

01 ELF Header组成

纯手搓C++实现读取ELF文件头信息、段表信息和节表信息_c代码实现解析elf文件-CSDN博客

  • elf header
  • programm header table
  • section header table
  • section

02 read elf

#include <iostream>
using namespace std;

using ELF64_Addr = uint64_t;
using ELF64_Off = uint64_t;
using ELF64_Half = uint16_t;
using ELF64_Word = uint32_t;
using ELF64_Sword = int32_t;
using ELF64_Xword = uint64_t;
using ELF64_Sxword = int64_t;

/* 
e_ident[16]
包含了Maigc Number用于表明这是一个ELF文件,共16字节。	
0~3:前4字节为Magic Number,固定为、'\\0x7f' 'E' 'L' 'F'。
4(EI_CLASS):00为非法文件,01位32位,02为64位。
5(EI_DATA):00为非法数据编码,01为小端序,02为大端序。
6(EI_VERSION):文件版本,固定为01。
7(EI_OSABI):操作系统ABI标识(实际未使用)。
8(EI_ABIVERSION):ABI版本(实际 未使用)。
9~15:对齐填充,无实际意义。
*/

typedef struct {
    unsigned char e_ident[16]; 

    ELF64_Half e_type;  // 可重定位、可执行、共享目标文件
    ELF64_Half e_machine; // CPU架构
    ELF64_Word e_version;
    ELF64_Addr e_entry;
    ELF64_Off e_phoff;
    ELF64_Off e_shoff;
    ELF64_Word e_flags;
    ELF64_Half e_ehsize;
    ELF64_Half e_phentsize;
    ELF64_Half e_phnum;
    ELF64_Half e_shentsize;
    ELF64_Half e_shnum;
    ELF64_Half e_shstrndx;
} ELF64_Ehdr;

typedef struct {
    ELF64_Half p_type;
    ELF64_Half p_flags;
    ELF64_Off p_offset;
    ELF64_Half p_offset;
    ELF64_Addr p_vaddr;
    ELF64_Addr p_paddr;
    ELF64_Xword p_filesz;
    ELF64_Xword p_memsz;
    ELF64_Xword p_align;
} ELF64_Phdr;

typedef struct {
    ELF64_Word sh_name;
    ELF64_Word sh_type;
    ELF64_Xword sh_flags;
    ELF64_Addr sh_addr;
    ELF64_Off sh_offset;
    ELF64_Xword sh_size;
    ELF64_Word sh_link;
    ELF64_Word sh_info;
    ELF64_Xword sh_addralign;
    ELF64_Xword sh_entsize;
} ELF64_Shdr;

int main() {
    char filename[10010];

    cin >> filename;
    FILE *fp = fopen(filename, "r");

    if (fp == NULL) {
        cout << "fail to open file" << endl;
        exit(0);
    }

    ELF64_Ehdr elf_head;
    int shnum, status;

    status = fread(&elf_head, sizeof(ELF64_Ehdr), 1, fp);

    if (status == 0) {
        cout << "fail to read elf header" << endl;
        exit(0);
    }

    if (elf_head.e_ident[0] != 0x7f ||
        elf_head.e_ident[1] != 'E' ||
        elf_head.e_ident[2] != 'L' ||
        elf_head.e_ident[3] != 'F') {
        
        cout << "not a elf file" << endl;
        exit(0);
    }

    printf("程序入口(start标签位置) %#x\\n\\n",elf_head.e_entry);
 
    printf("Program header table文件中偏移 %#x\\n",elf_head.e_phoff);
    printf("Program header table大小 %#x\\n",elf_head.e_phentsize*elf_head.e_phnum);
    printf("Program header数量 %d\\n\\n",elf_head.e_phnum);
 
    printf("Section header table文件中偏移 %#x\\n",elf_head.e_shoff);
    printf("Section header table大小 %#x\\n",elf_head.e_shentsize*elf_head.e_shnum);
    printf("Section header数量 %d\\n\\n",elf_head.e_shnum);
 
    // 解析Segment Header
 
    // 制作Segment Header数组用来存储每一个Segment Header
    ELF64_Phdr *phdr = (ELF64_Phdr*)malloc(sizeof(ELF64_Phdr) * elf_head.e_phnum);
	if (NULL == phdr)
	{
		printf("phdr malloc failed\\n");
		exit(0);
	}
 
    // 设置文件偏移量,定位到e_phoff
	status = fseek(fp, elf_head.e_phoff, SEEK_SET);
	if (0 != status)
	{
		printf("\\nfaile to fseek\\n");
		exit(0);
	}
 
	// 读取所有Segment Header 到 phdr, 大小为sizeof(Elf64_Phdr) * 数量
	status = fread(phdr, sizeof(ELF64_Phdr) * elf_head.e_phnum, 1, fp);
	if (0 == status)
	{
		printf("\\nfail to read segment\\n");
		exit(0);
	}
 
    // 重置指针位置到文件流开头
	rewind(fp);
 
    // 遍历每一个Segment Header
	for (int i = 0; i < elf_head.e_phnum; i++)
	{
		printf("段首的偏移: %#x\\n", phdr[i].p_offset);
		printf("段在文件中的大小: %#x\\n", phdr[i].p_filesz);
        printf("段的运行时虚拟内存地址: %#x\\n", phdr[i].p_vaddr);
        printf("段在内存中的大小: %#x\\n", phdr[i].p_memsz);
        printf("\\n");
	}
 
	
    // 解析Section Header
	// 制作Section Header数组用来存储每一个Section Header
	ELF64_Shdr *shdr = (ELF64_Shdr*)malloc(sizeof(ELF64_Shdr) * elf_head.e_shnum);
	if (NULL == shdr)
	{
		printf("shdr malloc failed\\n");
		exit(0);
	}
 
	// 设置文件偏移量,定位到e_shoff
	status = fseek(fp, elf_head.e_shoff, SEEK_SET);
	if (0 != status)
	{
		printf("\\nfaile to fseek\\n");
		exit(0);
	}
 
	// 读取所有Segment Header 到 phdr, 大小为sizeof(Elf64_Phdr) * 数量
	status = fread(shdr, sizeof(ELF64_Shdr) * elf_head.e_shnum, 1, fp);
	if (0 == status)
	{
		printf("\\nfail to read section\\n");
		exit(0);
	}
 
	// 重置指针位置到文件流开头
	rewind(fp);
 
	// 读取每个Section的名字
	// 将fp指针移到字符串表(.shstrtab)内容的偏移位置处
	fseek(fp, shdr[elf_head.e_shstrndx].sh_offset, SEEK_SET);
 
	// e_shstrndx项是字符串表(.shstrtab)的下标
	// 把这个段的内容全部存储到shstrtab数组里面
    uint64_t size = shdr[elf_head.e_shstrndx].sh_size; 
	char *shstrtab = (char*) malloc(size);
	char *temp = shstrtab;
 
	// 读取内容
	status = fread(shstrtab, shdr[elf_head.e_shstrndx].sh_size, 1, fp);
	if (0 == status)
	{
		printf("\\nfaile to read\\n");
	}
    
	// 遍历每一个节
	for (int i = 0; i < elf_head.e_shnum; i++)
	{
		// temp指针用于定位当前节的名字在.shstrtab节内容中的首地址
		temp = shstrtab;
		// shdr[i].sh_name表示这个节名字在(.shstrtab)节内容中的偏移
		temp = temp + shdr[i].sh_name;
		printf("节的名称: %s\\n", temp);
		printf("节首的偏移: %#x\\n", shdr[i].sh_offset);
		printf("节的大小: %#x\\n", shdr[i].sh_size);
        printf("节的运行时虚拟内存地址: %#x\\n", shdr[i].sh_addr);
        printf("\\n");
	}
    system("pause");
    return 0;
}


http://www.kler.cn/a/397143.html

相关文章:

  • 【redis】—— 环境搭建教程
  • Python学习从0到1 day29 Python 高阶技巧 ⑦ 正则表达式
  • 《C语言程序设计现代方法》note-4 基本类型 强制类型转换 类型定义
  • Python调用API翻译Excel中的英语句子并回填数据
  • HarmonyOS NEXT应用开发实战 ( 应用的签名、打包上架,各种证书详解)
  • 浅谈“通感一体”
  • HBase压测 ycsb
  • 建设工程监理规范 (2014年3月1日起实施)
  • 01、Spring MVC入门程序
  • 实施案例PPT | 数据湖+数据中台实施方案
  • 用go语言后端开发速查
  • Android从Drawable资源Id直接生成Bitmap,Kotlin
  • hive搭建
  • STM32传感器模块编程实践(十二) micro SD卡模块简介及驱动源码
  • [ACTF2020]Upload 1--详细解析
  • 健康之路三度冲击港交所,数字健康医疗平台IPO前景引关注
  • 【AI图像生成网站Golang】雪花算法
  • 前后端分离练习(云客项目)
  • 一文讲清楚人工智能自然语言处理中的数据预处理(数据清洗)
  • 【目标检测】用YOLOv8-Segment训练语义分割数据集(保姆级教学)
  • 34Web服务器(如Apache, Nginx)
  • SpringBoot如何集成WebSocket
  • 【LeetCode】每日一题 2024_11_15 最少翻转次数使二进制矩阵回文 I(模拟、矩阵遍历(竖着遍历))
  • SPIRiT-Diffusion:基于自一致性驱动的加速MRI扩散模型|文献速递-基于深度学习的病灶分割与数据超分辨率
  • 富格林:准确预判安全追损契机
  • flink架构 详解