/* BFD back-end data structures for ELF files.
- Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_size / (shdr)->sh_entsize)
/* If size isn't specified as 64 or 32, NAME macro should fail. */
+/* Do not "beautify" the CONCAT* macro args. Traditional C will not
+ remove whitespace added here, and thus will fail to concatenate
+ the tokens. */
#ifndef NAME
#if ARCH_SIZE==64
-#define NAME(x,y) CAT4(x,64,_,y)
+#define NAME(x,y) CONCAT4 (x,64,_,y)
#endif
#if ARCH_SIZE==32
-#define NAME(x,y) CAT4(x,32,_,y)
+#define NAME(x,y) CONCAT4 (x,32,_,y)
#endif
#endif
#ifndef NAME
-#define NAME(x,y) CAT4(x,NOSIZE,_,y)
+#define NAME(x,y) CONCAT4 (x,NOSIZE,_,y)
#endif
#define ElfNAME(X) NAME(Elf,X)
} elf_symbol_type;
\f
+struct elf_strtab_hash;
+
/* ELF linker hash table entries. */
struct elf_link_hash_entry
set to -2 if the symbol is used by a reloc. */
long indx;
- /* Symbol size. */
- bfd_size_type size;
-
/* Symbol index as a dynamic symbol. Initialized to -1, and remains
-1 if this is not a dynamic symbol. */
/* ??? Note that this is consistently used as a synonym for tests
/* String table index in .dynstr if this is a dynamic symbol. */
unsigned long dynstr_index;
+ /* Hash value of the name computed using the ELF hash function. */
+ unsigned long elf_hash_value;
+
/* If this is a weak defined symbol from a dynamic object, this
field points to a defined symbol with the same value, if there is
one. Otherwise it is NULL. */
struct elf_link_hash_entry *weakdef;
- /* If this symbol requires an entry in the global offset table, the
- processor specific backend uses this field to track usage and
- final offset. We use a union and two names primarily to document
- the intent of any particular piece of code. The field should be
- used as a count until size_dynamic_sections, at which point the
- contents of the .got is fixed. Afterward, if this field is -1,
- then the symbol does not require a global offset table entry. */
- union
- {
- bfd_signed_vma refcount;
- bfd_vma offset;
- } got;
-
- /* Same, but tracks a procedure linkage table entry. */
- union
- {
- bfd_signed_vma refcount;
- bfd_vma offset;
- } plt;
-
/* If this symbol is used in the linker created sections, the processor
specific backend uses this field to map the field into the offset
from the beginning of the section. */
/* Virtual table derivation info. */
struct elf_link_hash_entry *vtable_parent;
+ /* If this symbol requires an entry in the global offset table, the
+ processor specific backend uses this field to track usage and
+ final offset. We use a union and two names primarily to document
+ the intent of any particular piece of code. The field should be
+ used as a count until size_dynamic_sections, at which point the
+ contents of the .got is fixed. Afterward, if this field is -1,
+ then the symbol does not require a global offset table entry. */
+ union
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } got;
+
+ /* Same, but tracks a procedure linkage table entry. */
+ union
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } plt;
+
+ /* Symbol size. */
+ bfd_size_type size;
+
/* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */
char type;
/* Symbol st_other value, symbol visibility. */
unsigned char other;
- /* Hash value of the name computed using the ELF hash function. */
- unsigned long elf_hash_value;
-
/* Some flags; legal values follow. */
unsigned short elf_link_hash_flags;
/* Symbol is referenced by a non-shared object. */
Elf_Internal_Sym isym;
};
+enum elf_link_info_type
+{
+ ELF_INFO_TYPE_NONE,
+ ELF_INFO_TYPE_STABS,
+ ELF_INFO_TYPE_MERGE,
+ ELF_INFO_TYPE_EH_FRAME,
+ ELF_INFO_TYPE_EH_FRAME_HDR,
+ ELF_INFO_TYPE_LAST
+};
+
/* ELF linker hash table. */
struct elf_link_hash_table
/* The string table of dynamic symbols, which becomes the .dynstr
section. */
- struct bfd_strtab_hash *dynstr;
+ struct elf_strtab_hash *dynstr;
/* The number of buckets in the hash table in the .hash section.
This is based on the number of dynamic symbols. */
/* Returns true if the hash table is a struct elf_link_hash_table. */
#define is_elf_hash_table(p) \
((p)->hash->type == bfd_link_elf_hash_table)
+
+/* Used by bfd_section_from_r_symndx to cache a small number of local
+ symbol to section mappings. */
+#define LOCAL_SYM_CACHE_SIZE 32
+struct sym_sec_cache
+{
+ bfd *abfd;
+ unsigned long indx[LOCAL_SYM_CACHE_SIZE];
+ asection *sec[LOCAL_SYM_CACHE_SIZE];
+};
\f
/* Constant information held for an ELF backend. */
void (*write_relocs)
PARAMS ((bfd *, asection *, PTR));
void (*swap_symbol_out)
- PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+ PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
boolean (*slurp_reloc_table)
PARAMS ((bfd *, asection *, asymbol **, boolean));
long (*slurp_symbol_table)
reloc_class_copy
};
+struct elf_reloc_cookie
+{
+ Elf_Internal_Rela *rels, *rel, *relend;
+ PTR locsyms;
+ PTR locsym_shndx;
+ bfd *abfd;
+ size_t locsymcount;
+ size_t extsymoff;
+ struct elf_link_hash_entry **sym_hashes;
+ boolean bad_symtab;
+};
+
struct elf_backend_data
{
/* The architecture for this backend. */
section, *RETVAL should be left unchanged. If it is not a normal
ELF section *RETVAL should be set to the SHN_xxxx index. */
boolean (*elf_backend_section_from_bfd_section)
- PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *retval));
+ PARAMS ((bfd *, asection *, int *retval));
/* If this field is not NULL, it is called by the add_symbols phase
of a link just before adding a symbol to the global linker hash
PARAMS ((bfd *, struct bfd_link_info *, PTR,
boolean (*) (PTR, const char *, Elf_Internal_Sym *, asection *)));
- /* Copy any information related to dynamic linking from a pre-existing
- symbol IND to a newly created symbol DIR. */
+ /* Copy any information related to dynamic linking from a pre-existing
+ symbol to a newly created symbol. Also called to copy flags and
+ other back-end info to a weakdef, in which case the symbol is not
+ newly created and plt/got refcounts and dynamic indices should not
+ be copied. */
void (*elf_backend_copy_indirect_symbol)
PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
/* Modify any information related to dynamic linking such that the
symbol is not exported. */
void (*elf_backend_hide_symbol)
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
/* Emit relocations. Overrides default routine for emitting relocs,
except during a relocatable link, or if all relocs are being emitted. */
enum elf_reloc_type_class (*elf_backend_reloc_type_class)
PARAMS ((const Elf_Internal_Rela *));
+ /* This function, if defined, removes information about discarded functions
+ from other sections which mention them. */
+ boolean (*elf_backend_discard_info)
+ PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
+
+ /* This function, if defined, signals that the function above has removed
+ the discarded relocations for this section. */
+ boolean (*elf_backend_ignore_discarded_relocs)
+ PARAMS ((asection *));
+
+ /* This function, if defined, may write out the given section.
+ Returns true if it did so and false if the caller should. */
+ boolean (*elf_backend_write_section)
+ PARAMS ((bfd *, asection *, bfd_byte *));
+
/* The swapping table to use when dealing with ECOFF information.
Used for the MIPS ELF .mdebug section. */
const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap;
/* The number of relocations currently assigned to REL_HDR2. */
unsigned int rel_count2;
- /* The number of dynamic relocs copied for local symbols. */
- unsigned int local_dynrel;
+ /* A pointer to a linked list tracking dynamic relocs copied for
+ local symbols. */
+ PTR local_dynrel;
/* A pointer to the bfd section used for dynamic relocs. */
asection *sreloc;
no dynamic symbol for this section. */
long dynindx;
- /* A pointer used for .stab linking optimizations. */
- PTR stab_info;
+ /* A pointer used for various section optimizations. */
+ PTR sec_info;
- /* A pointer used for SEC_MERGE optimizations. */
- PTR merge_info;
+ /* Type of that information. */
+ enum elf_link_info_type sec_info_type;
+
+ /* Group name, if this section is part of a group. */
+ const char *group_name;
+
+ /* A linked list of sections in the group. Circular when used by
+ the linker. */
+ asection *next_in_group;
/* A pointer available for the processor specific ELF backend. */
PTR tdata;
};
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
+#define elf_group_name(sec) (elf_section_data(sec)->group_name)
+#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group)
+
+/* Return true if section has been discarded. */
+#define elf_discarded_section(sec) \
+ (!bfd_is_abs_section(sec) \
+ && bfd_is_abs_section((sec)->output_section) \
+ && elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
#define get_elf_backend_data(abfd) \
((struct elf_backend_data *) (abfd)->xvec->backend_data)
Elf_Internal_Shdr **elf_sect_ptr;
Elf_Internal_Phdr *phdr;
struct elf_segment_map *segment_map;
- struct bfd_strtab_hash *strtab_ptr;
+ struct elf_strtab_hash *strtab_ptr;
int num_locals;
int num_globals;
+ unsigned int num_elf_sections; /* elf_sect_ptr size */
int num_section_syms;
asymbol **section_syms; /* STT_SECTION symbols for each section */
Elf_Internal_Shdr symtab_hdr;
Elf_Internal_Shdr dynversym_hdr;
Elf_Internal_Shdr dynverref_hdr;
Elf_Internal_Shdr dynverdef_hdr;
+ Elf_Internal_Shdr symtab_shndx_hdr;
unsigned int symtab_section, shstrtab_section;
unsigned int strtab_section, dynsymtab_section;
+ unsigned int symtab_shndx_section;
unsigned int dynversym_section, dynverdef_section, dynverref_section;
file_ptr next_file_pos;
#if 0
void *prstatus; /* The raw /proc prstatus structure */
void *prpsinfo; /* The raw /proc prpsinfo structure */
#endif
- bfd_vma gp; /* The gp value (MIPS only, for now) */
- unsigned int gp_size; /* The gp size (MIPS only, for now) */
+ bfd_vma gp; /* The gp value */
+ unsigned int gp_size; /* The gp size */
+
+ Elf_Internal_Shdr **group_sect_ptr;
+ int num_group;
/* Information grabbed from an elf core file. */
int core_signal;
/* Used to determine if the e_flags field has been initialized */
boolean flags_init;
+ /* Used to determine if PT_GNU_EH_FRAME segment header should be
+ created. */
+ boolean eh_frame_hdr;
+
/* Number of symbol version definitions we are about to emit. */
unsigned int cverdefs;
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header)
#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr)
+#define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections)
#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)
#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)
+#define elf_symtab_shndx(bfd) (elf_tdata(bfd) -> symtab_shndx_section)
#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section)
#define elf_dynversym(bfd) (elf_tdata(bfd) -> dynversym_section)
#define elf_dynverdef(bfd) (elf_tdata(bfd) -> dynverdef_section)
extern char *bfd_elf_get_str_section
PARAMS ((bfd *, unsigned));
+extern boolean _bfd_elf_copy_private_bfd_data
+ PARAMS ((bfd *, bfd *));
extern boolean _bfd_elf_print_private_bfd_data
PARAMS ((bfd *, PTR));
extern void bfd_elf_print_symbol
extern enum elf_reloc_type_class _bfd_elf_reloc_type_class
PARAMS ((const Elf_Internal_Rela *));
+extern bfd_vma _bfd_elf_rela_local_sym
+ PARAMS ((bfd *, Elf_Internal_Sym *, asection *, Elf_Internal_Rela *));
+extern bfd_vma _bfd_elf_rel_local_sym
+ PARAMS ((bfd *, Elf_Internal_Sym *, asection **, bfd_vma));
+extern bfd_vma _bfd_elf_section_offset
+ PARAMS ((bfd *, struct bfd_link_info *, asection *, bfd_vma));
extern unsigned long bfd_elf_hash
PARAMS ((const char *));
extern void _bfd_elf_link_hash_copy_indirect
PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
extern void _bfd_elf_link_hash_hide_symbol
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
extern boolean _bfd_elf_link_hash_table_init
PARAMS ((struct elf_link_hash_table *, bfd *,
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
extern int _bfd_elf_symbol_from_bfd_symbol
PARAMS ((bfd *, asymbol **));
+extern asection *bfd_section_from_r_symndx
+ PARAMS ((bfd *, struct sym_sec_cache *, asection *, unsigned long));
extern asection *bfd_section_from_elf_index
PARAMS ((bfd *, unsigned int));
extern boolean _bfd_elf_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
extern struct bfd_strtab_hash *_bfd_elf_stringtab_init
PARAMS ((void));
+
+extern struct elf_strtab_hash * _bfd_elf_strtab_init
+ PARAMS ((void));
+extern void _bfd_elf_strtab_free
+ PARAMS ((struct elf_strtab_hash *));
+extern bfd_size_type _bfd_elf_strtab_add
+ PARAMS ((struct elf_strtab_hash *, const char *, boolean));
+extern void _bfd_elf_strtab_addref
+ PARAMS ((struct elf_strtab_hash *, bfd_size_type));
+extern void _bfd_elf_strtab_delref
+ PARAMS ((struct elf_strtab_hash *, bfd_size_type));
+extern void _bfd_elf_strtab_clear_all_refs
+ PARAMS ((struct elf_strtab_hash *));
+extern bfd_size_type _bfd_elf_strtab_size
+ PARAMS ((struct elf_strtab_hash *));
+extern bfd_size_type _bfd_elf_strtab_offset
+ PARAMS ((struct elf_strtab_hash *, bfd_size_type));
+extern boolean _bfd_elf_strtab_emit
+ PARAMS ((bfd *, struct elf_strtab_hash *));
+extern void _bfd_elf_strtab_finalize
+ PARAMS ((struct elf_strtab_hash *));
+
+extern boolean _bfd_elf_discard_section_eh_frame
+ PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *,
+ boolean (*) (bfd_vma, PTR), struct elf_reloc_cookie *));
+extern boolean _bfd_elf_discard_section_eh_frame_hdr
+ PARAMS ((bfd *, struct bfd_link_info *, asection *));
+extern bfd_vma _bfd_elf_eh_frame_section_offset
+ PARAMS ((bfd *, asection *, bfd_vma));
+extern boolean _bfd_elf_write_section_eh_frame
+ PARAMS ((bfd *, asection *, asection *, bfd_byte *));
+extern boolean _bfd_elf_write_section_eh_frame_hdr
+ PARAMS ((bfd *, asection *));
+extern boolean _bfd_elf_maybe_strip_eh_frame_hdr
+ PARAMS ((struct bfd_link_info *));
+
extern boolean _bfd_elf_link_record_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
extern long _bfd_elf_link_lookup_local_dynindx
PARAMS ((bfd *, struct bfd_link_info *));
extern void bfd_elf32_swap_symbol_in
- PARAMS ((bfd *, const Elf32_External_Sym *, Elf_Internal_Sym *));
+ PARAMS ((bfd *, const Elf32_External_Sym *, const Elf_External_Sym_Shndx *,
+ Elf_Internal_Sym *));
extern void bfd_elf32_swap_symbol_out
- PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+ PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
extern void bfd_elf32_swap_reloc_in
PARAMS ((bfd *, const Elf32_External_Rel *, Elf_Internal_Rel *));
extern void bfd_elf32_swap_reloc_out
PARAMS ((bfd *, struct bfd_link_info *));
extern void bfd_elf64_swap_symbol_in
- PARAMS ((bfd *, const Elf64_External_Sym *, Elf_Internal_Sym *));
+ PARAMS ((bfd *, const Elf64_External_Sym *, const Elf_External_Sym_Shndx *,
+ Elf_Internal_Sym *));
extern void bfd_elf64_swap_symbol_out
- PARAMS ((bfd *, const Elf_Internal_Sym *, PTR));
+ PARAMS ((bfd *, const Elf_Internal_Sym *, PTR, PTR));
extern void bfd_elf64_swap_reloc_in
PARAMS ((bfd *, const Elf64_External_Rel *, Elf_Internal_Rel *));
extern void bfd_elf64_swap_reloc_out
extern boolean _bfd_elf64_gc_record_vtentry
PARAMS ((bfd *, asection *, struct elf_link_hash_entry *, bfd_vma));
+extern boolean _bfd_elf32_reloc_symbol_deleted_p
+ PARAMS ((bfd_vma, PTR));
+extern boolean _bfd_elf64_reloc_symbol_deleted_p
+ PARAMS ((bfd_vma, PTR));
+
+/* Exported interface for writing elf corefile notes. */
+extern char *elfcore_write_note
+ PARAMS ((bfd *, char *, int *, char *, int, void *, int));
+extern char *elfcore_write_prpsinfo
+ PARAMS ((bfd *, char *, int *, char *, char *));
+extern char *elfcore_write_prstatus
+ PARAMS ((bfd *, char *, int *, long, int, void *));
+extern char * elfcore_write_pstatus
+ PARAMS ((bfd *, char *, int *, long, int, void *));
+extern char *elfcore_write_prfpreg
+ PARAMS ((bfd *, char *, int *, void *, int));
+extern char *elfcore_write_prxfpreg
+ PARAMS ((bfd *, char *, int *, void *, int));
+extern char *elfcore_write_lwpstatus
+ PARAMS ((bfd*, char*, int*, long, int, void*));
+
/* MIPS ELF specific routines. */
extern boolean _bfd_mips_elf_object_p
extern boolean _bfd_mips_elf_fake_sections
PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
extern boolean _bfd_mips_elf_section_from_bfd_section
- PARAMS ((bfd *, Elf_Internal_Shdr *, asection *, int *));
+ PARAMS ((bfd *, asection *, int *));
extern boolean _bfd_mips_elf_section_processing
PARAMS ((bfd *, Elf_Internal_Shdr *));
extern void _bfd_mips_elf_symbol_processing
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
extern boolean _bfd_mips_elf_set_private_flags
PARAMS ((bfd *, flagword));
-extern boolean _bfd_mips_elf_copy_private_bfd_data
- PARAMS ((bfd *, bfd *));
extern boolean _bfd_mips_elf_merge_private_bfd_data
PARAMS ((bfd *, bfd *));
extern boolean _bfd_mips_elf_find_nearest_line