This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: ld/1467: Orphaned section is put in the odd place
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Tue, 11 Oct 2005 22:49:33 -0700
- Subject: PATCH: ld/1467: Orphaned section is put in the odd place
The ELF linker doesn't check section type and checks section name when
placing orphan. Both may lead to odd orphaned section placement. This
patch adds section type check and removes the section name check.
H.J.
---
2005-10-11 H.J. Lu <hongjiu.lu@intel.com>
PR ld/1467
* emultempl/elf32.em: Include "elf-bfd.h".
(gld${EMULATION_NAME}_output_section_find): New.
(gld${EMULATION_NAME}_place_orphan): Use it. Don't use section
name. Check section type.
--- ld/emultempl/elf32.em.orphan 2005-09-07 11:42:00.000000000 -0700
+++ ld/emultempl/elf32.em 2005-10-11 22:40:13.000000000 -0700
@@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street - F
#include "ldemul.h"
#include <ldgram.h>
#include "elf/common.h"
+#include "elf-bfd.h"
/* Declare functions used by various EXTRA_EM_FILEs. */
static void gld${EMULATION_NAME}_before_parse (void);
@@ -1278,6 +1279,148 @@ output_rel_find (asection *sec, int isdy
return last;
}
+/* A variant of lang_output_section_find used by place_orphan.
+ Returns the output statement that should precede a new output
+ statement for SEC. If an exact match is found on certain flags,
+ sets *EXACT too. */
+
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_output_section_find
+ (const asection *sec, lang_output_section_statement_type **exact)
+{
+ lang_output_section_statement_type *first, *look, *found;
+ flagword flags;
+ unsigned int sh_type = elf_section_type (sec);
+
+ /* We know the first statement on this list is *ABS*. May as well
+ skip it. */
+ first = &lang_output_section_statement.head->output_section_statement;
+ first = first->next;
+
+ /* First try for an exact match. */
+ found = NULL;
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+ | SEC_READONLY | SEC_CODE | SEC_SMALL_DATA
+ | SEC_THREAD_LOCAL)))
+ found = look;
+ }
+ if (found != NULL)
+ {
+ *exact = found;
+ return found;
+ }
+
+ if (sec->flags & SEC_CODE)
+ {
+ /* Try for a rw code section. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+ | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+ found = look;
+ }
+ return found;
+ }
+
+ if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+ {
+ /* .rodata can go after .text, .sdata2 after .rodata. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+ | SEC_READONLY))
+ && !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+ found = look;
+ }
+ return found;
+ }
+
+ if (sec->flags & SEC_SMALL_DATA)
+ {
+ /* .sdata goes after .data, .sbss after .sdata. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+ | SEC_THREAD_LOCAL))
+ || ((look->flags & SEC_SMALL_DATA)
+ && !(sec->flags & SEC_HAS_CONTENTS)))
+ found = look;
+ }
+ return found;
+ }
+
+ if (sec->flags & SEC_HAS_CONTENTS)
+ {
+ /* .data goes after .rodata. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+ | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+ found = look;
+ }
+ return found;
+ }
+
+ /* .bss goes last. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (sh_type != elf_section_type (look->bfd_section))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & SEC_ALLOC))
+ found = look;
+ }
+
+ return found;
+}
+
/* Place an orphan section. We use this to put random SHF_ALLOC
sections in the right segment. */
@@ -1324,20 +1467,26 @@ gld${EMULATION_NAME}_place_orphan (lang_
lang_output_section_statement_type *after;
lang_output_section_statement_type *os;
int isdyn = 0;
+ unsigned int sh_type = elf_section_type (s);
secname = bfd_get_section_name (s->owner, s);
if (! link_info.relocatable
&& link_info.combreloc
- && (s->flags & SEC_ALLOC)
- && strncmp (secname, ".rel", 4) == 0)
- {
- if (secname[4] == 'a')
+ && (s->flags & SEC_ALLOC))
+ switch (sh_type)
+ {
+ case SHT_RELA:
secname = ".rela.dyn";
- else
+ isdyn = 1;
+ break;
+ case SHT_REL:
secname = ".rel.dyn";
- isdyn = 1;
- }
+ isdyn = 1;
+ break;
+ default:
+ break;
+ }
if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
{
@@ -1347,8 +1496,9 @@ gld${EMULATION_NAME}_place_orphan (lang_
if (os != NULL
&& (os->bfd_section == NULL
|| os->bfd_section->flags == 0
- || ((s->flags ^ os->bfd_section->flags)
- & (SEC_LOAD | SEC_ALLOC)) == 0))
+ || (sh_type == elf_section_type (os->bfd_section)
+ && ((s->flags ^ os->bfd_section->flags)
+ & (SEC_LOAD | SEC_ALLOC)) == 0)))
{
/* We already have an output section statement with this
name, and its bfd section, if any, has compatible flags.
@@ -1394,8 +1544,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
place = NULL;
if ((s->flags & SEC_ALLOC) == 0)
;
- else if ((s->flags & SEC_LOAD) != 0
- && strncmp (secname, ".note", 5) == 0)
+ else if ((s->flags & SEC_LOAD) != 0 && sh_type == SHT_NOTE)
place = &hold[orphan_interp];
else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
place = &hold[orphan_bss];
@@ -1403,7 +1552,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
place = &hold[orphan_sdata];
else if ((s->flags & SEC_READONLY) == 0)
place = &hold[orphan_data];
- else if (strncmp (secname, ".rel", 4) == 0
+ else if ((sh_type == SHT_RELA || sh_type == SHT_REL)
&& (s->flags & SEC_LOAD) != 0)
place = &hold[orphan_rel];
else if ((s->flags & SEC_CODE) == 0)
@@ -1423,7 +1572,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
}
after = place->os;
if (after == NULL)
- after = lang_output_section_find_by_flags (s, &place->os);
+ after = gld${EMULATION_NAME}_output_section_find (s, &place->os);
if (after == NULL)
/* *ABS* is always the first output section statement. */
after = &lang_output_section_statement.head->output_section_statement;