This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: PR ld/2065: "ld -r" is broken
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: "H. J. Lu" <hjl at lucon dot org>
- Cc: binutils at sources dot redhat dot com
- Date: Sat, 24 Dec 2005 18:16:26 +1030
- Subject: Re: PATCH: PR ld/2065: "ld -r" is broken
- References: <20051219000221.GB20796@lucon.org>
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