This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: PR ld/1487: ELF input section may not be handled properly
- From: "H. J. Lu" <hjl at lucon dot org>
- To: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- Cc: binutils at sourceware dot org
- Date: Thu, 20 Oct 2005 10:39:11 -0700
- Subject: PATCH: PR ld/1487: ELF input section may not be handled properly
- References: <200510192124.j9JLO9Ye023967@ignucius.se.axis.com>
On Wed, Oct 19, 2005 at 11:24:09PM +0200, Hans-Peter Nilsson wrote:
> Your new test seems to fail for cris-axis-elf but I'd guess the
> failure is not target-specific. My autotester binutils.log
> says:
>
If an ELF input section has a type, which isn't sepecial to bfd, we
don't handle it properly. This patch sets the output ELF section type
the same as the input. I also simplify the SHF_GROUP/SHF_LINK_ORDER
handling.
One side effect is that .IA_64.unwind now has the proper type so that
_bfd_elf_link_omit_section_dynsym will remove it from the .dynsym
section.
H.J.
-----
bfd/
2005-10-20 H.J. Lu <hongjiu.lu@intel.com>
PR ld/1487
* elf-bfd.h (_bfd_generic_init_private_section_data): New.
(_bfd_elf_init_private_section_data): New.
* elf.c (elf_fake_sections): Don't set SHF_GROUP for
relocatable link.
(bfd_elf_set_group_contents): Don't handle relocatable link
specially.
(assign_section_numbers): If it isn't called by assembler,
use the output section of elf_linked_to_section for
SHF_LINK_ORDER.
(_bfd_elf_init_private_section_data): New.
(_bfd_elf_copy_private_section_data): Call it.
* libbfd-in.h (_bfd_generic_init_private_section_data): New.
* libbfd.c (_bfd_generic_init_private_section_data): New.
* targets.c (BFD_JUMP_TABLE_COPY): Add
_bfd_generic_init_private_section_data.
(bfd_init_private_section_data): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
ld/
2005-10-20 H.J. Lu <hongjiu.lu@intel.com>
PR ld/1487
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Call
bfd_match_sections_by_type to match section types.
* ldlang.c (init_os): Take the input section. Call
bfd_init_private_section_data if the input section isn't NULL.
(exp_init_os): Pass NULL to init_os.
(map_input_to_output_sections): Likewise.
(lang_add_section): Pass the input section to init_os.
ld/testsuite/
2005-10-20 H.J. Lu <hongjiu.lu@intel.com>
PR ld/1487
* ld-ia64/tlspic.rd: Updated.
--- binutils/bfd/elf-bfd.h.copy 2005-10-17 09:40:29.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2005-10-20 10:12:36.000000000 -0700
@@ -1492,6 +1492,10 @@ extern bfd_boolean _bfd_elf_copy_private
(bfd *, bfd *);
extern bfd_boolean _bfd_elf_copy_private_symbol_data
(bfd *, asymbol *, bfd *, asymbol *);
+#define _bfd_generic_init_private_section_data \
+ _bfd_elf_init_private_section_data
+extern bfd_boolean _bfd_elf_init_private_section_data
+ (bfd *, asection *, bfd *, asection *, struct bfd_link_info *);
extern bfd_boolean _bfd_elf_copy_private_section_data
(bfd *, asection *, bfd *, asection *);
extern bfd_boolean _bfd_elf_write_object_contents
--- binutils/bfd/elf.c.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/bfd/elf.c 2005-10-20 10:32:57.000000000 -0700
@@ -2670,29 +2670,7 @@ elf_fake_sections (bfd *abfd, asection *
if (this_hdr->sh_type == SHT_NULL)
{
if ((asect->flags & SEC_GROUP) != 0)
- {
- /* We also need to mark SHF_GROUP here for relocatable
- link. */
- struct bfd_link_order *l;
- asection *elt;
-
- for (l = asect->map_head.link_order; l != NULL; l = l->next)
- if (l->type == bfd_indirect_link_order
- && (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
- do
- {
- /* The name is not important. Anything will do. */
- elf_group_name (elt->output_section) = "G";
- elf_section_flags (elt->output_section) |= SHF_GROUP;
-
- elt = elf_next_in_group (elt);
- /* During a relocatable link, the lists are
- circular. */
- }
- while (elt != elf_next_in_group (l->u.indirect.section));
-
- this_hdr->sh_type = SHT_GROUP;
- }
+ this_hdr->sh_type = SHT_GROUP;
else if ((asect->flags & SEC_ALLOC) != 0
&& (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|| (asect->flags & SEC_NEVER_LOAD) != 0))
@@ -2827,7 +2805,6 @@ bfd_elf_set_group_contents (bfd *abfd, a
unsigned long symindx;
asection *elt, *first;
unsigned char *loc;
- struct bfd_link_order *l;
bfd_boolean gas;
/* Ignore linker created group section. See elfNN_ia64_object_p in
@@ -2896,22 +2873,6 @@ bfd_elf_set_group_contents (bfd *abfd, a
break;
}
- /* If this is a relocatable link, then the above did nothing because
- SEC is the output section. Look through the input sections
- instead. */
- for (l = sec->map_head.link_order; l != NULL; l = l->next)
- if (l->type == bfd_indirect_link_order
- && (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
- do
- {
- loc -= 4;
- H_PUT_32 (abfd,
- elf_section_data (elt->output_section)->this_idx, loc);
- elt = elf_next_in_group (elt);
- /* During a relocatable link, the lists are circular. */
- }
- while (elt != elf_next_in_group (l->u.indirect.section));
-
if ((loc -= 4) != sec->contents)
abort ();
@@ -3091,67 +3052,46 @@ assign_section_numbers (bfd *abfd, struc
{
s = elf_linked_to_section (sec);
if (s)
- d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- else
{
- struct bfd_link_order *p;
-
- /* Find out what the corresponding section in output
- is. */
- for (p = sec->map_head.link_order; p != NULL; p = p->next)
+ if (link_info != NULL)
{
- s = p->u.indirect.section;
- if (p->type == bfd_indirect_link_order
- && (bfd_get_flavour (s->owner)
- == bfd_target_elf_flavour))
+ /* For linker, elf_linked_to_section points to the
+ input section. */
+ if (elf_discarded_section (s))
{
- Elf_Internal_Shdr ** const elf_shdrp
- = elf_elfsections (s->owner);
- int elfsec
- = _bfd_elf_section_from_bfd_section (s->owner, s);
- elfsec = elf_shdrp[elfsec]->sh_link;
- /* PR 290:
- The Intel C compiler generates SHT_IA_64_UNWIND with
- SHF_LINK_ORDER. But it doesn't set the sh_link or
- sh_info fields. Hence we could get the situation
- where elfsec is 0. */
- if (elfsec == 0)
- {
- const struct elf_backend_data *bed
- = get_elf_backend_data (abfd);
- if (bed->link_order_error_handler)
- bed->link_order_error_handler
- (_("%B: warning: sh_link not set for section `%A'"),
- abfd, s);
- }
- else
+ asection *kept;
+ (*_bfd_error_handler)
+ (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ abfd, d->this_hdr.bfd_section,
+ s, s->owner);
+ /* Point to the kept section if it has the same
+ size as the discarded one. */
+ kept = _bfd_elf_check_kept_section (s);
+ if (kept == NULL)
{
- s = elf_shdrp[elfsec]->bfd_section;
- if (elf_discarded_section (s))
- {
- asection *kept;
- (*_bfd_error_handler)
- (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
- abfd, d->this_hdr.bfd_section,
- s, s->owner);
- /* Point to the kept section if it has
- the same size as the discarded
- one. */
- kept = _bfd_elf_check_kept_section (s);
- if (kept == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- s = kept;
- }
- s = s->output_section;
- BFD_ASSERT (s != NULL);
- d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
- break;
+ s = kept;
}
+ s = s->output_section;
+ BFD_ASSERT (s != NULL);
}
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ }
+ else
+ {
+ /* PR 290:
+ The Intel C compiler generates SHT_IA_64_UNWIND with
+ SHF_LINK_ORDER. But it doesn't set the sh_link or
+ sh_info fields. Hence we could get the situation
+ where s is NULL. */
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (abfd);
+ if (bed->link_order_error_handler)
+ bed->link_order_error_handler
+ (_("%B: warning: sh_link not set for section `%A'"),
+ abfd, sec);
}
}
@@ -5665,6 +5605,62 @@ copy_private_bfd_data (bfd *ibfd, bfd *o
return TRUE;
}
+/* Initialize private output section information from input section. */
+
+bfd_boolean
+_bfd_elf_init_private_section_data (bfd *ibfd,
+ asection *isec,
+ bfd *obfd,
+ asection *osec,
+ struct bfd_link_info *link_info)
+
+{
+ Elf_Internal_Shdr *ihdr, *ohdr;
+ bfd_boolean need_group = link_info == NULL || link_info->relocatable;
+
+ if (ibfd->xvec->flavour != bfd_target_elf_flavour
+ || obfd->xvec->flavour != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* FIXME: What if the output ELF section type has been set to
+ something different? */
+ if (elf_section_type (osec) == SHT_NULL)
+ elf_section_type (osec) = elf_section_type (isec);
+
+ /* Set things up for objcopy and relocatable link. The output
+ SHT_GROUP section will have its elf_next_in_group pointing back
+ to the input group members. Ignore linker created group section.
+ See elfNN_ia64_object_p in elfxx-ia64.c. */
+
+ if (need_group)
+ {
+ if (elf_sec_group (isec) == NULL
+ || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
+ {
+ if (elf_section_flags (isec) & SHF_GROUP)
+ elf_section_flags (osec) |= SHF_GROUP;
+ elf_next_in_group (osec) = elf_next_in_group (isec);
+ elf_group_name (osec) = elf_group_name (isec);
+ }
+ }
+
+ ihdr = &elf_section_data (isec)->this_hdr;
+
+ /* We need to handle elf_linked_to_section for SHF_LINK_ORDER. We
+ don't use the output section of the linked-to section since it
+ may be NULL at this point. */
+ if ((ihdr->sh_flags & SHF_LINK_ORDER) != 0)
+ {
+ ohdr = &elf_section_data (osec)->this_hdr;
+ ohdr->sh_flags |= SHF_LINK_ORDER;
+ elf_linked_to_section (osec) = elf_linked_to_section (isec);
+ }
+
+ osec->use_rela_p = isec->use_rela_p;
+
+ return TRUE;
+}
+
/* Copy private section information. This copies over the entsize
field, and sometimes the info field. */
@@ -5691,27 +5687,8 @@ _bfd_elf_copy_private_section_data (bfd
|| ihdr->sh_type == SHT_GNU_verdef)
ohdr->sh_info = ihdr->sh_info;
- /* Set things up for objcopy. The output SHT_GROUP section will
- have its elf_next_in_group pointing back to the input group
- members. Ignore linker created group section. See
- elfNN_ia64_object_p in elfxx-ia64.c. We also need to handle
- elf_linked_to_section for SHF_LINK_ORDER. */
-
- if ((ihdr->sh_flags & SHF_LINK_ORDER) != 0
- && elf_linked_to_section (isec) != 0)
- elf_linked_to_section (osec)
- = elf_linked_to_section (isec)->output_section;
-
- if (elf_sec_group (isec) == NULL
- || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
- {
- elf_next_in_group (osec) = elf_next_in_group (isec);
- elf_group_name (osec) = elf_group_name (isec);
- }
-
- osec->use_rela_p = isec->use_rela_p;
-
- return TRUE;
+ return _bfd_elf_init_private_section_data (ibfd, isec, obfd, osec,
+ NULL);
}
/* Copy private header information. */
--- binutils/bfd/libbfd-in.h.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/bfd/libbfd-in.h 2005-10-20 10:12:36.000000000 -0700
@@ -234,6 +234,9 @@ extern bfd_boolean _bfd_generic_get_sect
#define _bfd_generic_bfd_print_private_bfd_data \
((bfd_boolean (*) (bfd *, void *)) bfd_true)
+extern bfd_boolean _bfd_generic_init_private_section_data
+ (bfd *, asection *, bfd *, asection *, struct bfd_link_info *);
+
/* Routines to use for BFD_JUMP_TABLE_CORE when there is no core file
support. Use BFD_JUMP_TABLE_CORE (_bfd_nocore). */
--- binutils/bfd/libbfd.c.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/bfd/libbfd.c 2005-10-20 10:12:36.000000000 -0700
@@ -1042,3 +1042,13 @@ _bfd_generic_match_sections_by_type (bfd
{
return TRUE;
}
+
+bfd_boolean
+_bfd_generic_init_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
+ asection *isec ATTRIBUTE_UNUSED,
+ bfd *obfd ATTRIBUTE_UNUSED,
+ asection *osec ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+{
+ return TRUE;
+}
--- binutils/bfd/targets.c.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/bfd/targets.c 2005-10-20 10:12:36.000000000 -0700
@@ -271,6 +271,7 @@ BFD_JUMP_TABLE macros.
.#define BFD_JUMP_TABLE_COPY(NAME) \
. NAME##_bfd_copy_private_bfd_data, \
. NAME##_bfd_merge_private_bfd_data, \
+. _bfd_generic_init_private_section_data, \
. NAME##_bfd_copy_private_section_data, \
. NAME##_bfd_copy_private_symbol_data, \
. NAME##_bfd_copy_private_header_data, \
@@ -283,6 +284,12 @@ BFD_JUMP_TABLE macros.
. {* Called to merge BFD general private data from one object file
. to a common output file when linking. *}
. bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *);
+. {* Called to initialize BFD private section data from one object file
+. to another. *}
+.#define bfd_init_private_section_data(ibfd, isec, obfd, osec, link_info) \
+. BFD_SEND (obfd, _bfd_init_private_section_data, (ibfd, isec, obfd, osec, link_info))
+. bfd_boolean (*_bfd_init_private_section_data)
+. (bfd *, sec_ptr, bfd *, sec_ptr, struct bfd_link_info *);
. {* Called to copy BFD private section data from one object file
. to another. *}
. bfd_boolean (*_bfd_copy_private_section_data)
--- binutils/ld/emultempl/elf32.em.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/ld/emultempl/elf32.em 2005-10-20 10:12:36.000000000 -0700
@@ -1363,8 +1363,9 @@ gld${EMULATION_NAME}_place_orphan (lang_
if (os != NULL
&& (os->bfd_section == NULL
|| os->bfd_section->flags == 0
- || ((!iself
- || sh_type == elf_section_type (os->bfd_section))
+ || (bfd_match_sections_by_type (output_bfd,
+ os->bfd_section,
+ s->owner, s)
&& ((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 0)))
{
--- binutils/ld/ldlang.c.copy 2005-10-15 07:58:32.000000000 -0700
+++ binutils/ld/ldlang.c 2005-10-20 10:12:36.000000000 -0700
@@ -1674,7 +1674,7 @@ sort_def_symbol (hash_entry, info)
/* Initialize an output section. */
static void
-init_os (lang_output_section_statement_type *s)
+init_os (lang_output_section_statement_type *s, asection *isec)
{
if (s->bfd_section != NULL)
return;
@@ -1711,6 +1711,11 @@ init_os (lang_output_section_statement_t
if (s->load_base != NULL)
exp_init_os (s->load_base);
+
+ if (isec)
+ bfd_init_private_section_data (isec->owner, isec,
+ output_bfd, s->bfd_section,
+ &link_info);
}
/* Make sure that all output sections mentioned in an expression are
@@ -1756,7 +1761,7 @@ exp_init_os (etree_type *exp)
os = lang_output_section_find (exp->name.name);
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
}
}
break;
@@ -1833,7 +1838,7 @@ lang_add_section (lang_statement_list_ty
flagword flags;
if (output->bfd_section == NULL)
- init_os (output);
+ init_os (output, section);
first = ! output->bfd_section->linker_has_input;
output->bfd_section->linker_has_input = 1;
@@ -3099,7 +3104,7 @@ map_input_to_output_sections
are initialized. */
exp_init_os (s->data_statement.exp);
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
/* The output section gets contents, and then we inspect for
any flags set in the input script which override any ALLOC. */
os->bfd_section->flags |= SEC_HAS_CONTENTS;
@@ -3113,11 +3118,11 @@ map_input_to_output_sections
case lang_padding_statement_enum:
case lang_input_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
break;
case lang_assignment_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
/* Make sure that any sections mentioned in the assignment
are initialized. */
@@ -3145,7 +3150,7 @@ map_input_to_output_sections
(s->address_statement.section_name));
if (aos->bfd_section == NULL)
- init_os (aos);
+ init_os (aos, NULL);
aos->addr_tree = s->address_statement.address;
}
break;
--- binutils/ld/testsuite/ld-ia64/tlspic.rd.copy 2005-08-24 08:27:16.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/tlspic.rd 2005-10-20 10:12:36.000000000 -0700
@@ -61,7 +61,6 @@ Symbol table '.dynsym' contains [0-9]+ e
.* NOTYPE +LOCAL +DEFAULT +UND *
.* SECTION LOCAL +DEFAULT +7 *
.* SECTION LOCAL +DEFAULT +8 *
-.* SECTION LOCAL +DEFAULT +9 *
.* SECTION LOCAL +DEFAULT +10 *
.* SECTION LOCAL +DEFAULT +11 *
.* SECTION LOCAL +DEFAULT +14 *