This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: PR ld/2065: "ld -r" is broken
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Cc: amodra at bigpond dot net dot au
- Date: Sun, 18 Dec 2005 16:02:21 -0800
- Subject: PATCH: PR ld/2065: "ld -r" is broken
I am resending this with proper subject.
H.J.
---
On Sun, Dec 18, 2005 at 03:42:23PM -0800, H. J. Lu wrote:
> On Sat, Dec 17, 2005 at 12:46:44PM +1030, Alan Modra wrote:
> > On Fri, Dec 16, 2005 at 05:46:40PM -0800, H. J. Lu wrote:
> > > bad.o is generated by the new linker. Alan, can you take a look?
> >
> > Sorry, not immediately. I'm just about to leave for a week at the
> > beach with my family.
> >
>
> I opened a PR:
>
> http://sourceware.org/bugzilla/show_bug.cgi?id=2065
>
> and I am checking this testcase.
>
The problem is introduced by
http://sourceware.org/ml/binutils/2005-11/msg00239.html
where the new prev field is never really set properly since the last
field used to set it points to the next field of the last element on
the list.
This hack seems to work for me. But I'd like to see the tail field in
lang_statement_list_type be removed if possible. Alan, can you take
a look after you come back?
Thanks.
H.J.
----
2005-12-18 H.J. Lu <hongjiu.lu@intel.com>
PR ld/2065
* ldlang.h (lang_statement_list_type): Add last.
* ldlang.c (file_chain): Set the last field.
(lang_list_init): Likewise.
(lang_insert_orphan): Likewise.
(lang_statement_append): Likewise.
(output_statement_newfunc): Set os.prev with last.
--- ld/ldlang.c.prev 2005-12-18 09:40:59.000000000 -0800
+++ ld/ldlang.c 2005-12-18 14:29:57.000000000 -0800
@@ -89,7 +89,7 @@ static void lang_do_version_exports_sect
lang_output_section_statement_type *abs_output_section;
lang_statement_list_type lang_output_section_statement;
lang_statement_list_type *stat_ptr = &statement_list;
-lang_statement_list_type file_chain = { NULL, NULL };
+lang_statement_list_type file_chain = { NULL, NULL, NULL };
struct bfd_sym_chain entry_symbol = { NULL, NULL };
static const char *entry_symbol_default = "start";
const char *entry_section = ".text";
@@ -742,6 +742,7 @@ void
lang_list_init (lang_statement_list_type *list)
{
list->head = NULL;
+ list->last = NULL;
list->tail = &list->head;
}
@@ -912,8 +913,10 @@ output_statement_newfunc (struct bfd_has
(lang_statement_union_type *) &ret->os,
&ret->os.header.next);
- ret->os.prev = &((*lang_output_section_statement.tail)
- ->output_section_statement);
+ if (lang_output_section_statement.last)
+ ret->os.prev
+ = &(lang_output_section_statement.last->output_section_statement);
+
/* GCC's strict aliasing rules prevent us from just casting the
address, so we store the pointer in a variable and cast that
instead. */
@@ -1531,7 +1534,10 @@ lang_insert_orphan (lang_input_statement
/* Fix the global list pointer if we happened to tack our
new list at the tail. */
if (*old->tail == add.head)
- old->tail = add.tail;
+ {
+ old->last = add.last;
+ old->tail = add.tail;
+ }
/* Save the end of this list. */
place->stmt = add.tail;
@@ -5836,6 +5842,7 @@ lang_statement_append (lang_statement_li
lang_statement_union_type **field)
{
*(list->tail) = element;
+ list->last = element;
list->tail = field;
}
--- ld/ldlang.h.prev 2005-12-18 09:40:59.000000000 -0800
+++ ld/ldlang.h 2005-12-18 14:12:14.000000000 -0800
@@ -44,6 +44,7 @@ struct _fill_type
typedef struct statement_list
{
union lang_statement_union *head;
+ union lang_statement_union *last;
union lang_statement_union **tail;
} lang_statement_list_type;