/* BFD back-end data structures for ELF files.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Cygnus Support.
/* The number of entries in a section is its size divided by the size
of a single entry. This is normally only applicable to reloc and
- symbol table sections. */
-#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_size / (shdr)->sh_entsize)
+ symbol table sections.
+ PR 9934: It is possible to have relocations that do not refer to
+ symbols, thus it is also possible to have a relocation section in
+ an object file, but no symbol table. */
+#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_entsize > 0 ? (shdr)->sh_size / (shdr)->sh_entsize : 0)
/* If size isn't specified as 64 or 32, NAME macro should fail. */
#ifndef NAME
struct got_entry;
struct plt_entry;
+union gotplt_union
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ struct got_entry *glist;
+ struct plt_entry *plist;
+ };
+
+struct elf_link_virtual_table_entry
+ {
+ /* Virtual table entry use information. This array is nominally of size
+ size/sizeof(target_void_pointer), though we have to be able to assume
+ and track a size while the symbol is still undefined. It is indexed
+ via offset/sizeof(target_void_pointer). */
+ size_t size;
+ bfd_boolean *used;
+
+ /* Virtual table derivation info. */
+ struct elf_link_hash_entry *parent;
+ };
+
/* ELF linker hash table entries. */
struct elf_link_hash_entry
require a global offset table entry. The second scheme allows
multiple GOT entries per symbol, managed via a linked list
pointed to by GLIST. */
- union gotplt_union
- {
- bfd_signed_vma refcount;
- bfd_vma offset;
- struct got_entry *glist;
- struct plt_entry *plist;
- } got;
+ union gotplt_union got;
/* Same, but tracks a procedure linkage table entry. */
union gotplt_union plt;
/* Symbol st_other value, symbol visibility. */
unsigned int other : 8;
- /* Symbol is referenced by a non-shared object. */
+ /* Symbol is referenced by a non-shared object (other than the object
+ in which it is defined). */
unsigned int ref_regular : 1;
/* Symbol is defined by a non-shared object. */
unsigned int def_regular : 1;
unsigned int ref_dynamic : 1;
/* Symbol is defined by a shared object. */
unsigned int def_dynamic : 1;
- /* Symbol has a non-weak reference from a non-shared object. */
+ /* Symbol has a non-weak reference from a non-shared object (other than
+ the object in which it is defined). */
unsigned int ref_regular_nonweak : 1;
/* Dynamic symbol has been adjustd. */
unsigned int dynamic_adjusted : 1;
/* Symbol is referenced with a relocation where C/C++ pointer equality
matters. */
unsigned int pointer_equality_needed : 1;
+ /* Symbol is a unique global symbol. */
+ unsigned int unique_global : 1;
/* String table index in .dynstr if this is a dynamic symbol. */
unsigned long dynstr_index;
struct bfd_elf_version_tree *vertree;
} verinfo;
- struct
- {
- /* Virtual table entry use information. This array is nominally of size
- size/sizeof(target_void_pointer), though we have to be able to assume
- and track a size while the symbol is still undefined. It is indexed
- via offset/sizeof(target_void_pointer). */
- size_t size;
- bfd_boolean *used;
-
- /* Virtual table derivation info. */
- struct elf_link_hash_entry *parent;
- } *vtable;
+ struct elf_link_virtual_table_entry *vtable;
};
/* Will references to this symbol always reference the symbol
asection *sec;
} u;
+ /* The offset of the personality data from the start of the CIE,
+ or 0 if the CIE doesn't have any. */
+ unsigned int personality_offset : 8;
+
/* True if we have marked relocations associated with this CIE. */
unsigned int gc_mark : 1;
a PC-relative one. */
unsigned int make_lsda_relative : 1;
- /* True if the CIE contains personality data and if that data
- uses a PC-relative encoding. */
+ /* True if we have decided to turn an absolute personality
+ encoding into a PC-relative one. */
+ unsigned int make_per_encoding_relative : 1;
+
+ /* True if the CIE contains personality data and if that
+ data uses a PC-relative encoding. Always true when
+ make_per_encoding_relative is. */
unsigned int per_encoding_relative : 1;
/* True if we need to add an 'R' (FDE encoding) entry to the
/* True if we have merged this CIE with another. */
unsigned int merged : 1;
+
+ /* Unused bits. */
+ unsigned int pad1 : 18;
} cie;
} u;
unsigned int reloc_index;
bfd_boolean table;
};
+/* Enum used to identify target specific extensions to the elf_obj_tdata
+ and elf_link_hash_table structures. Note the enums deliberately start
+ from 1 so that we can detect an uninitialized field. The generic value
+ is last so that additions to this enum do not need to modify more than
+ one line. */
+enum elf_target_id
+{
+ ALPHA_ELF_DATA = 1,
+ ARM_ELF_DATA,
+ AVR_ELF_DATA,
+ BFIN_ELF_DATA,
+ CRIS_ELF_DATA,
+ FRV_ELF_DATA,
+ HPPA32_ELF_DATA,
+ HPPA64_ELF_DATA,
+ I386_ELF_DATA,
+ IA64_ELF_DATA,
+ LM32_ELF_DATA,
+ M32R_ELF_DATA,
+ M68HC11_ELF_DATA,
+ M68K_ELF_DATA,
+ MICROBLAZE_ELF_DATA,
+ MIPS_ELF_DATA,
+ MN10300_ELF_DATA,
+ PPC32_ELF_DATA,
+ PPC64_ELF_DATA,
+ S390_ELF_DATA,
+ SH_ELF_DATA,
+ SPARC_ELF_DATA,
+ SPU_ELF_DATA,
+ TIC6X_ELF_DATA,
+ X86_64_ELF_DATA,
+ XTENSA_ELF_DATA,
+ GENERIC_ELF_DATA
+};
+
/* ELF linker hash table. */
struct elf_link_hash_table
{
struct bfd_link_hash_table root;
+ /* An identifier used to distinguish different target
+ specific extensions to this structure. */
+ enum elf_target_id hash_table_id;
+
/* Whether we have created the special dynamic sections required
when linking against or generating a shared object. */
bfd_boolean dynamic_sections_created;
/* A linked list of BFD's loaded in the link. */
struct elf_link_loaded_list *loaded;
+
+ /* Short-cuts to get to dynamic linker sections. */
+ asection *sgot;
+ asection *sgotplt;
+ asection *srelgot;
+ asection *splt;
+ asection *srelplt;
+ asection *igotplt;
+ asection *iplt;
+ asection *irelplt;
+ asection *irelifunc;
};
/* Look up an entry in an ELF linker hash table. */
#define elf_hash_table(p) ((struct elf_link_hash_table *) ((p)->hash))
+#define elf_hash_table_id(table) ((table) -> hash_table_id)
+
/* Returns TRUE if the hash table is a struct elf_link_hash_table. */
#define is_elf_hash_table(htab) \
(((struct bfd_link_hash_table *) (htab))->type == bfd_link_elf_hash_table)
-/* Used by bfd_section_from_r_symndx to cache a small number of local
- symbol to section mappings. */
+/* Used by bfd_sym_from_r_symndx to cache a small number of local
+ symbols. */
#define LOCAL_SYM_CACHE_SIZE 32
-struct sym_sec_cache
+struct sym_cache
{
bfd *abfd;
unsigned long indx[LOCAL_SYM_CACHE_SIZE];
- unsigned int shndx[LOCAL_SYM_CACHE_SIZE];
+ Elf_Internal_Sym sym[LOCAL_SYM_CACHE_SIZE];
};
\f
/* Constant information held for an ELF backend. */
/* The architecture for this backend. */
enum bfd_architecture arch;
+ /* An identifier used to distinguish different target specific
+ extensions to elf_obj_tdata and elf_link_hash_table structures. */
+ enum elf_target_id target_id;
+
/* The ELF machine code (EM_xxxx) for this backend. */
int elf_machine_code;
const char **name, flagword *flags, asection **sec, bfd_vma *value);
/* If this field is not NULL, it is called by the elf_link_output_sym
- phase of a link for each symbol which will appear in the object file. */
- bfd_boolean (*elf_backend_link_output_symbol_hook)
+ phase of a link for each symbol which will appear in the object file.
+ On error, this function returns 0. 1 is returned when the symbol
+ should be output, 2 is returned when the symbol should be discarded. */
+ int (*elf_backend_link_output_symbol_hook)
(struct bfd_link_info *info, const char *, Elf_Internal_Sym *,
asection *, struct elf_link_hash_entry *);
/* The section type to use for an attributes section. */
unsigned int obj_attrs_section_type;
- /* This function determines the order in which any attributes are written.
- It must be defined for input in the range 4..NUM_KNOWN_OBJ_ATTRIBUTES-1
- (this range is used in order to make unity easy). The returned value is
- the actual tag number to place in the input position. */
+ /* This function determines the order in which any attributes are
+ written. It must be defined for input in the range
+ LEAST_KNOWN_OBJ_ATTRIBUTE..NUM_KNOWN_OBJ_ATTRIBUTES-1 (this range
+ is used in order to make unity easy). The returned value is the
+ actual tag number to place in the input position. */
int (*obj_attrs_order) (int);
/* This is TRUE if the linker should act like collect and gather
#define get_elf_backend_data(abfd) \
xvec_get_elf_backend_data ((abfd)->xvec)
+/* The least object attributes (within an attributes subsection) known
+ for any target. Some code assumes that the value 0 is not used and
+ the field for that attribute can instead be used as a marker to
+ indicate that attributes have been initialized. */
+#define LEAST_KNOWN_OBJ_ATTRIBUTE 2
+
/* The maximum number of known object attributes for any target. */
#define NUM_KNOWN_OBJ_ATTRIBUTES 71
Tag_compatibility = 32
};
-/* Enum used to identify target specific extensions to the elf_obj_tdata
- structure. Note the enums deliberately start from 1 so that we can
- detect an uninitialized field. The generic value is last so that
- additions to this enum do not need to modify more than one line. */
-enum elf_object_id
-{
- ALPHA_ELF_TDATA = 1,
- ARM_ELF_TDATA,
- HPPA_ELF_TDATA,
- I386_ELF_TDATA,
- MIPS_ELF_TDATA,
- PPC32_ELF_TDATA,
- PPC64_ELF_TDATA,
- S390_ELF_TDATA,
- SH_ELF_TDATA,
- SPARC_ELF_TDATA,
- X86_64_ELF_TDATA,
- XTENSA_ELF_TDATA,
- GENERIC_ELF_TDATA
-};
-
/* Some private data is stashed away for future use using the tdata pointer
in the bfd structure. */
one. */
const char *dt_name;
+ /* The linker emulation needs to know what audit libs
+ are used by a dynamic object. */
+ const char *dt_audit;
+
/* Records the result of `get_program_header_size'. */
bfd_size_type program_header_size;
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;
+ enum elf_target_id object_id;
};
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
#define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
#define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents)
#define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name)
+#define elf_dt_audit(bfd) (elf_tdata(bfd) -> dt_audit)
#define elf_dyn_lib_class(bfd) (elf_tdata(bfd) -> dyn_lib_class)
#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)
(bfd *, asection *);
extern char *bfd_elf_string_from_elf_section
(bfd *, unsigned, unsigned);
-extern char *bfd_elf_get_str_section
- (bfd *, unsigned);
extern Elf_Internal_Sym *bfd_elf_get_elf_syms
(bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *,
Elf_External_Sym_Shndx *);
extern bfd_reloc_status_type bfd_elf_generic_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
extern bfd_boolean bfd_elf_allocate_object
- (bfd *, size_t, enum elf_object_id);
-extern bfd_boolean bfd_elf_make_generic_object
+ (bfd *, size_t, enum elf_target_id);
+extern bfd_boolean bfd_elf_make_object
(bfd *);
extern bfd_boolean bfd_elf_mkcorefile
(bfd *);
-extern Elf_Internal_Shdr *bfd_elf_find_section
- (bfd *, char *);
extern bfd_boolean _bfd_elf_make_section_from_shdr
(bfd *, Elf_Internal_Shdr *, const char *, int);
extern bfd_boolean _bfd_elf_make_section_from_phdr
(struct elf_link_hash_table *, bfd *,
struct bfd_hash_entry *(*)
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *),
- unsigned int);
+ unsigned int, enum elf_target_id);
extern bfd_boolean _bfd_elf_slurp_version_tables
(bfd *, bfd_boolean);
extern bfd_boolean _bfd_elf_merge_sections
(asection *, struct bfd_link_info *);
extern void _bfd_elf_link_just_syms
(asection *, struct bfd_link_info *);
+extern void _bfd_elf_copy_link_hash_symbol_type
+ (bfd *, struct bfd_link_hash_entry *, struct bfd_link_hash_entry *);
+extern bfd_boolean _bfd_elf_size_group_sections
+ (struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_fixup_group_sections
+(bfd *, asection *);
extern bfd_boolean _bfd_elf_copy_private_header_data
(bfd *, bfd *);
extern bfd_boolean _bfd_elf_copy_private_symbol_data
extern int _bfd_elf_symbol_from_bfd_symbol
(bfd *, asymbol **);
-extern asection *bfd_section_from_r_symndx
- (bfd *, struct sym_sec_cache *, asection *, unsigned long);
+extern Elf_Internal_Sym *bfd_sym_from_r_symndx
+ (struct sym_cache *, bfd *, unsigned long);
extern asection *bfd_section_from_elf_index
(bfd *, unsigned int);
extern struct bfd_strtab_hash *_bfd_elf_stringtab_init
(bfd *);
extern bfd_boolean bfd_elf32_core_file_matches_executable_p
(bfd *, bfd *);
+extern int bfd_elf32_core_file_pid
+ (bfd *);
extern bfd_boolean bfd_elf32_swap_symbol_in
(bfd *, const void *, const void *, Elf_Internal_Sym *);
(bfd *);
extern bfd_boolean bfd_elf64_core_file_matches_executable_p
(bfd *, bfd *);
+extern int bfd_elf64_core_file_pid
+ (bfd *);
extern bfd_boolean bfd_elf64_swap_symbol_in
(bfd *, const void *, const void *, Elf_Internal_Sym *);
extern bfd_boolean _bfd_elf_is_function_type (unsigned int);
+extern int bfd_elf_get_default_section_type (flagword);
+
extern Elf_Internal_Phdr * _bfd_elf_find_segment_containing_section
(bfd * abfd, asection * section);
(bfd *, char *, int *, const void *, int);
extern char *elfcore_write_prxfpreg
(bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_xstatereg
+ (bfd *, char *, int *, const void *, int);
extern char *elfcore_write_ppc_vmx
(bfd *, char *, int *, const void *, int);
extern char *elfcore_write_ppc_vsx
(bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_s390_timer
+ (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_s390_todcmp
+ (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_s390_todpreg
+ (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_s390_ctrs
+ (bfd *, char *, int *, const void *, int);
+extern char *elfcore_write_s390_prefix
+ (bfd *, char *, int *, const void *, int);
extern char *elfcore_write_lwpstatus
(bfd *, char *, int *, long, int, const void *);
extern char *elfcore_write_register_note
extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
+/* The linker may needs to keep track of the number of relocs that it
+ decides to copy as dynamic relocs in check_relocs for each symbol.
+ This is so that it can later discard them if they are found to be
+ unnecessary. We can store the information in a field extending the
+ regular ELF linker hash table. */
+
+struct elf_dyn_relocs
+{
+ struct elf_dyn_relocs *next;
+
+ /* The input section of the reloc. */
+ asection *sec;
+
+ /* Total number of relocs copied for the input section. */
+ bfd_size_type count;
+
+ /* Number of pc-relative relocs copied for the input section. */
+ bfd_size_type pc_count;
+};
+
+extern bfd_boolean _bfd_elf_create_ifunc_sections
+ (bfd *, struct bfd_link_info *);
+extern asection * _bfd_elf_create_ifunc_dyn_reloc
+ (bfd *, struct bfd_link_info *, asection *sec, asection *sreloc,
+ struct elf_dyn_relocs **);
+extern bfd_boolean _bfd_elf_allocate_ifunc_dyn_relocs
+ (struct bfd_link_info *, struct elf_link_hash_entry *,
+ struct elf_dyn_relocs **, unsigned int, unsigned int);
+
/* Large common section. */
extern asection _bfd_elf_large_com_section;
-/* SH ELF specific routine. */
-
-extern bfd_boolean _sh_elf_set_mach_from_flags
- (bfd *);
+/* Hash for local symbol with the first section id, ID, in the input
+ file and the local symbol index, SYM. */
+#define ELF_LOCAL_SYMBOL_HASH(ID, SYM) \
+ (((((ID) & 0xff) << 24) | (((ID) & 0xff00) << 8)) \
+ ^ (SYM) ^ ((ID) >> 16))
/* 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
return FALSE; \
warned = TRUE; \
} \
+ (void) unresolved_reloc; \
+ (void) warned; \
} \
while (0)
+/* This macro is to avoid lots of duplicated code in the body of the
+ loop over relocations in xxx_relocate_section() in the various
+ elfxx-xxxx.c files.
+
+ Handle relocations against symbols from removed linkonce sections,
+ or sections discarded by a linker script. When doing a relocatable
+ link, we remove such relocations. Otherwise, we just want the
+ section contents zeroed and avoid any special processing. */
+#define RELOC_AGAINST_DISCARDED_SECTION(info, input_bfd, input_section, \
+ rel, relend, howto, contents) \
+ { \
+ if (info->relocatable \
+ && (input_section->flags & SEC_DEBUGGING)) \
+ { \
+ /* Only remove relocations in debug sections since other \
+ sections may require relocations. */ \
+ Elf_Internal_Shdr *rel_hdr; \
+ \
+ rel_hdr = &elf_section_data (input_section->output_section)->rel_hdr; \
+ \
+ /* Avoid empty output section. */ \
+ if (rel_hdr->sh_size > rel_hdr->sh_entsize) \
+ { \
+ rel_hdr->sh_size -= rel_hdr->sh_entsize; \
+ rel_hdr = &elf_section_data (input_section)->rel_hdr; \
+ rel_hdr->sh_size -= rel_hdr->sh_entsize; \
+ \
+ memmove (rel, rel + 1, (relend - rel) * sizeof (*rel)); \
+ \
+ input_section->reloc_count--; \
+ relend--; \
+ rel--; \
+ continue; \
+ } \
+ } \
+ \
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); \
+ rel->r_info = 0; \
+ rel->r_addend = 0; \
+ continue; \
+ }
+
/* Will a symbol be bound to the the definition within the shared
- library, if any. */
+ library, if any. A unique symbol can never be bound locally. */
#define SYMBOLIC_BIND(INFO, H) \
- ((INFO)->symbolic || ((INFO)->dynamic && !(H)->dynamic))
+ (!(H)->unique_global \
+ && ((INFO)->symbolic || ((INFO)->dynamic && !(H)->dynamic)))
#endif /* _LIBELF_H_ */