bfd/
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:
parent
64c9be2ef3
commit
3aa14d16c6
|
@ -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.
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
178
bfd/elflink.c
178
bfd/elflink.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
/* STT_GNU_IFUNC symbol must go through PLT. */
|
||||||
|
if (h->type != STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
h->plt = elf_hash_table (info)->init_plt_offset;
|
h->plt = elf_hash_table (info)->init_plt_offset;
|
||||||
h->needs_plt = 0;
|
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. */
|
||||||
|
if ((h->type == STT_GNU_IFUNC
|
||||||
|
&& h->ref_regular
|
||||||
|
&& !finfo->info->relocatable)
|
||||||
|
|| ((h->dynindx != -1
|
||||||
|| h->forced_local)
|
|| h->forced_local)
|
||||||
&& ((finfo->info->shared
|
&& ((finfo->info->shared
|
||||||
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||||
|| h->root.type != bfd_link_hash_undefweak))
|
|| h->root.type != bfd_link_hash_undefweak))
|
||||||
|| !h->forced_local)
|
|| !h->forced_local)
|
||||||
&& elf_hash_table (finfo->info)->dynamic_sections_created)
|
&& 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;
|
||||||
}
|
}
|
||||||
|
|
10
ld/ChangeLog
10
ld/ChangeLog
|
@ -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'.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue