Windows下的ELF文件解析代码C++

ELF(Executable and Linkable Format)是Unix及类Unix系统下可执行文件、共享库等二进制文件标准格式。

ELF文件结构:

(1) ELF header
(2) Program header table,对应于segments
(3) Section header table,对应于sections
(4) 被Program header table或Sectionheader table指向的内容

segments与sections的关系:

(1) 每个segments可以包含多个sections
(2) 每个sections可以属于多个segments
(3) segments之间可以有重合的部分

下图是readelf工具输出的某ELF文件segments与sections信息:
Windows下的ELF文件解析代码C++_第1张图片
可以看到,segments部分包含各segments的地址、偏移、属性等;而sections部分则依次列出每个segment所包含的sections。注意到,sections通常为全小写字母,而segments通常为全大写字母。

此外,这两者之间另一个关键不同点是,sections包含的是链接时需要的信息,而segments包含运行时需要的信息。即,在链接时,链接器通过section header table去寻找sections;在运行时,加载器通过program header table去寻找segments。可见下图:
Windows下的ELF文件解析代码C++_第2张图片

比较重要的sections:
(1) .init_array: 动态库加载或可执行文件开始执行前调用的函数列表
(2) .text: 代码
(3) .got: Global offset table(GOT),包含加载时需要重定位的变量的地址
(4) .got.plt: 包含动态库中函数地址的GOT

比较重要的segments:
(1) LOAD: 运行时需要被加载进内存的segment
(2) GNU_STACK: 决定运行时栈是否可执行
(3) DYNAMIC: 动态链接信息,对应于.dynamicsection

#include 
#include 

//VS2015以上需要添加libucrtd.lib文件到工程目录下
#pragma comment(lib,"libucrtd.lib")

typedef unsigned short __u16;
typedef int __s32;
typedef unsigned int __u32;

typedef __u32     Elf32_Addr;
typedef __u16     Elf32_Half;
typedef __u32     Elf32_Off;
typedef __s32     Elf32_Sword;
typedef __u32     Elf32_Word;

#define EI_NIDENT     16

typedef struct elf32_hdr{
    unsigned char     e_ident[EI_NIDENT];
    Elf32_Half     e_type;
    Elf32_Half     e_machine;
    Elf32_Word     e_version;
    Elf32_Addr     e_entry; /* Entry point */
    Elf32_Off     e_phoff;
    Elf32_Off     e_shoff;
    Elf32_Word     e_flags;
    Elf32_Half     e_ehsize;
    Elf32_Half     e_phentsize;
    Elf32_Half     e_phnum;
    Elf32_Half     e_shentsize;
    Elf32_Half     e_shnum;
    Elf32_Half     e_shstrndx;
} Elf32_Ehdr;

typedef struct elf32_phdr{
    Elf32_Word     p_type;
    Elf32_Off     p_offset;
    Elf32_Addr     p_vaddr;
    Elf32_Addr     p_paddr;
    Elf32_Word     p_filesz;
    Elf32_Word     p_memsz;
    Elf32_Word     p_flags;
    Elf32_Word     p_align;
} Elf32_Phdr;

typedef struct {
    Elf32_Word     sh_name;
    Elf32_Word     sh_type;
    Elf32_Word     sh_flags;
    Elf32_Addr     sh_addr;
    Elf32_Off     sh_offset;
    Elf32_Word     sh_size;
    Elf32_Word     sh_link;
    Elf32_Word     sh_info;
    Elf32_Word     sh_addralign;
    Elf32_Word     sh_entsize;
} Elf32_Shdr;

int main(int argc, char* argv[])
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    HANDLE hMap = NULL;
    LPVOID pFile = NULL;

    hFile = CreateFile("F:\\Workspace\\a.out",
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_ARCHIVE,
        0);

    if(hFile==INVALID_HANDLE_VALUE)
    {
        printf("OpenFile Error,Code:%d\n",GetLastError());
        return 0;
    }     

    hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
    if(hMap == NULL)
    { 
        printf("CreateFileMapping Error,Code:%d\n",GetLastError());
        CloseHandle(hFile);
        return 0;
    }

    pFile = MapViewOfFile(hMap,FILE_MAP_READ|FILE_MAP_WRITE,NULL,NULL,NULL);
    if(pFile == NULL)
    {
        printf("MapViewOfFile Error,Code:%d\n",GetLastError());
        CloseHandle(hMap);
        CloseHandle(hFile);
        return 0;
    }

    Elf32_Ehdr* p_Elf32_Ehdr = (Elf32_Ehdr*)pFile;

    Elf32_Phdr* p_Elf32_Phdr = (Elf32_Phdr*)((char*)pFile + p_Elf32_Ehdr->e_phoff);
    {
        Elf32_Phdr *tmp = p_Elf32_Phdr;
        for (int i=0; ie_phnum; i++,tmp++) 
        {
            printf("%d off:%#10x filesize:%#10x memsize:%#10x\n",
                i,
                tmp->p_offset,
                tmp->p_filesz,
                tmp->p_memsz);
        }
    }

    printf("\n");

    Elf32_Shdr* p_Elf32_Shdr = (Elf32_Shdr*)((char*)pFile + p_Elf32_Ehdr->e_shoff);
    char *objsn = (char*)((char*)pFile + p_Elf32_Shdr[p_Elf32_Ehdr->e_shstrndx].sh_offset);
    {
        Elf32_Shdr *tmp = p_Elf32_Shdr;
        for (int i=0; ie_shnum; i++,tmp++) 
        {
            printf("%d off:%#10x size:%#10x entsize:%#10x %s\n",
                i,tmp->sh_offset,
                tmp->sh_size,
                tmp->sh_entsize,
                objsn + tmp->sh_name);
        }
    } 
    printf("\nenter:%#10x \n",p_Elf32_Ehdr->e_entry);

    UnmapViewOfFile(pFile);
    CloseHandle(hMap);     
    CloseHandle(hFile);


    return 0;
}

本文只做学习之用

你可能感兴趣的:(C++)