#include "elfreader.h" /******************************************************************************/ Elf_Ident* elf_ident( FILE *f ) { Elf_Ident *ret = NULL; size_t read_bytes = 0; if ( f == NULL ) { return NULL; } ret = malloc( sizeof(Elf_Ident) ); if ( ret == NULL ) { return NULL; } fseek( f, 0, SEEK_SET ); read_bytes = fread( ret->ident, 1, EI_NIDENT, f ); if ( read_bytes != EI_NIDENT ) { free( ret ); return NULL; } return ret; } /******************************************************************************/ int ident_check( Elf_Ident *ident ) { int ret=0; /* check if its elf file */ if ( (ident->ident[EI_MAG0] != ELFMAG0) || (ident->ident[EI_MAG1] != ELFMAG1) || (ident->ident[EI_MAG2] != ELFMAG2) || (ident->ident[EI_MAG3] != ELFMAG3) ) { printf("Elf header magic is wrong\n"); ret = -1; } /* check file class */ switch ( ident->ident[EI_CLASS] ) { case ELFCLASS32: case ELFCLASS64: break; default: printf("EI_CLASS not supported\n"); return -1; } return ret; } /******************************************************************************/ void ident_info( Elf_Ident *ident ) { printf("ELF IDENT:\n"); printf("ELFCLASS :0x%02x\n", ident->ident[EI_CLASS]); printf("ELFDATA :0x%02x\n", ident->ident[EI_DATA]); } /******************************************************************************/ int elf_ehdr_32( Elf_Ehdr *ehdr, Elf32_Ehdr *ehdr32, int byteorder ) { if ( byteorder == ELF_MLSB ) { /* working with MIPS on INTEL */ elf_ehdr32_bele( ehdr32 ); /* input was in MSB output now in LSB */ } else if ( (byteorder == ELF_MMSB) || (byteorder == ELF_LLSB) ) { /* no need to do something */ } else { /* is someone compile stuff on MIPS for Intel or so? */ ERROR("Not yet implemented\n"); /* Should be ok for now */ exit(0); } ehdr->e_type = ehdr32->e_type; ehdr->e_machine = ehdr32->e_machine; ehdr->e_version = ehdr32->e_version; ehdr->e_entry = ehdr32->e_entry; ehdr->e_phoff = ehdr32->e_phoff; ehdr->e_shoff = ehdr32->e_shoff; ehdr->e_flags = ehdr32->e_flags; ehdr->e_ehsize = ehdr32->e_ehsize; ehdr->e_phentsize = ehdr32->e_phentsize; ehdr->e_phnum = ehdr32->e_phnum; ehdr->e_shentsize = ehdr32->e_shentsize; ehdr->e_shnum = ehdr32->e_shnum; ehdr->e_shstrndx = ehdr32->e_shstrndx; return 0; } /******************************************************************************/ int elf_ehdr_64( Elf_Ehdr *ehdr, Elf64_Ehdr *ehdr64, int byteorder ) { ENL(); ehdr->e_type = ehdr64->e_type; ehdr->e_machine = ehdr64->e_machine; ehdr->e_version = ehdr64->e_version; ehdr->e_entry = ehdr64->e_entry; ehdr->e_phoff = ehdr64->e_phoff; ehdr->e_shoff = ehdr64->e_shoff; ehdr->e_flags = ehdr64->e_flags; ehdr->e_ehsize = ehdr64->e_ehsize; ehdr->e_phentsize = ehdr64->e_phentsize; ehdr->e_phnum = ehdr64->e_phnum; ehdr->e_shentsize = ehdr64->e_shentsize; ehdr->e_shnum = ehdr64->e_shnum; ehdr->e_shstrndx = ehdr64->e_shstrndx; return 0; } /******************************************************************************/ int elf_32_ehdr( Elf32_Ehdr *ehdr32, Elf_Ehdr *ehdr ) { ehdr32->e_type = ehdr->e_type; ehdr32->e_machine = ehdr->e_machine; ehdr32->e_version = ehdr->e_version; ehdr32->e_entry = ehdr->e_entry; ehdr32->e_phoff = ehdr->e_phoff; ehdr32->e_shoff = ehdr->e_shoff; ehdr32->e_flags = ehdr->e_flags; ehdr32->e_ehsize = ehdr->e_ehsize; ehdr32->e_phentsize = ehdr->e_phentsize; ehdr32->e_phnum = ehdr->e_phnum; ehdr32->e_shentsize = ehdr->e_shentsize; ehdr32->e_shnum = ehdr->e_shnum; ehdr32->e_shstrndx = ehdr->e_shstrndx; if ( ehdr->byteorder == ELF_MLSB ) { elf_ehdr32_bele( ehdr32 ); } else if ( (ehdr->byteorder == ELF_MMSB) || ( ehdr->byteorder == ELF_LLSB)) { /* No need to do anything */ } else { ERROR("Note implemtented\n"); } return 0; } /******************************************************************************/ int elf_64_ehdr( Elf64_Ehdr *ehdr64, Elf_Ehdr *ehdr ) { ehdr64->e_type = ehdr->e_type; ehdr64->e_machine = ehdr->e_machine; ehdr64->e_version = ehdr->e_version; ehdr64->e_entry = ehdr->e_entry; ehdr64->e_phoff = ehdr->e_phoff; ehdr64->e_shoff = ehdr->e_shoff; ehdr64->e_flags = ehdr->e_flags; ehdr64->e_ehsize = ehdr->e_ehsize; ehdr64->e_phentsize = ehdr->e_phentsize; ehdr64->e_phnum = ehdr->e_phnum; ehdr64->e_shentsize = ehdr->e_shentsize; ehdr64->e_shnum = ehdr->e_shnum; ehdr64->e_shstrndx = ehdr->e_shstrndx; return 0; } /******************************************************************************/ int elf_ehdr32_bele( Elf32_Ehdr *ehdr32 ) { int ret = 0; ehdr32->e_type = SWP16(ehdr32->e_type); ehdr32->e_machine = SWP16(ehdr32->e_machine); ehdr32->e_version = SWP32(ehdr32->e_version); ehdr32->e_entry = SWP32(ehdr32->e_entry); ehdr32->e_phoff = SWP32(ehdr32->e_phoff ); ehdr32->e_shoff = SWP32(ehdr32->e_shoff); ehdr32->e_flags = SWP32(ehdr32->e_flags); ehdr32->e_ehsize = SWP16(ehdr32->e_ehsize); ehdr32->e_phentsize = SWP16(ehdr32->e_phentsize); ehdr32->e_phnum = SWP16(ehdr32->e_phnum); ehdr32->e_shentsize = SWP16(ehdr32->e_shentsize); ehdr32->e_shnum = SWP16(ehdr32->e_shnum); ehdr32->e_shstrndx = SWP16(ehdr32->e_shstrndx); return ret; } /******************************************************************************/ int elf_ehdr32_lebe( Elf32_Ehdr *ehdr32 ) { int ret = 0; uint16_t u16; PNL(); /* ehdr32->e_type = SWP16(ehdr32->e_type); ehdr32->e_machine = SWP16(ehdr32->e_machine); ehdr32->e_version = SWP32(ehdr32->e_version); ehdr32->e_entry = SWP32(ehdr32->e_entry); ehdr32->e_phoff = SWP32(ehdr32->e_phoff ); ehdr32->e_shoff = SWP32(ehdr32->e_shoff); ehdr32->e_flags = SWP32(ehdr32->e_flags); ehdr32->e_ehsize = SWP16(ehdr32->e_ehsize); ehdr32->e_phentsize = SWP16(ehdr32->e_phentsize); ehdr32->e_phnum = SWP16(ehdr32->e_phnum); ehdr32->e_shentsize = SWP16(ehdr32->e_shentsize); ehdr32->e_shnum = SWP16(ehdr32->e_shnum); ehdr32->e_shstrndx = SWP16(ehdr32->e_shstrndx); */ return ret; } /******************************************************************************/ int elf_ehdr2mem( Elf_Ident *ident, Elf_Ehdr *ehdr, uint8_t *buf, int size ) { int ret = 0; int i,j; uint8_t *head = NULL; int sz_head = -1; if ( ehdr->type == ELF_TYPE_32 ) { sz_head = sizeof(Elf32_Ehdr); head = malloc( sz_head ); elf_32_ehdr( (Elf32_Ehdr *)head, ehdr ); } else if ( ehdr->type == ELF_TYPE_64 ) { sz_head = sizeof(Elf64_Ehdr); head = malloc( sz_head ); elf_64_ehdr( (Elf64_Ehdr *)head, ehdr ); } else { printf("Unknown ELF header type\n"); return -1; } memcpy( head, ident->ident, EI_NIDENT); for (i=0,j=0; (iident[EI_CLASS] ) { case ELFCLASS32: class = ELF_TYPE_32; sz_buf = sizeof(Elf32_Ehdr); break; case ELFCLASS64: class = ELF_TYPE_64; sz_buf = sizeof(Elf64_Ehdr); break; default: printf("Unknown ELFCLASS class\n"); } /* check file endianess */ switch ( ident->ident[EI_DATA] ) { case ELFDATA2LSB: if ( sysorder == __ORDER_LITTLE_ENDIAN__ ) { byteorder = ELF_LLSB; } else if ( sysorder == __ORDER_BIG_ENDIAN__ ) { byteorder = ELF_LMSB; } else { ENL(); } break; case ELFDATA2MSB: if ( sysorder == __ORDER_LITTLE_ENDIAN__ ) { byteorder = ELF_MLSB; } else if ( sysorder == __ORDER_BIG_ENDIAN__ ) { byteorder = ELF_MMSB; } else { ENL(); } break; case ELFDATANONE: default: printf("Unknown\n"); } /* create buffer for elf header */ buf = malloc( sz_buf ); if ( buf == NULL ) { printf("alloc NULL\n"); return NULL; } fseek( f, 0, SEEK_SET ); if ( fread( buf, 1, sz_buf, f) != sz_buf ) { free( buf ); printf("Cannot read ELF header\n"); return NULL; } //dont chk mmalc =P ret = malloc( sizeof(Elf_Ehdr) ); if ( class == ELF_TYPE_32 ) { PNL(); elf_ehdr_32( ret, (Elf32_Ehdr *)buf, byteorder ); ret->type = ELF_TYPE_32; ret->byteorder = byteorder; PNL(); } else if ( class == ELF_TYPE_64 ) { PNL(); elf_ehdr_64( ret, (Elf64_Ehdr *)buf, byteorder ); ret->type = ELF_TYPE_64; ret->byteorder = byteorder; } else { printf("Unknown elf class\n"); return NULL; } return ret; } /******************************************************************************/ void header_info( Elf_Ehdr *ehdr ) { printf("ELF EXCUTABLE HEADER\n"); printf("TYPE : 0x%04x\n", ehdr->e_type ); printf("ENTRY : 0x%08x\n", ehdr->e_entry ); printf("PHOFF : 0x%04x\n", ehdr->e_phoff ); printf("SHOFF : 0x%04x\n", ehdr->e_shoff ); printf("EHSIZE : 0x%04x(%u bytes)\n", ehdr->e_ehsize, ehdr->e_ehsize ); printf("PHENTSIZE : 0x%04x(%u bytes)\n", ehdr->e_phentsize, ehdr->e_phentsize ); printf("PHNUM : 0x%04x(%u bytes)\n", ehdr->e_phnum, ehdr->e_phnum ); printf("SHENTSIZE : 0x%04x(%u bytes)\n", ehdr->e_shentsize, ehdr->e_shentsize ); printf("SHNUM : 0x%04x(%u bytes)\n", ehdr->e_shnum, ehdr->e_shnum ); } /******************************************************************************/ int elf_phdr_32( Elf_Phdr *phdr, Elf32_Phdr *phdr32 ) { return -1; } /******************************************************************************/ int elf_phdr_64( Elf_Phdr *phdr, Elf64_Phdr *phdr64 ) { return -1; } /******************************************************************************/ int elf_32_phdr( Elf32_Phdr *phdr32, Elf_Phdr *phdr ) { return -1; } /******************************************************************************/ int elf_64_phdr( Elf64_Phdr *phdr64, Elf_Phdr *phdr ) { return -1; } /******************************************************************************/ Elf_Phdr* elf_phdr( FILE *f, Elf_Ehdr *ehdr ) { Elf_Phdr *ret = NULL; return ret; } /******************************************************************************/ int elf_shdr_32( Elf_Shdr *shdr, Elf32_Shdr *shdr32 ) { shdr->sh_name = shdr32->sh_name; shdr->sh_type = shdr32->sh_type; shdr->sh_flags = shdr32->sh_flags; shdr->sh_addr = shdr32->sh_addr; shdr->sh_offset = shdr32->sh_offset; shdr->sh_size = shdr32->sh_size; shdr->sh_link = shdr32->sh_link; shdr->sh_info = shdr32->sh_info; shdr->sh_addralign = shdr32->sh_addralign; shdr->sh_entsize = shdr32->sh_entsize; return 0; } /******************************************************************************/ int elf_shdr_64( Elf_Shdr *shdr, Elf64_Shdr *shdr64 ) { shdr->sh_name = shdr64->sh_name; shdr->sh_type = shdr64->sh_type; shdr->sh_flags = shdr64->sh_flags; shdr->sh_addr = shdr64->sh_addr; shdr->sh_offset = shdr64->sh_offset; shdr->sh_size = shdr64->sh_size; shdr->sh_link = shdr64->sh_link; shdr->sh_info = shdr64->sh_info; shdr->sh_addralign = shdr64->sh_addralign; shdr->sh_entsize = shdr64->sh_entsize; return 0; } /******************************************************************************/ int elf_32_shdr( Elf32_Shdr *shdr32, Elf_Shdr *shdr ) { shdr32->sh_name = shdr->sh_name; shdr32->sh_type = shdr->sh_type; shdr32->sh_flags = shdr->sh_flags; shdr32->sh_addr = shdr->sh_addr; shdr32->sh_offset = shdr->sh_offset; shdr32->sh_size = shdr->sh_size; shdr32->sh_link = shdr->sh_link; shdr32->sh_info = shdr->sh_info; shdr32->sh_addralign = shdr->sh_addralign; shdr32->sh_entsize = shdr->sh_entsize; return 0; } /******************************************************************************/ int elf_64_shdr( Elf64_Shdr *shdr64, Elf_Shdr *shdr ) { shdr64->sh_name = shdr->sh_name; shdr64->sh_type = shdr->sh_type; shdr64->sh_flags = shdr->sh_flags; shdr64->sh_addr = shdr->sh_addr; shdr64->sh_offset = shdr->sh_offset; shdr64->sh_size = shdr->sh_size; shdr64->sh_link = shdr->sh_link; shdr64->sh_info = shdr->sh_info; shdr64->sh_addralign = shdr->sh_addralign; shdr64->sh_entsize = shdr->sh_entsize; return 0; } /******************************************************************************/ int elf_shdr64_lebe( Elf64_Shdr *shdr64 ) { int ret = 0; ERROR("Not implemented\n"); return ret; } /******************************************************************************/ int elf_shdr32_lebe( Elf32_Shdr *shdr32 ) { int ret = 0; shdr32->sh_name = SWP32(shdr32->sh_name); shdr32->sh_type = SWP32(shdr32->sh_type); shdr32->sh_flags = SWP32(shdr32->sh_flags); shdr32->sh_addr = SWP32(shdr32->sh_addr); shdr32->sh_offset = SWP32(shdr32->sh_offset); shdr32->sh_size = SWP32(shdr32->sh_size); shdr32->sh_link = SWP32(shdr32->sh_link); shdr32->sh_info = SWP32(shdr32->sh_info); shdr32->sh_addralign = SWP32(shdr32->sh_addralign); shdr32->sh_entsize = SWP32(shdr32->sh_entsize); return ret; } /******************************************************************************/ int elf_shdr2mem( Elf_Shdr *shdr, uint8_t *buf, int size, int offset ) { int ret = 0; int i,j; uint8_t *sec_head = NULL; int sz_sec_head = -1; if ( shdr->type == ELF_TYPE_32 ) { sz_sec_head = sizeof(Elf32_Shdr); sec_head = malloc(sz_sec_head); elf_32_shdr( (Elf32_Shdr *)sec_head, shdr ); if (shdr->byteorder == ELF_MLSB) { elf_shdr32_lebe( (Elf32_Shdr *)sec_head ); } else if ( (shdr->byteorder == ELF_MMSB) || (shdr->byteorder == ELF_LLSB) ) { } else { ENL(); } } else if ( shdr->type == ELF_TYPE_64 ) { sz_sec_head = sizeof(Elf64_Shdr); sec_head = malloc( sz_sec_head ); elf_64_shdr( (Elf64_Shdr *)sec_head, shdr ); if (shdr->byteorder == ELF_MLSB) { elf_shdr64_lebe( (Elf64_Shdr *)sec_head ); } else if ( (shdr->byteorder == ELF_MMSB) || (shdr->byteorder == ELF_LLSB) ) { } else { ENL(); } } else { printf("Unknown type\n"); return -1; } for (i=offset,j=0; (je_shoff == 0) { printf("No section headers\n"); return NULL; } /* set section header size according of file class */ switch ( ehdr->type ) { case ELF_TYPE_32: sz_buf = sizeof(Elf32_Shdr); break; case ELF_TYPE_64: sz_buf = sizeof(Elf64_Shdr); break; default: printf("Unknown ELFCLASS\n"); return NULL; } /* Read/convert data accroding to elf class */ sh_num = ehdr->e_shnum; ret = malloc( sizeof(Elf_Shdr*)*(sh_num+1)); memset( ret, 0, sizeof(Elf_Shdr*)*(sh_num+1) ); // last value should be null buf = malloc( sz_buf ); //no check =P fseek( f, ehdr->e_shoff, SEEK_SET ); for (i=0; itype) { case ELF_TYPE_32: elf_shdr_32( sh, (Elf32_Shdr *)buf ); break; case ELF_TYPE_64: elf_shdr_64( sh, (Elf64_Shdr *)buf ); break; default: printf("Unknown class/ unknown state\n"); return NULL; } /* Remember section header type */ sh->type = ehdr->type; ret[i] = sh; } return ret; } void section_info( Elf_Shdr* shdr, Elf_Shdr_strtab *strtab ) { printf("ELF SECTION HEADER:\n"); if ( NULL == shdr || NULL == strtab ) { ENL(); return; } if ( strtab != NULL ) { char *s = NULL; s = strtab_name( strtab, shdr->sh_name); //printf("sh_name,0x%x\n",shdr->sh_name); //printf("offset,0x%x\n",strtab->offset+shdr->sh_name); if ( s != NULL ) { printf("NAME :%s\n", s); //free( s ); //s = NULL; } } printf("NAME : 0x%08x ", shdr->sh_name); printf("TYPE : 0x%02x ", shdr->sh_type); printf("OFFSET: 0x%08x ", shdr->sh_offset); printf("SIZE : 0x%08x\n", shdr->sh_size); } Elf_Shdr_strtab* strtab_search( FILE *f, Elf_Ehdr *ehdr, Elf_Shdr **shdr ) { uint16_t strndx; int i; Elf_Shdr_strtab *ret = NULL; Elf_Shdr *iter = NULL; if ( NULL == shdr || NULL == *shdr || NULL == ehdr || NULL == f ) { return NULL; } strndx = ehdr->e_shstrndx; if (strndx != 0) { iter = shdr[strndx]; } else { return NULL; } ret = malloc( sizeof(Elf_Shdr_strtab) ); ret->offset = iter->sh_offset; ret->sz_tab = iter->sh_size; ret->strtab = malloc(ret->sz_tab); fseek( f, ret->offset, SEEK_SET ); if ( fread( ret->strtab, 1, ret->sz_tab, f ) != ret->sz_tab ) { free( ret->strtab ); free( ret ); printf("Cannot read strtab\n"); return NULL; } return ret; } /* no need to free return value */ unsigned char* strtab_name( Elf_Shdr_strtab *strtab, long offset ) { unsigned char *ret = NULL; if ( strtab == NULL ) { return NULL; } if ( offset > strtab->sz_tab ) { printf("strtab offset > then header size\n"); return NULL; } if ( offset < 0 ) { printf("strtab offset <0\n"); return NULL; } ret = &strtab->strtab[offset]; return ret; }