* 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.
ld/
	* 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.
This commit is contained in:
Alan Modra
2005-12-08 11:41:12 +00:00
parent 362307121f
commit 0ba079102f
5 changed files with 124 additions and 3 deletions

View File

@ -1,3 +1,13 @@
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.

View File

@ -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.

View File

@ -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 *);

View File

@ -1,3 +1,12 @@
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.

View File

@ -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;