diff options
author | Alan Modra <amodra@gmail.com> | 2008-10-03 09:40:49 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2008-10-03 09:40:49 +0000 |
commit | bcacc0f587e22ba46333d9377e7e9e4576c90f74 (patch) | |
tree | 0035a6958c007460d3837b1e245b5f89edeb3661 /bfd | |
parent | 81ab4297b7f533d6750f073cad0fe6169f567e85 (diff) | |
download | gdb-bcacc0f587e22ba46333d9377e7e9e4576c90f74.zip gdb-bcacc0f587e22ba46333d9377e7e9e4576c90f74.tar.gz gdb-bcacc0f587e22ba46333d9377e7e9e4576c90f74.tar.bz2 |
bfd/
* elf.c (bfd_elf_set_group_contents): Assign sh_info for ld -r when
the signature symbol is global.
* elflink.c (elf_link_input_bfd): Ensure group signature symbol
is output when ld -r. Set group sh_info when local.
* linker.c (default_indirect_link_order): Handle group sections
specially.
ld/
* ldemul.c (ldemul_place_orphan): Add "name" param.
* ldemul.h (ldemul_place_orphan): Update prototype.
(struct ld_emulation_xfer_struct <place_orphan>): Likewise.
* ldlang.c (lang_place_orphans): Generate unique section names here..
* emultempl/elf32.em (place_orphan): ..rather than here. Don't
directly use an existing output section statement that has no
bfd section.
* emultempl/pe.em (place_orphan): Likewise.
* emultempl/pep.em (place_orphan): Likewise.
* emultempl/beos.em (place_orphan): Adjust.
* emultempl/spuelf.em (spu_place_special_section): Adjust
place_orphan call.
* emultempl/genelf.em (gld${EMULATION_NAME}_after_open): New function.
(LDEMUL_AFTER_OPEN): Define.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elf.c | 57 | ||||
-rw-r--r-- | bfd/elflink.c | 57 | ||||
-rw-r--r-- | bfd/linker.c | 42 |
4 files changed, 140 insertions, 25 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f775536..b95f322 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2008-10-03 Alan Modra <amodra@bigpond.net.au> + + * elf.c (bfd_elf_set_group_contents): Assign sh_info for ld -r when + the signature symbol is global. + * elflink.c (elf_link_input_bfd): Ensure group signature symbol + is output when ld -r. Set group sh_info when local. + * linker.c (default_indirect_link_order): Handle group sections + specially. + 2008-09-30 Wesley W. Terpstra <wesley@terpstra.ca> Nick Clifton <nickc@redhat.com> @@ -2681,13 +2681,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) *failedptr = TRUE; } -/* Fill in the contents of a SHT_GROUP section. */ +/* Fill in the contents of a SHT_GROUP section. Called from + _bfd_elf_compute_section_file_positions for gas, objcopy, and + when ELF targets use the generic linker, ld. Called for ld -r + from bfd_elf_final_link. */ void bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) { bfd_boolean *failedptr = failedptrarg; - unsigned long symindx; asection *elt, *first; unsigned char *loc; bfd_boolean gas; @@ -2698,20 +2700,49 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) || *failedptr) return; - symindx = 0; - if (elf_group_id (sec) != NULL) - symindx = elf_group_id (sec)->udata.i; + if (elf_section_data (sec)->this_hdr.sh_info == 0) + { + unsigned long symindx = 0; + + /* elf_group_id will have been set up by objcopy and the + generic linker. */ + if (elf_group_id (sec) != NULL) + symindx = elf_group_id (sec)->udata.i; - if (symindx == 0) + if (symindx == 0) + { + /* If called from the assembler, swap_out_syms will have set up + elf_section_syms. */ + BFD_ASSERT (elf_section_syms (abfd) != NULL); + symindx = elf_section_syms (abfd)[sec->index]->udata.i; + } + elf_section_data (sec)->this_hdr.sh_info = symindx; + } + else if (elf_section_data (sec)->this_hdr.sh_info == (unsigned int) -2) { - /* If called from the assembler, swap_out_syms will have set up - elf_section_syms; If called for "ld -r", use target_index. */ - if (elf_section_syms (abfd) != NULL) - symindx = elf_section_syms (abfd)[sec->index]->udata.i; - else - symindx = sec->target_index; + /* The ELF backend linker sets sh_info to -2 when the group + signature symbol is global, and thus the index can't be + set until all local symbols are output. */ + asection *igroup = elf_sec_group (elf_next_in_group (sec)); + struct bfd_elf_section_data *sec_data = elf_section_data (igroup); + unsigned long symndx = sec_data->this_hdr.sh_info; + unsigned long extsymoff = 0; + struct elf_link_hash_entry *h; + + if (!elf_bad_symtab (igroup->owner)) + { + Elf_Internal_Shdr *symtab_hdr; + + symtab_hdr = &elf_tdata (igroup->owner)->symtab_hdr; + extsymoff = symtab_hdr->sh_info; + } + h = elf_sym_hashes (igroup->owner)[symndx - extsymoff]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + elf_section_data (sec)->this_hdr.sh_info = h->indx; } - elf_section_data (sec)->this_hdr.sh_info = symindx; /* The contents won't be allocated for "ld -r" or objcopy. */ gas = TRUE; diff --git a/bfd/elflink.c b/bfd/elflink.c index 8e59383..d2dc17d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -9062,6 +9062,63 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) continue; } + if (finfo->info->relocatable + && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP) + { + /* Deal with the group signature symbol. */ + struct bfd_elf_section_data *sec_data = elf_section_data (o); + unsigned long symndx = sec_data->this_hdr.sh_info; + asection *osec = o->output_section; + + if (symndx >= locsymcount + || (elf_bad_symtab (input_bfd) + && finfo->sections[symndx] == NULL)) + { + struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Arrange for symbol to be output. */ + h->indx = -2; + elf_section_data (osec)->this_hdr.sh_info = -2; + } + else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION) + { + /* We'll use the output section target_index. */ + asection *sec = finfo->sections[symndx]->output_section; + elf_section_data (osec)->this_hdr.sh_info = sec->target_index; + } + else + { + if (finfo->indices[symndx] == -1) + { + /* Otherwise output the local symbol now. */ + Elf_Internal_Sym sym = isymbuf[symndx]; + asection *sec = finfo->sections[symndx]->output_section; + const char *name; + + name = bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + sym.st_name); + if (name == NULL) + return FALSE; + + sym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd, + sec); + if (sym.st_shndx == SHN_BAD) + return FALSE; + + sym.st_value += o->output_offset; + + finfo->indices[symndx] = bfd_get_symcount (output_bfd); + if (! elf_link_output_sym (finfo, name, &sym, o, NULL)) + return FALSE; + } + elf_section_data (osec)->this_hdr.sh_info + = finfo->indices[symndx]; + } + } + if ((o->flags & SEC_HAS_CONTENTS) == 0 || (o->size == 0 && (o->flags & SEC_RELOC) == 0)) continue; diff --git a/bfd/linker.c b/bfd/linker.c index baf280c..5080d7d 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -2796,18 +2796,36 @@ default_indirect_link_order (bfd *output_bfd, } } - /* Get and relocate the section contents. */ - sec_size = (input_section->rawsize > input_section->size - ? input_section->rawsize - : input_section->size); - contents = bfd_malloc (sec_size); - if (contents == NULL && sec_size != 0) - goto error_return; - new_contents = (bfd_get_relocated_section_contents - (output_bfd, info, link_order, contents, info->relocatable, - _bfd_generic_link_get_symbols (input_bfd))); - if (!new_contents) - goto error_return; + if ((output_section->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP + && input_section->size != 0) + { + /* Group section contents are set by bfd_elf_set_group_contents. */ + if (!output_bfd->output_has_begun) + { + /* FIXME: This hack ensures bfd_elf_set_group_contents is called. */ + if (!bfd_set_section_contents (output_bfd, output_section, "", 0, 1)) + goto error_return; + } + new_contents = output_section->contents; + BFD_ASSERT (new_contents != NULL); + BFD_ASSERT (input_section->output_offset == 0); + } + else + { + /* Get and relocate the section contents. */ + sec_size = (input_section->rawsize > input_section->size + ? input_section->rawsize + : input_section->size); + contents = bfd_malloc (sec_size); + if (contents == NULL && sec_size != 0) + goto error_return; + new_contents = (bfd_get_relocated_section_contents + (output_bfd, info, link_order, contents, + info->relocatable, + _bfd_generic_link_get_symbols (input_bfd))); + if (!new_contents) + goto error_return; + } /* Output the section contents. */ loc = input_section->output_offset * bfd_octets_per_byte (output_bfd); |