elf.c
/**************************************
*Copyright yldfree
*2017-10-5
* ************************************/
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "elf.h"
void show_arg_help(void)
{
printf("\t -ehdr filename show elf header\n");
printf("\t -phdr filename show elf program header info\n");
printf("\t -shdr filename show elf section header info\n");
printf("\t -symtab filename show elf symbol table info\n");
printf("\t -dsymtab filename show elf symbol table info\n");
printf("\t -dynamic filename show elf symbol table info\n");
return;
}
int parse_args(int argc,char*argv[],char *buff)
{
int index = 1;
if(!strcmp(argv[index],"-ehdr"))
{
strcpy(buff,argv[index+1]);
return SHOW_EHDR;
}
if(!strcmp(argv[index],"-phdr"))
{
strcpy(buff,argv[index+1]);
return SHOW_PHDR;
}
if(!strcmp(argv[index],"-shdr"))
{
strcpy(buff,argv[index+1]);
return SHOW_SHDR;
}
if(!strcmp(argv[index],"-symtab"))
{
strcpy(buff,argv[index+1]);
return SHOW_SYMTAB;
}
if(!strcmp(argv[index],"-dsymtab"))
{
strcpy(buff,argv[index+1]);
return SHOW_DSYMTAB;
}
if(!strcmp(argv[index],"-dynamic"))
{
strcpy(buff,argv[index+1]);
return SHOW_DYNAMIC;
}
if(!strcmp(argv[index],"-rel"))
{
strcpy(buff,argv[index+1]);
return SHOW_RELTAB;
}
show_arg_help();
return SHOW_MAX;
}
char *get_machine_type(int matype)
{
switch(matype)
{
case EM_M32: return "WE32100";
case EM_SPARC: return "Sparc";
case EM_386: return "Intel 80386";
case EM_68K: return "MC68000";
case EM_88K: return "MC88000";
case EM_860: return "Intel 80860";
case EM_MIPS: return "MIPS R3000";
case EM_PARISC: return "HPPA";
case EM_SPARC32PLUS: return "Sparc v8+" ;
case EM_PPC: return "PowerPC";
case EM_PPC64: return "PowerPC64";
case EM_S390: return "EM_S390";
case EM_SH: return "Renesas / SuperH SH";
case EM_SPARCV9: return "Sparc v9";
case EM_IA_64: return "Intel IA-64";
case EM_CRIS: return "Axis Communications 32-bit embedded processor";
case EM_V850: return "NEC v850";
case EM_X86_64: return "Advanced Micro Devices X86-64";
case EM_M32R: return "Renesas M32R";
case EM_H8_300: return "Renesas H8/300,300H,H8S";
case EM_MN10300: return "Panasonic/MEI MN10300, AM33";
default: return "Invalid";
}
}
void show_ehdr(ObjElf *pelf)
{
int i;
printf("*******************************show elf header****************************************\n\n");
printf("Magic: ");
for(i = 0; i < EI_NIDENT; i++)//EI_NIDENT=16
printf("%02x ",pelf->ehdr->e_ident[i]);
printf("\n");
printf("\t ************************************\n");
printf("\t * M[4]SysBit: ");
switch(pelf->ehdr->e_ident[4])
{
case 1:
printf("32 Bit \n");
break;
case 2:
printf("64 Bit \n");
break;
default:
printf("Undefined \n");
break;
}
printf("\t * M[5]CodeFormat: ");
switch(pelf->ehdr->e_ident[5])
{
case ELFDATA2LSB://1
printf("little endian \n");
break;
case ELFDATA2MSB:
printf("big endain \n");
break;
default:
printf("Invalid \n");
break;
}
printf("\t ************************************\n");
printf("File Type: ");
switch(pelf->ehdr->e_type)
{
case ET_REL:
printf("Relocatable File\n");
break;
case ET_EXEC:
printf("Execute File\n");
break;
case ET_DYN:
printf("Dynamic File\n");
break;
case ET_CORE:
printf("Core File\n");
break;
default:
printf("Invalid File\n");
break;
}
printf("Machine Type: %s\n",get_machine_type(pelf->ehdr->e_machine));
printf("Version: 0x%x\n",pelf->ehdr->e_version);
printf("Program Entry: 0x%x\n",pelf->ehdr->e_entry);
printf("Program Header Offset: 0x%x\n",pelf->ehdr->e_phoff);
printf("Pro Header item size: %d\n",pelf->ehdr->e_phentsize);
printf("Pro Header item Num: %d\n",pelf->ehdr->e_phnum);
printf("Section Header Offset: 0x%x\n",pelf->ehdr->e_shoff);
printf("Sec Header item size: %d\n",pelf->ehdr->e_shentsize);
printf("Sec Header item num: %d\n",pelf->ehdr->e_shnum);
printf("Flags: 0x%x\n",pelf->ehdr->e_flags);
printf("Elf header size: %d\n",pelf->ehdr->e_ehsize);
printf("SecName StrTab Index: %d\n",pelf->ehdr->e_shstrndx);
printf("\n**************************************************************************************\n");
}
char *get_phdr_type(int type)
{
switch(type)
{
case PT_NULL: return "NULL";
case PT_LOAD: return "LOAD";
case PT_DYNAMIC: return "DYNAMIC";
case PT_INTERP: return "INTERP";
case PT_NOTE: return "NOTE";
case PT_SHLIB: return "SHLIB";
case PT_PHDR: return "PHDR";
case PT_TLS: return"TLS";
case PT_GNU_EH_FRAME: return "EHFRAME";
case PT_GNU_STACK: return "STACK";
case PT_GNU_RELRO: return "RELRO";
}
return "NULL";
}
char * get_phdr_flags(int flag,char *buff)
{
if(flag & PF_R)
strcat(buff,"R");
if(flag & PF_W)
strcat(buff,"W");
if(flag & PF_X)
strcat(buff,"X");
if('\0' == buff[0])
strcat(buff,"NULL");
return buff;
}
void show_phdr(ObjElf *pelf)
{
int phnum = pelf->ehdr->e_phnum;
int phentsize = pelf->ehdr->e_phentsize;
int i = 0;
char buff[10];
if(NULL == pelf)
{
printf("Error !! parse Program header error\n");
return;
}
printf("\n********************************************Parser Program Header ***********************************************\n");
printf("* item size: %d, item num:%d R:读 W:写 X:执行*\n\n",phentsize,phnum);
printf("%7s | %4s | %8s(d) | %8s(x) | %8s(x) | %8s(d) | %8s(d) | %8s(x) |\n","Type","Flags","offset","vaddr","paddr","fsize","msize","align");
printf("-----------------------------------------------------------------------------------------------------\n");
for(i = 0; i < phnum; i++)
{
memset(buff,0,10);
if( 0 == i % 2)
printf("\033[32m");
printf("%7s | ",get_phdr_type(pelf->phdr[i].p_type));
printf("%4s |",get_phdr_flags(pelf->phdr[i].p_flags,buff));
printf("%8d |",pelf->phdr[i].p_offset);
printf("%8x |",pelf->phdr[i].p_vaddr);
printf("%8x |",pelf->phdr[i].p_paddr);
printf("%8ld |",pelf->phdr[i].p_filesz);
printf("%8ld |",pelf->phdr[i].p_memsz);
printf("%8x |",pelf->phdr[i].p_align);
if( 0 == i % 2)
printf("\033[0m");
printf("\n");
}
printf("------------------------------------------------------------------------------------------------------\n");
printf("NULL: 不知类型. \nLOAD: 可以加载,如(.data .text). \nDYNAMIC: 动态连接段. \nINTERP: 动态链接器.\n");
printf("NOTE: 辅助信息\nSHLIB: 保留字段\nPHDR: 指定程序头表在文件及程序内存映像中的位置和大小\n");
printf("TLS: 线程本地存储信息\nEHFRAME: 异常处理信息的位置和大小\n");
printf("STACK: 包含了堆栈段的权限 \nRELRO: 段内的数据在重定向后是只读的\n");
printf("\n*****************************************************************************************************************\n\n");
}
char *get_section_flag(int flag,char *buff)
{
if(flag & SHF_WRITE)
strcat(buff,"W");
if(flag & SHF_ALLOC)
strcat(buff,"A");
if(flag & SHF_EXECINSTR)
strcat(buff,"X");
if(flag & SHF_MERGE)
strcat(buff,"M");
if(flag & SHF_STRINGS)
strcat(buff,"S");
if(flag & SHF_INFO_LINK)
strcat(buff,"I");
if(flag & SHF_LINK_ORDER)
strcat(buff,"L");
if(flag & SHF_OS_NONCONFORMING)
strcat(buff,"O");
if(flag & SHF_GROUP)
strcat(buff,"G");
if(flag & SHF_TLS)
strcat(buff,"T");
if(flag & SHF_EXCLUDE)
strcat(buff,"E");
if(buff[0] == '\0')
strcat(buff,"NULL");
return buff;
}
char *get_section_type(int type)
{
switch(type)
{
case SHT_PROGBITS: return "PROGBITS";
case SHT_SYMTAB: return "SYMTAB";
case SHT_STRTAB: return "STRTAB";
case SHT_RELA: return "RELA";
case SHT_HASH: return "HASH";
case SHT_DYNAMIC: return "DYNAMIC";
case SHT_NOTE: return "NOTE";
case SHT_NOBITS: return "NOBITS";
case SHT_REL: return "REL";
case SHT_SHLIB: return "SHLIB";
case SHT_DYNSYM: return "DYNSYM";
case SHT_INIT_ARRAY: return "INIT_ARRAY";
case SHT_FINI_ARRAY: return "FINI_ARRAY";
case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY";
case SHT_GNU_HASH: return "GNU_HASH";
case SHT_GROUP: return "GROUP";
case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES";
case SHT_GNU_verdef: return "VERDEF";
case SHT_GNU_verneed: return "VERNEED";
case SHT_GNU_versym: return "VERSYM";
case 0x6ffffff0: return "VERSYM";
case 0x6ffffffc: return "VERDEF";
case 0x7ffffffd: return "AUXILIARY";
case 0x7fffffff: return "FILTER";
case SHT_GNU_LIBLIST: return "GNU_LIBLIST";
default: return "NULL";
}
return "NULL";
}
void show_shdr(ObjElf *pelf)
{
int i = 0;
int shnum = pelf->ehdr->e_shnum;
int shentsize = pelf->ehdr->e_ehsize;
char buff[256]={0};
printf("**************************************************************show section header********************************************************************\n");
printf("* section num:%d section item size:%d W:可写 A:占用内存 X:可执行*\n\n",shnum,shentsize);
printf("%20s | %23s | %5s | %9s | %8s | %8s | %8s | %8s | %8s | %12s |\n","name","type","flags","offset(d)","vaddr(x)","size(d)","link(d)","info(d)","align(x)","entsizd(d)");
printf("------------------------------------------------------------------------------------------------------------------------------------------\n");
for(i = 0; i < shnum; i++)
{
memset(buff,0,256);
if( 0 == i % 2)
printf("\033[32m");
printf("%20s | ",pelf->shstrtab+pelf->shdr[i].sh_name);
printf("%23s | ",get_section_type(pelf->shdr[i].sh_type));
printf("%5s | ", get_section_flag(pelf->shdr[i].sh_flags,buff));
printf("%9d | ",pelf->shdr[i].sh_offset);
printf("%8x | ",pelf->shdr[i].sh_addr);
printf("%8d | ",pelf->shdr[i].sh_size);
printf("%8d | ",pelf->shdr[i].sh_link);
printf("%8d | ",pelf->shdr[i].sh_info);
printf("%8x | ",pelf->shdr[i].sh_addralign);
printf("%12d | ",pelf->shdr[i].sh_entsize);
if( 0 == i % 2)
printf("\033[0m");
printf("\n");
}
printf("--------------------------------------------------------------------------------------------------------------------------------------------\n");
printf("\n*****************************************************************************************************************************************************\n");
}
char *get_symtabtype(int type)
{
switch(type)
{
case STT_NOTYPE: return "NOTYPE";
case STT_OBJECT: return "OBJECT";
case STT_FUNC: return "FUNC";
case STT_SECTION: return "SECT";
case STT_FILE: return "FILE";
case STT_COMMON: return "COMM";
case STT_TLS: return "TLS";
case STT_RELC: return "RELC";
case STT_SRELC: return "SRELC";
case STT_GNU_IFUNC: return "GNUIFUNC";
case STT_HIOS: return "HIOS";
}
return "INVAL";
}
char *get_symtabbind(int bind)
{
switch(bind)
{
case STB_LOCAL :return "LOCAL";
case STB_GLOBAL :return "GLOBAL";
case STB_WEAK :return "WEAK";
case STB_GNU_UNIQUE :return "GNUUNI";
case STB_HIOS :return "HIOS";
}
return "INVAL";
}
char *get_symtabndx(ObjElf *pelf,int ndx)
{
if(ndx == SHN_UNDEF)
return "UNDEF";
if(ndx == SHN_LORESERVE)
return "LORESERVE";
if(ndx == SHN_LOPROC)
return "LOPROC";
if(ndx == SHN_HIPROC)
return "HIPROC";
if(ndx == SHN_ABS)
return "ABS";
if(ndx == SHN_COMMON)
return "COMMON";
if(ndx >= pelf->ehdr->e_shnum)
return "INVAL";
return pelf->shstrtab + pelf->shdr[ndx].sh_name;
}
void show_symtab(ObjElf *pelf)
{
int i =0;
printf("%4s | %8s | %8s | %5s | %20s | %8s | %8s | %s \n","Num","type","bind","other","secname","value(x)","size(d)","name");
printf("-------------------------------------------------------------------------------------\n");
for(i; i < pelf->symnum; i++)
{
printf("%4d: ",i);
printf("%8s | ",get_symtabtype(ELF_ST_TYPE(pelf->symtab[i].st_info)));
printf("%8s | ",get_symtabbind(ELF_ST_BIND(pelf->symtab[i].st_info)));
printf("%5d | ",pelf->symtab[i].st_other);
printf("%20s | ",get_symtabndx(pelf,pelf->symtab[i].st_shndx),pelf->symtab[i].st_shndx);
printf("%8x | ",pelf->symtab[i].st_value);
printf("%8d | ",pelf->symtab[i].st_size);
printf("%s ",pelf->strtab+pelf->symtab[i].st_name);
printf("\n");
}
}
void show_dsymtab(ObjElf *pelf)
{
int i =0;
printf("%4s | %8s | %8s | %5s | %20s | %8s | %8s | %s \n","Num","type","bind","other","secname","value(x)","size(d)","name");
printf("-------------------------------------------------------------------------------------\n");
for(i; i < pelf->dsymnum; i++)
{
printf("%4d: ",i);
printf("%8s | ",get_symtabtype(ELF_ST_TYPE(pelf->dsymtab[i].st_info)));
printf("%8s | ",get_symtabbind(ELF_ST_BIND(pelf->dsymtab[i].st_info)));
printf("%5d | ",pelf->dsymtab[i].st_other);
printf("%20s | ",get_symtabndx(pelf,pelf->dsymtab[i].st_shndx),pelf->dsymtab[i].st_shndx);
printf("%8x | ",pelf->dsymtab[i].st_value);
printf("%8d | ",pelf->dsymtab[i].st_size);
printf("%s ",pelf->dstrtab+pelf->dsymtab[i].st_name);
printf("\n");
}
}
char *get_dynamic_tag(int tag)
{
switch(tag)
{
case DT_NEEDED :return "NEEDED";
case DT_NULL :return "NULL";
case DT_PLTRELSZ :return "PLTRELSZ";
case DT_PLTGOT :return "PLTGOT";
case DT_HASH :return "HASH";
case DT_STRTAB :return "STRTAB";
case DT_SYMTAB :return "SYMTAB";
case DT_RELA :return "RELA";
case DT_RELASZ :return "RELASZ";
case DT_RELAENT :return "RELAENT";
case DT_STRSZ :return "STRSZ";
case DT_SYMENT :return "SYMENT";
case DT_INIT :return "INIT";
case DT_FINI :return "FINI";
case DT_SONAME :return "SONAME";
case DT_RPATH :return "RPATH";
case DT_SYMBOLIC :return "SYMBOLIC";
case DT_REL :return "REL";
case DT_RELSZ :return "RELSZ";
case DT_RELENT :return "RELENT";
case DT_PLTREL :return "PLTREL";
case DT_DEBUG :return "DEBUG";
case DT_TEXTREL :return "TEXTREL";
case DT_JMPREL :return "JMPREL";
case DT_VERSYM : return "VERSYM";
case DT_VERDEF : return "VERDEF";
case DT_VERDEFNUM : return "VERDEFNUM";
case DT_VERNEED : return "VERNEED";
case DT_VERNEEDNUM: return "VERNEEDNUM";
case DT_GNU_HASH: return "GNUHASH";
}
return "INVAL";
}
char * get_dynamic_val(ObjElf *pelf,int index,char *buff)
{
int tag = pelf->dynamic[index].d_tag;
switch(tag)
{
case DT_NEEDED:
sprintf(buff,"%s", pelf->dstrtab + pelf->dynamic[index].d_un.d_val);
break;
case DT_NULL : break;
case DT_PLTRELSZ :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_PLTGOT :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_HASH :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_STRTAB :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_SYMTAB :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_RELA :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_RELASZ :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_RELAENT :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_STRSZ :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_SYMENT :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_INIT :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_FINI :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_SONAME :
sprintf(buff,"%s", pelf->dstrtab + pelf->dynamic[index].d_un.d_val);
break;
case DT_RPATH :
sprintf(buff,"%s", pelf->dstrtab + pelf->dynamic[index].d_un.d_val);
break;
case DT_SYMBOLIC :
break;
case DT_REL :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_RELSZ :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_RELENT :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_PLTREL :
sprintf(buff,"%d", pelf->dynamic[index].d_un.d_val);
break;
case DT_DEBUG :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_TEXTREL :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_JMPREL :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_VERSYM :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_VERDEF :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_VERDEFNUM :
sprintf(buff,"%d",pelf->dynamic[index].d_un.d_val);
break;
case DT_VERNEED :
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
case DT_VERNEEDNUM:
sprintf(buff,"%d",pelf->dynamic[index].d_un.d_val);
break;
case DT_GNU_HASH:
sprintf(buff,"0x%x",pelf->dynamic[index].d_un.d_ptr);
break;
}
return buff;
}
void show_dynamic(ObjElf *pelf)
{
int i = 0;
char tebuff[1024]={0};
printf("%23s | %s\n","tag","name/value");
printf("----------------------------------------------\n");
for(i; i<pelf->dynamicnum; i++)
{
memset(tebuff,0,1024);
if(0 == pelf->dynamic[i].d_tag)
continue;
printf("%13s(%8x) | ",get_dynamic_tag(pelf->dynamic[i].d_tag),pelf->dynamic[i].d_tag);
printf("%s ", get_dynamic_val(pelf,i,tebuff));
printf("\n");
}
printf("----------------------------------------------\n");
return;
}
char *get_reltype(int type)
{
switch(type)
{
case R_X86_64_NONE :return "NONE";
case R_X86_64_64 :return "R_X86_64_64";
case R_X86_64_PC32 :return "R_X86_64_PC32";
case R_X86_64_GOT32 :return "R_X86_64_GOT32";
case R_X86_64_PLT32 :return "R_X86_64_PLT32";
case R_X86_64_COPY :return "R_X86_64_COPY";
case R_X86_64_GLOB_DAT :return "R_X86_64_GLOB_DAT";
case R_X86_64_JUMP_SLOT :return "R_X86_64_JUMP_SLOT";
case R_X86_64_RELATIVE :return "R_X86_64_RELATIVE";
case R_X86_64_GOTPCREL :return "R_X86_64_GOTPCREL";
case R_X86_64_32 :return "R_X86_64_32";
case R_X86_64_32S :return "R_X86_64_32S";
case R_X86_64_16 :return "R_X86_64_16";
case R_X86_64_PC16 :return "R_X86_64_PC16";
case R_X86_64_8 :return "R_X86_64_8";
case R_X86_64_PC8 :return "R_X86_64_PC8";
}
return "INVALID";
}
void show_reltab(ObjElf *pelf)
{
int i,j;
int flag = 0;
int isappend;
int numitem;
Elf_Rel *prel = NULL;
Elf_Rela *prela = NULL;
for(i = 0; i < pelf->ehdr->e_shnum; i++)
{
if(pelf->shdr[i].sh_type == SHT_RELA)
{
if(0 == flag)
{
printf("%10s | %25s | %10s | %s\n","offset(x)","type","sym.val","append");
flag = 1;
}
prela = (Elf_Rela *)(pelf->base + pelf->shdr[i].sh_offset);
printf("--------------------%s---------------\n",pelf->shstrtab + pelf->shdr[i].sh_name);
numitem = pelf->shdr[i].sh_size / pelf->shdr[i].sh_entsize;
for(j = 0; j< numitem; j++)
{
printf("%10x | ",prela[j].r_offset);
printf("%25s | ",get_reltype(ELF_R_TYPE(prela[j].r_info)));
printf("%10d | ",pelf->dsymtab[ELF_R_SYM(prela[j].r_info)].st_value);
printf("%d ", prela[j].r_addend);
printf("\n");
}
}
else if(pelf->shdr[i].sh_type == SHT_REL)
{
if(0 == flag)
{
printf("%10s | %25s | %10s | %10s\n","offset(d)","type","sym.val","append");
flag = 1;
}
prel = (Elf_Rel *)(pelf->base + pelf->shdr[i].sh_offset);
printf("-------------------%s---------------\n",pelf->shstrtab + pelf->shdr[i].sh_name);
numitem = pelf->shdr[i].sh_size / pelf->shdr[i].sh_entsize;
for(j = 0; j< numitem; j++)
{
printf("%10x | ",prel[j].r_offset);
printf("%25s | ",get_reltype(ELF_R_TYPE(prel[j].r_info)));
printf("%10d | ",pelf->dsymtab[ELF_R_SYM(prel[j].r_info)].st_value);
printf("%d ", 0);
printf("\n");
}
}
}
}
void run_opcode(int type,ObjElf *pelf)
{
switch(type)
{
case SHOW_EHDR:
show_ehdr(pelf);
break;
case SHOW_PHDR:
show_phdr(pelf);
break;
case SHOW_SHDR:
show_shdr(pelf);
break;
case SHOW_SYMTAB:
show_symtab(pelf);
break;
case SHOW_DSYMTAB:
show_dsymtab(pelf);
break;
case SHOW_DYNAMIC:
show_dynamic(pelf);
break;
case SHOW_RELTAB:
show_reltab(pelf);
break;
default:
break;
}
return;
}
void set_stelf_value(ObjElf *pelf)
{
int i = 0;
int shnum = 0;
pelf->ehdr = (Elf_Ehdr *)pelf->base; //elf header
pelf->phdr = (Elf_Phdr *)(pelf->ehdr->e_phoff+pelf->base); //pro header offset
pelf->shdr = (Elf_Shdr *)(pelf->ehdr->e_shoff+pelf->base); //section header offset
pelf->shstrtab = (char*)(pelf->shdr[pelf->ehdr->e_shstrndx].sh_offset + pelf->base);//shstrtab offset
//获得符号表数组的地址和个数
shnum = pelf->ehdr->e_shnum;
for(i = 0 ;i < shnum; i++)
{
if(SHT_SYMTAB == pelf->shdr[i].sh_type)
{
pelf->symtab = (Elf_Sym *)(pelf->base + pelf->shdr[i].sh_offset);
pelf->symnum = pelf->shdr[i].sh_size / (pelf->shdr[i].sh_entsize);
}
if(SHT_STRTAB == pelf->shdr[i].sh_type)
{
if(!strcmp(pelf->shstrtab + pelf->shdr[i].sh_name,".strtab"))
{
pelf->strtab = (char*)(pelf->base+pelf->shdr[i].sh_offset);
}
else if(!strcmp(pelf->shstrtab + pelf->shdr[i].sh_name,".dynstr"))
{
pelf->dstrtab = (char*)(pelf->base+pelf->shdr[i].sh_offset);
}
}
if(SHT_DYNSYM == pelf->shdr[i].sh_type)
{
pelf->dsymtab = (Elf_Sym *)(pelf->base + pelf->shdr[i].sh_offset);
pelf->dsymnum = pelf->shdr[i].sh_size / (pelf->shdr[i].sh_entsize);
}
if(SHT_DYNAMIC == pelf->shdr[i].sh_type)
{
pelf->dynamic = (Elf_Dyn *)(pelf->base + pelf->shdr[i].sh_offset);
pelf->dynamicnum = pelf->shdr[i].sh_size / (pelf->shdr[i].sh_entsize);
}
}
}
int main(int argc,char *argv[])
{
struct stat sta;
ObjElf elf={0};
int type;
if(argc <= 1)
{
show_arg_help();
return -1;
}
type = parse_args(argc,argv,elf.filename);
if(type == SHOW_MAX)
{
return -1;
}
elf.optype = type;
if(elf.filename[0] == '\0')
{
show_arg_help();
return -1;
}
if(stat(elf.filename,&sta) < 0)
{
printf("error\n");
return -1;
}
elf.filesize = sta.st_size;
elf.fd = open(elf.filename,O_RDWR);
if(elf.fd < 0)
{
printf("open file %s error\n",elf.filename);
return -1;
}
elf.base = mmap(NULL,elf.filesize,PROT_READ|PROT_WRITE,MAP_PRIVATE,elf.fd,0);
if(NULL == elf.base)
{
printf("fail to map file %s\n",elf.filename);
goto out;
}
if(!(0x7f == elf.base[0] && !strncmp("ELF",&elf.base[1],3)))
{
printf("Elf format is error\n");
return -1;
}
set_stelf_value(&elf);
run_opcode(type,&elf);
out:
if(NULL != elf.base)
{
munmap(elf.base,elf.filesize);
}
if(elf.fd > 0)
close(elf.fd);
return 0;
}
elf.h
#ifndef __YLD_ELF_H
#define __YLD_ELF_H
#define SHF_MERGE (1 << 4) /* Data in this section can be merged */
#define SHF_STRINGS (1 << 5) /* Contains null terminated character strings */
#define SHF_INFO_LINK (1 << 6) /* sh_info holds section header table index */
#define SHF_LINK_ORDER (1 << 7) /* Preserve section ordering when linking */
#define SHF_OS_NONCONFORMING (1 << 8) /* OS specific processing required */
#define SHF_GROUP (1 << 9) /* Member of a section group */
#define SHF_TLS (1 << 10) /* Thread local storage section */
#define STT_RELC 8 /* Complex relocation expression */
#define STT_SRELC 9 /* Signed Complex relocation expression */
#define STT_LOOS 10 /* OS-specific semantics */
#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
#define STT_HIOS 12 /* OS-specific semantics */
#define STT_LOPROC 13 /* Processor-specific semantics */
#define STT_HIPROC 15 /* Processor-specific semantics */
#define STB_LOOS 10 /* OS-specific semantics */
#define STB_GNU_UNIQUE 10 /* Symbol is unique in namespace */
#define STB_HIOS 12 /* OS-specific semantics */
#define STB_LOPROC 13 /* Processor-specific semantics */
#define STB_HIPROC 15 /* Processor-specific semantics */
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
#define ELF_R_SYM ELF64_R_SYM
#define ELF_R_TYPE ELF64_R_TYPE
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Phdr Elf_Phdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Sym Elf_Sym;
typedef Elf64_Dyn Elf_Dyn;
typedef Elf64_Rel Elf_Rel;
typedef Elf64_Rela Elf_Rela;
typedef enum op_type{
SHOW_EHDR = 0,
SHOW_PHDR,
SHOW_SHDR,
SHOW_SYMTAB,
SHOW_DSYMTAB,
SHOW_DYNAMIC,
SHOW_RELTAB,
SHOW_MAX
}OpType;
typedef struct obj_elf
{
off_t filesize;
int fd;
int symnum;
int dsymnum;
int dynamicnum;
char *base;
char filename[256];
int optype;
char *shstrtab;
char *strtab;
char *dstrtab;
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
Elf_Sym *symtab;
Elf_Sym *dsymtab;
Elf_Dyn *dynamic;
}ObjElf;
#endif