欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对elf进行解析

程序员文章站 2022-07-15 16:29:53
...

 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