Browse Source

Allow ldconfig.host to build ld.so.cache for target, regardless of
the target system's byteorder

Eric Andersen 18 years ago
parent
commit
d5b26eae20
4 changed files with 315 additions and 35 deletions
  1. 9 3
      utils/Makefile
  2. 163 0
      utils/chroot_realpath.c
  3. 112 31
      utils/ldconfig.c
  4. 31 1
      utils/readsoname2.c

+ 9 - 3
utils/Makefile

@@ -31,6 +31,12 @@ else
 TARGET_ICONV =
 endif
 
+ifeq ($(strip $(LDSO_CACHE_SUPPORT)),y)
+HOST_LDSO_CACHE_FLAG = -D__LDSO_CACHE_SUPPORT__=1
+else
+HOST_LDSO_CACHE_FLAG =
+endif
+
 # NOTE: We build the utils AFTER we have a uClibc-targeted toolchain.
 
 ifeq ($(strip $(HAVE_SHARED)),y)
@@ -84,13 +90,13 @@ endif
 
 ldd.host: ldd.c
 	$(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
-		-DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+ 		-DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
 		-DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
 		$^ -o $@
 
-ldconfig.host: ldconfig.c
+ldconfig.host: ldconfig.c chroot_realpath.c
 	$(HOSTCC) $(HOSTCFLAGS) -Wl,-s \
-		-DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \
+ 		-DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" $(HOST_LDSO_CACHE_FLAG) \
 		-DUCLIBC_LDSO=$(UCLIBC_LDSO) -I. -I../ldso/include \
 		$^ -o $@
 

+ 163 - 0
utils/chroot_realpath.c

@@ -0,0 +1,163 @@
+/*
+ * chroot_realpath.c -- reslove pathname as if inside chroot
+ * Based on realpath.c Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library Public License for more details.
+ *
+ * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <limits.h>				/* for PATH_MAX */
+#include <sys/param.h>			/* for MAXPATHLEN */
+#include <errno.h>
+#ifndef __set_errno
+#define __set_errno(val) ((errno) = (val))
+#endif
+
+#include <sys/stat.h>			/* for S_IFLNK */
+
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+#define MAX_READLINKS 32
+
+char *chroot_realpath(const char *chroot, const char *path, char resolved_path[])
+{
+	char copy_path[PATH_MAX];
+	char link_path[PATH_MAX];
+	char got_path[PATH_MAX];
+	char *got_path_root = got_path;
+	char *new_path = got_path;
+	char *max_path;
+	int readlinks = 0;
+	int n;
+	int chroot_len;
+
+	/* Trivial case. */
+	if (chroot == NULL || *chroot == '\0' ||
+	    (*chroot == '/' && chroot[1] == '\0')) {
+		strcpy(resolved_path, path);
+		return resolved_path;
+	}
+
+	chroot_len = strlen(chroot);
+
+	if (chroot_len + strlen(path) >= PATH_MAX - 3) {
+		__set_errno(ENAMETOOLONG);
+		return NULL;
+	}
+
+	/* Make a copy of the source path since we may need to modify it. */
+	strcpy(copy_path, path);
+	path = copy_path;
+	max_path = copy_path + PATH_MAX - chroot_len - 3;
+
+	/* Start with the chroot path. */
+	strcpy(new_path, chroot);
+	new_path += chroot_len;
+	while (*new_path == '/' && new_path > got_path)
+		new_path--;
+	got_path_root = new_path;
+	*new_path++ = '/';
+
+	/* Expand each slash-separated pathname component. */
+	while (*path != '\0') {
+		/* Ignore stray "/". */
+		if (*path == '/') {
+			path++;
+			continue;
+		}
+		if (*path == '.') {
+			/* Ignore ".". */
+			if (path[1] == '\0' || path[1] == '/') {
+				path++;
+				continue;
+			}
+			if (path[1] == '.') {
+				if (path[2] == '\0' || path[2] == '/') {
+					path += 2;
+					/* Ignore ".." at root. */
+					if (new_path == got_path_root + 1)
+						continue;
+					/* Handle ".." by backing up. */
+					while ((--new_path)[-1] != '/');
+					continue;
+				}
+			}
+		}
+		/* Safely copy the next pathname component. */
+		while (*path != '\0' && *path != '/') {
+			if (path > max_path) {
+				__set_errno(ENAMETOOLONG);
+				return NULL;
+			}
+			*new_path++ = *path++;
+		}
+		if (*path == '\0')
+			/* Don't follow symlink for last pathname component. */
+			break;
+#ifdef S_IFLNK
+		/* Protect against infinite loops. */
+		if (readlinks++ > MAX_READLINKS) {
+			__set_errno(ELOOP);
+			return NULL;
+		}
+		/* See if latest pathname component is a symlink. */
+		*new_path = '\0';
+		n = readlink(got_path, link_path, PATH_MAX - 1);
+		if (n < 0) {
+			/* EINVAL means the file exists but isn't a symlink. */
+			if (errno != EINVAL) {
+				/* Make sure it's null terminated. */
+				*new_path = '\0';
+				strcpy(resolved_path, got_path);
+				return NULL;
+			}
+		} else {
+			/* Note: readlink doesn't add the null byte. */
+			link_path[n] = '\0';
+			if (*link_path == '/')
+				/* Start over for an absolute symlink. */
+				new_path = got_path_root;
+			else
+				/* Otherwise back up over this component. */
+				while (*(--new_path) != '/');
+			/* Safe sex check. */
+			if (strlen(path) + n >= PATH_MAX - 2) {
+				__set_errno(ENAMETOOLONG);
+				return NULL;
+			}
+			/* Insert symlink contents into path. */
+			strcat(link_path, path);
+			strcpy(copy_path, link_path);
+			path = copy_path;
+		}
+#endif							/* S_IFLNK */
+		*new_path++ = '/';
+	}
+	/* Delete trailing slash but don't whomp a lone slash. */
+	if (new_path != got_path + 1 && new_path[-1] == '/')
+		new_path--;
+	/* Make sure it's null terminated. */
+	*new_path = '\0';
+	strcpy(resolved_path, got_path);
+	return resolved_path;
+}

+ 112 - 31
utils/ldconfig.c

@@ -22,6 +22,8 @@
  *
  * This program may be used for any purpose as long as this
  * copyright notice is kept.
+ *
+ * 2005/09/16: Dan Howell (modified for cross-development)
  */
 
 #include <stdio.h>
@@ -37,6 +39,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include "bswap.h"
 #include "dl-defs.h"
 
 #define BUFFER_SIZE 4096
@@ -56,6 +59,7 @@ struct exec
 #if !defined (N_MAGIC)
 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
 #endif
+#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff)
 /* Code indicating object file or impure executable.  */
 #define OMAGIC 0407
 /* Code indicating pure executable.  */
@@ -97,6 +101,8 @@ void cache_dolib(const char *dir, const char *so, int libtype);
 char *conffile = LDSO_CONF;	/* default conf file */
 char *cachefile = LDSO_CACHE;	/* default cache file */
 #endif
+char *chroot_dir = NULL;
+int byteswap = 0;
 
 struct needed_tab
 {
@@ -117,6 +123,8 @@ struct needed_tab needed_tab[] = {
   { NULL,           LIB_ELF }
 };
 
+extern char *chroot_realpath(const char *chroot, const char *path, char resolved_path[]);
+
 
 /* These two are used internally -- you shouldn't need to use them */
 static void verror_msg(const char *s, va_list p)
@@ -242,6 +250,8 @@ char *is_shlib(const char *dir, const char *name, int *type,
     ElfW(Ehdr) *elf_hdr;
     struct stat statbuf;
     char buff[BUFFER_SIZE];
+    char real[BUFFER_SIZE];
+    static int byteswapflag = -1;	/* start with byte-order unknown */
 
     /* see if name is of the form *.so* */
     if (name[strlen(name)-1] != '~' && (cp = strstr(name, ".so")))
@@ -256,8 +266,12 @@ char *is_shlib(const char *dir, const char *name, int *type,
 	sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ?
 		"/" : "", name);
 
+	/* get real path in case of chroot */
+	if (!chroot_realpath(chroot_dir, buff, real))
+	    warn("can't resolve %s in chroot %s", buff, chroot_dir);
+
 	/* first, make sure it's a regular file */
-	if (lstat(buff, &statbuf))
+	if (lstat(real, &statbuf))
 	    warn("skipping %s", buff);
 	else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
 	    warnx("%s is not a regular file or symlink, skipping", buff);
@@ -267,14 +281,15 @@ char *is_shlib(const char *dir, const char *name, int *type,
 	    *islink = S_ISLNK(statbuf.st_mode);
 
 	    /* then try opening it */
-	    if (!(file = fopen(buff, "rb")))
+	    if (!(file = fopen(real, "rb")))
 		warn("skipping %s", buff);
 	    else
 	    {
 		/* now make sure it's a shared library */
 		if (fread(&exec, sizeof exec, 1, file) < 1)
 		    warnx("can't read header from %s, skipping", buff);
-		else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC)
+		else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC &&
+			 N_MAGIC_SWAP(exec) != ZMAGIC && N_MAGIC_SWAP(exec) != QMAGIC)
 		{
 		    elf_hdr = (ElfW(Ehdr) *) &exec;
 		    if (elf_hdr->e_ident[0] != 0x7f ||
@@ -294,6 +309,9 @@ char *is_shlib(const char *dir, const char *name, int *type,
 			*type = LIB_ELF;
 			good = readsoname(buff, file, expected_type, type, 
 				elf_hdr->e_ident[EI_CLASS]);
+			if (byteswapflag == -1)
+			    /* byte-order detected */
+			    byteswapflag = byteswap;
 			if (good == NULL || *islink)
 			{
 			    if (good != NULL)
@@ -313,6 +331,12 @@ char *is_shlib(const char *dir, const char *name, int *type,
 		}
 		else
 		{
+		    /* Determine byte-order */
+		    byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1;
+		    if (byteswapflag == -1)
+			/* byte-order detected */
+			byteswapflag = byteswap;
+
 		    if (*islink)
 			good = xstrdup(name);
 		    else
@@ -330,6 +354,14 @@ char *is_shlib(const char *dir, const char *name, int *type,
 		    *type = LIB_DLL;
 		}
 		fclose(file);
+
+		if (byteswapflag >= 0 && byteswap != byteswapflag)
+		{
+		    byteswapflag = -2;
+		    warnx("mixed byte-order detected, using host byte-order...");
+		}
+		if (byteswapflag == -2)
+		    byteswap = 0;
 	    }
 	}
     }
@@ -343,18 +375,24 @@ void link_shlib(const char *dir, const char *file, const char *so)
     int change = 1;
     char libname[BUFFER_SIZE];
     char linkname[BUFFER_SIZE];
+    char reallibname[BUFFER_SIZE];
+    char reallinkname[BUFFER_SIZE];
     struct stat libstat;
     struct stat linkstat;
 
     /* construct the full path names */
     sprintf(libname, "%s/%s", dir, file);
     sprintf(linkname, "%s/%s", dir, so);
+    if (!chroot_realpath(chroot_dir, libname, reallibname))
+	warn("can't resolve %s in chroot %s", libname, chroot_dir);
+    if (!chroot_realpath(chroot_dir, linkname, reallinkname))
+	warn("can't resolve %s in chroot %s", linkname, chroot_dir);
 
     /* see if a link already exists */
-    if (!stat(linkname, &linkstat))
+    if (!stat(reallinkname, &linkstat))
     {
 	/* now see if it's the one we want */
-	if (stat(libname, &libstat))
+	if (stat(reallibname, &libstat))
 	    warn("can't stat %s", libname);
 	else if (libstat.st_dev == linkstat.st_dev &&
 		libstat.st_ino == linkstat.st_ino)
@@ -364,14 +402,14 @@ void link_shlib(const char *dir, const char *file, const char *so)
     /* then update the link, if required */
     if (change > 0 && !nolinks)
     {
-	if (!lstat(linkname, &linkstat))
+	if (!lstat(reallinkname, &linkstat))
 	{
 	    if (!S_ISLNK(linkstat.st_mode))
 	    {
 		warnx("%s is not a symlink", linkname);
 		change = -1;
 	    }
-	    else if (remove(linkname))
+	    else if (remove(reallinkname))
 	    {
 		warn("can't unlink %s", linkname);
 		change = -1;
@@ -379,7 +417,7 @@ void link_shlib(const char *dir, const char *file, const char *so)
 	}
 	if (change > 0)
 	{
-	    if (symlink(file, linkname))
+	    if (symlink(file, reallinkname))
 	    {
 		warn("can't link %s to %s", linkname, file);
 		change = -1;
@@ -441,6 +479,7 @@ void scan_dir(const char *rawname)
     char *so, *path, *path_n;
     struct lib *lp, *libs = NULL;
     int i, libtype, islink, expected_type = LIB_ANY;
+    char realname[BUFFER_SIZE];
 
     /* We need a writable copy of this string */
     path = strdup(rawname);
@@ -500,8 +539,12 @@ void scan_dir(const char *rawname)
     if (verbose > 0)
 	printf("%s:\n", name);
 
+    /* get real path in case of chroot */
+    if (!chroot_realpath(chroot_dir, name, realname))
+	warn("can't resolve %s in chroot %s", name, chroot_dir);
+
     /* if we can't open it, we can't do anything */
-    if ((dir = opendir(name)) == NULL)
+    if ((dir = opendir(realname)) == NULL)
     {
 	warn("skipping %s", name);
 	free(path);
@@ -596,8 +639,12 @@ char *get_extpath(void)
     char *res = NULL, *cp;
     FILE *file;
     struct stat stat;
+    char realconffile[BUFFER_SIZE];
+
+    if (!chroot_realpath(chroot_dir, conffile, realconffile))
+	return NULL;
 
-    if ((file = fopen(conffile, "r")) != NULL)
+    if ((file = fopen(realconffile, "r")) != NULL)
     {
 	fstat(fileno(file), &stat);
 	res = xmalloc(stat.st_size + 1);
@@ -678,22 +725,38 @@ void cache_write(void)
 {
     int cachefd;
     int stroffset = 0;
+    char realcachefile[BUFFER_SIZE];
     char tempfile[BUFFER_SIZE];
+    header_t swap_magic;
+    header_t *magic_ptr;
+    libentry_t swap_lib;
+    libentry_t *lib_ptr;
     liblist_t *cur_lib;
 
     if (!magic.nlibs)
 	return;
 
-    sprintf(tempfile, "%s~", cachefile);
+    if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
+	err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
+	    cachefile, chroot_dir, strerror(errno));
+
+    sprintf(tempfile, "%s~", realcachefile);
 
     if (unlink(tempfile) && errno != ENOENT)
-	err(EXIT_FATAL,"can't unlink %s (%s)", tempfile, strerror(errno));
+	err(EXIT_FATAL,"can't unlink %s~ (%s)", cachefile, strerror(errno));
 
     if ((cachefd = creat(tempfile, 0644)) < 0)
-	err(EXIT_FATAL,"can't create %s (%s)", tempfile, strerror(errno));
-
-    if (write(cachefd, &magic, sizeof (header_t)) != sizeof (header_t))
-	err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
+	err(EXIT_FATAL,"can't create %s~ (%s)", cachefile, strerror(errno));
+
+    if (byteswap) {
+	swap_magic = magic;
+	swap_magic.nlibs = bswap_32(swap_magic.nlibs);
+	magic_ptr = &swap_magic;
+    } else {
+	magic_ptr = &magic;
+    }
+    if (write(cachefd, magic_ptr, sizeof (header_t)) != sizeof (header_t))
+	err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
 
     for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
     {
@@ -701,29 +764,37 @@ void cache_write(void)
 	stroffset += strlen(cur_lib->soname) + 1;
 	cur_lib->liboffset = stroffset;
 	stroffset += strlen(cur_lib->libname) + 1;
-	if (write(cachefd, cur_lib, sizeof (libentry_t)) !=
-		sizeof (libentry_t))
-	    err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
+	if (byteswap) {
+	    swap_lib.flags = bswap_32(cur_lib->flags);
+	    swap_lib.sooffset = bswap_32(cur_lib->sooffset);
+	    swap_lib.liboffset = bswap_32(cur_lib->liboffset);
+	    lib_ptr = &swap_lib;
+	} else {
+	    lib_ptr = (libentry_t *)cur_lib;
+	}
+	if (write(cachefd, lib_ptr, sizeof (libentry_t)) !=
+	    sizeof (libentry_t))
+	err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
     }
 
     for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next)
     {
 	if (write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1)
 		!= strlen(cur_lib->soname) + 1)
-	    err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
+	    err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
 	if (write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1)
 		!= strlen(cur_lib->libname) + 1)
-	    err(EXIT_FATAL,"can't write %s (%s)", tempfile, strerror(errno));
+	    err(EXIT_FATAL,"can't write %s~ (%s)", cachefile, strerror(errno));
     }
 
     if (close(cachefd))
-	err(EXIT_FATAL,"can't close %s (%s)", tempfile, strerror(errno));
+	err(EXIT_FATAL,"can't close %s~ (%s)", cachefile, strerror(errno));
 
     if (chmod(tempfile, 0644))
-	err(EXIT_FATAL,"can't chmod %s (%s)", tempfile, strerror(errno));
+	err(EXIT_FATAL,"can't chmod %s~ (%s)", cachefile, strerror(errno));
 
-    if (rename(tempfile, cachefile))
-	err(EXIT_FATAL,"can't rename %s (%s)", tempfile, strerror(errno));
+    if (rename(tempfile, realcachefile))
+	err(EXIT_FATAL,"can't rename %s~ (%s)", cachefile, strerror(errno));
 }
 
 void cache_print(void)
@@ -734,8 +805,13 @@ void cache_print(void)
     char *strs;
     header_t *header;
     libentry_t *libent;
+    char realcachefile[BUFFER_SIZE];
+
+    if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
+	err(EXIT_FATAL,"can't resolve %s in chroot %s (%s)",
+	    cachefile, chroot_dir, strerror(errno));
 
-    if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY))<0)
+    if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY))<0)
 	err(EXIT_FATAL,"can't read %s (%s)", cachefile, strerror(errno));
     if ((c = mmap(0,st.st_size, PROT_READ, MAP_SHARED ,fd, 0)) == (caddr_t)-1)
 	err(EXIT_FATAL,"can't map %s (%s)", cachefile, strerror(errno));
@@ -828,7 +904,6 @@ int main(int argc, char **argv)
     int nodefault = 0;
     char *cp, *dir, *so;
     int libtype, islink;
-    char *chroot_dir = NULL;
     int printcache = 0;
 #ifdef __LDSO_CACHE_SUPPORT__
     char *extpath;
@@ -891,10 +966,16 @@ int main(int argc, char **argv)
 	}
 
     if (chroot_dir && *chroot_dir) {
-	if (chroot(chroot_dir) < 0)
-	    err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
-	if (chdir("/") < 0)
-	    err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
+	if (chroot(chroot_dir) < 0) {
+	    if (chdir(chroot_dir) < 0)
+		err(EXIT_FATAL,"couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
+	}
+	else
+	{
+	    if (chdir("/") < 0)
+		err(EXIT_FATAL,"couldn't chdir to / (%s)", strerror(errno));
+	    chroot_dir = NULL;
+	}
     }
 
     /* allow me to introduce myself, hi, my name is ... */

+ 31 - 1
utils/readsoname2.c

@@ -26,7 +26,7 @@ char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
 
   if (fstat(fileno(infile), &st))
     return NULL;
-  header = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(infile), 0);
+  header = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(infile), 0);
   if (header == (caddr_t)-1)
     return NULL;
 
