This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
fix pr44
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Date: Wed, 13 Oct 2004 09:05:31 +0930
- Subject: fix pr44
This is a partial fix for the PE "NOCROSSREFS 2" failure. The PE
place_orphan code was missing a number of fixes added to the ELF
version, resulting in the linker losing output_section_statements for
.stab and .stabstr. Backporting the ELF changes cures this problem.
The test
int i = 4;
int
foo ()
{
return i;
}
still fails for me though. A little debugging shows that the
reloc in .text for i has been reduced to one against .data, but
.data is just a local symbol rather than being the section symbol.
Inside check_reloc_refs:
(gdb) p symname
$6 = 0x0
(gdb) p **q->sym_ptr_ptr
$7 = {the_bfd = 0x80eb928, name = 0x80f49f0 ".data", value = 0, flags = 1,
section = 0x80f5004, udata = {p = 0x0, i = 0}}
(gdb) p *info->defsec->symbol
$8 = {the_bfd = 0x80eb928, name = 0x80f3f38 ".data", value = 0, flags = 256,
section = 0x80f5004, udata = {p = 0x0, i = 0}}
I haven't yet looked into why the reloc symbol is like this.
* emultempl/pe.em (struct orphan_save): Add os_tail.
(place_orphan): Backport assorted fixes from elf32.em.
Index: ld/emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.96
diff -u -p -r1.96 pe.em
--- ld/emultempl/pe.em 30 Sep 2004 17:19:19 -0000 1.96
+++ ld/emultempl/pe.em 12 Oct 2004 23:33:13 -0000
@@ -1530,6 +1530,7 @@ struct orphan_save
lang_output_section_statement_type *os;
asection **section;
lang_statement_union_type **stmt;
+ lang_statement_union_type **os_tail;
};
static bfd_boolean
@@ -1573,10 +1574,14 @@ gld_${EMULATION_NAME}_place_orphan (lang
static struct orphan_save hold_rdata;
static struct orphan_save hold_data;
static struct orphan_save hold_bss;
+ static int count = 1;
char *outsecname;
lang_statement_list_type *old;
lang_statement_list_type add;
+ lang_statement_union_type **os_tail;
etree_type *address;
+ etree_type *load_base;
+ asection *sec;
/* Try to put the new output section in a reasonable place based
on the section name and section flags. */
@@ -1596,41 +1601,42 @@ gld_${EMULATION_NAME}_place_orphan (lang
&& (s->flags & SEC_READONLY) != 0
&& HAVE_SECTION (hold_rdata, ".rdata"))
place = &hold_rdata;
- else if ((s->flags & SEC_READONLY) != 0
+ else if ((s->flags & SEC_CODE) != 0
+ && (s->flags & SEC_READONLY) != 0
&& HAVE_SECTION (hold_text, ".text"))
place = &hold_text;
#undef HAVE_SECTION
- /* Choose a unique name for the section. This will be needed if
- the same section name appears in the input file with
- different loadable or allocatable characteristics. */
- outsecname = xstrdup (hold_section_name);
- if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
+ /* Choose a unique name for the section. This will be needed if the
+ same section name appears in the input file with different
+ loadable or allocatable characteristics. But if the section
+ already exists but does not have any flags set, then it has been
+ created by the linker, probably as a result of a --section-start
+ command line switch. */
+ sec = bfd_get_section_by_name (output_bfd, hold_section_name);
+ if (sec != NULL
+ && bfd_get_section_flags (output_bfd, sec) != 0)
{
- unsigned int len;
- char *newname;
- unsigned int i;
-
- len = strlen (outsecname);
- newname = xmalloc (len + 5);
- strcpy (newname, outsecname);
- i = 0;
- do
- {
- sprintf (newname + len, "%d", i);
- ++i;
- }
- while (bfd_get_section_by_name (output_bfd, newname) != NULL);
-
- free (outsecname);
- outsecname = newname;
+ outsecname = bfd_get_unique_section_name (output_bfd,
+ hold_section_name, &count);
+ if (outsecname == NULL)
+ einfo ("%F%P: place_orphan failed: %E\n");
}
+ else
+ outsecname = xstrdup (hold_section_name);
/* Start building a list of statements for this section. */
old = stat_ptr;
- stat_ptr = &add;
- lang_list_init (stat_ptr);
+
+ /* If we have found an appropriate place for the output section
+ statements for this orphan, add them to our own private list,
+ inserting them later into the global statement list. */
+ if (place != NULL)
+ {
+ stat_ptr = &add;
+ lang_list_init (stat_ptr);
+ }
if (config.build_constructors)
{
@@ -1662,10 +1668,21 @@ gld_${EMULATION_NAME}_place_orphan (lang
exp_nameop (NAME, "__section_alignment__"));
}
+ load_base = NULL;
+ if (place != NULL && place->os->load_base != NULL)
+ {
+ etree_type *lma_from_vma;
+ lma_from_vma = exp_binop ('-', place->os->load_base,
+ exp_nameop (ADDR, place->os->name));
+ load_base = exp_binop ('+', lma_from_vma,
+ exp_nameop (ADDR, secname));
+ }
+
+ os_tail = lang_output_section_statement.tail;
os = lang_enter_output_section_statement (outsecname, address, 0,
(etree_type *) NULL,
(etree_type *) NULL,
- (etree_type *) NULL, 0);
+ load_base, 0);
lang_add_section (&add_child, s, os, file);
@@ -1741,11 +1758,15 @@ gld_${EMULATION_NAME}_place_orphan (lang
read/write section before or amongst the read-only ones. */
if (add.head != NULL)
{
+ lang_statement_union_type *newly_added_os;
+
if (place->stmt == NULL)
{
/* Put the new statement list right at the head. */
*add.tail = place->os->header.next;
place->os->header.next = add.head;
+
+ place->os_tail = &place->os->next;
}
else
{
@@ -1761,6 +1782,21 @@ gld_${EMULATION_NAME}_place_orphan (lang
/* Save the end of this list. */
place->stmt = add.tail;
+
+ /* Do the same for the list of output section statements. */
+ newly_added_os = *os_tail;
+ *os_tail = NULL;
+ newly_added_os->output_section_statement.next = *place->os_tail;
+ *place->os_tail = newly_added_os;
+ place->os_tail = &newly_added_os->output_section_statement.next;
+
+ /* Fixing the global list pointer here is a little different.
+ We added to the list in lang_enter_output_section_statement,
+ trimmed off the new output_section_statment above when
+ assigning *os_tail = NULL, but possibly added it back in
+ the same place when assigning *place->os_tail. */
+ if (*os_tail == NULL)
+ lang_output_section_statement.tail = os_tail;
}
}
}
--
Alan Modra
IBM OzLabs - Linux Technology Centre