summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trunk/ChangeLog.cross5
-rw-r--r--trunk/src/gather.c121
2 files changed, 80 insertions, 46 deletions
diff --git a/trunk/ChangeLog.cross b/trunk/ChangeLog.cross
index 0427584..62f7f26 100644
--- a/trunk/ChangeLog.cross
+++ b/trunk/ChangeLog.cross
@@ -4,6 +4,11 @@
2006-11-28 Mark Shinwell <shinwell@codesourcery.com>
+ * src/gather.c (maybe_pie): New.
+ (gather_func): Use it.
+
+ 2006-11-28 Mark Shinwell <shinwell@codesourcery.com>
+
* src/canonicalize.c: Add prelink.h include directive.
Use wrap_readlink and wrap_lstat64.
* src/prelink.h: Declare wrap_readlink.
diff --git a/trunk/src/gather.c b/trunk/src/gather.c
index 9219fdf..8163fe2 100644
--- a/trunk/src/gather.c
+++ b/trunk/src/gather.c
@@ -673,6 +673,77 @@ add_dir_to_dirlist (const char *name, dev_t dev, int flags)
return 0;
}
+/* Determine if a buffer holding an ELF header and program header
+ table may be that of a position-independent executable. */
+static int
+maybe_pie (unsigned char *e_ident, int big_endian, int sixty_four)
+{
+ uint16_t num_phdrs;
+ uint16_t phdr;
+ size_t p_type_offset;
+ size_t phnum_offset;
+ unsigned char *phdr_table;
+ unsigned char *this_phdr;
+
+ if (sixty_four)
+ {
+ uint64_t phdr_offset;
+
+ p_type_offset = offsetof (Elf64_Phdr, p_type);
+ phnum_offset = offsetof (Elf64_Ehdr, e_phnum);
+ if (big_endian)
+ phdr_offset = buf_read_ube64 (&e_ident [offsetof (Elf64_Ehdr,
+ e_phoff)]);
+ else
+ phdr_offset = buf_read_ule64 (&e_ident [offsetof (Elf64_Ehdr,
+ e_phoff)]);
+ phdr_table = e_ident + phdr_offset;
+ }
+ else
+ {
+ uint32_t phdr_offset;
+
+ p_type_offset = offsetof (Elf32_Phdr, p_type);
+ phnum_offset = offsetof (Elf32_Ehdr, e_phnum);
+ if (big_endian)
+ phdr_offset = buf_read_ube32 (&e_ident [offsetof (Elf32_Ehdr,
+ e_phoff)]);
+ else
+ phdr_offset = buf_read_ule32 (&e_ident [offsetof (Elf32_Ehdr,
+ e_phoff)]);
+ phdr_table = e_ident + phdr_offset;
+ }
+
+ this_phdr = phdr_table;
+
+ if (big_endian)
+ num_phdrs = buf_read_ube16 (&e_ident [phnum_offset]);
+ else
+ num_phdrs = buf_read_ule16 (&e_ident [phnum_offset]);
+
+ for (phdr = 0; phdr < num_phdrs; phdr++)
+ {
+ unsigned char *p_type_start = this_phdr + p_type_offset;
+ uint32_t p_type;
+
+ if (big_endian)
+ p_type = buf_read_ube32 (p_type_start);
+ else
+ p_type = buf_read_ule32 (p_type_start);
+
+ if (p_type == PT_PHDR)
+ return 1;
+
+ /* Any PT_PHDR entry must come before any PT_LOAD entry. */
+ if (p_type == PT_LOAD)
+ return 0;
+
+ this_phdr += sixty_four ? sizeof (Elf64_Phdr) : sizeof (Elf32_Phdr);
+ }
+
+ return 0;
+}
+
static int
gather_func (const char *name, const struct stat64 *st, int type,
struct FTW *ftwp)
@@ -772,17 +843,7 @@ make_unprelinkable:
goto make_unprelinkable;
else if (e_ident [EI_CLASS] == ELFCLASS32)
{
- if (e_ident [offsetof (Elf32_Ehdr, e_phoff)]
- == sizeof (Elf32_Ehdr)
- && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff) + 1,
- "\0\0\0", 3) == 0
- && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type)] == PT_PHDR
- && memcmp (e_ident + sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type) + 1,
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 0, 0))
{
maybe_pie:
dso = fdopen_dso (fd, name);
@@ -799,17 +860,7 @@ maybe_pie:
}
else if (e_ident [EI_CLASS] == ELFCLASS64)
{
- if (e_ident [offsetof (Elf64_Ehdr, e_phoff)]
- == sizeof (Elf64_Ehdr)
- && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff) + 1,
- "\0\0\0\0\0\0\0", 7) == 0
- && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type)] == PT_PHDR
- && memcmp (e_ident + sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type) + 1,
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 0, 1))
goto maybe_pie;
goto close_it;
}
@@ -826,35 +877,13 @@ maybe_pie:
goto make_unprelinkable;
else if (e_ident [EI_CLASS] == ELFCLASS32)
{
- if (e_ident [offsetof (Elf32_Ehdr, e_phoff) + 3]
- == sizeof (Elf32_Ehdr)
- && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff),
- "\0\0\0", 3) == 0
- && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type) + 3]
- == PT_PHDR
- && memcmp (e_ident + sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type),
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 1, 0))
goto maybe_pie;
goto close_it;
}
else if (e_ident [EI_CLASS] == ELFCLASS64)
{
- if (e_ident [offsetof (Elf64_Ehdr, e_phoff) + 7]
- == sizeof (Elf64_Ehdr)
- && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff),
- "\0\0\0\0\0\0\0", 7) == 0
- && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type) + 3]
- == PT_PHDR
- && memcmp (e_ident + sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type),
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 1, 1))
goto maybe_pie;
goto close_it;
}