diff options
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 92 | ||||
-rw-r--r-- | bfd/elf32-ppc.h | 2 | ||||
-rw-r--r-- | ld/ChangeLog | 9 | ||||
-rw-r--r-- | ld/emultempl/ppc32elf.em | 14 |
5 files changed, 124 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1db9170..8d89bc1 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,15 @@ 2005-12-08 Alan Modra <amodra@bigpond.net.au> + * elf32-ppc.c (struct ppc_elf_link_hash_table): Add emit_stub_syms. + (ppc_elf_select_plt_layout): Add emit_stub_syms param, save to htab. + (add_stub_sym): New function. + (allocate_dynrelocs): Call add_stub_sym. + (ppc_elf_size_dynamic_sections): Emit __glink and __glink_PLTresolve + when emit_stub_syms. + * elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype. + +2005-12-08 Alan Modra <amodra@bigpond.net.au> + * reloc.c (enum complain_overflow): Correct comments. (bfd_check_overflow): Combine complain_overflow_bitfield and complain_overflow_signed code. diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 70d03a3..5b8c955 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -2353,6 +2353,9 @@ struct ppc_elf_link_hash_table unsigned int new_plt:1; unsigned int old_plt:1; + /* Set if we should emit symbols for stubs. */ + unsigned int emit_stub_syms:1; + /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; @@ -3593,7 +3596,8 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) int ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info, - int force_old_plt) + int force_old_plt, + int emit_stub_syms) { struct ppc_elf_link_hash_table *htab; flagword flags; @@ -3602,6 +3606,8 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED, if (force_old_plt || !htab->new_plt) htab->old_plt = 1; + htab->emit_stub_syms = emit_stub_syms; + if (htab->is_vxworks) { /* The VxWorks PLT is a loaded section with contents. */ @@ -4207,6 +4213,51 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return TRUE; } +/* Generate a symbol to mark plt call stubs, of the form + xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0, + specifying the addend on the plt relocation, or for -fPIC, + xxxxxxxx.got2_plt_call_<callee>. */ + +static bfd_boolean +add_stub_sym (struct plt_entry *ent, + struct elf_link_hash_entry *h, + struct ppc_elf_link_hash_table *htab) +{ + struct elf_link_hash_entry *sh; + size_t len1, len2, len3; + char *name; + + len1 = strlen (h->root.root.string); + len2 = sizeof ("plt_call_") - 1; + len3 = 0; + if (ent->sec) + len3 = strlen (ent->sec->name); + name = bfd_malloc (len1 + len2 + len3 + 10); + if (name == NULL) + return FALSE; + sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff); + if (ent->sec) + memcpy (name + 8, ent->sec->name, len3); + name[len3 + 8] = '_'; + memcpy (name + len3 + 9, "plt_call_", len2); + memcpy (name + len3 + 9 + len2, h->root.root.string, len1 + 1); + sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE); + if (sh == NULL) + return FALSE; + if (sh->root.type == bfd_link_hash_new) + { + sh->root.type = bfd_link_hash_defined; + sh->root.u.def.section = htab->glink; + sh->root.u.def.value = ent->glink_offset; + sh->ref_regular = 1; + sh->def_regular = 1; + sh->ref_regular_nonweak = 1; + sh->forced_local = 1; + sh->non_elf = 0; + } + return TRUE; +} + /* Allocate NEED contiguous space in .got, and return the offset. Handles allocation of the got header when crossing 32k. */ @@ -4308,6 +4359,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->root.u.def.value = glink_offset; } ent->glink_offset = glink_offset; + + if (htab->emit_stub_syms + && !add_stub_sym (ent, h, htab)) + return FALSE; } else { @@ -4747,6 +4802,41 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* Pad out to align the start of PLTresolve. */ htab->glink->size += -htab->glink->size & 15; htab->glink->size += GLINK_PLTRESOLVE; + + if (htab->emit_stub_syms) + { + struct elf_link_hash_entry *sh; + sh = elf_link_hash_lookup (&htab->elf, "__glink", + TRUE, FALSE, FALSE); + if (sh == NULL) + return FALSE; + if (sh->root.type == bfd_link_hash_new) + { + sh->root.type = bfd_link_hash_defined; + sh->root.u.def.section = htab->glink; + sh->root.u.def.value = htab->glink_pltresolve; + sh->ref_regular = 1; + sh->def_regular = 1; + sh->ref_regular_nonweak = 1; + sh->forced_local = 1; + sh->non_elf = 0; + } + sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve", + TRUE, FALSE, FALSE); + if (sh == NULL) + return FALSE; + if (sh->root.type == bfd_link_hash_new) + { + sh->root.type = bfd_link_hash_defined; + sh->root.u.def.section = htab->glink; + sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE; + sh->ref_regular = 1; + sh->def_regular = 1; + sh->ref_regular_nonweak = 1; + sh->forced_local = 1; + sh->non_elf = 0; + } + } } /* We've now determined the sizes of the various dynamic sections. diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h index 2bec595..5f8f63a 100644 --- a/bfd/elf32-ppc.h +++ b/bfd/elf32-ppc.h @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int); +int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int, int); asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *); bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *); void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *); diff --git a/ld/ChangeLog b/ld/ChangeLog index d517ddb..ab6b848 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,14 @@ 2005-12-08 Alan Modra <amodra@bigpond.net.au> + * emultempl/ppc32elf.em (emit_stub_syms): New var. + (ppc_after_open): Pass it to ppc_elf_select_plt_layout. + (PARSE_AND_LIST_PROLOGUE <OPTION_STUBSYMS>): Define. + (PARSE_AND_LIST_LONGOPTS): Add emit-stub-syms. + (PARSE_AND_LIST_OPTIONS): Describe emit-stub-syms. + (PARSE_AND_LIST_OPTIONS): Handle it. + +2005-12-08 Alan Modra <amodra@bigpond.net.au> + * pe-dll.c (build_filler_bfd): Conform error message to standard. (pe_dll_generate_implib): Use %E in error message. (add_bfd_to_link): Likewise. diff --git a/ld/emultempl/ppc32elf.em b/ld/emultempl/ppc32elf.em index e4d56de..10f9107 100644 --- a/ld/emultempl/ppc32elf.em +++ b/ld/emultempl/ppc32elf.em @@ -41,6 +41,9 @@ is_ppc_elf32_vec(const bfd_target * vec) /* Whether to run tls optimization. */ static int notlsopt = 0; +/* Whether to emit symbols for stubs. */ +static int emit_stub_syms = 0; + /* Chooses the correct place for .plt and .got. */ static int old_plt = 0; static int old_got = 0; @@ -58,7 +61,9 @@ ppc_after_open (void) lang_output_section_statement_type *plt_os[2]; lang_output_section_statement_type *got_os[2]; - new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt); + emit_stub_syms |= link_info.emitrelocations; + new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt, + emit_stub_syms); if (new_plt < 0) einfo ("%X%P: select_plt_layout problem %E\n"); @@ -126,9 +131,11 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_NO_TLS_OPT 301 #define OPTION_OLD_PLT 302 #define OPTION_OLD_GOT 303 +#define OPTION_STUBSYMS 304 ' PARSE_AND_LIST_LONGOPTS=' + { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS }, { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT }, { "bss-plt", no_argument, NULL, OPTION_OLD_PLT }, { "sdata-got", no_argument, NULL, OPTION_OLD_GOT }, @@ -136,6 +143,7 @@ PARSE_AND_LIST_LONGOPTS=' PARSE_AND_LIST_OPTIONS=' fprintf (file, _("\ + --emit-stub-syms Label linker stubs with a symbol.\n\ --no-tls-optimize Don'\''t try to optimize TLS accesses.\n\ --bss-plt Force old-style BSS PLT.\n\ --sdata-got Force GOT location just before .sdata.\n" @@ -143,6 +151,10 @@ PARSE_AND_LIST_OPTIONS=' ' PARSE_AND_LIST_ARGS_CASES=' + case OPTION_STUBSYMS: + emit_stub_syms = 1; + break; + case OPTION_NO_TLS_OPT: notlsopt = 1; break; |