r132 - trunk
Petter Reinholdtsen
pere at alioth.debian.org
Mon Sep 26 18:16:06 UTC 2011
Author: pere
Date: 2011-09-26 18:16:05 +0000 (Mon, 26 Sep 2011)
New Revision: 132
Modified:
trunk/AUTHORS
trunk/NEWS
trunk/chrpath.c
trunk/configure.ac
trunk/elf.c
trunk/killrpath.c
trunk/protos.h
Log:
Now works even when the ELF file has endianness/word length different from the host machime. Patch from Javier Serrano Polo, adjusted to compile with -ansi and -pedantic.
Modified: trunk/AUTHORS
===================================================================
--- trunk/AUTHORS 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/AUTHORS 2011-09-26 18:16:05 UTC (rev 132)
@@ -5,6 +5,8 @@
Implemented first version of killrpath.c.
Petter Reinholdtsen <pere at hungry.com>
Collected both implementations and made userfriendly wrapper.
+Javier Serrano Polo <jasp00 at terra.es>
+ Made it arch-independent so it can be used for cross-development.
With patches from:
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/NEWS 2011-09-26 18:16:05 UTC (rev 132)
@@ -6,6 +6,9 @@
* Document rpath size limitation better in the manual page.
Patch from Eric Raymond.
* Fix typo in handling of long arguments. Patch from Eric Raymond.
+ * Now works even when the ELF file has endianness/word length
+ different from the host machime. Patch from Javier Serrano Polo,
+ adjusted to compile with -ansi and -pedantic.
New in 0.13 released 2004-09-19:
* Change exit code handling. Return an error if the operation fail.
Modified: trunk/chrpath.c
===================================================================
--- trunk/chrpath.c 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/chrpath.c 2011-09-26 18:16:05 UTC (rev 132)
@@ -66,7 +66,7 @@
int i;
Elf_Phdr phdr;
Elf_Shdr shdr;
- Elf_Dyn *dyns;
+ void *dyns;
int rpathoff;
char * strtab;
char * rpath;
@@ -92,15 +92,15 @@
return 1;
}
- dyns = malloc(phdr.p_filesz);
+ dyns = malloc(PHDR(p_filesz));
if (dyns == NULL)
{
perror ("allocating memory for dynamic section");
return 1;
}
- memset(dyns, 0, phdr.p_filesz);
- if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
- || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ memset(dyns, 0, PHDR(p_filesz));
+ if (lseek(fd, PHDR(p_offset), SEEK_SET) == -1
+ || read(fd, dyns, PHDR(p_filesz)) != (int)PHDR(p_filesz))
{
perror ("reading dynamic section");
free(dyns);
@@ -108,12 +108,12 @@
}
rpathoff = -1;
- for ( rpath_dyns_index = 0; dyns[rpath_dyns_index].d_tag != DT_NULL;
+ for ( rpath_dyns_index = 0; DYNSS(rpath_dyns_index, d_tag) != DT_NULL;
++rpath_dyns_index )
{
- if ( elf_dynpath_tag(dyns[rpath_dyns_index].d_tag) )
+ if ( elf_dynpath_tag(DYNSS(rpath_dyns_index, d_tag)) )
{
- rpathoff = dyns[rpath_dyns_index].d_un.d_ptr;
+ rpathoff = DYNSU(rpath_dyns_index, d_un.d_ptr);
break;
}
}
@@ -124,47 +124,48 @@
return 2;
}
- if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1)
+ if (lseek(fd, EHDRU(e_shoff), SEEK_SET) == -1)
{
perror ("positioning for sections");
free(dyns);
return 1;
}
- for (i = 0; i < ehdr.e_shnum; i++)
+ for (i = 0; i < EHDRS(e_shnum); i++)
{
- if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+ const size_t sz_shdr = is_e32() ? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr);
+ if (read(fd, &shdr, sz_shdr) != (ssize_t)sz_shdr)
{
perror ("reading section header");
free(dyns);
return 1;
}
- if (shdr.sh_type == SHT_STRTAB)
+ if (SHDR(sh_type) == SHT_STRTAB)
break;
}
- if (i == ehdr.e_shnum)
+ if (i == EHDRS(e_shnum))
{
fprintf (stderr, "No string table found.\n");
free(dyns);
return 2;
}
- strtab = (char *)malloc(shdr.sh_size);
+ strtab = (char *)malloc(SHDR(sh_size));
if (strtab == NULL)
{
perror ("allocating memory for string table");
free(dyns);
return 1;
}
- memset(strtab, 0, shdr.sh_size);
+ memset(strtab, 0, SHDR(sh_size));
- if (lseek(fd, shdr.sh_offset, SEEK_SET) == -1)
+ if (lseek(fd, SHDR(sh_offset), SEEK_SET) == -1)
{
perror ("positioning for string table");
free(strtab);
free(dyns);
return 1;
}
- if (read(fd, strtab, shdr.sh_size) != (int)shdr.sh_size)
+ if (read(fd, strtab, SHDR(sh_size)) != (int)SHDR(sh_size))
{
perror ("reading string table");
free(strtab);
@@ -172,10 +173,10 @@
return 1;
}
- if ((int)shdr.sh_size < rpathoff)
+ if ((int)SHDR(sh_size) < rpathoff)
{
fprintf(stderr, "%s string offset not contained in string table",
- elf_tagname(dyns[rpath_dyns_index].d_tag));
+ elf_tagname(DYNSS(rpath_dyns_index, d_tag)));
free(strtab);
free(dyns);
return 5;
@@ -183,11 +184,16 @@
rpath = strtab+rpathoff;
#if defined(DT_RUNPATH)
- if (convert && dyns[rpath_dyns_index].d_tag == DT_RPATH)
+ if (convert && DYNSS(rpath_dyns_index, d_tag) == DT_RPATH)
{
- dyns[rpath_dyns_index].d_tag = DT_RUNPATH;
- if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
- || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ if (is_e32())
+ ((Elf32_Dyn *)dyns)[rpath_dyns_index].d_tag = swap_bytes() ?
+ bswap_32(DT_RUNPATH) : DT_RUNPATH;
+ else
+ ((Elf64_Dyn *)dyns)[rpath_dyns_index].d_tag = swap_bytes() ?
+ bswap_64(DT_RUNPATH) : DT_RUNPATH;
+ if (lseek(fd, PHDR(p_offset), SEEK_SET) == -1
+ || write(fd, dyns, PHDR(p_filesz)) != (int)PHDR(p_filesz))
{
perror ("converting RPATH to RUNPATH");
return 1;
@@ -196,7 +202,7 @@
}
#endif /* DT_RUNPATH */
- printf("%s: %s=%s\n", filename, elf_tagname(dyns[rpath_dyns_index].d_tag),
+ printf("%s: %s=%s\n", filename, elf_tagname(DYNSS(rpath_dyns_index, d_tag)),
rpath);
if (NULL == newpath)
@@ -212,7 +218,7 @@
* Calculate the maximum rpath length (will be equal to rpathlen unless
* we have previously truncated it).
*/
- for ( i = rpathoff + rpathlen ; (i < (int)shdr.sh_size
+ for ( i = rpathoff + rpathlen ; (i < (int)SHDR(sh_size)
&& strtab[i] == '\0') ; i++ )
;
i--;
@@ -232,7 +238,7 @@
memset(rpath, 0, rpathlen);
strcpy(rpath, newpath);
- if (lseek(fd, shdr.sh_offset+rpathoff, SEEK_SET) == -1)
+ if (lseek(fd, SHDR(sh_offset)+rpathoff, SEEK_SET) == -1)
{
perror ("positioning for RPATH");
free(dyns);
@@ -247,7 +253,7 @@
return 1;
}
printf("%s: new %s: %s\n", filename,
- elf_tagname(dyns[rpath_dyns_index].d_tag), rpath);
+ elf_tagname(DYNSS(rpath_dyns_index, d_tag)), rpath);
elf_close(fd);
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/configure.ac 2011-09-26 18:16:05 UTC (rev 132)
@@ -33,8 +33,6 @@
if eval "test x$GCC = xyes"; then
for flag in \
- -ansi \
- -pedantic \
-W \
-Wall \
-Wcast-align \
Modified: trunk/elf.c
===================================================================
--- trunk/elf.c 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/elf.c 2011-09-26 18:16:05 UTC (rev 132)
@@ -16,10 +16,32 @@
#include <fcntl.h>
#include "protos.h"
+#define EHDR_PS(x) (is_e32() ? DO_SWAPS32(ehdr->e32.x) : DO_SWAPS64(ehdr->e64.x))
+#define PHDR_PS(x) (is_e32() ? DO_SWAPS32(phdr->e32.x) : DO_SWAPS64(phdr->e64.x))
+#define EHDR_PU(x) (is_e32() ? DO_SWAPU32(ehdr->e32.x) : DO_SWAPU64(ehdr->e64.x))
+#define PHDR_PU(x) (is_e32() ? DO_SWAPU32(phdr->e32.x) : DO_SWAPU64(phdr->e64.x))
+
+static int is_e32_flag;
+static int swap_bytes_flag;
+
int
+is_e32(void)
+{
+ return is_e32_flag;
+}
+
+int
+swap_bytes(void)
+{
+ return swap_bytes_flag;
+}
+
+int
elf_open(const char *filename, int flags, Elf_Ehdr *ehdr)
{
int fd;
+ size_t sz_ehdr;
+ size_t sz_phdr;
fd = open(filename, flags);
if (fd == -1)
@@ -28,34 +50,43 @@
return -1;
}
- if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr))
+ if (read(fd, ehdr, EI_NIDENT) != EI_NIDENT)
{
- perror ("reading header");
+ perror ("reading header (e_ident)");
close(fd);
return -1;
}
if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
- ehdr->e_ident[EI_CLASS] != ELFCLASS ||
- ehdr->e_ident[EI_DATA] != ELFDATA2 ||
+ (ehdr->e_ident[EI_CLASS] != ELFCLASS32 &&
+ ehdr->e_ident[EI_CLASS] != ELFCLASS64) ||
+ (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
+ ehdr->e_ident[EI_DATA] != ELFDATA2MSB) ||
ehdr->e_ident[EI_VERSION] != EV_CURRENT)
{
- fprintf(stderr,
-#ifdef WORDS_BIGENDIAN
- "`%s' probably isn't a %d-bit MSB-first ELF file.\n",
-#else /* not WORD_BIGENDIAN */
- "`%s' probably isn't a %d-bit LSB-first ELF file.\n",
-#endif /* not WORD_BIGENDIAN */
- filename, SIZEOF_VOID_P * 8);
+ fprintf(stderr, "`%s' probably isn't an ELF file.\n", filename);
close(fd);
errno = ENOEXEC; /* Hm, is this the best errno code to use? */
return -1;
}
- if (ehdr->e_phentsize != sizeof(Elf_Phdr))
+ is_e32_flag = ehdr->e_ident[EI_CLASS] == ELFCLASS32;
+ swap_bytes_flag = ehdr->e_ident[EI_DATA] != ELFDATA2;
+
+ sz_ehdr = is_e32() ? sizeof(Elf32_Ehdr) : sizeof(Elf64_Ehdr);
+ if (read(fd, ((char *)ehdr) + EI_NIDENT, sz_ehdr - EI_NIDENT)
+ != (ssize_t)(sz_ehdr - EI_NIDENT))
{
+ perror ("reading header");
+ close(fd);
+ return -1;
+ }
+
+ sz_phdr = is_e32() ? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr);
+ if (EHDR_PS(e_phentsize) != sz_phdr)
+ {
fprintf(stderr, "section size was read as %d, not %d!\n",
- ehdr->e_phentsize, sizeof(Elf_Phdr));
+ (int)EHDR_PS(e_phentsize), (int)sz_phdr);
close(fd);
return -1;
}
@@ -66,29 +97,30 @@
elf_find_dynamic_section(int fd, Elf_Ehdr *ehdr, Elf_Phdr *phdr)
{
int i;
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1)
+ if (lseek(fd, EHDR_PU(e_phoff), SEEK_SET) == -1)
{
perror ("positioning for sections");
return 1;
}
- for (i = 0; i < ehdr->e_phnum; i++)
+ for (i = 0; i < EHDR_PS(e_phnum); i++)
{
- if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr))
+ const size_t sz_phdr = is_e32() ? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr);
+ if (read(fd, phdr, sz_phdr) != (ssize_t)sz_phdr)
{
perror ("reading section header");
return 1;
}
- if (phdr->p_type == PT_DYNAMIC)
+ if (PHDR_PU(p_type) == PT_DYNAMIC)
break;
}
- if (i == ehdr->e_phnum)
+ if (i == EHDR_PS(e_phnum))
{
fprintf (stderr, "No dynamic section found.\n");
return 2;
}
- if (0 == phdr->p_filesz)
+ if (0 == PHDR_PU(p_filesz))
{
fprintf (stderr, "Length of dynamic section is zero.\n");
return 3;
Modified: trunk/killrpath.c
===================================================================
--- trunk/killrpath.c 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/killrpath.c 2011-09-26 18:16:05 UTC (rev 132)
@@ -35,7 +35,7 @@
Elf_Ehdr ehdr;
int i;
Elf_Phdr phdr;
- Elf_Dyn *dyns;
+ void *dyns;
int dynpos;
fd = elf_open(filename, O_RDWR, &ehdr);
@@ -52,32 +52,40 @@
return 1;
}
- dyns = malloc(phdr.p_memsz);
+ dyns = malloc(PHDR(p_memsz));
if (dyns == NULL)
{
perror ("allocating memory for dynamic section");
return 1;
}
- memset(dyns, 0, phdr.p_memsz);
- if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
- || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ memset(dyns, 0, PHDR(p_memsz));
+ if (lseek(fd, PHDR(p_offset), SEEK_SET) == -1
+ || read(fd, dyns, PHDR(p_filesz)) != (int)PHDR(p_filesz))
{
perror ("reading dynamic section");
return 1;
}
dynpos = 0;
- for (i = 0; dyns[i].d_tag != DT_NULL; i++)
+ for (i = 0; DYNSS(i, d_tag) != DT_NULL; i++)
{
- dyns[dynpos] = dyns[i];
- if ( ! elf_dynpath_tag(dyns[i].d_tag) )
+ if (is_e32())
+ ((Elf32_Dyn *)dyns)[dynpos] = ((Elf32_Dyn *)dyns)[i];
+ else
+ ((Elf64_Dyn *)dyns)[dynpos] = ((Elf64_Dyn *)dyns)[i];
+ if ( ! elf_dynpath_tag(DYNSS(i, d_tag)) )
dynpos++;
}
for (; dynpos < i; dynpos++)
- dyns[dynpos].d_tag = DT_NULL;
+ {
+ if (is_e32())
+ ((Elf32_Dyn *)dyns)[dynpos].d_tag = DT_NULL;
+ else
+ ((Elf64_Dyn *)dyns)[dynpos].d_tag = DT_NULL;
+ }
- if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
- || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ if (lseek(fd, PHDR(p_offset), SEEK_SET) == -1
+ || write(fd, dyns, PHDR(p_filesz)) != (int)PHDR(p_filesz))
{
perror ("writing dynamic section");
return 1;
Modified: trunk/protos.h
===================================================================
--- trunk/protos.h 2011-09-26 17:49:53 UTC (rev 131)
+++ trunk/protos.h 2011-09-26 18:16:05 UTC (rev 132)
@@ -1,6 +1,7 @@
#ifndef PROTOS_H
#define PROTOS_H
+#include <byteswap.h>
#include <elf.h>
#include "config.h"
@@ -9,22 +10,43 @@
#else
#define ELFDATA2 ELFDATA2LSB
#endif
-#if SIZEOF_VOID_P == 8
-#define Elf_Ehdr Elf64_Ehdr
-#define ELFCLASS ELFCLASS64
-#define Elf_Phdr Elf64_Phdr
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Dyn Elf64_Dyn
-#elif SIZEOF_VOID_P == 4
-#define Elf_Ehdr Elf32_Ehdr
-#define ELFCLASS ELFCLASS32
-#define Elf_Phdr Elf32_Phdr
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Dyn Elf32_Dyn
-#else
+#if SIZEOF_VOID_P != 8 && SIZEOF_VOID_P != 4
#error "Unknown word size (SIZEOF_VOID_P)!"
#endif
+typedef union {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Ehdr e32;
+ Elf64_Ehdr e64;
+} Elf_Ehdr;
+
+typedef union {
+ Elf32_Shdr e32;
+ Elf64_Shdr e64;
+} Elf_Shdr;
+
+typedef union {
+ Elf32_Phdr e32;
+ Elf64_Phdr e64;
+} Elf_Phdr;
+
+int is_e32(void);
+int swap_bytes(void);
+
+#define DO_SWAPU32(x) ( !swap_bytes() ? x : (uint32_t)bswap_32(x) )
+#define DO_SWAPU64(x) ( !swap_bytes() ? x : (uint64_t)bswap_64(x) )
+#define DO_SWAPS32(x) ( !swap_bytes() ? x : (int32_t)bswap_32(x) )
+#define DO_SWAPS64(x) ( !swap_bytes() ? x : (int64_t)bswap_64(x) )
+
+#define EHDRS(x) (is_e32() ? DO_SWAPS32(ehdr.e32.x) : DO_SWAPS64(ehdr.e64.x))
+#define EHDRU(x) (is_e32() ? DO_SWAPU32(ehdr.e32.x) : DO_SWAPU64(ehdr.e64.x))
+#define PHDR(x) (is_e32() ? DO_SWAPU32(phdr.e32.x) : DO_SWAPU64(phdr.e64.x))
+#define SHDR(x) (is_e32() ? DO_SWAPU32(shdr.e32.x) : DO_SWAPU64(shdr.e64.x))
+#define DYNSU(i,x) (is_e32() ? DO_SWAPU32(((Elf32_Dyn *)dyns)[i].x) \
+ : DO_SWAPU64(((Elf64_Dyn *)dyns)[i].x))
+#define DYNSS(i,x) (is_e32() ? DO_SWAPS32(((Elf32_Dyn *)dyns)[i].x) \
+ : DO_SWAPS64(((Elf64_Dyn *)dyns)[i].x))
+
int killrpath(const char *filename);
int chrpath(const char *filename, const char *newpath, int convert);
More information about the Chrpath-commits
mailing list