Beginning to decode ELF binaries cross-endian

This commit is contained in:
Pierre Pronchery 2011-06-04 01:43:10 +00:00
parent 34dfcf56ea
commit 430d35282a

View File

@ -76,12 +76,16 @@ static int _init_32(FormatPlugin * format);
static int _exit_32(FormatPlugin * format);
static int _section_32(FormatPlugin * format, char const * name);
static void _swap_32_ehdr(Elf32_Ehdr * ehdr);
static void _swap_32_phdr(Elf32_Phdr * phdr);
static void _swap_32_shdr(Elf32_Shdr * shdr);
/* ELF64 */
static int _init_64(FormatPlugin * format);
static int _exit_64(FormatPlugin * format);
static int _section_64(FormatPlugin * format, char const * name);
static void _swap_64_ehdr(Elf64_Ehdr * ehdr);
static void _swap_64_phdr(Elf64_Phdr * phdr);
static void _swap_64_shdr(Elf64_Shdr * shdr);
/* ElfStrtab */
static int _elfstrtab_set(FormatPlugin * format, ElfStrtab * strtab,
@ -348,6 +352,8 @@ static int _elf_decode32(FormatPlugin * format)
|| helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr))
return -1;
if(ehdr.e_ident[EI_DATA] != elf_arch_native->endian)
_swap_32_ehdr(&ehdr);
if(_decode32_shdr(format, &ehdr, &shdr) != 0)
return -1;
if(_decode32_addr(format, &ehdr, &base) != 0
@ -379,6 +385,7 @@ static int _decode32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
{
FormatPluginHelper * helper = format->helper;
ssize_t size;
size_t i;
if(ehdr->e_shentsize == 0)
{
@ -399,6 +406,9 @@ static int _decode32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
free(*shdr);
return -1;
}
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
for(i = 0; i < ehdr->e_shnum; i++)
_swap_32_shdr(*shdr + i);
return 0;
}
@ -412,14 +422,18 @@ static int _decode32_addr(FormatPlugin * format, Elf32_Ehdr * ehdr,
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1;
for(i = 0; i < ehdr->e_phnum; i++)
{
if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr))
return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
_swap_32_phdr(&phdr);
if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{
*addr = phdr.p_vaddr;
return 0;
}
}
*addr = 0x0;
return 0;
}
@ -477,6 +491,8 @@ static int _elf_decode64(FormatPlugin * format)
|| helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr))
return -1;
if(ehdr.e_ident[EI_DATA] != elf_arch_native->endian)
_swap_64_ehdr(&ehdr);
if(_decode64_shdr(format, &ehdr, &shdr) != 0)
return -1;
if(_decode64_addr(format, &ehdr, &base) != 0
@ -508,6 +524,7 @@ static int _decode64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
{
FormatPluginHelper * helper = format->helper;
ssize_t size;
size_t i;
if(ehdr->e_shentsize == 0)
{
@ -528,6 +545,9 @@ static int _decode64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
free(*shdr);
return -1;
}
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
for(i = 0; i < ehdr->e_shnum; i++)
_swap_64_shdr(*shdr + i);
return 0;
}
@ -541,14 +561,18 @@ static int _decode64_addr(FormatPlugin * format, Elf64_Ehdr * ehdr,
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1;
for(i = 0; i < ehdr->e_phnum; i++)
{
if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr))
return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
_swap_64_phdr(&phdr);
if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{
*addr = phdr.p_vaddr;
return 0;
}
}
*addr = 0x0;
return 0;
}
@ -791,6 +815,36 @@ static void _swap_32_ehdr(Elf32_Ehdr * ehdr)
}
/* swap_32_phdr */
static void _swap_32_phdr(Elf32_Phdr * phdr)
{
phdr->p_type = _bswap32(phdr->p_type);
phdr->p_offset = _bswap32(phdr->p_offset);
phdr->p_vaddr = _bswap32(phdr->p_vaddr);
phdr->p_paddr = _bswap32(phdr->p_paddr);
phdr->p_filesz = _bswap32(phdr->p_filesz);
phdr->p_memsz = _bswap32(phdr->p_memsz);
phdr->p_flags = _bswap32(phdr->p_flags);
phdr->p_align = _bswap32(phdr->p_align);
}
/* swap_32_shdr */
static void _swap_32_shdr(Elf32_Shdr * shdr)
{
shdr->sh_name = _bswap32(shdr->sh_name);
shdr->sh_type = _bswap32(shdr->sh_type);
shdr->sh_flags = _bswap32(shdr->sh_flags);
shdr->sh_addr = _bswap32(shdr->sh_addr);
shdr->sh_offset = _bswap32(shdr->sh_offset);
shdr->sh_size = _bswap32(shdr->sh_size);
shdr->sh_link = _bswap32(shdr->sh_link);
shdr->sh_info = _bswap32(shdr->sh_info);
shdr->sh_addralign = _bswap32(shdr->sh_addralign);
shdr->sh_entsize = _bswap32(shdr->sh_entsize);
}
/* ELF64 */
/* variables */
static Elf64_Shdr * es64 = NULL;
@ -971,6 +1025,36 @@ static void _swap_64_ehdr(Elf64_Ehdr * ehdr)
}
/* swap_64_phdr */
static void _swap_64_phdr(Elf64_Phdr * phdr)
{
phdr->p_type = _bswap32(phdr->p_type);
phdr->p_flags = _bswap32(phdr->p_flags);
phdr->p_offset = _bswap64(phdr->p_offset);
phdr->p_vaddr = _bswap64(phdr->p_vaddr);
phdr->p_paddr = _bswap64(phdr->p_paddr);
phdr->p_filesz = _bswap64(phdr->p_filesz);
phdr->p_memsz = _bswap64(phdr->p_memsz);
phdr->p_align = _bswap64(phdr->p_align);
}
/* swap_64_shdr */
static void _swap_64_shdr(Elf64_Shdr * shdr)
{
shdr->sh_name = _bswap32(shdr->sh_name);
shdr->sh_type = _bswap32(shdr->sh_type);
shdr->sh_flags = _bswap64(shdr->sh_flags);
shdr->sh_addr = _bswap64(shdr->sh_addr);
shdr->sh_offset = _bswap64(shdr->sh_offset);
shdr->sh_size = _bswap64(shdr->sh_size);
shdr->sh_link = _bswap32(shdr->sh_link);
shdr->sh_info = _bswap32(shdr->sh_info);
shdr->sh_addralign = _bswap64(shdr->sh_addralign);
shdr->sh_entsize = _bswap64(shdr->sh_entsize);
}
/* ElfStrtab */
/* private */
/* functions */