aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog20
-rw-r--r--bfd/elf-bfd.h10
-rw-r--r--bfd/elflink.c174
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/scripttempl/elf.sc24
5 files changed, 139 insertions, 99 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 24800c5..615530b 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
* elf32-i386.c (link_hash_newfunc): Add elf_i386_ prefix.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index adac206..258d11c 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1299,9 +1299,6 @@ struct bfd_elf_section_data
/* A pointer to the bfd section used for dynamic relocs. */
asection *sreloc;
- /* A pointer to the bfd section used for dynamic relocs against ifunc symbols. */
- asection *indirect_relocs;
-
union {
/* Group name, if this section is a member of a group. */
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 bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
-extern asection * _bfd_elf_make_ifunc_reloc_section
- (bfd *, asection *, bfd *, unsigned int);
+extern bfd_boolean _bfd_elf_create_static_ifunc_sections
+ (bfd *, struct bfd_link_info *);
/* Large common 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.
If our finish_dynamic_symbol isn't called, we'll need to do something
about initializing any .plt and .got entries in relocate_section. */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index cb5ca09..d182807 100644
--- a/bfd/elflink.c
+++ b/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;
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))
{
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);
}
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type == STT_GNU_IFUNC)
+ h->needs_plt = 1;
+
/* Merge st_other field. */
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,
bfd_boolean force_local)
{
- h->plt = elf_hash_table (info)->init_plt_offset;
- h->needs_plt = 0;
+ /* STT_GNU_IFUNC symbol must go through PLT. */
+ if (h->type != STT_GNU_IFUNC)
+ {
+ h->plt = elf_hash_table (info)->init_plt_offset;
+ h->needs_plt = 0;
+ }
if (force_local)
{
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,
and also to finish up anything that needs to be done for this
symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for
- forced local syms when non-shared is due to a historical quirk. */
- if ((h->dynindx != -1
- || h->forced_local)
- && ((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)
+ forced local syms when non-shared is due to a historical quirk.
+ 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)
+ && ((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)
(finfo->output_bfd, finfo->info, h, &sym)))
@@ -12487,88 +12492,87 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec,
return reloc_sec;
}
-/* Returns the name of the ifunc using dynamic reloc section associated with SEC. */
-#define IFUNC_INFIX ".ifunc"
+/* Create sections needed by STT_GNU_IFUNC symbol for static
+ executables. */
-static const char *
-get_ifunc_reloc_section_name (bfd * abfd,
- asection * sec)
+bfd_boolean
+_bfd_elf_create_static_ifunc_sections (bfd *abfd,
+ struct bfd_link_info *info)
{
- 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);
+ flagword flags, pltflags;
+ int ptralign;
+ asection *s;
+ const struct elf_backend_data *bed;
- return name;
-}
+ /* Should never be called for shared library. */
+ BFD_ASSERT (!info->shared);
-/* 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. */
+ /* This function may be called more than once. */
+ s = bfd_get_section_by_name (abfd, ".iplt");
+ if (s != NULL)
+ return TRUE;
-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;
+ bed = get_elf_backend_data (abfd);
- if (reloc_sec == NULL)
- {
- const char * name = get_ifunc_reloc_section_name (abfd, sec);
+ /* We need to create .iplt, .rel[a].iplt, .igot, .igot.plt, */
+ flags = bed->dynamic_sec_flags;
- if (name == NULL)
- return NULL;
+ 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;
- reloc_sec = bfd_get_section_by_name (owner, name);
+ s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+ return FALSE;
- if (reloc_sec == NULL)
- {
- flagword flags;
+ 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;
- flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
+ switch (bed->s->arch_size)
+ {
+ case 32:
+ ptralign = 2;
+ break;
- 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;
- }
+ case 64:
+ ptralign = 3;
+ break;
- elf_section_data (sec)->indirect_relocs = reloc_sec;
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
- return reloc_sec;
-}
-
-/* Returns true if the hash entry refers to a symbol marked for
- indirect handling during reloc processing. */
-
-bfd_boolean
-_bfd_elf_is_ifunc_symbol (bfd *abfd, struct elf_link_hash_entry *h)
-{
- const struct elf_backend_data * bed;
-
- if (abfd == NULL || h == NULL)
- return FALSE;
+ /* We don't need the .igot section if we have the .igot.plt
+ section. */
- bed = get_elf_backend_data (abfd);
+ 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;
+ }
- /* GNU/Linux is still using the default value ELFOSABI_NONE. */
- return (h->type == STT_GNU_IFUNC
- && (bed->elf_osabi == ELFOSABI_LINUX
- || bed->elf_osabi == ELFOSABI_NONE));
+ return TRUE;
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 9c4b545..306ed8f 100644
--- a/ld/ChangeLog
+++ b/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>
* deffilep.y (%union): Add new string-type semantic value 'digits'.
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 123a989..75efa32 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -113,15 +113,15 @@ if test -z "${INITIAL_READONLY_SECTIONS}${CREATE_SHLIB}"; then
INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }"
fi
if test -z "$PLT"; then
- PLT=".plt ${RELOCATING-0} : { *(.plt) }"
+ PLT=".plt ${RELOCATING-0} : { *(.plt) *(.iplt)}"
fi
test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT=yes
if test -z "$GOT"; 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
- GOT=".got ${RELOCATING-0} : { *(.got) }"
- GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) }"
+ GOT=".got ${RELOCATING-0} : { *(.got) *(.igot) }"
+ GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) }"
fi
fi
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
@@ -354,8 +354,20 @@ EOF
fi
cat >> ldscripts/dyntmp.$$ <<EOF
- .rel.plt ${RELOCATING-0} : { *(.rel.plt) }
- .rela.plt ${RELOCATING-0} : { *(.rela.plt) }
+ .rel.plt ${RELOCATING-0} :
+ {
+ *(.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}
EOF