diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-05-02 13:20:59 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-05-02 13:20:59 +0000 |
commit | 776eae615326f6439734b05fa39c335bf2dc681b (patch) | |
tree | 99245d080a0e236fb6a8a1d41611f70bcc60d9ec /ldso/util | |
parent | 538aa2d8716fae77b9d613a59438d477ff8580ac (diff) |
Make ldd and readelf work even with byte swapped binaries
Diffstat (limited to 'ldso/util')
-rw-r--r-- | ldso/util/ldd.c | 73 | ||||
-rw-r--r-- | ldso/util/readelf.c | 65 |
2 files changed, 105 insertions, 33 deletions
diff --git a/ldso/util/ldd.c b/ldso/util/ldd.c index 253cf3503..3cbdf61aa 100644 --- a/ldso/util/ldd.c +++ b/ldso/util/ldd.c @@ -2,9 +2,8 @@ /* * A small little ldd implementation for uClibc * - * Copyright (C) 2000 by Lineo, inc. - * Copyright (C) 2000,2001 Erik Andersen <andersee@debian.org> - * Written by Erik Andersen <andersee@debian.org> + * Copyright (C) 2000 by Lineo, inc and Erik Andersen + * Copyright (C) 2000-2002 Erik Andersen <andersee@debian.org> * * Several functions in this file (specifically, elf_find_section_type(), * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from @@ -39,6 +38,8 @@ #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> +#include <endian.h> +#include <byteswap.h> #include "elf.h" #ifdef DMALLOC #include <dmalloc.h> @@ -52,15 +53,26 @@ struct library { }; struct library *lib_list = NULL; char not_found[] = "not found"; +int byteswap; + +inline uint32_t byteswap32_to_host(uint32_t value) +{ + if (byteswap==1) { + return(bswap_32(value)); + } else { + return(value); + } +} Elf32_Shdr * elf_find_section_type( int key, Elf32_Ehdr *ehdr) { int j; - Elf32_Shdr *shdr = (Elf32_Shdr *)(ehdr->e_shoff + (char *)ehdr); + Elf32_Shdr *shdr; + shdr = (Elf32_Shdr *)(ehdr->e_shoff + (char *)ehdr); for (j = ehdr->e_shnum; --j>=0; ++shdr) { - if (shdr->sh_type == key) { + if (key==byteswap32_to_host(shdr->sh_type)) { return shdr; } } @@ -72,7 +84,7 @@ Elf32_Phdr * elf_find_phdr_type( int type, Elf32_Ehdr *ehdr) int j; Elf32_Phdr *phdr = (Elf32_Phdr *)(ehdr->e_phoff + (char *)ehdr); for (j = ehdr->e_phnum; --j>=0; ++phdr) { - if (type==phdr->p_type) { + if (type==byteswap32_to_host(phdr->p_type)) { return phdr; } } @@ -84,19 +96,19 @@ void * elf_find_dynamic(int const key, Elf32_Dyn *dynp, Elf32_Ehdr *ehdr, int return_val) { Elf32_Phdr *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); - unsigned tx_reloc = pt_text->p_vaddr - pt_text->p_offset; - for (; DT_NULL!=dynp->d_tag; ++dynp) { - if (dynp->d_tag == key) { + unsigned tx_reloc = byteswap32_to_host(pt_text->p_vaddr) - byteswap32_to_host(pt_text->p_offset); + for (; DT_NULL!=byteswap32_to_host(dynp->d_tag); ++dynp) { + if (key == byteswap32_to_host(dynp->d_tag)) { if (return_val == 1) - return (void *)dynp->d_un.d_val; + return (void *)byteswap32_to_host(dynp->d_un.d_val); else - return (void *)(dynp->d_un.d_val - tx_reloc + (char *)ehdr ); + return (void *)(byteswap32_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr ); } } return NULL; } -int check_elf_header(Elf32_Ehdr const *const ehdr) +int check_elf_header(Elf32_Ehdr *const ehdr) { if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 || ehdr->e_ident[EI_CLASS] != ELFCLASS32 || @@ -104,6 +116,30 @@ int check_elf_header(Elf32_Ehdr const *const ehdr) { return 1; } + + /* Check if the target endianness matches the host's endianness */ + byteswap = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2MSB) { + /* Ick -- we will have to byte-swap everything */ + byteswap = 1; + } +#elif __BYTE_ORDER == __BIG_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2LSB) { + byteswap = 1; + } +#else +#error Unknown host byte order! +#endif + /* Be vary lazy, and only byteswap the stuff we use */ + if (byteswap==1) { + ehdr->e_type=bswap_16(ehdr->e_type); + ehdr->e_phoff=bswap_32(ehdr->e_phoff); + ehdr->e_shoff=bswap_32(ehdr->e_shoff); + ehdr->e_phnum=bswap_16(ehdr->e_phnum); + ehdr->e_shnum=bswap_16(ehdr->e_shnum); + } + return 0; } @@ -295,13 +331,14 @@ static void find_needed_libraries(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *st /* Find the path where the shared lib loader lives */ phdr = elf_find_phdr_type(PT_INTERP, ehdr); if (phdr) { - ldpath = strdup((char*)ehdr + phdr->p_offset); + ldpath = strdup((char*)ehdr + byteswap32_to_host(phdr->p_offset)); ldpath = basename(ldpath); } - for (dyns=dynamic; dyns->d_tag!=DT_NULL; ++dyns) { - if (dyns->d_tag == DT_NEEDED) { - add_library(ehdr, dynamic, strtab, is_setuid, (char*)strtab + dyns->d_un.d_val, ldpath); + for (dyns=dynamic; byteswap32_to_host(dyns->d_tag)!=DT_NULL; ++dyns) { + if (DT_NEEDED == byteswap32_to_host(dyns->d_tag)) { + add_library(ehdr, dynamic, strtab, is_setuid, (char*)strtab + + byteswap32_to_host(dyns->d_un.d_val), ldpath); } } } @@ -317,7 +354,7 @@ static void find_elf_interpreter(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *str phdr = elf_find_phdr_type(PT_INTERP, ehdr); if (phdr) { struct library *cur, *newlib=NULL; - char *s = (char*)ehdr + phdr->p_offset; + char *s = (char*)ehdr + byteswap32_to_host(phdr->p_offset); char *tmp, *tmp1; tmp1 = tmp = s; @@ -413,7 +450,7 @@ foo: dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); if (dynsec) { - dynamic = (Elf32_Dyn*)(dynsec->sh_offset + (int)ehdr); + dynamic = (Elf32_Dyn*)(byteswap32_to_host(dynsec->sh_offset) + (int)ehdr); dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); find_needed_libraries(ehdr, dynamic, dynstr, is_suid); } diff --git a/ldso/util/readelf.c b/ldso/util/readelf.c index 903b63148..98df3ffda 100644 --- a/ldso/util/readelf.c +++ b/ldso/util/readelf.c @@ -2,9 +2,8 @@ /* * A small little readelf implementation for uClibc * - * Copyright (C) 2000 by Lineo, inc. - * Copyright (C) 2000,2001 Erik Andersen <andersee@debian.org> - * Written by Erik Andersen <andersee@debian.org> + * Copyright (C) 2000 by Lineo, inc and Erik Andersen + * Copyright (C) 2000-2002 Erik Andersen <andersee@debian.org> * * Several functions in this file (specifically, elf_find_section_type(), * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from @@ -37,16 +36,27 @@ #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> +#include <endian.h> +#include <byteswap.h> #include "elf.h" +int byteswap; +inline uint32_t byteswap32_to_host(uint32_t value) +{ + if (byteswap==1) { + return(bswap_32(value)); + } else { + return(value); + } +} Elf32_Shdr * elf_find_section_type( int key, Elf32_Ehdr *ehdr) { int j; Elf32_Shdr *shdr = (Elf32_Shdr *)(ehdr->e_shoff + (char *)ehdr); for (j = ehdr->e_shnum; --j>=0; ++shdr) { - if (shdr->sh_type == key) { + if (key==byteswap32_to_host(shdr->sh_type)) { return shdr; } } @@ -58,7 +68,7 @@ Elf32_Phdr * elf_find_phdr_type( int type, Elf32_Ehdr *ehdr) int j; Elf32_Phdr *phdr = (Elf32_Phdr *)(ehdr->e_phoff + (char *)ehdr); for (j = ehdr->e_phnum; --j>=0; ++phdr) { - if (type==phdr->p_type) { + if (type==byteswap32_to_host(phdr->p_type)) { return phdr; } } @@ -70,19 +80,19 @@ void * elf_find_dynamic(int const key, Elf32_Dyn *dynp, Elf32_Ehdr *ehdr, int return_val) { Elf32_Phdr *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); - unsigned tx_reloc = pt_text->p_vaddr - pt_text->p_offset; - for (; DT_NULL!=dynp->d_tag; ++dynp) { - if (dynp->d_tag == key) { + unsigned tx_reloc = byteswap32_to_host(pt_text->p_vaddr) - byteswap32_to_host(pt_text->p_offset); + for (; DT_NULL!=byteswap32_to_host(dynp->d_tag); ++dynp) { + if (key == byteswap32_to_host(dynp->d_tag)) { if (return_val == 1) - return (void *)dynp->d_un.d_val; + return (void *)byteswap32_to_host(dynp->d_un.d_val); else - return (void *)(dynp->d_un.d_val - tx_reloc + (char *)ehdr ); + return (void *)(byteswap32_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr ); } } return NULL; } -int check_elf_header(Elf32_Ehdr const *const ehdr) +int check_elf_header(Elf32_Ehdr *const ehdr) { if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 || ehdr->e_ident[EI_CLASS] != ELFCLASS32 || @@ -90,9 +100,34 @@ int check_elf_header(Elf32_Ehdr const *const ehdr) { return 1; } + + /* Check if the target endianness matches the host's endianness */ + byteswap = 0; +#if __BYTE_ORDER == __LITTLE_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2MSB) { + /* Ick -- we will have to byte-swap everything */ + byteswap = 1; + } +#elif __BYTE_ORDER == __BIG_ENDIAN + if (ehdr->e_ident[5] == ELFDATA2LSB) { + byteswap = 1; + } +#else +#error Unknown host byte order! +#endif + /* Be vary lazy, and only byteswap the stuff we use */ + if (byteswap==1) { + ehdr->e_type=bswap_16(ehdr->e_type); + ehdr->e_machine=bswap_16(ehdr->e_machine); + ehdr->e_phoff=bswap_32(ehdr->e_phoff); + ehdr->e_shoff=bswap_32(ehdr->e_shoff); + ehdr->e_phnum=bswap_16(ehdr->e_phnum); + ehdr->e_shnum=bswap_16(ehdr->e_shnum); + } return 0; } + #define ELFOSABI_NONE 0 /* UNIX System V ABI */ #define ELFOSABI_HPUX 1 /* HP-UX operating system */ #define ELFOSABI_NETBSD 2 /* NetBSD */ @@ -245,9 +280,9 @@ static void list_needed_libraries(Elf32_Dyn* dynamic, char *strtab) Elf32_Dyn *dyns; printf("Dependancies:\n"); - for (dyns=dynamic; dyns->d_tag!=DT_NULL; ++dyns) { + for (dyns=dynamic; byteswap32_to_host(dyns->d_tag)!=DT_NULL; ++dyns) { if (dyns->d_tag == DT_NEEDED) { - printf("\t%s\n", (char*)strtab + dyns->d_un.d_val); + printf("\t%s\n", (char*)strtab + byteswap32_to_host(dyns->d_un.d_val)); } } } @@ -257,7 +292,7 @@ static void describe_elf_interpreter(Elf32_Ehdr* ehdr) Elf32_Phdr *phdr; phdr = elf_find_phdr_type(PT_INTERP, ehdr); if (phdr) { - printf("Interpreter:\t%s\n", (char*)ehdr + phdr->p_offset); + printf("Interpreter:\t%s\n", (char*)ehdr + byteswap32_to_host(phdr->p_offset)); } } @@ -304,7 +339,7 @@ foo: dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); if (dynsec) { - dynamic = (Elf32_Dyn*)(dynsec->sh_offset + (int)ehdr); + dynamic = (Elf32_Dyn*)(byteswap32_to_host(dynsec->sh_offset) + (int)ehdr); dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); list_needed_libraries(dynamic, dynstr); } |