2009-06-01  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (struct bfd_elf_section_data): Remove indirect_relocs.
	(_bfd_elf_make_ifunc_reloc_section): Removed.
	(_bfd_elf_is_ifunc_symbol): Likewise.
	(_bfd_elf_create_static_ifunc_sections): New.

	* elflink.c (_bfd_elf_adjust_dynamic_symbol): Move STT_GNU_IFUNC
	symbol check to ...
	(elf_link_add_object_symbols): Here.
	(_bfd_elf_link_hash_hide_symbol): Don't clean plt on
	STT_GNU_IFUNC symbol.
	(elf_link_output_extsym): Call elf_backend_finish_dynamic_symbol
	if a STT_GNU_IFUNC symbol is referenced in a non-shared object.
	(IFUNC_INFIX): Removed.
	(get_ifunc_reloc_section_name): Likewise.
	(_bfd_elf_make_ifunc_reloc_section): Likewise.
	(_bfd_elf_is_ifunc_symbol): Likewise.
	(_bfd_elf_create_static_ifunc_sections): New.

ld/

2009-06-01  H.J. Lu  <hongjiu.lu@intel.com>

	* scripttempl/elf.sc (PLT): Add "*(.iplt)".
	(GOT): Add "*(.igot.plt)a" and "*(.igot)".
	(GOTPLT): Add "*(.igot)".
	(__rel_iplt_start): New.
	(__rel_iplt_end): Likewise.
	(__rela_iplt_start): Likewise.
	(__rela_iplt_end): Likewise.
This commit is contained in:
H.J. Lu 2009-06-01 12:53:00 +00:00
parent 64c9be2ef3
commit 3aa14d16c6
5 changed files with 148 additions and 108 deletions

View File

@ -1,3 +1,23 @@
2009-06-01 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (struct bfd_elf_section_data): Remove indirect_relocs.
(_bfd_elf_make_ifunc_reloc_section): Removed.
(_bfd_elf_is_ifunc_symbol): Likewise.
(_bfd_elf_create_static_ifunc_sections): New.
* elflink.c (_bfd_elf_adjust_dynamic_symbol): Move STT_GNU_IFUNC
symbol check to ...
(elf_link_add_object_symbols): Here.
(_bfd_elf_link_hash_hide_symbol): Don't clean plt on
STT_GNU_IFUNC symbol.
(elf_link_output_extsym): Call elf_backend_finish_dynamic_symbol
if a STT_GNU_IFUNC symbol is referenced in a non-shared object.
(IFUNC_INFIX): Removed.
(get_ifunc_reloc_section_name): Likewise.
(_bfd_elf_make_ifunc_reloc_section): Likewise.
(_bfd_elf_is_ifunc_symbol): Likewise.
(_bfd_elf_create_static_ifunc_sections): New.
2009-05-29 H.J. Lu <hongjiu.lu@intel.com> 2009-05-29 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (link_hash_newfunc): Add elf_i386_ prefix. * elf32-i386.c (link_hash_newfunc): Add elf_i386_ prefix.

View File

@ -1299,9 +1299,6 @@ struct bfd_elf_section_data
/* A pointer to the bfd section used for dynamic relocs. */ /* A pointer to the bfd section used for dynamic relocs. */
asection *sreloc; asection *sreloc;
/* A pointer to the bfd section used for dynamic relocs against ifunc symbols. */
asection *indirect_relocs;
union { union {
/* Group name, if this section is a member of a group. */ /* Group name, if this section is a member of a group. */
const char *name; const char *name;
@ -2149,15 +2146,12 @@ extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int);
extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *); extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *); extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
extern asection * _bfd_elf_make_ifunc_reloc_section extern bfd_boolean _bfd_elf_create_static_ifunc_sections
(bfd *, asection *, bfd *, unsigned int); (bfd *, struct bfd_link_info *);
/* Large common section. */ /* Large common section. */
extern asection _bfd_elf_large_com_section; extern asection _bfd_elf_large_com_section;
extern bfd_boolean _bfd_elf_is_ifunc_symbol
(bfd *, struct elf_link_hash_entry *);
/* This is the condition under which finish_dynamic_symbol will be called. /* This is the condition under which finish_dynamic_symbol will be called.
If our finish_dynamic_symbol isn't called, we'll need to do something If our finish_dynamic_symbol isn't called, we'll need to do something
about initializing any .plt and .got entries in relocate_section. */ about initializing any .plt and .got entries in relocate_section. */

View File

