+2009-04-30 Nick Clifton <nickc@redhat.com>
+
+ * elf-bfd.h (struct bfd_elf_section_data): Add indirect_relocs
+ section pointer.
+ (struct elf_obj_data): Add has_ifunc_symbols boolean.
+ * elf.c (swap_out_syms): Convert BSF_GNU_INDIRECT_FUNCTION flags
+ into a STT_GNU_IFUNC symbol type.
+ (_bfd_elf_is_function_type): Accept STT_GNU_IFUNC as a function
+ type.
+ (_bfd_elf_set_osabi): Set the osasbi field to ELFOSABI_LINUX if
+ the binary contains ifunc symbols.
+ * elfcode.h (elf_slurp_symbol_table): Translate the STT_GNU_IFUNC
+ symbol type into a BSF_GNU_INDIRECT_FUNCTION flag.
+ * elf32-i386.c (is_indirect_function): New function.
+ (elf_i386_check_relocs): Create an ifunc output section.
+ (allocate_dynrelocs): Create dynamic relocs in the ifunc output
+ section if necessary.
+ (elf_i386_relocate_section): Emit a reloc against an ifunc symbol
+ if necessary.
+ (elf_i386_add_symbol_hook): New function. Set the
+ has_ifunc_symbols field of the elf_obj_data structure if an ifunc
+ symbol is encountered.
+ (elf_backend_post_process_headers): Define.
+ (elf_backend_add_symbol_hook): Define.
+ (elf_i386_post_process_headers): Rename to
+ elf_i388_fbsd_post_process_headers.
+ * elf64-x86_64.c (IS_X86_64_PCREL_TYPE): New macro.
+ (is_indirect_function): New function.
+ (elf64_x86_64_check_relocs): Create an ifunc output section.
+ (allocate_dynrelocs): Create dynamic relocs in the ifunc output
+ section if necessary.
+ (elf64_x86_64_relocate_section): Emit a reloc against an ifunc
+ symbol if necessary.
+ (elf_i386_add_symbol_hook): Set the has_ifunc_symbols field of the
+ elf_obj_data structure if an ifunc symbol is encountered.
+ (elf_backend_post_process_headers): Define.
+ * elflink.c (_bfd_elf_adjust_dynamic_symbol): Always create a PLT
+ if we have ifunc symbols to handle.
+ (get_ifunc_reloc_section_name): New function. Computes the name
+ for an ifunc section.
+ (_bfd_elf_make_ifunc_reloc_section): New function. Creates a
+ section to hold ifunc relocs.
+ * syms.c (BSF_GNU_INDIRECT_FUNCTION): Define.
+ (bfd_print_symbol_vandf): Handle ifunc symbols.
+ (bfd_decode_symclass): Likewise.
+ * bfd-in2.h: Regenerate.
+
2009-04-30 Joseph Myers <joseph@codesourcery.com>
* elf32-arm.c (elf32_arm_check_relocs): Give errors for absolute
/* This symbol was created by bfd_get_synthetic_symtab. */
#define BSF_SYNTHETIC (1 << 21)
+ /* This symbol is an indirect code object. Unrelated to BSF_INDIRECT.
+ The dynamic linker will compute the value of this symbol by
+ calling the function that it points to. BSF_FUNCTION must
+ also be also set. */
+#define BSF_GNU_INDIRECT_FUNCTION (1 << 22)
+
flagword flags;
/* A pointer to the section to which this symbol is
/* 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;
bfd_size_type build_id_size;
bfd_byte *build_id;
+ /* True if the bfd contains symbols that have the STT_GNU_IFUNC
+ symbol type. Used to set the osabi field in the ELF header
+ structure. */
+ bfd_boolean has_ifunc_symbols;
+
/* An identifier used to distinguish different target
specific extensions to this structure. */
enum elf_object_id object_id;
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);
+
/* Large common section. */
extern asection _bfd_elf_large_com_section;
if ((flags & BSF_THREAD_LOCAL) != 0)
type = STT_TLS;
+ else if ((flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
+ type = STT_GNU_IFUNC;
else if ((flags & BSF_FUNCTION) != 0)
type = STT_FUNC;
else if ((flags & BSF_OBJECT) != 0)
i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+
+ /* To make things simpler for the loader on Linux systems we set the
+ osabi field to ELFOSABI_LINUX if the binary contains symbols of
+ the STT_GNU_IFUNC type. */
+ if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
+ && elf_tdata (abfd)->has_ifunc_symbols)
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
}
/* Return TRUE for ELF symbol types that represent functions.
This is the default version of this function, which is sufficient for
- most targets. It returns true if TYPE is STT_FUNC. */
+ most targets. It returns true if TYPE is STT_FUNC or STT_GNU_IFUNC. */
bfd_boolean
_bfd_elf_is_function_type (unsigned int type)
{
- return (type == STT_FUNC);
+ return (type == STT_FUNC
+ || type == STT_GNU_IFUNC);
}
return TRUE;
}
+/* Returns true if the hash entry refers to a symbol
+ marked for indirect handling during reloc processing. */
+
+static bfd_boolean
+is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
+{
+ const struct elf_backend_data * bed;
+
+ if (abfd == NULL || h == NULL)
+ return FALSE;
+
+ bed = get_elf_backend_data (abfd);
+
+ return h->type == STT_GNU_IFUNC
+ && (bed->elf_osabi == ELFOSABI_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || bed->elf_osabi == ELFOSABI_NONE);
+}
+
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure linkage
table, and dynamic reloc sections. */
if (sreloc == NULL)
return FALSE;
+
+ /* Create the ifunc section as well, even if we have not encountered a
+ indirect function symbol yet. We may not even see one in the input
+ object file, but we can still encounter them in libraries. */
+ (void) _bfd_elf_make_ifunc_reloc_section
+ (abfd, sec, htab->elf.dynobj, 2);
}
/* If this is a global symbol, we count the number of
struct elf_i386_link_hash_table *htab;
struct elf_i386_link_hash_entry *eh;
struct elf_i386_dyn_relocs *p;
+ bfd_boolean use_indirect_section = FALSE;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
}
}
}
+ else if (is_indirect_symbol (info->output_bfd, h)
+ && h->dynindx == -1
+ && ! h->forced_local)
+ {
+ if (bfd_elf_link_record_dynamic_symbol (info, h)
+ && h->dynindx != -1)
+ use_indirect_section = TRUE;
+ else
+ return FALSE;
+ }
else if (ELIMINATE_COPY_RELOCS)
{
/* For the non-shared case, discard space for relocs against
{
asection *sreloc;
- sreloc = elf_section_data (p->sec)->sreloc;
+ if (use_indirect_section)
+ sreloc = elf_section_data (p->sec)->indirect_relocs;
+ else
+ sreloc = elf_section_data (p->sec)->sreloc;
BFD_ASSERT (sreloc != NULL);
sreloc->size += p->count * sizeof (Elf32_External_Rel);
|| h->root.type != bfd_link_hash_undefweak)
&& (r_type != R_386_PC32
|| !SYMBOL_CALLS_LOCAL (info, h)))
+ || (! info->shared
+ && h != NULL
+ && h->dynindx != -1
+ && ! h->forced_local
+ && ((struct elf_i386_link_hash_entry *) h)->dyn_relocs != NULL
+ && is_indirect_symbol (output_bfd, h))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& h != NULL
outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
}
- sreloc = elf_section_data (input_section)->sreloc;
+ if (! info->shared
+ && h != NULL
+ && h->dynindx != -1
+ && ! h->forced_local
+ && is_indirect_symbol (output_bfd, h)
+ && elf_section_data (input_section)->indirect_relocs != NULL
+ && elf_section_data (input_section)->indirect_relocs->contents != NULL)
+ sreloc = elf_section_data (input_section)->indirect_relocs;
+ else
+ sreloc = elf_section_data (input_section)->sreloc;
BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
return _bfd_elf_hash_symbol (h);
}
+/* Hook called by the linker routine which adds symbols from an object
+ file. */
+
+static bfd_boolean
+elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info * info ATTRIBUTE_UNUSED,
+ Elf_Internal_Sym * sym,
+ const char ** namep ATTRIBUTE_UNUSED,
+ flagword * flagsp ATTRIBUTE_UNUSED,
+ asection ** secp ATTRIBUTE_UNUSED,
+ bfd_vma * valp ATTRIBUTE_UNUSED)
+{
+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+ elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+
+ return TRUE;
+}
+
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#define elf_backend_hash_symbol elf_i386_hash_symbol
+#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers _bfd_elf_set_osabi
#include "elf32-target.h"
executables and (for simplicity) also all other object files. */
static void
-elf_i386_post_process_headers (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED)
+elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
{
- Elf_Internal_Ehdr *i_ehdrp;
-
- i_ehdrp = elf_elfheader (abfd);
+ _bfd_elf_set_osabi (abfd, info);
- /* Put an ABI label supported by FreeBSD >= 4.1. */
- i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
#ifdef OLD_FREEBSD_ABI_LABEL
/* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
}
#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers elf_i386_post_process_headers
+#define elf_backend_post_process_headers elf_i386_fbsd_post_process_headers
#undef elf32_bed
#define elf32_bed elf32_i386_fbsd_bed
+#undef elf_backend_add_symbol_hook
+
#include "elf32-target.h"
/* VxWorks support. */
FALSE)
};
+#define IS_X86_64_PCREL_TYPE(TYPE) \
+ ( ((TYPE) == R_X86_64_PC8) \
+ || ((TYPE) == R_X86_64_PC16) \
+ || ((TYPE) == R_X86_64_PC32) \
+ || ((TYPE) == R_X86_64_PC64))
+
/* Map BFD relocs to the x86_64 elf relocs. */
struct elf_reloc_map
{
return TRUE;
}
+/* Returns true if the hash entry refers to a symbol
+ marked for indirect handling during reloc processing. */
+
+static bfd_boolean
+is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
+{
+ const struct elf_backend_data * bed;
+
+ if (abfd == NULL || h == NULL)
+ return FALSE;
+
+ bed = get_elf_backend_data (abfd);
+
+ return h->type == STT_GNU_IFUNC
+ && (bed->elf_osabi == ELFOSABI_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || bed->elf_osabi == ELFOSABI_NONE);
+}
+
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure
linkage table, and dynamic reloc sections. */
sym_hashes = elf_sym_hashes (abfd);
sreloc = NULL;
-
+
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
may need to keep relocations for symbols satisfied by a
dynamic library if we manage to avoid copy relocs for the
symbol. */
-
if ((info->shared
&& (sec->flags & SEC_ALLOC) != 0
- && (((r_type != R_X86_64_PC8)
- && (r_type != R_X86_64_PC16)
- && (r_type != R_X86_64_PC32)
- && (r_type != R_X86_64_PC64))
+ && (! IS_X86_64_PCREL_TYPE (r_type)
|| (h != NULL
&& (! SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
if (sreloc == NULL)
return FALSE;
+
+ /* Create the ifunc section, even if we will not encounter an
+ indirect function symbol. We may not even see one in the input
+ object file, but we can still encounter them in libraries. */
+ (void) _bfd_elf_make_ifunc_reloc_section
+ (abfd, sec, htab->elf.dynobj, 2);
}
/* If this is a global symbol, we count the number of
if (p == NULL || p->sec != sec)
{
bfd_size_type amt = sizeof *p;
+
p = ((struct elf64_x86_64_dyn_relocs *)
bfd_alloc (htab->elf.dynobj, amt));
if (p == NULL)
}
p->count += 1;
- if (r_type == R_X86_64_PC8
- || r_type == R_X86_64_PC16
- || r_type == R_X86_64_PC32
- || r_type == R_X86_64_PC64)
+ if (IS_X86_64_PCREL_TYPE (r_type))
p->pc_count += 1;
}
break;
struct elf64_x86_64_link_hash_table *htab;
struct elf64_x86_64_link_hash_entry *eh;
struct elf64_x86_64_dyn_relocs *p;
+ bfd_boolean use_indirect_section = FALSE;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
&& !info->shared
&& h->dynindx == -1
&& elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
- h->got.offset = (bfd_vma) -1;
+ {
+ h->got.offset = (bfd_vma) -1;
+ }
else if (h->got.refcount > 0)
{
asection *s;
/* Make sure undefined weak symbols are output as a dynamic
symbol in PIEs. */
else if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
+ && ! h->forced_local
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
}
}
+ else if (is_indirect_symbol (info->output_bfd, h)
+ && h->dynindx == -1
+ && ! h->forced_local)
+ {
+ if (bfd_elf_link_record_dynamic_symbol (info, h)
+ && h->dynindx != -1)
+ use_indirect_section = TRUE;
+ else
+ return FALSE;
+ }
else if (ELIMINATE_COPY_RELOCS)
{
/* For the non-shared case, discard space for relocs against
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
+ && ! h->forced_local
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
/* If that succeeded, we know we'll be keeping all the
relocs. */
{
asection * sreloc;
- sreloc = elf_section_data (p->sec)->sreloc;
+ if (use_indirect_section)
+ sreloc = elf_section_data (p->sec)->indirect_relocs;
+ else
+ sreloc = elf_section_data (p->sec)->sreloc;
BFD_ASSERT (sreloc != NULL);
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
- && ((r_type != R_X86_64_PC8
- && r_type != R_X86_64_PC16
- && r_type != R_X86_64_PC32
- && r_type != R_X86_64_PC64)
- || !SYMBOL_CALLS_LOCAL (info, h)))
+ && (! IS_X86_64_PCREL_TYPE (r_type)
+ || ! SYMBOL_CALLS_LOCAL (info, h)))
+ || (! info->shared
+ && h != NULL
+ && h->dynindx != -1
+ && ! h->forced_local
+ && ((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs != NULL
+ && is_indirect_symbol (output_bfd, h))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& h != NULL
become local. */
else if (h != NULL
&& h->dynindx != -1
- && (r_type == R_X86_64_PC8
- || r_type == R_X86_64_PC16
- || r_type == R_X86_64_PC32
- || r_type == R_X86_64_PC64
- || !info->shared
- || !SYMBOLIC_BIND (info, h)
- || !h->def_regular))
+ && (IS_X86_64_PCREL_TYPE (r_type)
+ || ! info->shared
+ || ! SYMBOLIC_BIND (info, h)
+ || ! h->def_regular))
{
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
outrel.r_addend = rel->r_addend;
}
}
- sreloc = elf_section_data (input_section)->sreloc;
-
+ if (! info->shared
+ && h != NULL
+ && h->dynindx != -1
+ && ! h->forced_local
+ && is_indirect_symbol (output_bfd, h)
+ && elf_section_data (input_section)->indirect_relocs != NULL
+ && elf_section_data (input_section)->indirect_relocs->contents != NULL)
+ sreloc = elf_section_data (input_section)->indirect_relocs;
+ else
+ sreloc = elf_section_data (input_section)->sreloc;
+
BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
loc = sreloc->contents;
static bfd_boolean
elf64_x86_64_add_symbol_hook (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED,
- asection **secp, bfd_vma *valp)
+ asection **secp,
+ bfd_vma *valp)
{
asection *lcomm;
*valp = sym->st_size;
break;
}
+
+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+ elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+
return TRUE;
}
#define elf_backend_hash_symbol \
elf64_x86_64_hash_symbol
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers _bfd_elf_set_osabi
+
#include "elf64-target.h"
/* FreeBSD support. */
#undef ELF_OSABI
#define ELF_OSABI ELFOSABI_FREEBSD
-#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
-
#undef elf64_bed
#define elf64_bed elf64_x86_64_fbsd_bed
case STT_SRELC:
sym->symbol.flags |= BSF_SRELC;
break;
+ case STT_GNU_IFUNC:
+ sym->symbol.flags |= BSF_GNU_INDIRECT_FUNCTION;
+ break;
}
if (dynamic)
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;
return reloc_sec;
}
+
+/* Returns the name of the ifunc using dynamic reloc section associated with SEC. */
+#define IFUNC_INFIX ".ifunc"
+
+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;
+}
. {* This symbol was created by bfd_get_synthetic_symtab. *}
.#define BSF_SYNTHETIC (1 << 21)
.
+. {* This symbol is an indirect code object. Unrelated to BSF_INDIRECT.
+. The dynamic linker will compute the value of this symbol by
+. calling the function that it points to. BSF_FUNCTION must
+. also be also set. *}
+.#define BSF_GNU_INDIRECT_FUNCTION (1 << 22)
+.
. flagword flags;
.
. {* A pointer to the section to which this symbol is
(type & BSF_WEAK) ? 'w' : ' ',
(type & BSF_CONSTRUCTOR) ? 'C' : ' ',
(type & BSF_WARNING) ? 'W' : ' ',
- (type & BSF_INDIRECT) ? 'I' : ' ',
+ (type & BSF_INDIRECT) ? 'I' : (type & BSF_GNU_INDIRECT_FUNCTION) ? 'i' : ' ',
(type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
((type & BSF_FUNCTION)
? 'F'
}
if (bfd_is_ind_section (symbol->section))
return 'I';
+ if (symbol->flags & BSF_GNU_INDIRECT_FUNCTION)
+ return 'i';
if (symbol->flags & BSF_WEAK)
{
/* If weak, determine if it's specifically an object
+2009-04-30 Nick Clifton <nickc@redhat.com>
+
+ * common.h (STT_GNU_IFUNC): Define.
+
2009-04-24 Cary Coutant <ccoutant@google.com>
* dwarf2.h (DW_LNE_set_discriminator): New enum value.
#define STT_RELC 8 /* Complex relocation expression */
#define STT_SRELC 9 /* Signed Complex relocation expression */
#define STT_LOOS 10 /* OS-specific semantics */
+#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
#define STT_HIOS 12 /* OS-specific semantics */
#define STT_LOPROC 13 /* Processor-specific semantics */
#define STT_HIPROC 15 /* Processor-specific semantics */