aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjakub <jakub@94c539fb-cf18-0410-b60f-edeeb537fa16>2006-07-18 13:58:08 +0000
committerjakub <jakub@94c539fb-cf18-0410-b60f-edeeb537fa16>2006-07-18 13:58:08 +0000
commitd6b2c648f298938ecee1a5cb97976aee95c75cea (patch)
tree296c04ffdff0680b18788082303258eb12b6d8ff
parent89c8ad83256e900bda44c2604b001bde47a47438 (diff)
downloadprelink-cross-d6b2c648f298938ecee1a5cb97976aee95c75cea.tar.gz
prelink-cross-d6b2c648f298938ecee1a5cb97976aee95c75cea.tar.bz2
prelink-cross-d6b2c648f298938ecee1a5cb97976aee95c75cea.zip
20060621
git-svn-id: http://sourceware.org/svn/prelink@131 94c539fb-cf18-0410-b60f-edeeb537fa16
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in36
-rw-r--r--src/arch-x86_64.c4
-rw-r--r--src/cache.c159
-rw-r--r--src/canonicalize.c319
-rw-r--r--src/dso.c1
-rw-r--r--src/gather.c6
-rw-r--r--src/prelink.h3
-rw-r--r--testsuite/Makefile.am2
-rw-r--r--testsuite/Makefile.in2
-rw-r--r--testsuite/shuffle8.c20
-rwxr-xr-xtestsuite/shuffle8.sh19
12 files changed, 494 insertions, 79 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cabe12..6cfe1e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@ common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \
prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \
gather.c layout.c main.c prelink.c \
prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \
- verify.c md5.c md5.h sha.c sha.h \
+ verify.c canonicalize.c md5.c md5.h sha.c sha.h \
$(common_SOURCES) $(arch_SOURCES)
prelink_LDADD = @LIBGELF@
prelink_LDFLAGS = -all-static
diff --git a/src/Makefile.in b/src/Makefile.in
index 9867eff..908f76c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -115,7 +115,7 @@ common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \
prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \
gather.c layout.c main.c prelink.c \
prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \
- verify.c md5.c md5.h sha.c sha.h \
+ verify.c canonicalize.c md5.c md5.h sha.c sha.h \
$(common_SOURCES) $(arch_SOURCES)
prelink_LDADD = @LIBGELF@
@@ -150,8 +150,9 @@ am_prelink_OBJECTS = cache.$(OBJEXT) conflict.$(OBJEXT) cxx.$(OBJEXT) \
doit.$(OBJEXT) exec.$(OBJEXT) execle_open.$(OBJEXT) \
get.$(OBJEXT) gather.$(OBJEXT) layout.$(OBJEXT) main.$(OBJEXT) \
prelink.$(OBJEXT) reloc.$(OBJEXT) space.$(OBJEXT) \
- undo.$(OBJEXT) undoall.$(OBJEXT) verify.$(OBJEXT) md5.$(OBJEXT) \
- sha.$(OBJEXT) $(am__objects_1) $(am__objects_2)
+ undo.$(OBJEXT) undoall.$(OBJEXT) verify.$(OBJEXT) \
+ canonicalize.$(OBJEXT) md5.$(OBJEXT) sha.$(OBJEXT) \
+ $(am__objects_1) $(am__objects_2)
prelink_OBJECTS = $(am_prelink_OBJECTS)
prelink_DEPENDENCIES =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -168,20 +169,20 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/arch-sparc.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/arch-sparc64.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/arch-x86_64.Po ./$(DEPDIR)/cache.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/checksum.Po ./$(DEPDIR)/conflict.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/crc32.Po ./$(DEPDIR)/cxx.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/data.Po ./$(DEPDIR)/doit.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/dso.Po ./$(DEPDIR)/dwarf2.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/exec.Po ./$(DEPDIR)/execle_open.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/execstack.Po ./$(DEPDIR)/fptr.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/gather.Po ./$(DEPDIR)/get.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/hashtab.Po ./$(DEPDIR)/layout.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/md5.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/mdebug.Po ./$(DEPDIR)/prelink.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/reloc.Po ./$(DEPDIR)/sha.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/space.Po ./$(DEPDIR)/stabs.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/undo.Po ./$(DEPDIR)/undoall.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/verify.Po
+@AMDEP_TRUE@ ./$(DEPDIR)/canonicalize.Po ./$(DEPDIR)/checksum.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/conflict.Po ./$(DEPDIR)/crc32.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/cxx.Po ./$(DEPDIR)/data.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/doit.Po ./$(DEPDIR)/dso.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/dwarf2.Po ./$(DEPDIR)/exec.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/execle_open.Po ./$(DEPDIR)/execstack.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/fptr.Po ./$(DEPDIR)/gather.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/get.Po ./$(DEPDIR)/hashtab.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/layout.Po ./$(DEPDIR)/main.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/md5.Po ./$(DEPDIR)/mdebug.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/prelink.Po ./$(DEPDIR)/reloc.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/sha.Po ./$(DEPDIR)/space.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/stabs.Po ./$(DEPDIR)/undo.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/undoall.Po ./$(DEPDIR)/verify.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
@@ -287,6 +288,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-sparc64.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-x86_64.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canonicalize.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checksum.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conflict.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc32.Po@am__quote@
diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c
index b19e061..0db1a23 100644
--- a/src/arch-x86_64.c
+++ b/src/arch-x86_64.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2006 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
@@ -529,6 +529,6 @@ PL_ARCH = {
even dlopened libraries will get the slots they desire. */
.mmap_base = 0x3000000000LL,
.mmap_end = 0x4000000000LL,
- .max_page_size = 0x100000,
+ .max_page_size = 0x200000,
.page_size = 0x1000
};
diff --git a/src/cache.c b/src/cache.c
index 2825421..476d83d 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -92,23 +92,35 @@ prelink_find_entry (const char *filename, const struct stat64 *stp,
int insert)
{
struct prelink_entry e, *ent = NULL;
- void **filename_slot;
- void **devino_slot;
+ void **filename_slot, *dummy = NULL;
+ void **devino_slot = NULL;
struct stat64 st;
+ char *canon_filename = NULL;
e.filename = filename;
- filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT);
+ filename_slot = htab_find_slot (prelink_filename_htab, &e,
+ insert ? INSERT : NO_INSERT);
if (filename_slot == NULL)
- goto error_out;
+ {
+ if (insert)
+ goto error_out;
+ filename_slot = &dummy;
+ }
if (*filename_slot != NULL)
return (struct prelink_entry *) *filename_slot;
if (! stp)
{
- if (stat64 (filename, &st) < 0)
+ canon_filename = prelink_canonicalize (filename, &st);
+ if (canon_filename == NULL && stat64 (filename, &st) < 0)
{
error (0, errno, "Could not stat %s", filename);
+ if (insert)
+ {
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+ }
return NULL;
}
stp = &st;
@@ -116,52 +128,38 @@ prelink_find_entry (const char *filename, const struct stat64 *stp,
e.dev = stp->st_dev;
e.ino = stp->st_ino;
- devino_slot = htab_find_slot (prelink_devino_htab, &e, INSERT);
+ devino_slot = htab_find_slot (prelink_devino_htab, &e,
+ insert ? INSERT : NO_INSERT);
if (devino_slot == NULL)
- goto error_out;
+ {
+ if (insert)
+ goto error_out;
+ free (canon_filename);
+ return NULL;
+ }
if (*devino_slot != NULL)
{
- char *canon_filename;
-
ent = (struct prelink_entry *) *devino_slot;
- canon_filename = canonicalize_file_name (filename);
+ if (canon_filename == NULL)
+ canon_filename = prelink_canonicalize (filename, NULL);
if (canon_filename == NULL)
{
error (0, 0, "Could not canonicalize filename %s", filename);
- return NULL;
+ goto error_out2;
}
if (strcmp (canon_filename, ent->canon_filename) != 0)
{
struct prelink_link *hardlink;
- if (ent->flags & PCF_VERIFY_CANONFNAME)
- {
- char *canon_ent_filename
- = canonicalize_file_name (ent->canon_filename);
-
- ent->flags &= ~PCF_VERIFY_CANONFNAME;
- if (canon_ent_filename == NULL
- || strcmp (canon_ent_filename, ent->canon_filename) != 0)
- {
- free (canon_ent_filename);
- canon_ent_filename = (char *) ent->canon_filename;
- ent->canon_filename = canon_filename;
- free (canon_ent_filename);
- return ent;
- }
- free (canon_ent_filename);
- }
-
hardlink = (struct prelink_link *)
malloc (sizeof (struct prelink_link));
if (hardlink == NULL)
{
error (0, ENOMEM, "Could not record hardlink %s to %s",
canon_filename, ent->canon_filename);
- free (canon_filename);
- return NULL;
+ goto error_out2;
}
hardlink->canon_filename = canon_filename;
@@ -174,7 +172,11 @@ prelink_find_entry (const char *filename, const struct stat64 *stp,
}
if (! insert)
- return NULL;
+ {
+ if (canon_filename != NULL)
+ free (canon_filename);
+ return NULL;
+ }
ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1);
if (ent == NULL)
@@ -184,11 +186,16 @@ prelink_find_entry (const char *filename, const struct stat64 *stp,
if (ent->filename == NULL)
goto error_out;
- ent->canon_filename = canonicalize_file_name (filename);
+ if (canon_filename != NULL)
+ ent->canon_filename = canon_filename;
+ else
+ ent->canon_filename = prelink_canonicalize (filename, NULL);
if (ent->canon_filename == NULL)
{
error (0, 0, "Could not canonicalize filename %s", filename);
- return NULL;
+ free ((char *) ent->filename);
+ free (ent);
+ goto error_out2;
}
ent->dev = stp->st_dev;
@@ -204,6 +211,22 @@ prelink_find_entry (const char *filename, const struct stat64 *stp,
error_out:
free (ent);
error (0, ENOMEM, "Could not insert %s into hash table", filename);
+error_out2:
+ if (insert)
+ {
+ if (filename_slot != NULL)
+ {
+ assert (*filename_slot == NULL);
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+ }
+ if (devino_slot != NULL && *devino_slot == NULL)
+ {
+ *devino_slot = &dummy;
+ htab_clear_slot (prelink_devino_htab, devino_slot);
+ }
+ }
+ free (canon_filename);
return NULL;
}
@@ -211,10 +234,11 @@ static struct prelink_entry *
prelink_load_entry (const char *filename)
{
struct prelink_entry e, *ent = NULL;
- void **filename_slot;
- void **devino_slot, *dummy = NULL;
+ void **filename_slot, *dummy = NULL;
+ void **devino_slot = &dummy;
struct stat64 st;
uint32_t ctime = 0, mtime = 0;
+ char *canon_filename = NULL;
e.filename = filename;
filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT);
@@ -224,11 +248,32 @@ prelink_load_entry (const char *filename)
if (*filename_slot != NULL)
return (struct prelink_entry *) *filename_slot;
- if (stat64 (filename, &st) < 0)
+ canon_filename = prelink_canonicalize (filename, &st);
+ if (canon_filename == NULL)
+ goto error_out2;
+ if (strcmp (canon_filename, filename) != 0)
{
- e.dev = 0;
- e.ino = 0;
- devino_slot = &dummy;
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+
+ e.filename = canon_filename;
+ filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT);
+ if (filename_slot == NULL)
+ goto error_out;
+
+ if (*filename_slot != NULL)
+ {
+ free (canon_filename);
+ return (struct prelink_entry *) *filename_slot;
+ }
+ }
+
+ if (! S_ISREG (st.st_mode))
+ {
+ free (canon_filename);
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+ return NULL;
}
else
{
@@ -242,7 +287,12 @@ prelink_load_entry (const char *filename)
}
if (*devino_slot != NULL)
- return (struct prelink_entry *) *devino_slot;
+ {
+ free (canon_filename);
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+ return (struct prelink_entry *) *devino_slot;
+ }
ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1);
if (ent == NULL)
@@ -252,13 +302,7 @@ prelink_load_entry (const char *filename)
if (ent->filename == NULL)
goto error_out;
- ent->canon_filename = strdup (filename);
- if (ent->canon_filename == NULL)
- {
- free ((char *) ent->filename);
- goto error_out;
- }
-
+ ent->canon_filename = canon_filename;
ent->dev = e.dev;
ent->ino = e.ino;
ent->ctime = ctime;
@@ -271,6 +315,18 @@ prelink_load_entry (const char *filename)
error_out:
free (ent);
error (0, ENOMEM, "Could not insert %s into hash table", filename);
+error_out2:
+ if (filename_slot != NULL)
+ {
+ *filename_slot = &dummy;
+ htab_clear_slot (prelink_filename_htab, filename_slot);
+ }
+ if (devino_slot != NULL && devino_slot != &dummy)
+ {
+ *devino_slot = &dummy;
+ htab_clear_slot (prelink_devino_htab, devino_slot);
+ }
+ free (canon_filename);
return NULL;
}
@@ -365,9 +421,9 @@ prelink_load_cache (void)
ents[i]->end = cache->entry[i].end;
ents[i]->type = (ents[i]->base == 0 && ents[i]->end == 0)
? ET_CACHE_EXEC : ET_CACHE_DYN;
- ents[i]->flags = cache->entry[i].flags | PCF_VERIFY_CANONFNAME;
+ ents[i]->flags = cache->entry[i].flags;
- if (ents[i]->flags == (PCF_UNPRELINKABLE | PCF_VERIFY_CANONFNAME))
+ if (ents[i]->flags == PCF_UNPRELINKABLE)
ents[i]->type = (quick || print_cache) ? ET_UNPRELINKABLE : ET_NONE;
/* If mtime is equal to ctime, assume the filesystem does not store
@@ -575,8 +631,7 @@ prelink_save_cache (int do_warn)
data[i].filename = (strings - (char *) data) + sizeof (cache);
strings = stpcpy (strings, l.ents[i]->canon_filename) + 1;
data[i].checksum = l.ents[i]->checksum;
- data[i].flags = l.ents[i]->flags
- & ~(PCF_PRELINKED | PCF_VERIFY_CANONFNAME);
+ data[i].flags = l.ents[i]->flags & ~PCF_PRELINKED;
data[i].ctime = l.ents[i]->ctime;
data[i].mtime = l.ents[i]->mtime;
if (l.ents[i]->type == ET_EXEC || l.ents[i]->type == ET_CACHE_EXEC)
diff --git a/src/canonicalize.c b/src/canonicalize.c
new file mode 100644
index 0000000..79df44e
--- /dev/null
+++ b/src/canonicalize.c
@@ -0,0 +1,319 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+
+#include "hashtab.h"
+
+htab_t prelink_dirname_htab;
+
+struct dirname_entry
+{
+ const char *dirname;
+ size_t dirname_len;
+ const char *canon_dirname;
+ size_t canon_dirname_len;
+};
+
+static hashval_t
+dirname_hash (const void *p)
+{
+ struct dirname_entry *e = (struct dirname_entry *)p;
+ const unsigned char *s = (const unsigned char *)e->dirname;
+ hashval_t h = 0;
+ unsigned char c;
+ size_t len = e->dirname_len;
+
+ while (len--)
+ {
+ c = *s++;
+ h += c + (c << 17);
+ h ^= h >> 2;
+ }
+ return h + e->dirname_len + (e->dirname_len << 17);
+}
+
+static int
+dirname_eq (const void *p, const void *q)
+{
+ struct dirname_entry *e = (struct dirname_entry *)p;
+ struct dirname_entry *f = (struct dirname_entry *)q;
+
+ return (e->dirname_len == f->dirname_len
+ && memcmp (e->dirname, f->dirname, e->dirname_len) == 0);
+}
+
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any `.', `..' components nor any repeated path
+ separators ('/') or symlinks. All path components must exist.
+ The result is malloc'd. */
+
+static char *
+canon_filename (const char *name, int nested, struct stat64 *stp)
+{
+ char *rpath, *dest, *extra_buf = NULL;
+ const char *start, *end, *rpath_limit;
+ long int path_max;
+ int num_links = 0;
+ int stp_initialized = 0;
+
+ if (name == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (name[0] == '\0')
+ {
+ errno = ENOENT;
+ return NULL;
+ }
+
+#ifdef PATH_MAX
+ path_max = PATH_MAX;
+#else
+ path_max = pathconf (name, _PC_PATH_MAX);
+ if (path_max <= 0)
+ path_max = 1024;
+#endif
+
+ rpath = malloc (path_max);
+ if (rpath == NULL)
+ return NULL;
+ rpath_limit = rpath + path_max;
+
+ if (name[0] != '/')
+ {
+ if (!getcwd (rpath, path_max))
+ {
+ rpath[0] = '\0';
+ goto error;
+ }
+ dest = strchr (rpath, '\0');
+ }
+ else
+ {
+ rpath[0] = '/';
+ dest = rpath + 1;
+
+ if (!nested)
+ {
+ if (prelink_dirname_htab == NULL)
+ prelink_dirname_htab = htab_try_create (100, dirname_hash,
+ dirname_eq, NULL);
+ if (prelink_dirname_htab == NULL)
+ nested = 1;
+ }
+ if (!nested)
+ {
+ struct dirname_entry e;
+ void **dirname_slot;
+
+ end = strrchr (name, '/');
+
+ e.dirname = name;
+ e.dirname_len = end - name;
+ dirname_slot = htab_find_slot (prelink_dirname_htab, &e, INSERT);
+ if (*dirname_slot == NULL)
+ {
+ struct dirname_entry *ep = malloc (sizeof (struct dirname_entry)
+ + e.dirname_len + 1);
+ if (ep != NULL)
+ {
+ char *dirname = (char *) (ep + 1);
+ struct stat64 st;
+
+ ep->dirname = (const char *) dirname;
+ ep->dirname_len = e.dirname_len;
+ memcpy (dirname, name, ep->dirname_len);
+ dirname[ep->dirname_len] = '\0';
+ ep->canon_dirname = canon_filename (ep->dirname, 1, &st);
+ if (ep->canon_dirname == NULL || !S_ISDIR (st.st_mode))
+ free (ep);
+ else
+ {
+ ep->canon_dirname_len = strlen (ep->canon_dirname);
+ *dirname_slot = ep;
+ }
+ }
+ }
+
+ if (*dirname_slot != NULL)
+ {
+ struct dirname_entry *ep = *dirname_slot;
+
+ if (rpath + ep->canon_dirname_len + 1 >= rpath_limit)
+ {
+ size_t new_size;
+ char *new_rpath;
+
+ new_size = rpath_limit - rpath;
+ if (ep->canon_dirname_len + 1 > path_max)
+ new_size += ep->canon_dirname_len + 1;
+ else
+ new_size += path_max;
+ new_rpath = (char *) realloc (rpath, new_size);
+ if (new_rpath == NULL)
+ goto error;
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+ }
+ dest = mempcpy (rpath, ep->canon_dirname, ep->canon_dirname_len);
+ *dest = '\0';
+ name = end + 1;
+ }
+ }
+ }
+
+ for (start = end = name; *start; start = end)
+ {
+ int n;
+
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/');
+ stp_initialized = 0;
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+ char *new_rpath;
+
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > path_max)
+ new_size += end - start + 1;
+ else
+ new_size += path_max;
+ new_rpath = (char *) realloc (rpath, new_size);
+ if (new_rpath == NULL)
+ goto error;
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = mempcpy (dest, start, end - start);
+ *dest = '\0';
+
+ if (lstat64 (rpath, stp) < 0)
+ goto error;
+
+ stp_initialized = 1;
+
+ if (S_ISLNK (stp->st_mode))
+ {
+ char *buf = alloca (path_max);
+ size_t len;
+
+ if (++num_links > MAXSYMLINKS)
+ {
+ errno = ELOOP;
+ goto error;
+ }
+
+ n = readlink (rpath, buf, path_max);
+ if (n < 0)
+ goto error;
+ buf[n] = '\0';
+
+ if (!extra_buf)
+ extra_buf = alloca (path_max);
+
+ len = strlen (end);
+ if ((long int) (n + len) >= path_max)
+ {
+ errno = ENAMETOOLONG;
+ goto error;
+ }
+
+ /* Careful here, end may be a pointer into extra_buf... */
+ memmove (&extra_buf[n], end, len + 1);
+ name = end = memcpy (extra_buf, buf, n);
+
+ if (buf[0] == '/')
+ dest = rpath + 1; /* It's an absolute symlink */
+ else
+ /* Back up to previous component, ignore if at root already: */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/');
+ }
+ else if (!S_ISDIR (stp->st_mode) && *end != '\0')
+ {
+ errno = ENOTDIR;
+ goto error;
+ }
+ }
+ }
+ if (dest > rpath + 1 && dest[-1] == '/')
+ --dest;
+ *dest = '\0';
+
+ if (!stp_initialized && lstat64 (rpath, stp) < 0)
+ goto error;
+
+ if (dest + 1 - rpath <= (rpath_limit - rpath) / 2)
+ {
+ char *new_rpath = realloc (rpath, dest + 1 - rpath);
+
+ if (new_rpath != NULL)
+ return new_rpath;
+ }
+ return rpath;
+
+error:
+ free (rpath);
+ return NULL;
+}
+
+char *
+prelink_canonicalize (const char *name, struct stat64 *stp)
+{
+ struct stat64 st;
+ return canon_filename (name, 0, stp ? stp : &st);
+}
diff --git a/src/dso.c b/src/dso.c
index 1e43e69..8a9512e 100644
--- a/src/dso.c
+++ b/src/dso.c
@@ -1462,7 +1462,6 @@ recompute_nonalloc_offsets (DSO *dso)
first_nonalloc = i;
if (dso->ehdr.e_shoff < dso->shdr[i].sh_offset)
{
- assert (dso->shdr[i - 1].sh_offset < dso->ehdr.e_shoff);
dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1);
last_offset = dso->ehdr.e_shoff + shdrsize;
}
diff --git a/src/gather.c b/src/gather.c
index 1e23d9d..a3d0870 100644
--- a/src/gather.c
+++ b/src/gather.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
@@ -587,7 +587,7 @@ add_dir_to_dirlist (const char *name, dev_t dev, int flags)
struct prelink_dir *dir;
size_t len;
- canon_name = canonicalize_file_name (name);
+ canon_name = prelink_canonicalize (name, NULL);
if (canon_name == NULL)
{
if (! all && implicit)
@@ -1226,7 +1226,7 @@ add_to_blacklist (const char *name, int deref, int onefs)
return 0;
}
- canon_name = canonicalize_file_name (name);
+ canon_name = prelink_canonicalize (name, NULL);
if (canon_name == NULL)
{
if (implicit)
diff --git a/src/prelink.h b/src/prelink.h
index b0ca720..9eb2b81 100644
--- a/src/prelink.h
+++ b/src/prelink.h
@@ -226,7 +226,6 @@ struct prelink_cache_entry
uint32_t filename;
uint32_t depends;
uint32_t checksum;
-#define PCF_VERIFY_CANONFNAME 0x80000
#define PCF_UNPRELINKABLE 0x40000
#define PCF_PRELINKED 0x20000
#define PCF_ELF64 0x10000
@@ -406,6 +405,8 @@ void prelink_all (void);
int undo_all (void);
+char *prelink_canonicalize (const char *name, struct stat64 *stp);
+
extern const char *dynamic_linker;
extern const char *ld_library_path;
extern const char *prelink_cache;
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 1cebc8f..3af929b 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -9,7 +9,7 @@ TESTS = movelibs.sh \
reloc1.sh reloc2.sh reloc3.sh reloc4.sh reloc5.sh reloc6.sh \
reloc7.sh reloc8.sh reloc9.sh reloc10.sh reloc11.sh \
shuffle1.sh shuffle2.sh shuffle3.sh shuffle4.sh shuffle5.sh \
- shuffle6.sh shuffle7.sh undo1.sh \
+ shuffle6.sh shuffle7.sh shuffle8.sh undo1.sh \
layout1.sh layout2.sh \
tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \
cxx1.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index b8f07b9..53feb82 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -104,7 +104,7 @@ TESTS = movelibs.sh \
reloc1.sh reloc2.sh reloc3.sh reloc4.sh reloc5.sh reloc6.sh \
reloc7.sh reloc8.sh reloc9.sh reloc10.sh reloc11.sh \
shuffle1.sh shuffle2.sh shuffle3.sh shuffle4.sh shuffle5.sh \
- shuffle6.sh shuffle7.sh undo1.sh \
+ shuffle6.sh shuffle7.sh shuffle8.sh undo1.sh \
layout1.sh layout2.sh \
tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \
cxx1.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \
diff --git a/testsuite/shuffle8.c b/testsuite/shuffle8.c
new file mode 100644
index 0000000..4e80184
--- /dev/null
+++ b/testsuite/shuffle8.c
@@ -0,0 +1,20 @@
+#include "reloc1.h"
+#include <stdlib.h>
+
+static struct A local = { 77, &local, &bar + 4 };
+int vbss[16384] __attribute__((aligned (4096)));
+int vdata __attribute__((aligned (4096))) = 5;
+
+asm (".text; .balign 4096; vtext:; .previous");
+
+int main()
+{
+ if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26)
+ abort ();
+ if (f1 () != 11 || f2 () != 12)
+ abort ();
+ local.c -= 4;
+ if (local.a != 77 || local.b != &local || local.c != &bar)
+ abort ();
+ exit (vbss[31] + vdata - 5);
+}
diff --git a/testsuite/shuffle8.sh b/testsuite/shuffle8.sh
new file mode 100755
index 0000000..d0768a4
--- /dev/null
+++ b/testsuite/shuffle8.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+. `dirname $0`/functions.sh
+rm -f shuffle8 shuffle8lib*.so shuffle8.log shuffle8.lds
+rm -f prelink.cache
+$CC -shared -O2 -fpic -o shuffle8lib1.so $srcdir/reloc1lib1.c
+$CC -shared -O2 -fpic -o shuffle8lib2.so $srcdir/reloc1lib2.c shuffle8lib1.so
+BINS="shuffle8"
+LIBS="shuffle8lib1.so shuffle8lib2.so"
+$CCLINK -o shuffle8 $srcdir/shuffle8.c -Wl,--rpath-link,. shuffle8lib2.so
+strip -R .comment shuffle8
+savelibs
+echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle8 > shuffle8.log
+$PRELINK ${PRELINK_OPTS--vm} ./shuffle8 >> shuffle8.log 2>&1 || exit 1
+grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle8.log && exit 2
+LD_LIBRARY_PATH=. ./shuffle8 || exit 3
+readelf -a ./shuffle8 >> shuffle8.log 2>&1 || exit 4
+# So that it is not prelinked again
+chmod -x ./shuffle8
+comparelibs >> shuffle8.log 2>&1 || exit 5