ELF 解析所以重定位节 包含REL RELA,并未支持所有平台,仅实现了i386和arm平台 32位支持
/*
* ParseRelocation.c
*
* Created on: 2014年7月20日
* Author: angel-toms
*/
#include "ElfParser.h"
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;
}
}