summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-05-02 13:20:59 +0000
committerEric Andersen <andersen@codepoet.org>2002-05-02 13:20:59 +0000
commit776eae615326f6439734b05fa39c335bf2dc681b (patch)
tree99245d080a0e236fb6a8a1d41611f70bcc60d9ec /ldso
parent538aa2d8716fae77b9d613a59438d477ff8580ac (diff)
Make ldd and readelf work even with byte swapped binaries
Diffstat (limited to 'ldso')
-rw-r--r--ldso/util/ldd.c73
-rw-r--r--ldso/util/readelf.c65
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);
}