qsort: ldctor.c CONSTRUCTORS
authorAlan Modra <amodra@gmail.com>
Mon, 14 Oct 2019 03:27:01 +0000 (13:57 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 14 Oct 2019 06:17:13 +0000 (16:47 +1030)
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.

ld/ChangeLog
ld/ldctor.c
ld/ldctor.h

index 19ed0b5f21c1c5435ff36859bce6d8fed3ead0cf..f8dca8633f7df0c8d8438199c991061b8f7827d8 100644 (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.
index ba8cac1e353dd7503ce44968878aace90a3b5b3f..881ca258cbc2d403eeaa1da2c70ee858da5adead 100644 (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)
            {
index fa21277fe63b2196869bf28d7753fe8995132d84..b48a0dbb635d2ad40d7524cc962f0053b3c61a87 100644 (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.  */