[binutils-gdb] qsort: ldctor.c CONSTRUCTORS

Alan Modra amodra@sourceware.org
Mon Oct 14 06:18:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3d9ee7d24be691e8b89cb5ebf0db744be279d8db

commit 3d9ee7d24be691e8b89cb5ebf0db744be279d8db
Author: Alan Modra <amodra@gmail.com>
Date:   Mon Oct 14 13:57:01 2019 +1030

    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.

Diff:
---
 ld/ChangeLog |  9 +++++++++
 ld/ldctor.c  | 38 ++++++++++++++++++--------------------
 ld/ldctor.h  |  5 ++++-
 3 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 19ed0b5..f8dca86 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,14 @@
 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.
 	(reloc_sort): Perform final sort by idx.
 	(generate_reloc): Set idx.
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)
 	    {
diff --git a/ld/ldctor.h b/ld/ldctor.h
index fa21277..b48a0db 100644
--- a/ld/ldctor.h
+++ b/ld/ldctor.h
@@ -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.  */



More information about the Binutils-cvs mailing list