This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: PR ld/6931: COMDAT group is broken
On Fri, Oct 03, 2008 at 12:41:01PM -0700, H.J. Lu wrote:
> It is unsafe to use an existing section symbol as group signature
> since "ld -r" may change section symbol if there is a duplicate.
> This patch disallows using section symbol as group signature.
> OK to install?
This fixes the latest problem HJ has found with section groups and
ld -r. To stop ld -r merging sections that are part of a group, ld
generated unique names for them. If a renamed section symbol is used
as the group signature, then the group is broken. So, don't rename
sections. This was suprisingly easy to do with the existing SPECIAL
section support.
* ldemul.c (ldemul_place_orphan): Add "constraint" param.
* ldemul.h (ldemul_place_orphan): Update prototype.
(struct ld_emulation_xfer_struct <place_orphan>): Likewise add param.
* ldlang.c (unique_section_p): Make static.
(lang_output_section_statement_lookup): Optimise creation of SPECIAL
sections.
(lang_insert_orphan): Add "constraint" param. Pass to
lang_enter_output_section_statement.
(init_os): Don't use an existing bfd section for SPECIAL sections.
(lang_place_orphans): Don't rename unique output sections, instead
mark their output section statements SPECIAL.
* ldlang.h (lang_insert_orphan): Update prototype.
(unique_section_p): Delete.
* emultempl/beos.em (place_orphan): Add "constraint" param.
* emultempl/elf32.em (place_orphan): Likewise. Don't match existing
output sections if set.
* emultempl/pe.em (place_orphan): Likewise.
* emultempl/pep.em (place_orphan): Likewise.
* emultempl/mmo.em (mmo_place_orphan): Update.
* emultempl/spuelf.em (spu_place_special_section): Update.
Index: ld/ldemul.c
===================================================================
RCS file: /cvs/src/src/ld/ldemul.c,v
retrieving revision 1.28
diff -u -p -r1.28 ldemul.c
--- ld/ldemul.c 3 Oct 2008 09:40:49 -0000 1.28
+++ ld/ldemul.c 4 Oct 2008 01:17:49 -0000
@@ -120,10 +120,10 @@ ldemul_open_dynamic_archive (const char
}
bfd_boolean
-ldemul_place_orphan (asection *s, const char *name)
+ldemul_place_orphan (asection *s, const char *name, int constraint)
{
if (ld_emulation->place_orphan)
- return (*ld_emulation->place_orphan) (s, name);
+ return (*ld_emulation->place_orphan) (s, name, constraint);
return FALSE;
}
Index: ld/ldemul.h
===================================================================
RCS file: /cvs/src/src/ld/ldemul.h,v
retrieving revision 1.20
diff -u -p -r1.20 ldemul.h
--- ld/ldemul.h 3 Oct 2008 09:40:49 -0000 1.20
+++ ld/ldemul.h 4 Oct 2008 01:17:49 -0000
@@ -59,7 +59,7 @@ extern void ldemul_set_symbols
extern void ldemul_create_output_section_statements
(void);
extern bfd_boolean ldemul_place_orphan
- (asection *, const char *);
+ (asection *, const char *, int);
extern bfd_boolean ldemul_parse_args
(int, char **);
extern void ldemul_add_options
@@ -152,7 +152,7 @@ typedef struct ld_emulation_xfer_struct
the default action should be taken. This field may be NULL, in
which case the default action will always be taken. */
bfd_boolean (*place_orphan)
- (asection *, const char *);
+ (asection *, const char *, int);
/* Run after assigning parsing with the args, but before
reading the script. Used to initialize symbols used in the script. */
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.293
diff -u -p -r1.293 ldlang.c
--- ld/ldlang.c 3 Oct 2008 09:40:49 -0000 1.293
+++ ld/ldlang.c 4 Oct 2008 01:17:53 -0000
@@ -193,7 +193,7 @@ input_statement_is_archive_path (const c
return match;
}
-bfd_boolean
+static bfd_boolean
unique_section_p (const asection *sec)
{
struct unique_sections *unam;
@@ -1278,19 +1278,25 @@ lang_output_section_statement_lookup (co
struct out_section_hash_entry *last_ent;
unsigned long hash = entry->root.hash;
- do
- {
- if (entry->s.output_section_statement.constraint >= 0
- && (constraint == 0
- || (constraint == entry->s.output_section_statement.constraint
- && constraint != SPECIAL)))
- return &entry->s.output_section_statement;
- last_ent = entry;
- entry = (struct out_section_hash_entry *) entry->root.next;
- }
- while (entry != NULL
- && entry->root.hash == hash
- && strcmp (name, entry->s.output_section_statement.name) == 0);
+ if (create && constraint == SPECIAL)
+ /* Not traversing to the end reverses the order of the second
+ and subsequent SPECIAL sections in the hash table chain,
+ but that shouldn't matter. */
+ last_ent = entry;
+ else
+ do
+ {
+ if (entry->s.output_section_statement.constraint >= 0
+ && (constraint == 0
+ || (constraint
+ == entry->s.output_section_statement.constraint)))
+ return &entry->s.output_section_statement;
+ last_ent = entry;
+ entry = (struct out_section_hash_entry *) entry->root.next;
+ }
+ while (entry != NULL
+ && entry->root.hash == hash
+ && strcmp (name, entry->s.output_section_statement.name) == 0);
if (!create)
return NULL;
@@ -1556,6 +1562,7 @@ insert_os_after (lang_output_section_sta
lang_output_section_statement_type *
lang_insert_orphan (asection *s,
const char *secname,
+ int constraint,
lang_output_section_statement_type *after,
struct orphan_save *place,
etree_type *address,
@@ -1611,7 +1618,7 @@ lang_insert_orphan (asection *s,
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
- NULL, 0);
+ NULL, constraint);
if (add_child == NULL)
add_child = &os->children;
@@ -1914,10 +1921,11 @@ init_os (lang_output_section_statement_t
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
- s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
+ if (s->constraint != SPECIAL)
+ s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
if (s->bfd_section == NULL)
- s->bfd_section = bfd_make_section_with_flags (link_info.output_bfd,
- s->name, flags);
+ s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
+ s->name, flags);
if (s->bfd_section == NULL)
{
einfo (_("%P%F: output format %s cannot represent section called %s\n"),
@@ -5655,23 +5663,16 @@ lang_place_orphans (void)
else
{
const char *name = s->name;
+ int constraint = 0;
- if ((config.unique_orphan_sections
- || unique_section_p (s))
- && bfd_get_section_by_name (link_info.output_bfd,
- name) != NULL)
- {
- static int count = 1;
- name = bfd_get_unique_section_name (link_info.output_bfd,
- name, &count);
- if (name == NULL)
- einfo ("%F%P: place_orphan failed: %E\n");
- }
+ if (config.unique_orphan_sections || unique_section_p (s))
+ constraint = SPECIAL;
- if (!ldemul_place_orphan (s, name))
+ if (!ldemul_place_orphan (s, name, constraint))
{
lang_output_section_statement_type *os;
- os = lang_output_section_statement_lookup (name, 0,
+ os = lang_output_section_statement_lookup (name,
+ constraint,
TRUE);
lang_add_section (&os->children, s, os);
}
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.79
diff -u -p -r1.79 ldlang.h
--- ld/ldlang.h 7 Sep 2008 04:02:30 -0000 1.79
+++ ld/ldlang.h 4 Oct 2008 01:17:53 -0000
@@ -536,7 +536,7 @@ extern lang_output_section_statement_typ
(const asection *, lang_output_section_statement_type **,
lang_match_sec_type_func);
extern lang_output_section_statement_type *lang_insert_orphan
- (asection *, const char *, lang_output_section_statement_type *,
+ (asection *, const char *, int, lang_output_section_statement_type *,
struct orphan_save *, etree_type *, lang_statement_list_type *);
extern lang_input_statement_type *lang_add_input_file
(const char *, lang_input_file_enum_type, const char *);
@@ -604,8 +604,6 @@ extern void lang_register_vers_node
extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
extern void lang_append_dynamic_list_cpp_typeinfo (void);
extern void lang_append_dynamic_list_cpp_new (void);
-bfd_boolean unique_section_p
- (const asection *);
extern void lang_add_unique
(const char *);
extern const char *lang_get_output_target
Index: ld/emultempl/beos.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/beos.em,v
retrieving revision 1.41
diff -u -p -r1.41 beos.em
--- ld/emultempl/beos.em 3 Oct 2008 09:40:49 -0000 1.41
+++ ld/emultempl/beos.em 4 Oct 2008 01:17:54 -0000
@@ -665,7 +665,9 @@ gld_${EMULATION_NAME}_before_allocation
which are not mentioned in the linker script. */
static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
+gld${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
{
char *output_secname, *ps;
lang_output_section_statement_type *os;
@@ -694,7 +696,7 @@ gld${EMULATION_NAME}_place_orphan (asect
output_secname = xstrdup (secname);
ps = strchr (output_secname + 1, '\$');
*ps = 0;
- os = lang_output_section_statement_lookup (output_secname, 0, TRUE);
+ os = lang_output_section_statement_lookup (output_secname, constraint, TRUE);
/* Find the '\$' wild statement for this section. We currently require the
linker script to explicitly mention "*(.foo\$)".
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.193
diff -u -p -r1.193 elf32.em
--- ld/emultempl/elf32.em 3 Oct 2008 09:40:49 -0000 1.193
+++ ld/emultempl/elf32.em 4 Oct 2008 01:33:57 -0000
@@ -62,7 +62,8 @@ fragment <<EOF
static void gld${EMULATION_NAME}_before_parse (void);
static void gld${EMULATION_NAME}_after_open (void);
static void gld${EMULATION_NAME}_before_allocation (void);
-static bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *, const char *);
+static bfd_boolean gld${EMULATION_NAME}_place_orphan
+ (asection *, const char *, int);
static void gld${EMULATION_NAME}_finish (void);
EOF
@@ -1635,7 +1636,9 @@ output_rel_find (asection *sec, int isdy
sections in the right segment. */
static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
+gld${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
{
static struct orphan_save hold[] =
{
@@ -1705,9 +1708,8 @@ gld${EMULATION_NAME}_place_orphan (asect
}
/* Look through the script to see where to place this section. */
- os = lang_output_section_find (secname);
-
- if (os != NULL
+ if (constraint == 0
+ && (os = lang_output_section_find (secname)) != NULL
&& os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| (_bfd_elf_match_sections_by_type (link_info.output_bfd,
@@ -1796,7 +1798,7 @@ gld${EMULATION_NAME}_place_orphan (asect
after = &lang_output_section_statement.head->output_section_statement;
}
- lang_insert_orphan (s, secname, after, place, NULL, NULL);
+ lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
return TRUE;
}
Index: ld/emultempl/mmo.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/mmo.em,v
retrieving revision 1.22
diff -u -p -r1.22 mmo.em
--- ld/emultempl/mmo.em 15 Feb 2008 03:35:53 -0000 1.22
+++ ld/emultempl/mmo.em 4 Oct 2008 01:17:55 -0000
@@ -47,7 +47,9 @@ fragment <<EOF
from elf32.em. */
static bfd_boolean
-mmo_place_orphan (asection *s)
+mmo_place_orphan (asection *s,
+ const char *secname,
+ int constraint ATTRIBUTE_UNUSED)
{
static struct orphan_save hold_text =
{
@@ -56,7 +58,6 @@ mmo_place_orphan (asection *s)
0, 0, 0, 0
};
struct orphan_save *place;
- const char *secname;
lang_output_section_statement_type *after;
lang_output_section_statement_type *os;
@@ -66,7 +67,6 @@ mmo_place_orphan (asection *s)
return FALSE;
/* Only care for sections we're going to load. */
- secname = s->name;
os = lang_output_section_find (secname);
/* We have an output section by this name. Place the section inside it
@@ -93,7 +93,7 @@ mmo_place_orphan (asection *s)
/* If there's an output section by this name, we'll use it, regardless
of section flags, in contrast to what's done in elf32.em. */
- os = lang_insert_orphan (s, secname, after, place, NULL, NULL);
+ os = lang_insert_orphan (s, secname, 0, after, place, NULL, NULL);
/* We need an output section for .text as a root, so if there was none
(might happen with a peculiar linker script such as in "map
Index: ld/emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.135
diff -u -p -r1.135 pe.em
--- ld/emultempl/pe.em 3 Oct 2008 09:40:49 -0000 1.135
+++ ld/emultempl/pe.em 4 Oct 2008 01:17:56 -0000
@@ -1613,7 +1613,9 @@ gld_${EMULATION_NAME}_finish (void)
sort_sections. */
static bfd_boolean
-gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
+gld_${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
{
const char *orig_secname = secname;
char *dollar = NULL;
@@ -1631,11 +1633,10 @@ gld_${EMULATION_NAME}_place_orphan (asec
secname = newname;
}
- os = lang_output_section_find (secname);
-
lang_list_init (&add_child);
- if (os != NULL
+ if (constraint == 0
+ && (os = lang_output_section_find (secname)) != NULL
&& os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| ((s->flags ^ os->bfd_section->flags)
@@ -1721,7 +1722,8 @@ gld_${EMULATION_NAME}_place_orphan (asec
/* All sections in an executable must be aligned to a page boundary. */
address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
- os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+ os = lang_insert_orphan (s, secname, constraint, after, place, address,
+ &add_child);
}
{
Index: ld/emultempl/pep.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pep.em,v
retrieving revision 1.14
diff -u -p -r1.14 pep.em
--- ld/emultempl/pep.em 3 Oct 2008 09:40:49 -0000 1.14
+++ ld/emultempl/pep.em 4 Oct 2008 01:17:57 -0000
@@ -1372,7 +1372,9 @@ gld_${EMULATION_NAME}_finish (void)
sort_sections. */
static bfd_boolean
-gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
+gld_${EMULATION_NAME}_place_orphan (asection *s,
+ const char *secname,
+ int constraint)
{
const char *orig_secname = secname;
char *dollar = NULL;
@@ -1390,11 +1392,10 @@ gld_${EMULATION_NAME}_place_orphan (asec
secname = newname;
}
- os = lang_output_section_find (secname);
-
lang_list_init (&add_child);
- if (os != NULL
+ if (constraint == 0
+ && (os = lang_output_section_find (secname)) != NULL
&& os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| ((s->flags ^ os->bfd_section->flags)
@@ -1480,7 +1481,8 @@ gld_${EMULATION_NAME}_place_orphan (asec
/* All sections in an executable must be aligned to a page boundary. */
address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
- os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+ os = lang_insert_orphan (s, secname, constraint, after, place, address,
+ &add_child);
}
{
Index: ld/emultempl/spuelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/spuelf.em,v
retrieving revision 1.27
diff -u -p -r1.27 spuelf.em
--- ld/emultempl/spuelf.em 3 Oct 2008 09:40:49 -0000 1.27
+++ ld/emultempl/spuelf.em 4 Oct 2008 01:17:58 -0000
@@ -114,7 +114,7 @@ spu_place_special_section (asection *s,
os = lang_output_section_find (o != NULL ? o->name : output_name);
if (os == NULL)
- gld${EMULATION_NAME}_place_orphan (s, output_name);
+ gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
else if (o != NULL && os->children.head != NULL)
{
lang_statement_list_type add;
--
Alan Modra
Australia Development Lab, IBM