解析 ELF 文件

#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>

// size : 64 byte
// typedef uint32_t Elf64_Word;
// typedef uint64_t Elf64_Xword;
// typedef uint64_t Elf64_Addr;
// typedef uint64_t Elf64_Off;

// typedef struct
// {
//   Elf64_Word	sh_name;		/* Section name (string tbl index) */
//   Elf64_Word	sh_type;		/* Section type */
//   Elf64_Xword	sh_flags;		/* Section flags */
//   Elf64_Addr	sh_addr;		/* Section virtual addr at execution */
//   Elf64_Off	sh_offset;		/* Section file offset */
//   Elf64_Xword	sh_size;		/* Section size in bytes */
//   Elf64_Word	sh_link;		/* Link to another section */
//   Elf64_Word	sh_info;		/* Additional section information */
//   Elf64_Xword	sh_addralign;		/* Section alignment */
//   Elf64_Xword	sh_entsize;		/* Entry size if section holds table */
// } Elf64_Shdr;
int main(int argc, char* argv[]) {
    printf("hello ELF \n");

    char* fileName = argv[1];
    struct stat st;
    if (-1 == stat(fileName, &st)) {
        printf("%s not exist \n", fileName);
        return -1;
    } else {
        printf("parse ELF file %s, size %ld \n", fileName, st.st_size);
    }
    char* buf = (char*)malloc(st.st_size); 

    FILE* fp = fopen(fileName, "rb");
    if (fp) {
        size_t count = fread(buf, 1, st.st_size, fp);
        fclose(fp);
        printf("load %ld bytes from %s \n", count, fileName);
    }
    fseek (fp, 0, SEEK_SET);

    // 64 bytes
    Elf64_Ehdr elf64_header;
    // 64 bytes
    Elf64_Shdr elf64_secHeader;
    // printf("sizeof elf64_header %ld, section header: %ld \n", sizeof(elf64_header), sizeof(elf64_secHeader));

    // parse header 
    memcpy(&elf64_header, buf, sizeof(Elf64_Ehdr));
    printf("\nELF Header:");
    printf("程序入口地址: 0x%lx \n", elf64_header.e_entry);
    printf("段信息: \n");
    printf("\tsection table entry: 0x%lx, \n\teach section size: 0x%x, \n\tsection count: %d, \n\tsymtab index: %d \n", 
            elf64_header.e_shoff, elf64_header.e_shentsize, elf64_header.e_shnum, elf64_header.e_shstrndx);
    printf("\n");

    fseek (fp, 0, SEEK_SET);
    int secNum = elf64_header.e_shnum;
    size_t secTabSize = elf64_header.e_shentsize * secNum;
    Elf64_Shdr* secTabPtr = (Elf64_Shdr*)malloc(secTabSize);
    memset(secTabPtr, 0, secTabSize);
    memcpy((void*)secTabPtr, buf + elf64_header.e_shoff, secTabSize);


    // 1. section string section 
    Elf64_Shdr* ptr = (Elf64_Shdr*)((char*)secTabPtr + elf64_header.e_shstrndx * elf64_header.e_shentsize);
    Elf64_Off sh_offset = ptr->sh_offset;
    Elf64_Xword	sh_size = ptr->sh_size;
    printf("sh_offset : 0x%lx, sh_size 0x%lx \n", sh_offset, sh_size);
    char* shstrPtr = (char*)malloc(sh_size);
    memcpy(shstrPtr, buf + ptr->sh_offset, sh_size);
    printf("shstr 段: \n");
    for (int i = 0; i < sh_size; i++) printf("%c", shstrPtr[i]);
    printf("\n");

    // 打印各段的header信息
    int strtabIndex, texttabIndex, datatabIndex, bsstabIndex, symtabIndex;
    for (int i = 0; i < secNum; i++) {
        Elf64_Shdr* ptr = (Elf64_Shdr*)((char*)secTabPtr + i * elf64_header.e_shentsize);
        printf("Section[%d]: name %s, sh_addr 0x%lx, sh_offset 0x%lx, sh_size 0x%lx \n",
                i, shstrPtr + ptr->sh_name, ptr->sh_addr, ptr->sh_offset, ptr->sh_size);

        if (strcmp(shstrPtr + ptr->sh_name, ".text") == 0) texttabIndex = i;
        if (strcmp(shstrPtr + ptr->sh_name, ".data") == 0) datatabIndex = i;
        if (strcmp(shstrPtr + ptr->sh_name, ".bss") == 0) bsstabIndex = i;
        if (strcmp(shstrPtr + ptr->sh_name, ".symtab") == 0) symtabIndex = i;
        if (strcmp(shstrPtr + ptr->sh_name, ".strtab") == 0) strtabIndex = i;
    }

    // 获取段信息
    // 2. .strtab 字符串表
    printf("\n.strtab 段: \n");
    Elf64_Shdr* strtabPtr = (Elf64_Shdr*)((char*)secTabPtr + strtabIndex * elf64_header.e_shentsize);
    Elf64_Off strtab_offset = strtabPtr->sh_offset;
    Elf64_Xword	strtab_size = strtabPtr->sh_size;
    char* strtab_buf = (char*)malloc(strtab_size);
    memcpy((void*)strtab_buf, buf + strtab_offset, strtab_size);
    for (int i = 0; i < sh_size; i++) printf("%c", strtab_buf[i]);
    printf("\n");

    // 3. 解析 .symtab 符号表
    Elf64_Shdr* symtabPtr = (Elf64_Shdr*)((char*)secTabPtr + symtabIndex * elf64_header.e_shentsize);
    Elf64_Off symtab_offset = symtabPtr->sh_offset;
    Elf64_Xword	symtab_size = symtabPtr->sh_size;
    int sym_count = symtab_size / sizeof(Elf64_Sym);
    char* symtab_buf = (char*)malloc(symtab_size);
    memcpy((void*)symtab_buf, buf + symtab_offset, symtab_size);
    printf("symtab offset 0x%lx, size 0x%lx, sizeof Elf64_Sym %ld \n", symtab_offset, symtab_size, sizeof(Elf64_Sym));
    for (int i = 0; i < sym_count; i++) {
        Elf64_Sym* ptr = (Elf64_Sym*)((char*)symtab_buf + i * sizeof(Elf64_Sym));
        // st_value 是在 st_shndx 段内的偏移量
        printf("symtab [%d] name %s, st_value 0x%lx, st_size 0x%lx, sec index %d \n",
                i, strtab_buf + ptr->st_name, ptr->st_value, ptr->st_size, ptr->st_shndx);
    }

    printf("\n");
    // free
    free(shstrPtr);
    free(secTabPtr);
    free(buf);

    printf("END \n");


    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值