@ -2675,13 +2675,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
dynobj = elf_hash_table (eif->info)->dynobj; dynobj = elf_hash_table (eif->info)->dynobj;
bed = get_elf_backend_data (dynobj); bed = get_elf_backend_data (dynobj);
if (h->type == STT_GNU_IFUNC
&& (bed->elf_osabi == ELFOSABI_LINUX
/* GNU/Linux is still using the default value 0. */
|| bed->elf_osabi == ELFOSABI_NONE))
h->needs_plt = 1;
if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h)) if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
{ {
eif->failed = TRUE; eif->failed = TRUE;
@ -4295,6 +4288,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
h->type = ELF_ST_TYPE (isym->st_info); h->type = ELF_ST_TYPE (isym->st_info);
} }
/* STT_GNU_IFUNC symbol must go through PLT. */
if (h->type == STT_GNU_IFUNC)
h->needs_plt = 1;
/* Merge st_other field. */ /* Merge st_other field. */
elf_merge_st_other (abfd, h, isym, definition, dynamic); elf_merge_st_other (abfd, h, isym, definition, dynamic);
@ -6669,8 +6666,12 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h, struct elf_link_hash_entry *h,
bfd_boolean force_local) bfd_boolean force_local)
{ {
h->plt = elf_hash_table (info)->init_plt_offset; /* STT_GNU_IFUNC symbol must go through PLT. */
h->needs_plt = 0; if (h->type != STT_GNU_IFUNC)
{
h->plt = elf_hash_table (info)->init_plt_offset;
h->needs_plt = 0;
}
if (force_local) if (force_local)
{ {
h->forced_local = 1; h->forced_local = 1;
@ -8649,14 +8650,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
/* Give the processor backend a chance to tweak the symbol value, /* Give the processor backend a chance to tweak the symbol value,
and also to finish up anything that needs to be done for this and also to finish up anything that needs to be done for this
symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
forced local syms when non-shared is due to a historical quirk. */ forced local syms when non-shared is due to a historical quirk.
if ((h->dynindx != -1 STT_GNU_IFUNC symbol must go through PLT. */
|| h->forced_local) if ((h->type == STT_GNU_IFUNC
&& ((finfo->info->shared && h->ref_regular
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !finfo->info->relocatable)
|| h->root.type != bfd_link_hash_undefweak)) || ((h->dynindx != -1
|| !h->forced_local) || h->forced_local)
&& elf_hash_table (finfo->info)->dynamic_sections_created) && ((finfo->info->shared
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
|| !h->forced_local)
&& elf_hash_table (finfo->info)->dynamic_sections_created))
{ {
if (! ((*bed->elf_backend_finish_dynamic_symbol) if (! ((*bed->elf_backend_finish_dynamic_symbol)
(finfo->output_bfd, finfo->info, h, &sym))) (finfo->output_bfd, finfo->info, h, &sym)))
@ -12487,88 +12492,87 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec,
return reloc_sec; return reloc_sec;
} }
/* Returns the name of the ifunc using dynamic reloc section associated with SEC. */ /* Create sections needed by STT_GNU_IFUNC symbol for static
#define IFUNC_INFIX ".ifunc" executables. */
static const char *
get_ifunc_reloc_section_name (bfd * abfd,
asection * sec)
{
const char * dot;
char * name;
const char * base_name;
unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
base_name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
if (base_name == NULL)
return NULL;
dot = strchr (base_name + 1, '.');
name = bfd_alloc (abfd, strlen (base_name) + strlen (IFUNC_INFIX) + 1);
sprintf (name, "%.*s%s%s", (int)(dot - base_name), base_name, IFUNC_INFIX, dot);
return name;
}
/* Like _bfd_elf_make_dynamic_reloc_section but it creates a
section for holding relocs against symbols with the STT_GNU_IFUNC
type. The section is attached to the OWNER bfd but it is created
with a name based on SEC from ABFD. */
asection *
_bfd_elf_make_ifunc_reloc_section (bfd * abfd,
asection * sec,
bfd * owner,
unsigned int align)
{
asection * reloc_sec = elf_section_data (sec)->indirect_relocs;
if (reloc_sec == NULL)
{
const char * name = get_ifunc_reloc_section_name (abfd, sec);
if (name == NULL)
return NULL;
reloc_sec = bfd_get_section_by_name (owner, name);
if (reloc_sec == NULL)
{
flagword flags;
flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
reloc_sec = bfd_make_section_with_flags (owner, name, flags);
if (reloc_sec != NULL
&& ! bfd_set_section_alignment (owner, reloc_sec, align))
reloc_sec = NULL;
}
elf_section_data (sec)->indirect_relocs = reloc_sec;
}
return reloc_sec;
}
/* Returns true if the hash entry refers to a symbol marked for
indirect handling during reloc processing. */
bfd_boolean bfd_boolean
_bfd_elf_is_ifunc_symbol (bfd *abfd, struct elf_link_hash_entry *h) _bfd_elf_create_static_ifunc_sections (bfd *abfd,
struct bfd_link_info *info)
{ {
const struct elf_backend_data * bed; flagword flags, pltflags;
int ptralign;
asection *s;
const struct elf_backend_data *bed;
if (abfd == NULL || h == NULL) /* Should never be called for shared library. */
return FALSE; BFD_ASSERT (!info->shared);
/* This function may be called more than once. */
s = bfd_get_section_by_name (abfd, ".iplt");
if (s != NULL)
return TRUE;
bed = get_elf_backend_data (abfd); bed = get_elf_backend_data (abfd);
/* GNU/Linux is still using the default value ELFOSABI_NONE. */ /* We need to create .iplt, .rel[a].iplt, .igot, .igot.plt, */
return (h->type == STT_GNU_IFUNC flags = bed->dynamic_sec_flags;
&& (bed->elf_osabi == ELFOSABI_LINUX
|| bed->elf_osabi == ELFOSABI_NONE)); pltflags = flags;
if (bed->plt_not_loaded)
/* We do not clear SEC_ALLOC here because we still want the OS to
allocate space for the section; it's just that there's nothing
to read in from the object file. */
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
else
pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
s = bfd_make_section_with_flags (abfd,
(bed->rela_plts_and_copies_p
? ".rela.iplt" : ".rel.iplt"),
flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
switch (bed->s->arch_size)
{
case 32:
ptralign = 2;
break;
case 64:
ptralign = 3;
break;
default:
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* We don't need the .igot section if we have the .igot.plt
section. */
if (bed->want_got_plt)
{
s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
}
else
{
s = bfd_make_section_with_flags (abfd, ".igot", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
}
return TRUE;
} }

View File

@ -1,3 +1,13 @@
2009-06-01 H.J. Lu <hongjiu.lu@intel.com>
* scripttempl/elf.sc (PLT): Add "*(.iplt)".
(GOT): Add "*(.igot.plt)a" and "*(.igot)".
(GOTPLT): Add "*(.igot)".
(__rel_iplt_start): New.
(__rel_iplt_end): Likewise.
(__rela_iplt_start): Likewise.
(__rela_iplt_end): Likewise.
2009-05-27 Dave Korn <dave.korn.cygwin@gmail.com> 2009-05-27 Dave Korn <dave.korn.cygwin@gmail.com>
* deffilep.y (%union): Add new string-type semantic value 'digits'. * deffilep.y (%union): Add new string-type semantic value 'digits'.

View File

@ -113,15 +113,15 @@ if test -z "${INITIAL_READONLY_SECTIONS}${CREATE_SHLIB}"; then
INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }" INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }"
fi fi
if test -z "$PLT"; then if test -z "$PLT"; then
PLT=".plt ${RELOCATING-0} : { *(.plt) }" PLT=".plt ${RELOCATING-0} : { *(.plt) *(.iplt)}"
fi fi
test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT=yes test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT=yes
if test -z "$GOT"; then if test -z "$GOT"; then
if test -z "$SEPARATE_GOTPLT"; then if test -z "$SEPARATE_GOTPLT"; then
GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.got) }" GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }"
else else
GOT=".got ${RELOCATING-0} : { *(.got) }" GOT=".got ${RELOCATING-0} : { *(.got) *(.igot) }"
GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) }" GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) }"
fi fi
fi fi
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }" DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
@ -354,8 +354,20 @@ EOF
fi fi
cat >> ldscripts/dyntmp.$$ <<EOF cat >> ldscripts/dyntmp.$$ <<EOF
.rel.plt ${RELOCATING-0} : { *(.rel.plt) } .rel.plt ${RELOCATING-0} :
.rela.plt ${RELOCATING-0} : { *(.rela.plt) } {
*(.rel.plt)
${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_start = .);}}
*(.rel.iplt)
${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_end = .);}}
}
.rela.plt ${RELOCATING-0} :
{
*(.rela.plt)
${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_start = .);}}
*(.rela.iplt)
${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_end = .);}}
}
${OTHER_PLT_RELOC_SECTIONS} ${OTHER_PLT_RELOC_SECTIONS}
EOF EOF