aboutsummaryrefslogtreecommitdiff
path: root/ld/ldctor.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-10-14 13:57:01 +1030
committerAlan Modra <amodra@gmail.com>2019-10-14 16:47:13 +1030
commit3d9ee7d24be691e8b89cb5ebf0db744be279d8db (patch)
tree147e7737f9ad5aece81d86128dd57becec88730d /ld/ldctor.c
parent08dec09d8a26c115921b17110da1e07cb233c494 (diff)
downloadfsf-binutils-gdb-3d9ee7d24be691e8b89cb5ebf0db744be279d8db.zip
fsf-binutils-gdb-3d9ee7d24be691e8b89cb5ebf0db744be279d8db.tar.gz
fsf-binutils-gdb-3d9ee7d24be691e8b89cb5ebf0db744be279d8db.tar.bz2
qsort: ldctor.c CONSTRUCTORS
ctor_cmp had an ineffective comparison of addresses in an attempt to ensure sort stability. Comparing the addresses passed to the comparison function can't work since those addresses may be from an array that is already perturbed by qsort. * ldctor.h (struct set_element): Make next field a union, adding idx field. * ldctor.c (ctor_cmp): Dereference pointer and lose unnecessary const. Replace final sort on pointer value with final sort on idx. (ldctor_add_set_entry): Adjust next field access. (ldctor_build_sets): Likewise. Set u.idx field for sort.
Diffstat (limited to 'ld/ldctor.c')
-rw-r--r--ld/ldctor.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/ld/ldctor.c b/ld/ldctor.c
index ba8cac1..881ca25 100644
--- a/ld/ldctor.c
+++ b/ld/ldctor.c
@@ -106,12 +106,12 @@ ldctor_add_set_entry (struct bfd_link_hash_entry *h,
}
e = (struct set_element *) xmalloc (sizeof (struct set_element));
- e->next = NULL;
+ e->u.next = NULL;
e->name = name;
e->section = section;
e->value = value;
- for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
+ for (epp = &p->elements; *epp != NULL; epp = &(*epp)->u.next)
;
*epp = e;
@@ -152,19 +152,17 @@ ctor_prio (const char *name)
static int
ctor_cmp (const void *p1, const void *p2)
{
- const struct set_element *const *pe1
- = (const struct set_element *const *) p1;
- const struct set_element *const *pe2
- = (const struct set_element *const *) p2;
+ const struct set_element *pe1 = *(const struct set_element **) p1;
+ const struct set_element *pe2 = *(const struct set_element **) p2;
const char *n1;
const char *n2;
int prio1;
int prio2;
- n1 = (*pe1)->name;
+ n1 = pe1->name;
if (n1 == NULL)
n1 = "";
- n2 = (*pe2)->name;
+ n2 = pe2->name;
if (n2 == NULL)
n2 = "";
@@ -178,17 +176,15 @@ ctor_cmp (const void *p1, const void *p2)
/* We sort in reverse order because that is what g++ expects. */
if (prio1 < prio2)
return 1;
- else if (prio1 > prio2)
+ if (prio1 > prio2)
return -1;
/* Force a stable sort. */
-
- if (pe1 < pe2)
+ if (pe1->u.idx < pe2->u.idx)
return -1;
- else if (pe1 > pe2)
+ if (pe1->u.idx > pe2->u.idx)
return 1;
- else
- return 0;
+ return 0;
}
/* This function is called after the first phase of the link and
@@ -214,22 +210,24 @@ ldctor_build_sets (void)
for (p = sets; p != NULL; p = p->next)
{
int c, i;
- struct set_element *e;
+ struct set_element *e, *enext;
struct set_element **array;
if (p->elements == NULL)
continue;
c = 0;
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = e->u.next)
++c;
array = (struct set_element **) xmalloc (c * sizeof *array);
i = 0;
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = enext)
{
array[i] = e;
+ enext = e->u.next;
+ e->u.idx = i;
++i;
}
@@ -238,8 +236,8 @@ ldctor_build_sets (void)
e = array[0];
p->elements = e;
for (i = 0; i < c - 1; i++)
- array[i]->next = array[i + 1];
- array[i]->next = NULL;
+ array[i]->u.next = array[i + 1];
+ array[i]->u.next = NULL;
free (array);
}
@@ -334,7 +332,7 @@ ldctor_build_sets (void)
FALSE));
lang_add_data (size, exp_intop (p->count));
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = e->u.next)
{
if (config.map_file != NULL)
{