从图中可以看出该目标文件包含8个程序头节,当然在程序编写时,需要先从elf头中获取该程序头节的个数和大小,我以此为例,并且假设程序头节的个数为8,大致解析程序如下(稍有不同 但足矣):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <elf.h>
#include <unistd.h>
#define elf_file_path "/home/code/test/main"
#define MA 1
#define PHDR_SIZE 8
int main(int argc, char** argv) {
#ifdef __x86_64__
#if MA
Elf64_Phdr *phdrs = malloc(sizeof (Elf64_Phdr)*PHDR_SIZE);
if (phdrs == NULL) {
perror("malloc error");
}
#else
Elf64_Phdr phdrs[PHDR_SIZE];
#endif
#else
#if MA
Elf32_Phdr *phdrs = malloc(sizeof(Elf32_Phdr)*PHDR_SIZE);
if (phdrs == NULL) {
perror("malloc error");
}
#else
Elf32_Phdr phdrs[PHDR_SIZE];
#endif
#endif
#ifdef __x86_64__
memset(phdrs, 0, sizeof (Elf64_Phdr)*PHDR_SIZE);
#else
memset(phdrs, 0, sizeof (Elf32_Phdr)*PHDR_SIZE);
#endif
int fd = open(elf_file_path, O_RDONLY);
if (fd < 0) {
perror("open elf file failed");
}
#ifdef __x86_64__
lseek(fd, 64, SEEK_SET);
int ret;
if ((ret = read(fd, phdrs, sizeof (Elf64_Phdr)*PHDR_SIZE)) < 1) {
perror("read elf file failed");
}
#else
lseek(fd, 52, SEEK_SET);
int ret;
if ((ret = read(fd, phdrs, sizeof (Elf32_Phdr)*PHDR_SIZE)) < 1) {
perror("read elf file failed");
}
#endif
int i = 0;
printf("Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n");
#if 1
for (; i < PHDR_SIZE; i++) {
#ifdef __x86_64__
#if MA
Elf64_Phdr *phdr = phdrs++;
#else
Elf64_Phdr *phdr = &phdrs[i];
#endif
#else
#if MA
Elf32_Phdr *phdr = phdrs++;
#else
Elf32_Phdr *phdr = &phdrs[i];
#endif
#endif
switch (phdr->p_type) {
case PT_NULL:
printf("%s ", "NULL");
break;
case PT_LOAD:
printf("%s ", "LOAD");
break;
case PT_DYNAMIC:
printf("%s ", "DYNA");
break;
case PT_INTERP:
printf("%s ", "INTERP");
break;
case PT_NOTE:
printf("%s ", "NOTE");
break;
case PT_SHLIB:
printf("%s ", "SHLIB");
break;
case PT_PHDR:
printf("%s ", "PHDR");
break;
case PT_TLS:
printf("%s ", "TLS");
break;
case PT_NUM:
printf("%s ", "NUM");
break;
case PT_LOOS:
printf("%s ", "LOOS");
break;
case PT_GNU_EH_FRAME:
printf("%s ", "GNU_EH_FRAME");
break;
case PT_GNU_STACK:
printf("%s ", "GNU_STACK");
break;
default:
printf("%s ", "OTHER");
break;
}
printf(" 0x%-6X 0x%-8X 0x%-8X 0x%-6X 0x%-6X",
(phdr)->p_offset,
(phdr)->p_vaddr,
(phdr)->p_paddr,
(phdr)->p_filesz,
(phdr)->p_memsz);
switch ((phdr)->p_flags) {
case PF_W:
printf(" %s", " W ");
break;
case PF_R:
printf(" %s", "R ");
break;
case (PF_W + PF_R):
printf(" %s", "RW ");
break;
case PF_X:
printf(" %s", " E");
break;
case (PF_X + PF_R):
printf(" %s", "R E");
break;
case (PF_X + PF_W):
printf(" %s", " WE");
break;
case (PF_X + PF_W + PF_R):
printf(" %s", "RWE");
break;
case (PF_MASKOS):
printf(" %s", "MASKOS");
break;
case (PF_MASKPROC):
printf(" %s", "MASKPROC");
break;
default:
printf(" %s", " ");
break;
}
printf(" 0x%-4X\n", (phdr)->p_align);
}
#if MA
if (phdrs != NULL){
phdrs = phdrs - PHDR_SIZE;
free(phdrs);
}
#endif
#endif
close(fd);
return (EXIT_SUCCESS);
}