summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trunk/ChangeLog7
-rw-r--r--trunk/src/cxx.c92
-rw-r--r--trunk/src/get.c2
-rw-r--r--trunk/src/prelink.c60
-rw-r--r--trunk/src/prelink.h2
5 files changed, 110 insertions, 53 deletions
diff --git a/trunk/ChangeLog b/trunk/ChangeLog
index 3c5f337..2bb9e03 100644
--- a/trunk/ChangeLog
+++ b/trunk/ChangeLog
@@ -1,5 +1,12 @@
2007-10-09 Jakub Jelinek <jakub@redhat.com>
+ * src/prelink.h (struct prelink_conflict): Add next2 field.
+ (struct prelink_conflicts): Add hash2 field.
+ * src/get.c (prelink_record_relocations): Clear next2 fields.
+ * src/prelink.c (free_info): Also free hash2 table.
+ * src/cxx.c (remove_redundant_cxx_conflicts): Populate hash2
+ if not populated yet, use it to speed up pltref checking.
+
* src/prelink.h (struct prelink_conflicts): New type.
(struct prelink_info): Change type of conflicts and curconflicts
fields to struct prelink_conflicts *.
diff --git a/trunk/src/cxx.c b/trunk/src/cxx.c
index 541ae4b..0268fc2 100644
--- a/trunk/src/cxx.c
+++ b/trunk/src/cxx.c
@@ -529,7 +529,7 @@ check_pltref:
if (sym.st_shndx == SHN_UNDEF && sym.st_value)
{
struct prelink_symbol *s;
- size_t maxidx = 1, l;
+ size_t maxidx, l;
if (verbose > 4)
error (0, 0, "Possible C++ conflict removal due to reference to binary's .plt at %s:%s+%d",
@@ -537,36 +537,78 @@ check_pltref:
(int) (info->conflict_rela[i].r_offset
- fcs1.sym.st_value));
- if (info->conflicts[fcs1.n].hash
- != &info->conflicts[fcs1.n].first)
- maxidx = 251;
for (s = &info->symbols[ndx]; s; s = s->next)
if (s->reloc_class == RTYPE_CLASS_PLT)
- {
- for (l = 0; l < maxidx; l++)
- for (conflict = info->conflicts[fcs1.n].hash[l];
- conflict; conflict = conflict->next)
+ break;
+
+ if (s == NULL)
+ break;
+
+ maxidx = 1;
+ if (info->conflicts[fcs1.n].hash
+ != &info->conflicts[fcs1.n].first)
+ {
+ if (info->conflicts[fcs1.n].hash2 == NULL)
+ {
+ info->conflicts[fcs1.n].hash2
+ = calloc (sizeof (struct prelink_conflict *), 251);
+ if (info->conflicts[fcs1.n].hash2 != NULL)
+ {
+ for (l = 0; l < 251; l++)
+ for (conflict = info->conflicts[fcs1.n].hash[l];
+ conflict; conflict = conflict->next)
+ if (conflict->reloc_class == RTYPE_CLASS_VALID
+ && conflict->conflict.ent)
+ {
+ size_t ccidx
+ = (conflict->lookup.ent->base
+ + conflict->lookupval) % 251;
+ conflict->next2
+ = info->conflicts[fcs1.n].hash2[ccidx];
+ info->conflicts[fcs1.n].hash2[ccidx]
+ = conflict;
+ }
+ }
+ }
+ if (info->conflicts[fcs1.n].hash2 != NULL)
+ {
+ size_t ccidx = info->conflict_rela[i].r_addend % 251;
+ for (conflict = info->conflicts[fcs1.n].hash2[ccidx];
+ conflict; conflict = conflict->next2)
if (conflict->lookup.ent->base + conflict->lookupval
== info->conflict_rela[i].r_addend
- && conflict->conflict.ent
&& (conflict->conflict.ent->base
+ conflict->conflictval
- == s->u.ent->base + s->value)
- && conflict->reloc_class == RTYPE_CLASS_VALID)
- {
- if (verbose > 3)
- error (0, 0, "Removing C++ conflict due to reference to binary's .plt at %s:%s+%d",
- fcs1.dso->filename, name,
- (int) (info->conflict_rela[i].r_offset
- - fcs1.sym.st_value));
-
- info->conflict_rela[i].r_info =
- GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info));
- ++removed;
- goto pltref_check_done;
- }
- break;
- }
+ == s->u.ent->base + s->value))
+ goto pltref_remove;
+ break;
+ }
+ maxidx = 251;
+ }
+
+ for (l = 0; l < maxidx; l++)
+ for (conflict = info->conflicts[fcs1.n].hash[l];
+ conflict; conflict = conflict->next)
+ if (conflict->lookup.ent->base + conflict->lookupval
+ == info->conflict_rela[i].r_addend
+ && conflict->conflict.ent
+ && (conflict->conflict.ent->base
+ + conflict->conflictval == s->u.ent->base + s->value)
+ && conflict->reloc_class == RTYPE_CLASS_VALID)
+ {
+pltref_remove:
+ if (verbose > 3)
+ error (0, 0, "Removing C++ conflict due to reference to binary's .plt at %s:%s+%d",
+ fcs1.dso->filename, name,
+ (int) (info->conflict_rela[i].r_offset
+ - fcs1.sym.st_value));
+
+ info->conflict_rela[i].r_info =
+ GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info));
+ ++removed;
+ goto pltref_check_done;
+ }
+
pltref_check_done:
break;
}
diff --git a/trunk/src/get.c b/trunk/src/get.c
index 928e57c..cea3309 100644
--- a/trunk/src/get.c
+++ b/trunk/src/get.c
@@ -411,6 +411,7 @@ prelink_record_relocations (struct prelink_info *info, FILE *f,
}
conflict->next = info->conflicts[symowner].hash[idx];
+ conflict->next2 = NULL;
info->conflicts[symowner].hash[idx] = conflict;
conflict->lookup.tls = tls;
conflict->conflict.tls = tls;
@@ -543,6 +544,7 @@ prelink_record_relocations (struct prelink_info *info, FILE *f,
}
conflict->next = info->conflicts[symowner].hash[idx];
+ conflict->next2 = NULL;
info->conflicts[symowner].hash[idx] = conflict;
if (reloc_class != RTYPE_CLASS_TLS)
{
diff --git a/trunk/src/prelink.c b/trunk/src/prelink.c
index 9b1998c..0d113b7 100644
--- a/trunk/src/prelink.c
+++ b/trunk/src/prelink.c
@@ -813,35 +813,39 @@ free_info (struct prelink_info *info)
if (info->conflicts)
{
for (i = 0; i < info->ent->ndepends + 1; ++i)
- if (info->conflicts[i].hash == &info->conflicts[i].first)
- {
- struct prelink_conflict *c = info->conflicts[i].first;
- void *f;
-
- while (c != NULL)
- {
- f = c;
- c = c->next;
- free (f);
- }
- }
- else
- {
- int j;
- for (j = 0; j < 251; j++)
- {
- struct prelink_conflict *c = info->conflicts[i].hash[j];
- void *f;
+ {
+ if (info->conflicts[i].hash == &info->conflicts[i].first)
+ {
+ struct prelink_conflict *c = info->conflicts[i].first;
+ void *f;
- while (c != NULL)
- {
- f = c;
- c = c->next;
- free (f);
- }
- }
- free (info->conflicts[i].hash);
- }
+ while (c != NULL)
+ {
+ f = c;
+ c = c->next;
+ free (f);
+ }
+ }
+ else
+ {
+ int j;
+ for (j = 0; j < 251; j++)
+ {
+ struct prelink_conflict *c = info->conflicts[i].hash[j];
+ void *f;
+
+ while (c != NULL)
+ {
+ f = c;
+ c = c->next;
+ free (f);
+ }
+ }
+ free (info->conflicts[i].hash);
+ }
+ if (info->conflicts[i].hash2 != NULL)
+ free (info->conflicts[i].hash2);
+ }
free (info->conflicts);
}
if (info->sonames)
diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h
index 770e345..1661779 100644
--- a/trunk/src/prelink.h
+++ b/trunk/src/prelink.h
@@ -389,6 +389,7 @@ struct prelink_symbol
struct prelink_conflict
{
struct prelink_conflict *next;
+ struct prelink_conflict *next2;
/* Object which it was relocated to. */
union
{
@@ -411,6 +412,7 @@ struct prelink_conflicts
{
struct prelink_conflict *first;
struct prelink_conflict **hash;
+ struct prelink_conflict **hash2;
size_t count;
};