@@ -34,6 +34,19 @@ char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
   if ((char *)(epnt+1) > (char *)(header + st.st_size))
     goto skip;
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0;
+#else
+#error Unknown host byte order!
+#endif
+  /* Be very lazy, and only byteswap the stuff we use */
+  if (byteswap==1) {
+    epnt->e_phoff=bswap_32(epnt->e_phoff);
+    epnt->e_phnum=bswap_16(epnt->e_phnum);
+  }
+
   ppnt = (ElfW(Phdr) *)&header[epnt->e_phoff];
   if ((char *)ppnt < (char *)header ||
       (char *)(ppnt+epnt->e_phnum) > (char *)(header + st.st_size))
@@ -41,6 +54,14 @@ char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
 
   for(i = 0; i < epnt->e_phnum; i++)
   {
+    /* Be very lazy, and only byteswap the stuff we use */
+    if (byteswap==1) {
+      ppnt->p_type=bswap_32(ppnt->p_type);
+      ppnt->p_vaddr=bswap_32(ppnt->p_vaddr);
+      ppnt->p_offset=bswap_32(ppnt->p_offset);
+      ppnt->p_filesz=bswap_32(ppnt->p_filesz);
+    }
+
     if (loadaddr == -1 && ppnt->p_type == PT_LOAD) 
       loadaddr = (ppnt->p_vaddr & ~(page_size-1)) -
 	(ppnt->p_offset & ~(page_size-1));
@@ -58,11 +79,20 @@ char *readsonameXX(char *name, FILE *infile, int expected_type, int *type)
       (char *)(dpnt+dynamic_size) > (char *)(header + st.st_size))
     goto skip;
   
+  if (byteswap==1) {
+    dpnt->d_tag=bswap_32(dpnt->d_tag);
+    dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
+  }
+
   while (dpnt->d_tag != DT_NULL)
   {
     if (dpnt->d_tag == DT_STRTAB)
       strtab_val = dpnt->d_un.d_val;
     dpnt++;
+    if (byteswap==1) {
+      dpnt->d_tag=bswap_32(dpnt->d_tag);
+      dpnt->d_un.d_val=bswap_32(dpnt->d_un.d_val);
+    }
   };
 
   if (!strtab_val)