Bump to chrpath 0.16
[platform/upstream/chrpath.git] / elf.c
diff --git a/elf.c b/elf.c
index 63c9403..5b9e8b1 100644 (file)
--- a/elf.c
+++ b/elf.c
 #include <fcntl.h>
 #include "protos.h"
 
+#define EHDR_PWS(x) (is_e32() ? DO_SWAPS32(ehdr->e32.x) : DO_SWAPS64(ehdr->e64.x))
+#define EHDR_PHS(x) (is_e32() ? DO_SWAPS16(ehdr->e32.x) : DO_SWAPS16(ehdr->e64.x))
+#define PHDR_PWS(x) (is_e32() ? DO_SWAPS32(phdr->e32.x) : DO_SWAPS64(phdr->e64.x))
+#define EHDR_PWU(x) (is_e32() ? DO_SWAPU32(ehdr->e32.x) : DO_SWAPU64(ehdr->e64.x))
+#define EHDR_PHU(x) (is_e32() ? DO_SWAPU16(ehdr->e32.x) : DO_SWAPU16(ehdr->e64.x))
+#define PHDR_PWU(x) (is_e32() ? DO_SWAPU32(phdr->e32.x) : DO_SWAPU32(phdr->e64.x))
+#define PHDR_POU(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 +53,43 @@ elf_open(const char *filename, int flags, Elf_Ehdr *ehdr)
      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 ((size_t)EHDR_PHS(e_phentsize) != sz_phdr)
    {
-     fprintf(stderr, "section size was read as %d, not %d!\n",
-            ehdr->e_phentsize, sizeof(Elf_Phdr));
+     fprintf(stderr, "section size was read as %zd, not %zd!\n",
+            (size_t)EHDR_PHS(e_phentsize), sz_phdr);
      close(fd);
      return -1;
    }
@@ -66,29 +100,30 @@ int
 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_PWU(e_phoff), SEEK_SET) == -1)
   {
     perror ("positioning for sections");
     return 1;
   }
 
-  for (i = 0; i < ehdr->e_phnum; i++)
+  for (i = 0; i < EHDR_PHS(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_PWU(p_type) == PT_DYNAMIC)
       break;
   }
-  if (i == ehdr->e_phnum)
+  if (i == EHDR_PHS(e_phnum))
     {
       fprintf (stderr, "No dynamic section found.\n");
       return 2;
     }
 
-  if (0 == phdr->p_filesz)
+  if (0 == PHDR_POU(p_filesz))
     {
       fprintf (stderr, "Length of dynamic section is zero.\n");
       return 3;