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.
This commit is contained in:
Alan Modra
2019-10-14 13:57:01 +10:30
parent 08dec09d8a
commit 3d9ee7d24b
3 changed files with 31 additions and 21 deletions

View File

@ -1,3 +1,12 @@
2019-10-14 Alan Modra <amodra@gmail.com>
* 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.
2019-10-14 Alan Modra <amodra@gmail.com>
* pe-dll.c (reloc_data_type): Add idx field.

View File

@ -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)
{

View File

@ -40,7 +40,10 @@ struct set_info {
};
struct set_element {
struct set_element *next; /* Next element. */
union {
struct set_element *next; /* Next element. */
long idx;
} u;
const char *name; /* Name in set (may be NULL). */
asection *section; /* Section of value in set. */
bfd_vma value; /* Value in set. */