This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: PR ld/2065: "ld -r" is broken


On Sun, Dec 18, 2005 at 03:59:19PM -0800, H. J. Lu wrote:
> The problem is introduced by
> http://sourceware.org/ml/binutils/2005-11/msg00239.html
> where the new prev field is never really set properly

Yes, I slipped up.  I missed adjusting "prev" in lang_insert_orphan
too.  Obviously not enough testing.  Thanks for adding the new test, and
reverting the bad patch.

	* ldlang.h (lang_output_section_statement_type): Add prev.
	* ldlang.c (output_statement_newfunc): Set os.prev.
	(lang_insert_orphan): Likewise.
	(output_prev_sec_find): Use os.prev.

Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.59
diff -u -p -r1.59 ldlang.h
--- ld/ldlang.h	19 Dec 2005 15:06:40 -0000	1.59
+++ ld/ldlang.h	24 Dec 2005 07:24:34 -0000
@@ -130,6 +130,7 @@ typedef struct lang_output_section_state
   lang_statement_header_type header;
   lang_statement_list_type children;
   struct lang_output_section_statement_struct *next;
+  struct lang_output_section_statement_struct *prev;
   const char *name;
   asection *bfd_section;
   lang_memory_region_type *region;
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.211
diff -u -p -r1.211 ldlang.c
--- ld/ldlang.c	19 Dec 2005 15:06:40 -0000	1.211
+++ ld/ldlang.c	24 Dec 2005 07:24:34 -0000
@@ -912,6 +912,14 @@ output_statement_newfunc (struct bfd_has
 			 (lang_statement_union_type *) &ret->os,
 			 &ret->os.header.next);
 
+  /* For every output section statement added to the list, except the
+     first one, lang_output_section_statement.tail points to the "next"
+     field of the last element of the list.  */
+  if (lang_output_section_statement.head != NULL)
+    ret->os.prev = (lang_output_section_statement_type *)
+      ((char *) lang_output_section_statement.tail
+       - offsetof (lang_output_section_statement_type, next));
+
   /* GCC's strict aliasing rules prevent us from just casting the
      address, so we store the pointer in a variable and cast that
      instead.  */
@@ -1290,20 +1298,15 @@ lang_output_section_find_by_flags (const
 static asection *
 output_prev_sec_find (lang_output_section_statement_type *os)
 {
-  asection *s = (asection *) NULL;
   lang_output_section_statement_type *lookup;
 
-  for (lookup = &lang_output_section_statement.head->output_section_statement;
-       lookup != NULL;
-       lookup = lookup->next)
+  for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
     {
       if (lookup->constraint == -1)
 	continue;
-      if (lookup == os)
-	return s;
 
       if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
-	s = lookup->bfd_section;
+	return lookup->bfd_section;
     }
 
   return NULL;
@@ -1544,7 +1547,12 @@ lang_insert_orphan (asection *s,
 	  /* Do the same for the list of output section statements.  */
 	  newly_added_os = *os_tail;
 	  *os_tail = NULL;
+	  newly_added_os->prev = (lang_output_section_statement_type *)
+	    ((char *) place->os_tail
+	     - offsetof (lang_output_section_statement_type, next));
 	  newly_added_os->next = *place->os_tail;
+	  if (newly_added_os->next != NULL)
+	    newly_added_os->next->prev = newly_added_os;
 	  *place->os_tail = newly_added_os;
 	  place->os_tail = &newly_added_os->next;
 
-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]