代码拉取完成,页面将自动刷新
#include<stdlib.h>
#include<stdio.h>
#include "elf.h"
int a = 3;
int main(int argc, char *argv[])
{
// 参数错误
if (argc < 2) {
printf("invalid arguments\n");
exit(0);
}
// 打开文件
FILE *fp;
fp = fopen(argv[1], "r");
if (NULL == fp) {
printf("fail to open the file");
exit(0);
}
// 解析head
struct Elf64_Ehdr elf_head;
int shnum, a;
// 读取 head 到elf_head
a = fread(&elf_head, sizeof(struct Elf64_Ehdr), 1, fp);
if (0 == a) {
printf("fail to read head\n");
exit(0);
}
// 判断elf文件类型
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') {
printf("Not a ELF file\n");
exit(0);
}
// 解析section 分配内存 section * 数量
struct Elf64_Shdr *shdr =
(struct Elf64_Shdr *)malloc(sizeof(struct Elf64_Shdr) *
elf_head.e_shnum);
if (NULL == shdr) {
printf("shdr malloc failed\n");
exit(0);
}
// 设置fp偏移量 offset
a = fseek(fp, elf_head.e_shoff, SEEK_SET);
if (0 != a) {
printf("\nfaile to fseek\n");
exit(0);
}
// 读取section 到 shdr, 大小为shdr * 数量
a = fread(shdr, sizeof(struct Elf64_Shdr) * elf_head.e_shnum, 1, fp);
if (0 == a) {
printf("\nfail to read section\n");
exit(0);
}
// 重置指针位置
rewind(fp);
#if 0
#endif
// 将fp指针移到 字符串表偏移位置处
fseek(fp, shdr[elf_head.e_shstrndx].sh_offset, SEEK_SET);
// 第e_shstrndx项是字符串表 定义 字节 长度 char类型 数组
char shstrtab[shdr[elf_head.e_shstrndx].sh_size];
char *temp = shstrtab;
// 读取内容
a = fread(shstrtab, shdr[elf_head.e_shstrndx].sh_size, 1, fp);
if (0 == a) {
printf("\nfaile to read\n");
}
// printf("\n\节的信息: \n");
// 遍历
// for (int i = 0; i < elf_head.e_shnum; i++)
// {
// temp = 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_offset + shdr[i].sh_size);
// printf("\n");
// }
// 解析 segment
struct Elf64_Phdr *phdr =
(struct Elf64_Phdr *)malloc(sizeof(struct Elf64_Phdr) *
elf_head.e_phnum);
a = fseek(fp, elf_head.e_phoff, SEEK_SET);
a = fread(phdr, sizeof(struct Elf64_Phdr) * elf_head.e_phnum, 1, fp);
rewind(fp);
fseek(fp, phdr[elf_head.e_shentsize].p_offset, SEEK_SET);
char phstrtab[phdr[elf_head.e_shentsize].p_filesz];
a = fread(phstrtab, phdr[elf_head.e_shentsize].p_filesz, 1, fp);
printf("\n\n段的信息:\n");
for (int i = 0; i < elf_head.e_phnum; i++) {
printf("%d: \n", i);
printf(" 该段首相对偏移: %llx \n", phdr[i].p_offset);
printf(" 该段的大小: %llx \n", phdr[i].p_memsz);
printf(" 该段尾相对偏移: %llx \n",
phdr[i].p_memsz + phdr[i].p_offset);
printf(" *该段包含的节有:\n");
for (int j = 0; j < elf_head.e_shnum; j++) {
if ((shdr[j].sh_offset > phdr[i].p_offset) &&
((shdr[j].sh_offset + shdr[j].sh_size) <
(phdr[i].p_offset + phdr[i].p_memsz))
) {
temp = shstrtab;
temp = temp + shdr[j].sh_name;
printf(" 节的名称: %s\n", temp);
printf(" 节首的偏移: %llx\n",
shdr[j].sh_offset);
printf(" 节的大小: %llx\n",
shdr[j].sh_size);
printf(" 节尾的地址: %llx\n",
shdr[j].sh_offset + shdr[j].sh_size);
printf("\n");
}
}
printf("\n");
}
//test sh_info
int err;
for (int i = 0; i < elf_head.e_shnum; i++) {
unsigned int infosec = shdr[i].sh_info;
printf("infosec: %d\n", infosec);
/* Not a valid relocation section? */
if (infosec >= elf_head.e_shnum)
continue;
// /* Don't bother with non-allocated sections */
// if (!(shdr[infosec].sh_flags & SHF_ALLOC))
// continue;
// 是重定位段
// if (shdr[i].sh_type == SHT_REL)
// err = apply_relocate(info->sechdrs, info->strtab,
// info->index.sym, i, mod);
// else if (info->sechdrs[i].sh_type == SHT_RELA)
// err = apply_relocate_add(info->sechdrs, info->strtab,
// info->index.sym, i, mod);
// if (err < 0)
// break;
}
printf("\n");
return 0;
}
#if 0
static void get_rel_dyn_type(u2 machineType,u4 rInfo,u1* type);
void print_elf_section_of_reldyn(MemMapping* mem,Elf32_Ehdr* pHeader,Elf32_Shdr* pSheader){
Elf32_Rel* pRel = NULL;
Elf32_Sym* pSymMem = NULL;
u1* shStringTableMem = NULL;
u4 i = 0;
u4 size = 0;
u1 buf[55];
LookupSection* pLookupSection = NULL;
LookupSection* pLookupStrSection = NULL;
Elf32_Shdr* pReldyn = NULL;
shStringTableMem = get_elf_section_of_shstr_table(mem,pHeader,pSheader);
if(NULL == shStringTableMem){
printf("Error,get elf section header string table failed !\n");
goto Exit;
}
for( ; i < pHeader->e_shnum ; i++){
if(pSheader[i].sh_type == SHT_REL && strcmp((const char*)(shStringTableMem + pSheader[i].sh_name),".rel.dyn") == 0){
size = (pSheader[i].sh_size / pSheader[i].sh_entsize);
pRel = (Elf32_Rel*)(mem->base + pSheader[i].sh_offset);
pReldyn = (Elf32_Shdr*) &pSheader[i];
break;
}
continue;
}
if(NULL != pRel){
//@1 by default ,rel.dyn link dynsym ,so it sh_link is the index
pLookupSection = get_section_by_index(mem,pHeader,pSheader,pReldyn->sh_link);
if(NULL == pLookupSection){
printf("Error,get section by index failed\n");
goto Exit;
}
pSymMem = (Elf32_Sym*)pLookupSection->base;
pLookupStrSection = get_section_by_index(mem,pHeader,pSheader,pLookupSection->link);
if(NULL == pLookupStrSection){
printf("Error,get sym tab link failed\n");
goto Exit;
}
i = 0;
printf("Relocation section '.rel.dyn' at offset 0x%.8x contains %d entries:\n",pReldyn->sh_addr,size);
printf("Offset Info Type Sym.Value Sym. Name\n");
for( ; i < size ; i++ ){
printf("0x%.8x ",pRel[i].r_offset);
printf("%.8x ",pRel[i].r_info);
memset(&buf,0,55);
get_rel_dyn_type((u2)pHeader->e_machine,(u4)ELF32_R_TYPE(pRel[i].r_info),(u1*)buf);
printf("%-15s",buf);
if(pSymMem[ELF32_R_SYM(pRel[i].r_info)].st_name != 0){
printf("%.8x ",pSymMem[ELF32_R_SYM(pRel[i].r_info)].st_value);
printf("%s",(pLookupStrSection->base + pSymMem[ELF32_R_SYM(pRel[i].r_info)].st_name));
}
printf("\n");
}
}
Exit:
if(shStringTableMem)
free(shStringTableMem);
if(pLookupSection)
free(pLookupSection);
if(pLookupStrSection)
free(pLookupStrSection);
}
//this impl code almost sample as the top print_elf_section_of_reldyn,but its' sh_info point to which section will be relocated
void print_elf_section_of_relplt(MemMapping* mem,Elf32_Ehdr* pHeader,Elf32_Shdr* pSheader){
Elf32_Rel* pRelplt = NULL;
Elf32_Sym* pSymMem = NULL;
u1* shStringTableMem = NULL;
u4 i = 0;
u4 size = 0;
u1 buf[55];
LookupSection* pLookupSection = NULL;
LookupSection* pLookupStrSection = NULL;
Elf32_Shdr* pThisSection = NULL;
shStringTableMem = get_elf_section_of_shstr_table(mem,pHeader,pSheader);
if(NULL == shStringTableMem){
printf("Error,get elf section header string table failed !\n");
goto Exit;
}
for( ; i < pHeader->e_shnum ; i++){
if(pSheader[i].sh_type == SHT_REL && strcmp((const char*)(shStringTableMem + pSheader[i].sh_name),".rel.plt") == 0){
size = (pSheader[i].sh_size / pSheader[i].sh_entsize);
pRelplt = (Elf32_Rel*)(mem->base + pSheader[i].sh_offset);
pThisSection = (Elf32_Shdr*)&pSheader[i];
break;
}
continue;
}
if(NULL != pRelplt){
//@1 by default ,rel.dyn link dynsym ,so it sh_link is the index
pLookupSection = get_section_by_index(mem,pHeader,pSheader,pThisSection->sh_link);
if(NULL == pLookupSection){
printf("Error,get section by index failed\n");
goto Exit;
}
pSymMem = (Elf32_Sym*)pLookupSection->base;
pLookupStrSection = get_section_by_index(mem,pHeader,pSheader,pLookupSection->link);
if(NULL == pLookupStrSection){
printf("Error,get sym tab link failed\n");
goto Exit;
}
i = 0;
printf("Relocation section '.rel.plt' at offset 0x%.8x contains %d entries:\n",pThisSection->sh_addr,size);
printf("Offset Info Type Sym.Value Sym. Name\n");
for( ; i < size ; i++ ){
printf("0x%.8x ",pRelplt[i].r_offset);
printf("%.8x ",pRelplt[i].r_info);
memset(&buf,0,55);
get_rel_dyn_type((u2)pHeader->e_machine,(u4)ELF32_R_TYPE(pRelplt[i].r_info),(u1*)buf);
printf("%s ",buf);
if(pSymMem[ELF32_R_SYM(pRelplt[i].r_info)].st_name != 0){
printf("%.8x ",pSymMem[ELF32_R_SYM(pRelplt[i].r_info)].st_value);
printf("%s",(pLookupStrSection->base + pSymMem[ELF32_R_SYM(pRelplt[i].r_info)].st_name));
}
printf("\n");
}
}
Exit:
if(shStringTableMem)
free(shStringTableMem);
if(pLookupSection)
free(pLookupSection);
if(pLookupStrSection)
free(pLookupStrSection);
}
void print_elf_section_of_allrela(MemMapping* mem,Elf32_Ehdr* pHeader,Elf32_Shdr* pSheader){
Elf32_Rela* pRelplt = NULL;
Elf32_Sym* pRelaMem = NULL;
u4 i = 0;
u4 size = 0;
u1 buf[55];
LookupSection* pLookupSection = NULL;
LookupSection* pLookupStrSection = NULL;
Elf32_Shdr* pThisSection;
u1* shStringTableMem = NULL;
shStringTableMem = get_elf_section_of_shstr_table(mem,pHeader,pSheader);
if(NULL == shStringTableMem){
printf("Error,get elf section header string table failed !\n");
goto Exit;
}
for( ; i < pHeader->e_shnum ; i++){
if(pSheader[i].sh_type == SHT_RELA){
size = (pSheader[i].sh_size / pSheader[i].sh_entsize);
pRelplt = (Elf32_Rela*)(mem->base + pSheader[i].sh_offset);
pThisSection = (Elf32_Shdr*)(&pSheader[i]);
if(NULL != pRelplt){
//@1 by default ,RELA link dynsym ,so it sh_link is the index
pLookupSection = get_section_by_index(mem,pHeader,pSheader,pThisSection->sh_link);
if(NULL == pLookupSection){
printf("Error,get section by index failed\n");
goto Exit;
}
pRelaMem = (Elf32_Sym*)pLookupSection->base;
pLookupStrSection = get_section_by_index(mem,pHeader,pSheader,pLookupSection->link);
if(NULL == pLookupStrSection){
printf("Error,get sym tab link failed\n");
goto Exit;
}
u4 j = 0;
printf("Relocation section '%s' at offset 0x%.8x contains %d entries:\n",(shStringTableMem + pSheader[i].sh_name),pThisSection->sh_offset,size);
printf("Offset Info Type Sym.Value Sym. Name + Addend\n");
for( ; j < size ; j++ ){
printf("0x%.8x ",pRelplt[j].r_offset);
printf("%.8x ",pRelplt[j].r_info);
memset(&buf,0,55);
get_rel_dyn_type((u2)pHeader->e_machine,(u4)ELF32_R_TYPE(pRelplt[j].r_info),(u1*)buf);
printf("%-15s ",buf);
if(pRelaMem[ELF32_R_SYM(pRelplt[j].r_info)].st_name != 0){
printf("%.8x ",pRelaMem[ELF32_R_SYM(pRelplt[j].r_info)].st_value);
printf("%-10s ",(pLookupStrSection->base + pRelaMem[ELF32_R_SYM(pRelplt[j].r_info)].st_name));
}
else{
printf("%-22s","");
}
printf("%.8x",pRelplt[j].r_addend);
printf("\n");
}
memset(pLookupSection,0,GET_SIZE(LookupSection));
memset(pLookupSection,0,GET_SIZE(pLookupStrSection));
}
}
continue;
}
Exit:
if(shStringTableMem)
free(shStringTableMem);
if(pLookupSection){
free(pLookupSection);
pLookupSection = NULL;
}
if(pLookupStrSection){
free(pLookupStrSection);
pLookupStrSection = NULL;
}
return;
}
static void get_rel_dyn_type(u2 machineType,u4 rInfo,u1* type){
switch(machineType){
case EM_386:
switch(rInfo){
case R_386_NONE:
memcpy(type,"R_386_NONE",strlen("R_386_NONE"));
break;
case R_386_32:
memcpy(type,"R_386_32",strlen("R_386_32"));
break;
case R_386_PC32:
memcpy(type,"R_386_NONE",strlen("R_386_PC32"));
break;
case R_386_GOT32:
memcpy(type,"R_386_GOT32",strlen("R_386_GOT32"));
break;
case R_386_PLT32:
memcpy(type,"R_386_PLT32",strlen("R_386_PLT32"));
break;
case R_386_COPY:
memcpy(type,"R_386_COPY",strlen("R_386_COPY"));
break;
case R_386_GLOB_DAT:
memcpy(type,"R_386_GLOB_DAT",strlen("R_386_GLOB_DAT"));
break;
case R_386_JMP_SLOT:
memcpy(type,"R_386_JMP_SLOT",strlen("R_386_JMP_SLOT"));
break;
case R_386_RELATIVE:
memcpy(type,"R_386_RELATIVE",strlen("R_386_RELATIVE"));
break;
case R_386_GOTOFF:
memcpy(type,"R_386_GOTOFF",strlen("R_386_GOTOFF"));
break;
case R_386_GOTPC:
memcpy(type,"R_386_GLOB_DAT",strlen("R_386_GOTPC"));
break;
case R_386_TLS_TPOFF:
memcpy(type,"R_386_TLS_TPOFF",strlen("R_386_TLS_TPOFF"));
break;
case R_386_TLS_IE:
memcpy(type,"R_386_TLS_IE",strlen("R_386_TLS_IE"));
break;
case R_386_TLS_GOTIE:
memcpy(type,"R_386_TLS_GOTIE",strlen("R_386_TLS_GOTIE"));
break;
case R_386_TLS_LE:
memcpy(type,"R_386_TLS_LE",strlen("R_386_TLS_LE"));
break;
case R_386_TLS_GD:
memcpy(type,"R_386_TLS_GD",strlen("R_386_TLS_GD"));
break;
case R_386_TLS_LDM:
memcpy(type,"R_386_TLS_LDM",strlen("R_386_TLS_LDM"));
break;
case R_386_16:
memcpy(type,"R_386_16",strlen("R_386_16"));
break;
case R_386_PC16:
memcpy(type,"R_386_PC16",strlen("R_386_PC16"));
break;
case R_386_8:
memcpy(type,"R_386_8",strlen("R_386_8"));
break;
case R_386_PC8:
memcpy(type,"R_386_PC8",strlen("R_386_PC8"));
break;
case R_386_TLS_GD_32:
memcpy(type,"R_386_TLS_GD_32",strlen("R_386_TLS_GD_32"));
break;
case R_386_TLS_GD_PUSH:
memcpy(type,"R_386_TLS_GD_PUSH",strlen("R_386_TLS_GD_PUSH"));
break;
case R_386_TLS_GD_CALL:
memcpy(type,"R_386_TLS_GD_CALL",strlen("R_386_TLS_GD_CALL"));
break;
case R_386_TLS_GD_POP:
memcpy(type,"R_386_TLS_GD_POP",strlen("R_386_TLS_GD_POP"));
break;
case R_386_TLS_LDM_32:
memcpy(type,"R_386_TLS_LDM_32",strlen("R_386_TLS_LDM_32"));
break;
case R_386_TLS_LDM_PUSH:
memcpy(type,"R_386_TLS_LDM_PUSH",strlen("R_386_TLS_LDM_PUSH"));
break;
case R_386_TLS_LDM_CALL:
memcpy(type,"R_386_TLS_LDM_CALL",strlen("R_386_TLS_LDM_CALL"));
break;
case R_386_TLS_LDM_POP:
memcpy(type,"R_386_TLS_LDM_POP",strlen("R_386_TLS_LDM_POP"));
break;
case R_386_TLS_LDO_32:
memcpy(type,"R_386_TLS_LDO_32",strlen("R_386_TLS_LDO_32"));
break;
case R_386_TLS_IE_32:
memcpy(type,"R_386_TLS_IE_32",strlen("R_386_TLS_IE_32"));
break;
case R_386_TLS_LE_32:
memcpy(type,"R_386_TLS_LE_32",strlen("R_386_TLS_LE_32"));
break;
case R_386_TLS_DTPMOD32:
memcpy(type,"R_386_TLS_DTPMOD32",strlen("R_386_TLS_DTPMOD32"));
break;
case R_386_TLS_DTPOFF32:
memcpy(type,"R_386_TLS_DTPOFF32",strlen("R_386_TLS_DTPOFF32"));
break;
case R_386_TLS_TPOFF32:
memcpy(type,"R_386_TLS_TPOFF32",strlen("R_386_TLS_TPOFF32"));
break;
case R_386_IRELATIVE:
memcpy(type,"R_386_IRELATIVE",strlen("R_386_IRELATIVE"));
break;
default:
break;
}
break;
case EM_ARM:
switch(rInfo){
case R_ARM_NONE:
memcpy(type,"R_ARM_NONE",strlen("R_ARM_NONE"));
break;
case R_ARM_PC24:
memcpy(type,"R_ARM_PC24",strlen("R_ARM_PC24"));
break;
case R_ARM_ABS32:
memcpy(type,"R_ARM_ABS32",strlen("R_ARM_ABS32"));
break;
case R_ARM_REL32:
memcpy(type,"R_ARM_REL32",strlen("R_ARM_REL32"));
break;
case R_ARM_PC13:
memcpy(type,"R_ARM_PC13",strlen("R_ARM_PC13"));
break;
case R_ARM_ABS16:
memcpy(type,"R_ARM_ABS16",strlen("R_ARM_ABS16"));
break;
case R_ARM_ABS12:
memcpy(type,"R_ARM_ABS12",strlen("R_ARM_ABS12"));
break;
case R_ARM_THM_ABS5:
memcpy(type,"R_ARM_THM_ABS5",strlen("R_ARM_THM_ABS5"));
break;
case R_ARM_ABS8:
memcpy(type,"R_ARM_ABS8",strlen("R_ARM_ABS8"));
break;
case R_ARM_SBREL32:
memcpy(type,"R_ARM_SBREL32",strlen("R_ARM_SBREL32"));
break;
case R_ARM_THM_PC22:
memcpy(type,"R_ARM_THM_PC22",strlen("R_ARM_THM_PC22"));
break;
case R_ARM_THM_PC8:
memcpy(type,"R_ARM_THM_PC8",strlen("R_ARM_THM_PC8"));
break;
case R_ARM_AMP_VCALL9:
memcpy(type,"R_ARM_AMP_VCALL9",strlen("R_ARM_AMP_VCALL9"));
break;
case R_ARM_SWI24:
memcpy(type,"R_ARM_SWI24",strlen("R_ARM_SWI24"));
break;
case R_ARM_THM_SWI8:
memcpy(type,"R_ARM_THM_SWI8",strlen("R_ARM_THM_SWI8"));
break;
case R_ARM_XPC25:
memcpy(type,"R_ARM_XPC25",strlen("R_ARM_XPC25"));
break;
case R_ARM_THM_XPC22:
memcpy(type,"R_ARM_THM_XPC22",strlen("R_ARM_THM_XPC22"));
break;
case R_ARM_TLS_DTPMOD32:
memcpy(type,"R_ARM_TLS_DTPMOD32",strlen("R_ARM_TLS_DTPMOD32"));
break;
case R_ARM_TLS_DTPOFF32:
memcpy(type,"R_ARM_TLS_DTPOFF32",strlen("R_ARM_TLS_DTPOFF32"));
break;
case R_ARM_TLS_TPOFF32:
memcpy(type,"R_ARM_TLS_TPOFF32",strlen("R_ARM_TLS_TPOFF32"));
break;
case R_ARM_COPY:
memcpy(type,"R_ARM_COPY",strlen("R_ARM_COPY"));
break;
case R_ARM_GLOB_DAT:
memcpy(type,"R_ARM_GLOB_DAT",strlen("R_ARM_GLOB_DAT"));
break;
case R_ARM_JUMP_SLOT:
memcpy(type,"R_ARM_JUMP_SLOT",strlen("R_ARM_JUMP_SLOT"));
break;
case R_ARM_RELATIVE:
memcpy(type,"R_ARM_RELATIVE",strlen("R_ARM_RELATIVE"));
break;
case R_ARM_GOTOFF:
memcpy(type,"R_ARM_GOTOFF",strlen("R_ARM_GOTOFF"));
break;
case R_ARM_GOTPC:
memcpy(type,"R_ARM_GOTPC",strlen("R_ARM_GOTPC"));
break;
case R_ARM_GOT32:
memcpy(type,"R_ARM_GOT32",strlen("R_ARM_GOT32"));
break;
case R_ARM_PLT32:
memcpy(type,"R_ARM_PLT32",strlen("R_ARM_PLT32"));
break;
case R_ARM_GNU_VTENTRY:
memcpy(type,"R_ARM_GNU_VTENTRY",strlen("R_ARM_GNU_VTENTRY"));
break;
case R_ARM_GNU_VTINHERIT:
memcpy(type,"R_ARM_GNU_VTINHERIT",strlen("R_ARM_GNU_VTINHERIT"));
break;
case R_ARM_RSBREL32:
memcpy(type,"R_ARM_RSBREL32",strlen("R_ARM_RSBREL32"));
break;
case R_ARM_THM_RPC22:
memcpy(type,"R_ARM_THM_RPC22",strlen("R_ARM_THM_RPC22"));
break;
case R_ARM_RREL32:
memcpy(type,"R_ARM_RREL32",strlen("R_ARM_RREL32"));
break;
case R_ARM_RABS32:
memcpy(type,"R_ARM_RABS32",strlen("R_ARM_RABS32"));
break;
case R_ARM_RPC24:
memcpy(type,"R_ARM_RPC24",strlen("R_ARM_RPC24"));
break;
case R_ARM_RBASE:
memcpy(type,"R_ARM_RBASE",strlen("R_ARM_RBASE"));
break;
default:
break;
}
break;
default :
//TODO other ellipsis...
break;
}
}
练习:读取section names
从这一讲开始,都会有练习,方便我们把前面的理论知识综合运用。
下面这个练习的目标是:从一个ELF文件中读取存储section name的字符串表。前面讲过,该字符串表也是一个section,section header table中有其对应的section header,并且ELF文件头中给出了节名字符串表对应的section header的索引,e_shstrndx。
我们的思路是这样:
从ELF header中读取section header table的起始位置,每个section header的大小,以及节名字符串表对应section header的索引。
计算section_header_table_offset + section_header_size * e_shstrndx 就是节名字符串表对应section header的偏移。
读取section header,可以从中得到节名字符串表在文件中的偏移和大小。
把节名字符串表读取到内存中,打印其内容。
代码如下:
/* 64位ELF文件读取section name string table */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
/* 打开本地的ELF可执行文件hello */
FILE *fp = fopen("./hello", "rb");
if(!fp) {
perror("open ELF file");
exit(1);
}
/* 1. 通过读取ELF header得到section header table的偏移 */
/* for 64 bit ELF,
e_ident(16) + e_type(2) + e_machine(2) +
e_version(4) + e_entry(8) + e_phoff(8) = 40 */
fseek(fp, 40, SEEK_SET);
uint64_t sh_off;
int r = fread(&sh_off, 1, 8, fp);
if (r != 8) {
perror("read section header offset");
exit(2);
}
/* 得到的这个偏移值,可以用`reaelf -h hello`来验证是否正确 */
printf("section header offset in file: %ld (0x%lx)\n", sh_off, sh_off);
/* 2. 读取每个section header的大小e_shentsize,
section header的数量e_shnum,
以及对应section name字符串表的section header的索引e_shstrndx
得到这些值后,都可以用`readelf -h hello`来验证是否正确 */
/* e_flags(4) + e_ehsize(2) + e_phentsize(2) + e_phnum(2) = 10 */
fseek(fp, 10, SEEK_CUR);
uint16_t sh_ent_size; /* 每个section header的大小 */
r = fread(&sh_ent_size, 1, 2, fp);
if (r != 2) {
perror("read section header entry size");
exit(2);
}
printf("section header entry size: %d\n", sh_ent_size);
uint16_t sh_num; /* section header的数量 */
r = fread(&sh_num, 1, 2, fp);
if (r != 2) {
perror("read section header number");
exit(2);
}
printf("section header number: %d\n", sh_num);
uint16_t sh_strtab_index; /* 节名字符串表对应的节头的索引 */
r = fread(&sh_strtab_index, 1, 2, fp);
if (r != 2) {
perror("read section header string table index");
exit(2);
}
printf("section header string table index: %d\n", sh_strtab_index);
/* 3. read section name string table offset, size */
/* 先找到节头字符串表对应的section header的偏移位置 */
fseek(fp, sh_off + sh_strtab_index * sh_ent_size, SEEK_SET);
/* 再从section header中找到节头字符串表的偏移 */
/* sh_name(4) + sh_type(4) + sh_flags(8) + sh_addr(8) = 24 */
fseek(fp, 24, SEEK_CUR);
uint64_t str_table_off;
r = fread(&str_table_off, 1, 8, fp);
if (r != 8) {
perror("read section name string table offset");
exit(2);
}
printf("section name string table offset: %ld\n", str_table_off);
/* 从section header中找到节头字符串表的大小 */
uint64_t str_table_size;
r = fread(&str_table_size, 1, 8, fp);
if (r != 8) {
perror("read section name string table size");
exit(2);
}
printf("section name string table size: %ld\n", str_table_size);
/* 动态分配内存,把节头字符串表读到内存中 */
char *buf = (char *)malloc(str_table_size);
if(!buf) {
perror("allocate memory for section name string table");
exit(3);
}
fseek(fp, str_table_off, SEEK_SET);
r = fread(buf, 1, str_table_size, fp);
if(r != str_table_size) {
perror("read section name string table");
free(buf);
exit(2);
}
uint16_t i;
for(i = 0; i < str_table_size; ++i) {
/* 如果节头字符串表中的字节是0,就打印`\0` */
if (buf[i] == 0)
printf("\\0");
else
printf("%c", buf[i]);
}
printf("\n");
free(buf);
fclose(fp);
return 0;
}
#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。