diff options
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 207 |
1 files changed, 92 insertions, 115 deletions
@@ -2670,29 +2670,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) 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, asection *sec, void *failedptrarg) 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, asection *sec, void *failedptrarg) 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, struct bfd_link_info *link_info) { 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 *obfd) 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 *ibfd, || 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. */ |