/* MIPS-specific support for ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
long min_got_dynindx;
/* The greatest dynamic symbol table index corresponding to a symbol
with a GOT entry that is not referenced (e.g., a dynamic symbol
- with dynamic relocations pointing to it from non-primary
- GOTs). */
+ with dynamic relocations pointing to it from non-primary GOTs). */
long max_unref_got_dynindx;
/* The greatest dynamic symbol table index not corresponding to a
symbol without a GOT entry. */
a readonly section. */
bfd_boolean readonly_reloc;
- /* The index of the first dynamic relocation (in the .rel.dyn
- section) against this symbol. */
- unsigned int min_dyn_reloc_index;
-
/* We must not create a stub for a symbol that has relocations
related to taking the function's address, i.e. any but
R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
#define rpdNil ((pRPDR) 0)
\f
static struct bfd_hash_entry *mips_elf_link_hash_newfunc
- PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+ (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
static void ecoff_swap_rpdr_out
- PARAMS ((bfd *, const RPDR *, struct rpdr_ext *));
+ (bfd *, const RPDR *, struct rpdr_ext *);
static bfd_boolean mips_elf_create_procedure_table
- PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *,
- struct ecoff_debug_info *));
+ (void *, bfd *, struct bfd_link_info *, asection *,
+ struct ecoff_debug_info *);
static bfd_boolean mips_elf_check_mips16_stubs
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
+ (struct mips_elf_link_hash_entry *, void *);
static void bfd_mips_elf32_swap_gptab_in
- PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
+ (bfd *, const Elf32_External_gptab *, Elf32_gptab *);
static void bfd_mips_elf32_swap_gptab_out
- PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
+ (bfd *, const Elf32_gptab *, Elf32_External_gptab *);
static void bfd_elf32_swap_compact_rel_out
- PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
+ (bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *);
static void bfd_elf32_swap_crinfo_out
- PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
-#if 0
-static void bfd_mips_elf_swap_msym_in
- PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));
-#endif
-static void bfd_mips_elf_swap_msym_out
- PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));
+ (bfd *, const Elf32_crinfo *, Elf32_External_crinfo *);
static int sort_dynamic_relocs
- PARAMS ((const void *, const void *));
+ (const void *, const void *);
static int sort_dynamic_relocs_64
- PARAMS ((const void *, const void *));
+ (const void *, const void *);
static bfd_boolean mips_elf_output_extsym
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
-static int gptab_compare PARAMS ((const void *, const void *));
-static asection * mips_elf_rel_dyn_section PARAMS ((bfd *, bfd_boolean));
-static asection * mips_elf_got_section PARAMS ((bfd *, bfd_boolean));
+ (struct mips_elf_link_hash_entry *, void *);
+static int gptab_compare
+ (const void *, const void *);
+static asection *mips_elf_rel_dyn_section
+ (bfd *, bfd_boolean);
+static asection *mips_elf_got_section
+ (bfd *, bfd_boolean);
static struct mips_got_info *mips_elf_got_info
- PARAMS ((bfd *, asection **));
+ (bfd *, asection **);
static bfd_vma mips_elf_local_got_index
- PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma));
+ (bfd *, bfd *, struct bfd_link_info *, bfd_vma);
static bfd_vma mips_elf_global_got_index
- PARAMS ((bfd *, bfd *, struct elf_link_hash_entry *));
+ (bfd *, bfd *, struct elf_link_hash_entry *);
static bfd_vma mips_elf_got_page
- PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));
+ (bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *);
static bfd_vma mips_elf_got16_entry
- PARAMS ((bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_boolean));
+ (bfd *, bfd *, struct bfd_link_info *, bfd_vma, bfd_boolean);
static bfd_vma mips_elf_got_offset_from_index
- PARAMS ((bfd *, bfd *, bfd *, bfd_vma));
+ (bfd *, bfd *, bfd *, bfd_vma);
static struct mips_got_entry *mips_elf_create_local_got_entry
- PARAMS ((bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma));
+ (bfd *, bfd *, struct mips_got_info *, asection *, bfd_vma);
static bfd_boolean mips_elf_sort_hash_table
- PARAMS ((struct bfd_link_info *, unsigned long));
+ (struct bfd_link_info *, unsigned long);
static bfd_boolean mips_elf_sort_hash_table_f
- PARAMS ((struct mips_elf_link_hash_entry *, PTR));
+ (struct mips_elf_link_hash_entry *, void *);
static bfd_boolean mips_elf_record_local_got_symbol
- PARAMS ((bfd *, long, bfd_vma, struct mips_got_info *));
+ (bfd *, long, bfd_vma, struct mips_got_info *);
static bfd_boolean mips_elf_record_global_got_symbol
- PARAMS ((struct elf_link_hash_entry *, bfd *, struct bfd_link_info *,
- struct mips_got_info *));
+ (struct elf_link_hash_entry *, bfd *, struct bfd_link_info *,
+ struct mips_got_info *);
static const Elf_Internal_Rela *mips_elf_next_relocation
- PARAMS ((bfd *, unsigned int, const Elf_Internal_Rela *,
- const Elf_Internal_Rela *));
+ (bfd *, unsigned int, const Elf_Internal_Rela *, const Elf_Internal_Rela *);
static bfd_boolean mips_elf_local_relocation_p
- PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
-static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
-static bfd_boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
-static bfd_vma mips_elf_high PARAMS ((bfd_vma));
-static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
-static bfd_vma mips_elf_highest PARAMS ((bfd_vma));
+ (bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean);
+static bfd_boolean mips_elf_overflow_p
+ (bfd_vma, int);
+static bfd_vma mips_elf_high
+ (bfd_vma);
+static bfd_vma mips_elf_higher
+ (bfd_vma);
+static bfd_vma mips_elf_highest
+ (bfd_vma);
static bfd_boolean mips_elf_create_compact_rel_section
- PARAMS ((bfd *, struct bfd_link_info *));
+ (bfd *, struct bfd_link_info *);
static bfd_boolean mips_elf_create_got_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
-static asection *mips_elf_create_msym_section
- PARAMS ((bfd *));
+ (bfd *, struct bfd_link_info *, bfd_boolean);
static bfd_reloc_status_type mips_elf_calculate_relocation
- PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
- const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
- Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
- bfd_boolean *, bfd_boolean));
+ (bfd *, bfd *, asection *, struct bfd_link_info *,
+ const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
+ Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
+ bfd_boolean *, bfd_boolean);
static bfd_vma mips_elf_obtain_contents
- PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
+ (reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *);
static bfd_boolean mips_elf_perform_relocation
- PARAMS ((struct bfd_link_info *, reloc_howto_type *,
- const Elf_Internal_Rela *, bfd_vma, bfd *, asection *, bfd_byte *,
- bfd_boolean));
+ (struct bfd_link_info *, reloc_howto_type *, const Elf_Internal_Rela *,
+ bfd_vma, bfd *, asection *, bfd_byte *, bfd_boolean);
static bfd_boolean mips_elf_stub_section_p
- PARAMS ((bfd *, asection *));
+ (bfd *, asection *);
static void mips_elf_allocate_dynamic_relocations
- PARAMS ((bfd *, unsigned int));
+ (bfd *, unsigned int);
static bfd_boolean mips_elf_create_dynamic_relocation
- PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
- struct mips_elf_link_hash_entry *, asection *,
- bfd_vma, bfd_vma *, asection *));
-static void mips_set_isa_flags PARAMS ((bfd *));
-static INLINE char* elf_mips_abi_name PARAMS ((bfd *));
+ (bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
+ struct mips_elf_link_hash_entry *, asection *, bfd_vma,
+ bfd_vma *, asection *);
+static void mips_set_isa_flags
+ (bfd *);
+static INLINE char *elf_mips_abi_name
+ (bfd *);
static void mips_elf_irix6_finish_dynamic_symbol
- PARAMS ((bfd *, const char *, Elf_Internal_Sym *));
-static bfd_boolean mips_mach_extends_p PARAMS ((unsigned long, unsigned long));
-static bfd_boolean mips_32bit_flags_p PARAMS ((flagword));
-static INLINE hashval_t mips_elf_hash_bfd_vma PARAMS ((bfd_vma));
-static hashval_t mips_elf_got_entry_hash PARAMS ((const PTR));
-static int mips_elf_got_entry_eq PARAMS ((const PTR, const PTR));
+ (bfd *, const char *, Elf_Internal_Sym *);
+static bfd_boolean mips_mach_extends_p
+ (unsigned long, unsigned long);
+static bfd_boolean mips_32bit_flags_p
+ (flagword);
+static INLINE hashval_t mips_elf_hash_bfd_vma
+ (bfd_vma);
+static hashval_t mips_elf_got_entry_hash
+ (const void *);
+static int mips_elf_got_entry_eq
+ (const void *, const void *);
static bfd_boolean mips_elf_multi_got
- PARAMS ((bfd *, struct bfd_link_info *, struct mips_got_info *,
- asection *, bfd_size_type));
-static hashval_t mips_elf_multi_got_entry_hash PARAMS ((const PTR));
-static int mips_elf_multi_got_entry_eq PARAMS ((const PTR, const PTR));
-static hashval_t mips_elf_bfd2got_entry_hash PARAMS ((const PTR));
-static int mips_elf_bfd2got_entry_eq PARAMS ((const PTR, const PTR));
-static int mips_elf_make_got_per_bfd PARAMS ((void **, void *));
-static int mips_elf_merge_gots PARAMS ((void **, void *));
-static int mips_elf_set_global_got_offset PARAMS ((void**, void *));
-static int mips_elf_resolve_final_got_entry PARAMS ((void**, void *));
+ (bfd *, struct bfd_link_info *, struct mips_got_info *,
+ asection *, bfd_size_type);
+static hashval_t mips_elf_multi_got_entry_hash
+ (const void *);
+static int mips_elf_multi_got_entry_eq
+ (const void *, const void *);
+static hashval_t mips_elf_bfd2got_entry_hash
+ (const void *);
+static int mips_elf_bfd2got_entry_eq
+ (const void *, const void *);
+static int mips_elf_make_got_per_bfd
+ (void **, void *);
+static int mips_elf_merge_gots
+ (void **, void *);
+static int mips_elf_set_global_got_offset
+ (void **, void *);
+static int mips_elf_set_no_stub
+ (void **, void *);
+static int mips_elf_resolve_final_got_entry
+ (void **, void *);
static void mips_elf_resolve_final_got_entries
- PARAMS ((struct mips_got_info *));
+ (struct mips_got_info *);
static bfd_vma mips_elf_adjust_gp
- PARAMS ((bfd *, struct mips_got_info *, bfd *));
+ (bfd *, struct mips_got_info *, bfd *);
static struct mips_got_info *mips_elf_got_for_ibfd
- PARAMS ((struct mips_got_info *, bfd *));
+ (struct mips_got_info *, bfd *);
/* This will be used when we sort the dynamic relocation records. */
static bfd *reldyn_sorting_bfd;
/* The name of the options section. */
#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
- (ABI_64_P (abfd) ? ".MIPS.options" : ".options")
+ (NEWABI_P (abfd) ? ".MIPS.options" : ".options")
/* The name of the stub section. */
-#define MIPS_ELF_STUB_SECTION_NAME(abfd) \
- (ABI_64_P (abfd) ? ".MIPS.stubs" : ".stub")
+#define MIPS_ELF_STUB_SECTION_NAME(abfd) ".MIPS.stubs"
/* The size of an external REL relocation. */
#define MIPS_ELF_REL_SIZE(abfd) \
/* The default alignment for sections, as a power of two. */
#define MIPS_ELF_LOG_FILE_ALIGN(abfd) \
- (get_elf_backend_data (abfd)->s->file_align == 8 ? 3 : 2)
+ (get_elf_backend_data (abfd)->s->log_file_align)
/* Get word-sized data. */
#define MIPS_ELF_GET_WORD(abfd, ptr) \
: bfd_put_32 (abfd, val, ptr))
/* Add a dynamic symbol table-entry. */
-#ifdef BFD64
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
- (ABI_64_P (elf_hash_table (info)->dynobj) \
- ? bfd_elf64_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val) \
- : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#else
-#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
- (ABI_64_P (elf_hash_table (info)->dynobj) \
- ? (abort (), FALSE) \
- : bfd_elf32_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
-#endif
+#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
+ _bfd_elf_add_dynamic_entry (info, tag, val)
#define MIPS_ELF_RTYPE_TO_HOWTO(abfd, rtype, rela) \
(get_elf_backend_data (abfd)->elf_backend_mips_rtype_to_howto (rtype, rela))
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
from smaller values. Start with zero, widen, *then* decrement. */
#define MINUS_ONE (((bfd_vma)0) - 1)
+#define MINUS_TWO (((bfd_vma)0) - 2)
/* The number of local .got entries we reserve. */
#define MIPS_RESERVED_GOTNO (2)
offsets from $gp. */
#define MIPS_ELF_GOT_MAX_SIZE(abfd) (ELF_MIPS_GP_OFFSET(abfd) + 0x7fff)
-/* Instructions which appear in a stub. For some reason the stub is
- slightly different on an SGI system. */
+/* Instructions which appear in a stub. */
#define STUB_LW(abfd) \
((ABI_64_P (abfd) \
? 0xdf998010 /* ld t9,0x8010(gp) */ \
: 0x8f998010)) /* lw t9,0x8010(gp) */
#define STUB_MOVE(abfd) \
- (SGI_COMPAT (abfd) ? 0x03e07825 : 0x03e07821) /* move t7,ra */
-#define STUB_JALR 0x0320f809 /* jal t9 */
+ ((ABI_64_P (abfd) \
+ ? 0x03e0782d /* daddu t7,ra */ \
+ : 0x03e07821)) /* addu t7,ra */
+#define STUB_JALR 0x0320f809 /* jalr t9,ra */
#define STUB_LI16(abfd) \
- (SGI_COMPAT (abfd) ? 0x34180000 : 0x24180000) /* ori t8,zero,0 */
+ ((ABI_64_P (abfd) \
+ ? 0x64180000 /* daddiu t8,zero,0 */ \
+ : 0x24180000)) /* addiu t8,zero,0 */
#define MIPS_FUNCTION_STUB_SIZE (16)
/* The name of the dynamic interpreter. This is put in the .interp
#define mips_elf_link_hash_traverse(table, func, info) \
(elf_link_hash_traverse \
(&(table)->root, \
- (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+ (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
(info)))
/* Get the MIPS ELF linker hash table from a link_info structure. */
/* Create an entry in a MIPS ELF linker hash table. */
static struct bfd_hash_entry *
-mips_elf_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+mips_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table, const char *string)
{
struct mips_elf_link_hash_entry *ret =
(struct mips_elf_link_hash_entry *) entry;
/* Allocate the structure if it has not already been allocated by a
subclass. */
- if (ret == (struct mips_elf_link_hash_entry *) NULL)
- ret = ((struct mips_elf_link_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct mips_elf_link_hash_entry)));
- if (ret == (struct mips_elf_link_hash_entry *) NULL)
+ if (ret == NULL)
+ ret = bfd_hash_allocate (table, sizeof (struct mips_elf_link_hash_entry));
+ if (ret == NULL)
return (struct bfd_hash_entry *) ret;
/* Call the allocation method of the superclass. */
ret = ((struct mips_elf_link_hash_entry *)
_bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
- if (ret != (struct mips_elf_link_hash_entry *) NULL)
+ if (ret != NULL)
{
/* Set local fields. */
memset (&ret->esym, 0, sizeof (EXTR));
ret->esym.ifd = -2;
ret->possibly_dynamic_relocs = 0;
ret->readonly_reloc = FALSE;
- ret->min_dyn_reloc_index = 0;
ret->no_fn_stub = FALSE;
ret->fn_stub = NULL;
ret->need_fn_stub = FALSE;
}
bfd_boolean
-_bfd_mips_elf_new_section_hook (abfd, sec)
- bfd *abfd;
- asection *sec;
+_bfd_mips_elf_new_section_hook (bfd *abfd, asection *sec)
{
struct _mips_elf_section_data *sdata;
bfd_size_type amt = sizeof (*sdata);
- sdata = (struct _mips_elf_section_data *) bfd_zalloc (abfd, amt);
+ sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
return FALSE;
- sec->used_by_bfd = (PTR) sdata;
+ sec->used_by_bfd = sdata;
return _bfd_elf_new_section_hook (abfd, sec);
}
ecoff_debug_info structure. */
bfd_boolean
-_bfd_mips_elf_read_ecoff_info (abfd, section, debug)
- bfd *abfd;
- asection *section;
- struct ecoff_debug_info *debug;
+_bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
+ struct ecoff_debug_info *debug)
{
HDRR *symhdr;
const struct ecoff_debug_swap *swap;
- char *ext_hdr = NULL;
+ char *ext_hdr;
swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
memset (debug, 0, sizeof (*debug));
- ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
+ ext_hdr = bfd_malloc (swap->external_hdr_size);
if (ext_hdr == NULL && swap->external_hdr_size != 0)
goto error_return;
- if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
+ if (! bfd_get_section_contents (abfd, section, ext_hdr, 0,
swap->external_hdr_size))
goto error_return;
else \
{ \
bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
- debug->ptr = (type) bfd_malloc (amt); \
+ debug->ptr = bfd_malloc (amt); \
if (debug->ptr == NULL) \
goto error_return; \
- if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
+ if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0 \
|| bfd_bread (debug->ptr, amt, abfd) != amt) \
goto error_return; \
}
READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
- READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
- READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
- READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
- READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
+ READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
+ READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, void *);
+ READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, void *);
+ READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, void *);
READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
union aux_ext *);
READ (ss, cbSsOffset, issMax, sizeof (char), char *);
READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
- READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
- READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
- READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
+ READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, void *);
+ READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, void *);
+ READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, void *);
#undef READ
debug->fdr = NULL;
- debug->adjust = NULL;
return TRUE;
/* Swap RPDR (runtime procedure table entry) for output. */
static void
-ecoff_swap_rpdr_out (abfd, in, ex)
- bfd *abfd;
- const RPDR *in;
- struct rpdr_ext *ex;
+ecoff_swap_rpdr_out (bfd *abfd, const RPDR *in, struct rpdr_ext *ex)
{
H_PUT_S32 (abfd, in->adr, ex->p_adr);
H_PUT_32 (abfd, in->regmask, ex->p_regmask);
/* Create a runtime procedure table from the .mdebug section. */
static bfd_boolean
-mips_elf_create_procedure_table (handle, abfd, info, s, debug)
- PTR handle;
- bfd *abfd;
- struct bfd_link_info *info;
- asection *s;
- struct ecoff_debug_info *debug;
+mips_elf_create_procedure_table (void *handle, bfd *abfd,
+ struct bfd_link_info *info, asection *s,
+ struct ecoff_debug_info *debug)
{
const struct ecoff_debug_swap *swap;
HDRR *hdr = &debug->symbolic_header;
RPDR *rpdr, *rp;
struct rpdr_ext *erp;
- PTR rtproc;
+ void *rtproc;
struct pdr_ext *epdr;
struct sym_ext *esym;
char *ss, **sv;
{
size = swap->external_pdr_size;
- epdr = (struct pdr_ext *) bfd_malloc (size * count);
+ epdr = bfd_malloc (size * count);
if (epdr == NULL)
goto error_return;
- if (! _bfd_ecoff_get_accumulated_pdr (handle, (PTR) epdr))
+ if (! _bfd_ecoff_get_accumulated_pdr (handle, (bfd_byte *) epdr))
goto error_return;
size = sizeof (RPDR);
- rp = rpdr = (RPDR *) bfd_malloc (size * count);
+ rp = rpdr = bfd_malloc (size * count);
if (rpdr == NULL)
goto error_return;
size = sizeof (char *);
- sv = (char **) bfd_malloc (size * count);
+ sv = bfd_malloc (size * count);
if (sv == NULL)
goto error_return;
count = hdr->isymMax;
size = swap->external_sym_size;
- esym = (struct sym_ext *) bfd_malloc (size * count);
+ esym = bfd_malloc (size * count);
if (esym == NULL)
goto error_return;
- if (! _bfd_ecoff_get_accumulated_sym (handle, (PTR) esym))
+ if (! _bfd_ecoff_get_accumulated_sym (handle, (bfd_byte *) esym))
goto error_return;
count = hdr->issMax;
- ss = (char *) bfd_malloc (count);
+ ss = bfd_malloc (count);
if (ss == NULL)
goto error_return;
- if (! _bfd_ecoff_get_accumulated_ss (handle, (PTR) ss))
+ if (! _bfd_ecoff_get_accumulated_ss (handle, ss))
goto error_return;
count = hdr->ipdMax;
for (i = 0; i < (unsigned long) count; i++, rp++)
{
- (*swap->swap_pdr_in) (abfd, (PTR) (epdr + i), &pdr);
- (*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
+ (*swap->swap_pdr_in) (abfd, epdr + i, &pdr);
+ (*swap->swap_sym_in) (abfd, &esym[pdr.isym], &sym);
rp->adr = sym.value;
rp->regmask = pdr.regmask;
rp->regoffset = pdr.regoffset;
size = sizeof (struct rpdr_ext) * (count + 2) + sindex;
size = BFD_ALIGN (size, 16);
- rtproc = (PTR) bfd_alloc (abfd, size);
+ rtproc = bfd_alloc (abfd, size);
if (rtproc == NULL)
{
mips_elf_hash_table (info)->procedure_count = 0;
mips_elf_hash_table (info)->procedure_count = count + 2;
- erp = (struct rpdr_ext *) rtproc;
+ erp = rtproc;
memset (erp, 0, sizeof (struct rpdr_ext));
erp++;
str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
H_PUT_S32 (abfd, -1, (erp + count)->p_adr);
/* Set the size and contents of .rtproc section. */
- s->_raw_size = size;
- s->contents = (bfd_byte *) rtproc;
+ s->size = size;
+ s->contents = rtproc;
/* Skip this section later on (I don't think this currently
matters, but someday it might). */
- s->link_order_head = (struct bfd_link_order *) NULL;
+ s->link_order_head = NULL;
if (epdr != NULL)
free (epdr);
discard them. */
static bfd_boolean
-mips_elf_check_mips16_stubs (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data ATTRIBUTE_UNUSED;
+mips_elf_check_mips16_stubs (struct mips_elf_link_hash_entry *h,
+ void *data ATTRIBUTE_UNUSED)
{
if (h->root.root.type == bfd_link_hash_warning)
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
/* We don't need the fn_stub; the only references to this symbol
are 16 bit calls. Clobber the size to 0 to prevent it from
being included in the link. */
- h->fn_stub->_raw_size = 0;
- h->fn_stub->_cooked_size = 0;
+ h->fn_stub->size = 0;
h->fn_stub->flags &= ~SEC_RELOC;
h->fn_stub->reloc_count = 0;
h->fn_stub->flags |= SEC_EXCLUDE;
/* We don't need the call_stub; this is a 16 bit function, so
calls from other 16 bit functions are OK. Clobber the size
to 0 to prevent it from being included in the link. */
- h->call_stub->_raw_size = 0;
- h->call_stub->_cooked_size = 0;
+ h->call_stub->size = 0;
h->call_stub->flags &= ~SEC_RELOC;
h->call_stub->reloc_count = 0;
h->call_stub->flags |= SEC_EXCLUDE;
/* We don't need the call_stub; this is a 16 bit function, so
calls from other 16 bit functions are OK. Clobber the size
to 0 to prevent it from being included in the link. */
- h->call_fp_stub->_raw_size = 0;
- h->call_fp_stub->_cooked_size = 0;
+ h->call_fp_stub->size = 0;
h->call_fp_stub->flags &= ~SEC_RELOC;
h->call_fp_stub->reloc_count = 0;
h->call_fp_stub->flags |= SEC_EXCLUDE;
}
\f
bfd_reloc_status_type
-_bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp)
- bfd *abfd;
- asymbol *symbol;
- arelent *reloc_entry;
- asection *input_section;
- bfd_boolean relocateable;
- PTR data;
- bfd_vma gp;
+_bfd_mips_elf_gprel16_with_gp (bfd *abfd, asymbol *symbol,
+ arelent *reloc_entry, asection *input_section,
+ bfd_boolean relocatable, void *data, bfd_vma gp)
{
bfd_vma relocation;
- unsigned long insn;
- unsigned long val;
+ bfd_signed_vma val;
+ bfd_reloc_status_type status;
if (bfd_is_com_section (symbol->section))
relocation = 0;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
- if (reloc_entry->address > input_section->_cooked_size)
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
/* Set val to the offset into the section or symbol. */
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case occurs with the 64-bit MIPS ELF ABI. */
- val = reloc_entry->addend;
- }
- else
- {
- val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
- if (val & 0x8000)
- val -= 0x10000;
- }
+ val = reloc_entry->addend;
+
+ _bfd_mips_elf_sign_extend (val, 16);
/* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
+ are producing relocatable output, we don't want to do this for
an external symbol. */
- if (! relocateable
+ if (! relocatable
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
- insn = (insn & ~0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+ if (reloc_entry->howto->partial_inplace)
+ {
+ status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+ (bfd_byte *) data
+ + reloc_entry->address);
+ if (status != bfd_reloc_ok)
+ return status;
+ }
+ else
+ reloc_entry->addend = val;
+
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+}
+
+/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
+ R_MIPS_GOT16. REL is the relocation, INPUT_SECTION is the section
+ that contains the relocation field and DATA points to the start of
+ INPUT_SECTION. */
+
+struct mips_hi16
+{
+ struct mips_hi16 *next;
+ bfd_byte *data;
+ asection *input_section;
+ arelent rel;
+};
+
+/* FIXME: This should not be a static variable. */
+
+static struct mips_hi16 *mips_hi16_list;
+
+/* A howto special_function for REL *HI16 relocations. We can only
+ calculate the correct value once we've seen the partnering
+ *LO16 relocation, so just save the information for later.
+
+ The ABI requires that the *LO16 immediately follow the *HI16.
+ However, as a GNU extension, we permit an arbitrary number of
+ *HI16s to be associated with a single *LO16. This significantly
+ simplies the relocation handling in gcc. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+ asymbol *symbol ATTRIBUTE_UNUSED, void *data,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ struct mips_hi16 *n;
- if (relocateable)
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
+ n = bfd_malloc (sizeof *n);
+ if (n == NULL)
+ return bfd_reloc_outofrange;
+
+ n->next = mips_hi16_list;
+ n->data = data;
+ n->input_section = input_section;
+ n->rel = *reloc_entry;
+ mips_hi16_list = n;
+
+ if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
- else if ((long) val >= 0x8000 || (long) val < -0x8000)
- return bfd_reloc_overflow;
+ return bfd_reloc_ok;
+}
+
+/* A howto special_function for REL R_MIPS_GOT16 relocations. This is just
+ like any other 16-bit relocation when applied to global symbols, but is
+ treated in the same as R_MIPS_HI16 when applied to local symbols. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section,
+ bfd *output_bfd, char **error_message)
+{
+ if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (symbol))
+ || bfd_is_com_section (bfd_get_section (symbol)))
+ /* The relocation is against a global symbol. */
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
+
+ return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* A howto special_function for REL *LO16 relocations. The *LO16 itself
+ is a straightforward 16 bit inplace relocation, but we must deal with
+ any partnering high-part relocations as well. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section,
+ bfd *output_bfd, char **error_message)
+{
+ bfd_vma vallo;
+
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
+ vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+ while (mips_hi16_list != NULL)
+ {
+ bfd_reloc_status_type ret;
+ struct mips_hi16 *hi;
+
+ hi = mips_hi16_list;
+
+ /* R_MIPS_GOT16 relocations are something of a special case. We
+ want to install the addend in the same way as for a R_MIPS_HI16
+ relocation (with a rightshift of 16). However, since GOT16
+ relocations can also be used with global symbols, their howto
+ has a rightshift of 0. */
+ if (hi->rel.howto->type == R_MIPS_GOT16)
+ hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);
+
+ /* VALLO is a signed 16-bit number. Bias it by 0x8000 so that any
+ carry or borrow will induce a change of +1 or -1 in the high part. */
+ hi->rel.addend += (vallo + 0x8000) & 0xffff;
+
+ ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
+ hi->input_section, output_bfd,
+ error_message);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ mips_hi16_list = hi->next;
+ free (hi);
+ }
+
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
+}
+
+/* A generic howto special_function. This calculates and installs the
+ relocation itself, thus avoiding the oft-discussed problems in
+ bfd_perform_relocation and bfd_install_relocation. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+ asymbol *symbol, void *data ATTRIBUTE_UNUSED,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ bfd_signed_vma val;
+ bfd_reloc_status_type status;
+ bfd_boolean relocatable;
+
+ relocatable = (output_bfd != NULL);
+
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ return bfd_reloc_outofrange;
+
+ /* Build up the field adjustment in VAL. */
+ val = 0;
+ if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
+ {
+ /* Either we're calculating the final field value or we have a
+ relocation against a section symbol. Add in the section's
+ offset or address. */
+ val += symbol->section->output_section->vma;
+ val += symbol->section->output_offset;
+ }
+
+ if (!relocatable)
+ {
+ /* We're calculating the final field value. Add in the symbol's value
+ and, if pc-relative, subtract the address of the field itself. */
+ val += symbol->value;
+ if (reloc_entry->howto->pc_relative)
+ {
+ val -= input_section->output_section->vma;
+ val -= input_section->output_offset;
+ val -= reloc_entry->address;
+ }
+ }
+
+ /* VAL is now the final adjustment. If we're keeping this relocation
+ in the output file, and if the relocation uses a separate addend,
+ we just need to add VAL to that addend. Otherwise we need to add
+ VAL to the relocation field itself. */
+ if (relocatable && !reloc_entry->howto->partial_inplace)
+ reloc_entry->addend += val;
+ else
+ {
+ /* Add in the separate addend, if any. */
+ val += reloc_entry->addend;
+
+ /* Add VAL to the relocation field. */
+ status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+ (bfd_byte *) data
+ + reloc_entry->address);
+ if (status != bfd_reloc_ok)
+ return status;
+ }
+
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
on the equivalence of the two elements of the union. */
static void
-bfd_mips_elf32_swap_gptab_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_gptab *ex;
- Elf32_gptab *in;
+bfd_mips_elf32_swap_gptab_in (bfd *abfd, const Elf32_External_gptab *ex,
+ Elf32_gptab *in)
{
in->gt_entry.gt_g_value = H_GET_32 (abfd, ex->gt_entry.gt_g_value);
in->gt_entry.gt_bytes = H_GET_32 (abfd, ex->gt_entry.gt_bytes);
}
static void
-bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_gptab *in;
- Elf32_External_gptab *ex;
+bfd_mips_elf32_swap_gptab_out (bfd *abfd, const Elf32_gptab *in,
+ Elf32_External_gptab *ex)
{
H_PUT_32 (abfd, in->gt_entry.gt_g_value, ex->gt_entry.gt_g_value);
H_PUT_32 (abfd, in->gt_entry.gt_bytes, ex->gt_entry.gt_bytes);
}
static void
-bfd_elf32_swap_compact_rel_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_compact_rel *in;
- Elf32_External_compact_rel *ex;
+bfd_elf32_swap_compact_rel_out (bfd *abfd, const Elf32_compact_rel *in,
+ Elf32_External_compact_rel *ex)
{
H_PUT_32 (abfd, in->id1, ex->id1);
H_PUT_32 (abfd, in->num, ex->num);
}
static void
-bfd_elf32_swap_crinfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_crinfo *in;
- Elf32_External_crinfo *ex;
+bfd_elf32_swap_crinfo_out (bfd *abfd, const Elf32_crinfo *in,
+ Elf32_External_crinfo *ex)
{
unsigned long l;
H_PUT_32 (abfd, in->konst, ex->konst);
H_PUT_32 (abfd, in->vaddr, ex->vaddr);
}
-
-#if 0
-/* Swap in an MSYM entry. */
-
-static void
-bfd_mips_elf_swap_msym_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_Msym *ex;
- Elf32_Internal_Msym *in;
-{
- in->ms_hash_value = H_GET_32 (abfd, ex->ms_hash_value);
- in->ms_info = H_GET_32 (abfd, ex->ms_info);
-}
-#endif
-/* Swap out an MSYM entry. */
-
-static void
-bfd_mips_elf_swap_msym_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_Internal_Msym *in;
- Elf32_External_Msym *ex;
-{
- H_PUT_32 (abfd, in->ms_hash_value, ex->ms_hash_value);
- H_PUT_32 (abfd, in->ms_info, ex->ms_info);
-}
\f
/* A .reginfo section holds a single Elf32_RegInfo structure. These
routines swap this structure in and out. They are used outside of
BFD, so they are globally visible. */
void
-bfd_mips_elf32_swap_reginfo_in (abfd, ex, in)
- bfd *abfd;
- const Elf32_External_RegInfo *ex;
- Elf32_RegInfo *in;
+bfd_mips_elf32_swap_reginfo_in (bfd *abfd, const Elf32_External_RegInfo *ex,
+ Elf32_RegInfo *in)
{
in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
in->ri_cprmask[0] = H_GET_32 (abfd, ex->ri_cprmask[0]);
}
void
-bfd_mips_elf32_swap_reginfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf32_RegInfo *in;
- Elf32_External_RegInfo *ex;
+bfd_mips_elf32_swap_reginfo_out (bfd *abfd, const Elf32_RegInfo *in,
+ Elf32_External_RegInfo *ex)
{
H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
H_PUT_32 (abfd, in->ri_cprmask[0], ex->ri_cprmask[0]);
without worrying about whether the 64 bit ABI has been included. */
void
-bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
- bfd *abfd;
- const Elf64_External_RegInfo *ex;
- Elf64_Internal_RegInfo *in;
+bfd_mips_elf64_swap_reginfo_in (bfd *abfd, const Elf64_External_RegInfo *ex,
+ Elf64_Internal_RegInfo *in)
{
in->ri_gprmask = H_GET_32 (abfd, ex->ri_gprmask);
in->ri_pad = H_GET_32 (abfd, ex->ri_pad);
}
void
-bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
- bfd *abfd;
- const Elf64_Internal_RegInfo *in;
- Elf64_External_RegInfo *ex;
+bfd_mips_elf64_swap_reginfo_out (bfd *abfd, const Elf64_Internal_RegInfo *in,
+ Elf64_External_RegInfo *ex)
{
H_PUT_32 (abfd, in->ri_gprmask, ex->ri_gprmask);
H_PUT_32 (abfd, in->ri_pad, ex->ri_pad);
/* Swap in an options header. */
void
-bfd_mips_elf_swap_options_in (abfd, ex, in)
- bfd *abfd;
- const Elf_External_Options *ex;
- Elf_Internal_Options *in;
+bfd_mips_elf_swap_options_in (bfd *abfd, const Elf_External_Options *ex,
+ Elf_Internal_Options *in)
{
in->kind = H_GET_8 (abfd, ex->kind);
in->size = H_GET_8 (abfd, ex->size);
/* Swap out an options header. */
void
-bfd_mips_elf_swap_options_out (abfd, in, ex)
- bfd *abfd;
- const Elf_Internal_Options *in;
- Elf_External_Options *ex;
+bfd_mips_elf_swap_options_out (bfd *abfd, const Elf_Internal_Options *in,
+ Elf_External_Options *ex)
{
H_PUT_8 (abfd, in->kind, ex->kind);
H_PUT_8 (abfd, in->size, ex->size);
entries by increasing r_symndx value. */
static int
-sort_dynamic_relocs (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
+sort_dynamic_relocs (const void *arg1, const void *arg2)
{
Elf_Internal_Rela int_reloc1;
Elf_Internal_Rela int_reloc2;
/* Like sort_dynamic_relocs, but used for elf64 relocations. */
static int
-sort_dynamic_relocs_64 (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
+sort_dynamic_relocs_64 (const void *arg1, const void *arg2)
{
Elf_Internal_Rela int_reloc1[3];
Elf_Internal_Rela int_reloc2[3];
when generating a final executable. */
static bfd_boolean
-mips_elf_output_extsym (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data;
+mips_elf_output_extsym (struct mips_elf_link_hash_entry *h, void *data)
{
- struct extsym_info *einfo = (struct extsym_info *) data;
+ struct extsym_info *einfo = data;
bfd_boolean strip;
asection *sec, *output_section;
if (h->root.indx == -2)
strip = FALSE;
- else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ else if ((h->root.def_dynamic
+ || h->root.ref_dynamic)
+ && !h->root.def_regular
+ && !h->root.ref_regular)
strip = TRUE;
else if (einfo->info->strip == strip_all
|| (einfo->info->strip == strip_some
else
h->esym.asym.value = 0;
}
- else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ else if (h->root.needs_plt)
{
struct mips_elf_link_hash_entry *hd = h;
bfd_boolean no_fn_stub = h->no_fn_stub;
/* A comparison routine used to sort .gptab entries. */
static int
-gptab_compare (p1, p2)
- const PTR p1;
- const PTR p2;
+gptab_compare (const void *p1, const void *p2)
{
- const Elf32_gptab *a1 = (const Elf32_gptab *) p1;
- const Elf32_gptab *a2 = (const Elf32_gptab *) p2;
+ const Elf32_gptab *a1 = p1;
+ const Elf32_gptab *a2 = p2;
return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
}
hash number. */
static INLINE hashval_t
-mips_elf_hash_bfd_vma (addr)
- bfd_vma addr;
+mips_elf_hash_bfd_vma (bfd_vma addr)
{
#ifdef BFD64
return addr + (addr >> 32);
union members. */
static hashval_t
-mips_elf_got_entry_hash (entry_)
- const PTR entry_;
+mips_elf_got_entry_hash (const void *entry_)
{
const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
}
static int
-mips_elf_got_entry_eq (entry1, entry2)
- const PTR entry1;
- const PTR entry2;
+mips_elf_got_entry_eq (const void *entry1, const void *entry2)
{
const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
accordingly. */
static hashval_t
-mips_elf_multi_got_entry_hash (entry_)
- const PTR entry_;
+mips_elf_multi_got_entry_hash (const void *entry_)
{
const struct mips_got_entry *entry = (struct mips_got_entry *)entry_;
}
static int
-mips_elf_multi_got_entry_eq (entry1, entry2)
- const PTR entry1;
- const PTR entry2;
+mips_elf_multi_got_entry_eq (const void *entry1, const void *entry2)
{
const struct mips_got_entry *e1 = (struct mips_got_entry *)entry1;
const struct mips_got_entry *e2 = (struct mips_got_entry *)entry2;
/* Returns the dynamic relocation section for DYNOBJ. */
static asection *
-mips_elf_rel_dyn_section (dynobj, create_p)
- bfd *dynobj;
- bfd_boolean create_p;
+mips_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
{
static const char dname[] = ".rel.dyn";
asection *sreloc;
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, sreloc,
- 4))
+ MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
return NULL;
}
return sreloc;
/* Returns the GOT section for ABFD. */
static asection *
-mips_elf_got_section (abfd, maybe_excluded)
- bfd *abfd;
- bfd_boolean maybe_excluded;
+mips_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
{
asection *sgot = bfd_get_section_by_name (abfd, ".got");
if (sgot == NULL
section. */
static struct mips_got_info *
-mips_elf_got_info (abfd, sgotp)
- bfd *abfd;
- asection **sgotp;
+mips_elf_got_info (bfd *abfd, asection **sgotp)
{
asection *sgot;
struct mips_got_info *g;
-1 if no satisfactory GOT offset can be found. */
static bfd_vma
-mips_elf_local_got_index (abfd, ibfd, info, value)
- bfd *abfd, *ibfd;
- struct bfd_link_info *info;
- bfd_vma value;
+mips_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+ bfd_vma value)
{
asection *sgot;
struct mips_got_info *g;
/* Returns the GOT index for the global symbol indicated by H. */
static bfd_vma
-mips_elf_global_got_index (abfd, ibfd, h)
- bfd *abfd, *ibfd;
- struct elf_link_hash_entry *h;
+mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h)
{
bfd_vma index;
asection *sgot;
if (g->bfd2got && ibfd)
{
struct mips_got_entry e, *p;
-
+
BFD_ASSERT (h->dynindx >= 0);
g = mips_elf_got_for_ibfd (g, ibfd);
e.symndx = -1;
e.d.h = (struct mips_elf_link_hash_entry *)h;
- p = (struct mips_got_entry *) htab_find (g->got_entries, &e);
+ p = htab_find (g->got_entries, &e);
BFD_ASSERT (p->gotidx > 0);
return p->gotidx;
BFD_ASSERT (h->dynindx >= global_got_dynindx);
index = ((h->dynindx - global_got_dynindx + g->local_gotno)
* MIPS_ELF_GOT_SIZE (abfd));
- BFD_ASSERT (index < sgot->_raw_size);
+ BFD_ASSERT (index < sgot->size);
return index;
}
OFFSETP, if it is non-NULL. */
static bfd_vma
-mips_elf_got_page (abfd, ibfd, info, value, offsetp)
- bfd *abfd, *ibfd;
- struct bfd_link_info *info;
- bfd_vma value;
- bfd_vma *offsetp;
+mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+ bfd_vma value, bfd_vma *offsetp)
{
asection *sgot;
struct mips_got_info *g;
if (!entry)
return MINUS_ONE;
-
+
index = entry->gotidx;
if (offsetp)
for value. Return the index into the GOT for this entry. */
static bfd_vma
-mips_elf_got16_entry (abfd, ibfd, info, value, external)
- bfd *abfd, *ibfd;
- struct bfd_link_info *info;
- bfd_vma value;
- bfd_boolean external;
+mips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
+ bfd_vma value, bfd_boolean external)
{
asection *sgot;
struct mips_got_info *g;
in the GOT. */
static bfd_vma
-mips_elf_got_offset_from_index (dynobj, output_bfd, input_bfd, index)
- bfd *dynobj;
- bfd *output_bfd;
- bfd *input_bfd;
- bfd_vma index;
+mips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
+ bfd *input_bfd, bfd_vma index)
{
asection *sgot;
bfd_vma gp;
g = mips_elf_got_info (dynobj, &sgot);
gp = _bfd_get_gp_value (output_bfd)
+ mips_elf_adjust_gp (output_bfd, g, input_bfd);
-
+
return sgot->output_section->vma + sgot->output_offset + index - gp;
}
or -1 if it could not be created. */
static struct mips_got_entry *
-mips_elf_create_local_got_entry (abfd, ibfd, gg, sgot, value)
- bfd *abfd, *ibfd;
- struct mips_got_info *gg;
- asection *sgot;
- bfd_vma value;
+mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd,
+ struct mips_got_info *gg,
+ asection *sgot, bfd_vma value)
{
struct mips_got_entry entry, **loc;
struct mips_got_info *g;
INSERT);
if (*loc)
return *loc;
-
+
entry.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
*loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
if (! *loc)
return NULL;
-
+
memcpy (*loc, &entry, sizeof entry);
if (g->assigned_gotno >= g->local_gotno)
section symbols are added and the count is higher. */
static bfd_boolean
-mips_elf_sort_hash_table (info, max_local)
- struct bfd_link_info *info;
- unsigned long max_local;
+mips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
{
struct mips_elf_hash_sort_data hsd;
struct mips_got_info *g;
g = mips_elf_got_info (dynobj, NULL);
hsd.low = NULL;
- hsd.max_unref_got_dynindx =
+ hsd.max_unref_got_dynindx =
hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
/* In the multi-got case, assigned_gotno of the master got_info
indicate the number of entries that aren't referenced in the
index. */
static bfd_boolean
-mips_elf_sort_hash_table_f (h, data)
- struct mips_elf_link_hash_entry *h;
- PTR data;
+mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
{
- struct mips_elf_hash_sort_data *hsd
- = (struct mips_elf_hash_sort_data *) data;
+ struct mips_elf_hash_sort_data *hsd = data;
if (h->root.root.type == bfd_link_hash_warning)
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
posterity. */
static bfd_boolean
-mips_elf_record_global_got_symbol (h, abfd, info, g)
- struct elf_link_hash_entry *h;
- bfd *abfd;
- struct bfd_link_info *info;
- struct mips_got_info *g;
+mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
+ bfd *abfd, struct bfd_link_info *info,
+ struct mips_got_info *g)
{
struct mips_got_entry entry, **loc;
_bfd_mips_elf_hide_symbol (info, h, TRUE);
break;
}
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (! *loc)
return FALSE;
-
+
entry.gotidx = -1;
memcpy (*loc, &entry, sizeof entry);
SYMNDX in input bfd ABDF, plus ADDEND. */
static bfd_boolean
-mips_elf_record_local_got_symbol (abfd, symndx, addend, g)
- bfd *abfd;
- long symndx;
- bfd_vma addend;
- struct mips_got_info *g;
+mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
+ struct mips_got_info *g)
{
struct mips_got_entry entry, **loc;
if (! *loc)
return FALSE;
-
+
memcpy (*loc, &entry, sizeof entry);
return TRUE;
/* Compute the hash value of the bfd in a bfd2got hash entry. */
static hashval_t
-mips_elf_bfd2got_entry_hash (entry_)
- const PTR entry_;
+mips_elf_bfd2got_entry_hash (const void *entry_)
{
const struct mips_elf_bfd2got_hash *entry
= (struct mips_elf_bfd2got_hash *)entry_;
/* Check whether two hash entries have the same bfd. */
static int
-mips_elf_bfd2got_entry_eq (entry1, entry2)
- const PTR entry1;
- const PTR entry2;
+mips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
{
const struct mips_elf_bfd2got_hash *e1
= (const struct mips_elf_bfd2got_hash *)entry1;
be the master GOT data. */
static struct mips_got_info *
-mips_elf_got_for_ibfd (g, ibfd)
- struct mips_got_info *g;
- bfd *ibfd;
+mips_elf_got_for_ibfd (struct mips_got_info *g, bfd *ibfd)
{
struct mips_elf_bfd2got_hash e, *p;
return g;
e.bfd = ibfd;
- p = (struct mips_elf_bfd2got_hash *) htab_find (g->bfd2got, &e);
+ p = htab_find (g->bfd2got, &e);
return p ? p->g : NULL;
}
bfd requires. */
static int
-mips_elf_make_got_per_bfd (entryp, p)
- void **entryp;
- void *p;
+mips_elf_make_got_per_bfd (void **entryp, void *p)
{
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
struct mips_elf_got_per_bfd_arg *arg = (struct mips_elf_got_per_bfd_arg *)p;
struct mips_got_info *g;
struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
void **bfdgotp;
-
+
/* Find the got_info for this GOT entry's input bfd. Create one if
none exists. */
bfdgot_entry.bfd = entry->abfd;
g->local_gotno = 0;
g->assigned_gotno = -1;
g->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
- mips_elf_multi_got_entry_eq,
- (htab_del) NULL);
+ mips_elf_multi_got_entry_eq, NULL);
if (g->got_entries == NULL)
{
arg->obfd = 0;
entryp = htab_find_slot (g->got_entries, entry, INSERT);
if (*entryp != NULL)
return 1;
-
+
*entryp = entry;
if (entry->symndx >= 0 || entry->d.h->forced_local)
and then make make the new got current. */
static int
-mips_elf_merge_gots (bfd2got_, p)
- void **bfd2got_;
- void *p;
+mips_elf_merge_gots (void **bfd2got_, void *p)
{
struct mips_elf_bfd2got_hash *bfd2got
= (struct mips_elf_bfd2got_hash *)*bfd2got_;
unsigned int lcount = bfd2got->g->local_gotno;
unsigned int gcount = bfd2got->g->global_gotno;
unsigned int maxcnt = arg->max_count;
-
+
/* If we don't have a primary GOT and this is not too big, use it as
a starting point for the primary GOT. */
if (! arg->primary && lcount + gcount <= maxcnt)
got entries, since they're all in the master got_entries hash
table anyway. */
- BFD_ASSERT (old_lcount + lcount == arg->primary->local_gotno);
+ BFD_ASSERT (old_lcount + lcount >= arg->primary->local_gotno);
BFD_ASSERT (old_gcount + gcount >= arg->primary->global_gotno);
arg->primary_count = arg->primary->local_gotno
htab_delete (g->got_entries);
- BFD_ASSERT (old_lcount + lcount == arg->current->local_gotno);
+ BFD_ASSERT (old_lcount + lcount >= arg->current->local_gotno);
BFD_ASSERT (old_gcount + gcount >= arg->current->global_gotno);
arg->current_count = arg->current->local_gotno
{
bfd2got->g->next = arg->current;
arg->current = bfd2got->g;
-
+
arg->current_count = lcount + gcount;
}
first available global GOT entry in G. VALUE must contain the size
of a GOT entry in bytes. For each global GOT entry that requires a
dynamic relocation, NEEDED_RELOCS is incremented, and the symbol is
- marked as not elligible for lazy resolution through a function
+ marked as not eligible for lazy resolution through a function
stub. */
static int
-mips_elf_set_global_got_offset (entryp, p)
- void **entryp;
- void *p;
+mips_elf_set_global_got_offset (void **entryp, void *p)
{
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
struct mips_elf_set_global_got_offset_arg *arg
BFD_ASSERT (g->global_gotsym == NULL);
entry->gotidx = arg->value * (long) g->assigned_gotno++;
- /* We can't do lazy update of GOT entries for
- non-primary GOTs since the PLT entries don't use the
- right offsets, so punt at it for now. */
- entry->d.h->no_fn_stub = TRUE;
if (arg->info->shared
|| (elf_hash_table (arg->info)->dynamic_sections_created
- && ((entry->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((entry->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ && entry->d.h->root.def_dynamic
+ && !entry->d.h->root.def_regular))
++arg->needed_relocs;
}
else
return 1;
}
+/* Mark any global symbols referenced in the GOT we are iterating over
+ as inelligible for lazy resolution stubs. */
+static int
+mips_elf_set_no_stub (void **entryp, void *p ATTRIBUTE_UNUSED)
+{
+ struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
+
+ if (entry->abfd != NULL
+ && entry->symndx == -1
+ && entry->d.h->root.dynindx != -1)
+ entry->d.h->no_fn_stub = TRUE;
+
+ return 1;
+}
+
/* Follow indirect and warning hash entries so that each got entry
points to the final symbol definition. P must point to a pointer
to the hash table we're traversing. Since this traversal may
we've made a potentially-destructive change to the hash table, so
the traversal must be restarted. */
static int
-mips_elf_resolve_final_got_entry (entryp, p)
- void **entryp;
- void *p;
+mips_elf_resolve_final_got_entry (void **entryp, void *p)
{
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
htab_t got_entries = *(htab_t *)p;
if (entry->d.h == h)
return 1;
-
+
entry->d.h = h;
/* If we can't find this entry with the new bfd hash, re-insert
/* We might want to decrement the global_gotno count, but it's
either too early or too late for that at this point. */
}
-
+
return 1;
}
/* Turn indirect got entries in a got_entries table into their final
locations. */
static void
-mips_elf_resolve_final_got_entries (g)
- struct mips_got_info *g;
+mips_elf_resolve_final_got_entries (struct mips_got_info *g)
{
htab_t got_entries;
/* Return the offset of an input bfd IBFD's GOT from the beginning of
the primary GOT. */
static bfd_vma
-mips_elf_adjust_gp (abfd, g, ibfd)
- bfd *abfd;
- struct mips_got_info *g;
- bfd *ibfd;
+mips_elf_adjust_gp (bfd *abfd, struct mips_got_info *g, bfd *ibfd)
{
if (g->bfd2got == NULL)
return 0;
BFD_ASSERT (g->next);
g = g->next;
-
+
return (g->local_gotno + g->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
}
a sequence of GOTs, each one 16-bit addressable. */
static bfd_boolean
-mips_elf_multi_got (abfd, info, g, got, pages)
- bfd *abfd;
- struct bfd_link_info *info;
- struct mips_got_info *g;
- asection *got;
- bfd_size_type pages;
+mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
+ struct mips_got_info *g, asection *got,
+ bfd_size_type pages)
{
struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
unsigned int assign;
g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
- mips_elf_bfd2got_entry_eq,
- (htab_del) NULL);
+ mips_elf_bfd2got_entry_eq, NULL);
if (g->bfd2got == NULL)
return FALSE;
g->next->assigned_gotno = 0;
g->next->got_entries = htab_try_create (1, mips_elf_multi_got_entry_hash,
mips_elf_multi_got_entry_eq,
- (htab_del) NULL);
+ NULL);
if (g->next->got_entries == NULL)
return FALSE;
g->next->bfd2got = NULL;
{
struct mips_elf_bfd2got_hash *bfdgot;
void **bfdgotp;
-
+
bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
(abfd, sizeof (struct mips_elf_bfd2got_hash));
the cache. Also, knowing that every external symbol has a GOT
helps speed up the resolution of local symbols too, so GNU/Linux
follows IRIX's practice.
-
+
The number 2 is used by mips_elf_sort_hash_table_f to count
global GOT symbols that are unreferenced in the primary GOT, with
an initial dynamic index computed from gg->assigned_gotno, where
g->next = gg->next;
gg->next = g;
g = gn;
+
+ /* Mark global symbols in every non-primary GOT as ineligible for
+ stubs. */
+ if (g)
+ htab_traverse (g->got_entries, mips_elf_set_no_stub, NULL);
}
while (g);
- got->_raw_size = (gg->next->local_gotno
+ got->size = (gg->next->local_gotno
+ gg->next->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
-
+
return TRUE;
}
-
+
\f
/* Returns the first relocation of type r_type found, beginning with
RELOCATION. RELEND is one-past-the-end of the relocation table. */
static const Elf_Internal_Rela *
-mips_elf_next_relocation (abfd, r_type, relocation, relend)
- bfd *abfd ATTRIBUTE_UNUSED;
- unsigned int r_type;
- const Elf_Internal_Rela *relocation;
- const Elf_Internal_Rela *relend;
-{
- /* According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must be
- immediately following. However, for the IRIX6 ABI, the next
- relocation may be a composed relocation consisting of several
- relocations for the same address. In that case, the R_MIPS_LO16
- relocation may occur as one of these. We permit a similar
- extension in general, as that is useful for GCC. */
+mips_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
+ const Elf_Internal_Rela *relocation,
+ const Elf_Internal_Rela *relend)
+{
while (relocation < relend)
{
if (ELF_R_TYPE (abfd, relocation->r_info) == r_type)
/* Return whether a relocation is against a local symbol. */
static bfd_boolean
-mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
- check_forced)
- bfd *input_bfd;
- const Elf_Internal_Rela *relocation;
- asection **local_sections;
- bfd_boolean check_forced;
+mips_elf_local_relocation_p (bfd *input_bfd,
+ const Elf_Internal_Rela *relocation,
+ asection **local_sections,
+ bfd_boolean check_forced)
{
unsigned long r_symndx;
Elf_Internal_Shdr *symtab_hdr;
while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning)
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
- if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ if (h->root.forced_local)
return TRUE;
}
\f
/* Sign-extend VALUE, which has the indicated number of BITS. */
-static bfd_vma
-mips_elf_sign_extend (value, bits)
- bfd_vma value;
- int bits;
+bfd_vma
+_bfd_mips_elf_sign_extend (bfd_vma value, int bits)
{
if (value & ((bfd_vma) 1 << (bits - 1)))
/* VALUE is negative. */
}
/* Return non-zero if the indicated VALUE has overflowed the maximum
- range expressable by a signed number with the indicated number of
+ range expressible by a signed number with the indicated number of
BITS. */
static bfd_boolean
-mips_elf_overflow_p (value, bits)
- bfd_vma value;
- int bits;
+mips_elf_overflow_p (bfd_vma value, int bits)
{
bfd_signed_vma svalue = (bfd_signed_vma) value;
/* Calculate the %high function. */
static bfd_vma
-mips_elf_high (value)
- bfd_vma value;
+mips_elf_high (bfd_vma value)
{
return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff;
}
/* Calculate the %higher function. */
static bfd_vma
-mips_elf_higher (value)
- bfd_vma value ATTRIBUTE_UNUSED;
+mips_elf_higher (bfd_vma value ATTRIBUTE_UNUSED)
{
#ifdef BFD64
return ((value + (bfd_vma) 0x80008000) >> 32) & 0xffff;
#else
abort ();
- return (bfd_vma) -1;
+ return MINUS_ONE;
#endif
}
/* Calculate the %highest function. */
static bfd_vma
-mips_elf_highest (value)
- bfd_vma value ATTRIBUTE_UNUSED;
+mips_elf_highest (bfd_vma value ATTRIBUTE_UNUSED)
{
#ifdef BFD64
return ((value + (((bfd_vma) 0x8000 << 32) | 0x80008000)) >> 48) & 0xffff;
#else
abort ();
- return (bfd_vma) -1;
+ return MINUS_ONE;
#endif
}
\f
/* Create the .compact_rel section. */
static bfd_boolean
-mips_elf_create_compact_rel_section (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
+mips_elf_create_compact_rel_section
+ (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
flagword flags;
register asection *s;
MIPS_ELF_LOG_FILE_ALIGN (abfd)))
return FALSE;
- s->_raw_size = sizeof (Elf32_External_compact_rel);
+ s->size = sizeof (Elf32_External_compact_rel);
}
return TRUE;
/* Create the .got section to hold the global offset table. */
static bfd_boolean
-mips_elf_create_got_section (abfd, info, maybe_exclude)
- bfd *abfd;
- struct bfd_link_info *info;
- bfd_boolean maybe_exclude;
+mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info,
+ bfd_boolean maybe_exclude)
{
flagword flags;
register asection *s;
if (maybe_exclude)
flags |= SEC_EXCLUDE;
+ /* We have to use an alignment of 2**4 here because this is hardcoded
+ in the function stub generation and in the linker script. */
s = bfd_make_section (abfd, ".got");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags)
bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, FALSE,
- get_elf_backend_data (abfd)->collect, &bh)))
+ 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_OBJECT;
if (info->shared
- && ! bfd_elf32_link_record_dynamic_symbol (info, h))
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
amt = sizeof (struct mips_got_info);
- g = (struct mips_got_info *) bfd_alloc (abfd, amt);
+ g = bfd_alloc (abfd, amt);
if (g == NULL)
return FALSE;
g->global_gotsym = NULL;
+ g->global_gotno = 0;
g->local_gotno = MIPS_RESERVED_GOTNO;
g->assigned_gotno = MIPS_RESERVED_GOTNO;
g->bfd2got = NULL;
g->next = NULL;
g->got_entries = htab_try_create (1, mips_elf_got_entry_hash,
- mips_elf_got_entry_eq,
- (htab_del) NULL);
+ mips_elf_got_entry_eq, NULL);
if (g->got_entries == NULL)
return FALSE;
mips_elf_section_data (s)->u.got_info = g;
return TRUE;
}
-
-/* Returns the .msym section for ABFD, creating it if it does not
- already exist. Returns NULL to indicate error. */
-
-static asection *
-mips_elf_create_msym_section (abfd)
- bfd *abfd;
-{
- asection *s;
-
- s = bfd_get_section_by_name (abfd, ".msym");
- if (!s)
- {
- s = bfd_make_section (abfd, ".msym");
- if (!s
- || !bfd_set_section_flags (abfd, s,
- SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || !bfd_set_section_alignment (abfd, s,
- MIPS_ELF_LOG_FILE_ALIGN (abfd)))
- return NULL;
- }
-
- return s;
-}
\f
/* Calculate the value produced by the RELOCATION (which comes from
the INPUT_BFD). The ADDEND is the addend to use for this
overflow occurs, and bfd_reloc_ok to indicate success. */
static bfd_reloc_status_type
-mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
- relocation, addend, howto, local_syms,
- local_sections, valuep, namep,
- require_jalxp, save_addend)
- bfd *abfd;
- bfd *input_bfd;
- asection *input_section;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *relocation;
- bfd_vma addend;
- reloc_howto_type *howto;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
- bfd_vma *valuep;
- const char **namep;
- bfd_boolean *require_jalxp;
- bfd_boolean save_addend;
+mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
+ asection *input_section,
+ struct bfd_link_info *info,
+ const Elf_Internal_Rela *relocation,
+ bfd_vma addend, reloc_howto_type *howto,
+ Elf_Internal_Sym *local_syms,
+ asection **local_sections, bfd_vma *valuep,
+ const char **namep, bfd_boolean *require_jalxp,
+ bfd_boolean save_addend)
{
/* The eventual value we will return. */
bfd_vma value;
}
else
{
+ /* ??? Could we use RELOC_FOR_GLOBAL_SYMBOL here ? */
+
/* For global symbols we look up the symbol in the hash-table. */
h = ((struct mips_elf_link_hash_entry *)
elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
/* See if this is the special _gp_disp symbol. Note that such a
symbol must always be a global symbol. */
- if (strcmp (h->root.root.root.string, "_gp_disp") == 0
+ if (strcmp (*namep, "_gp_disp") == 0
&& ! NEWABI_P (input_bfd))
{
/* Relocations against _gp_disp are permitted only with
and check to see if they exist by looking at their
addresses. */
symbol = 0;
- else if (info->shared
- && !info->no_undefined
+ else if (info->unresolved_syms_in_objects == RM_IGNORE
&& ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
symbol = 0;
- else if (strcmp (h->root.root.root.string, "_DYNAMIC_LINK") == 0 ||
- strcmp (h->root.root.root.string, "_DYNAMIC_LINKING") == 0)
+ else if (strcmp (*namep, SGI_COMPAT (input_bfd)
+ ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING") == 0)
{
/* If this is a dynamic link, we should have created a
_DYNAMIC_LINK symbol or _DYNAMIC_LINKING(for normal mips) symbol
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.root.string, input_bfd,
input_section, relocation->r_offset,
- (!info->shared || info->no_undefined
- || ELF_ST_VISIBILITY (h->root.other)))))
+ (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+ || ELF_ST_VISIBILITY (h->root.other))))
return bfd_reloc_undefined;
symbol = 0;
}
/* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
need to redirect the call to the stub, unless we're already *in*
a stub. */
- if (r_type != R_MIPS16_26 && !info->relocateable
+ if (r_type != R_MIPS16_26 && !info->relocatable
&& ((h != NULL && h->fn_stub != NULL)
|| (local_p && elf_tdata (input_bfd)->local_stubs != NULL
&& elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
}
/* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
need to redirect the call to the stub. */
- else if (r_type == R_MIPS16_26 && !info->relocateable
+ else if (r_type == R_MIPS16_26 && !info->relocatable
&& h != NULL
&& (h->call_stub != NULL || h->call_fp_stub != NULL)
&& !target_is_16_bit_code_p)
else
sec = h->call_fp_stub;
- BFD_ASSERT (sec->_raw_size > 0);
+ BFD_ASSERT (sec->size > 0);
symbol = sec->output_section->vma + sec->output_offset;
}
/* Calls from 16-bit code to 32-bit code and vice versa require the
special jalx instruction. */
- *require_jalxp = (!info->relocateable
+ *require_jalxp = (!info->relocatable
&& (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
|| ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
and we're going to need it, get it now. */
switch (r_type)
{
+ case R_MIPS_GOT_PAGE:
+ case R_MIPS_GOT_OFST:
+ /* We need to decay to GOT_DISP/addend if the symbol doesn't
+ bind locally. */
+ local_p = local_p || _bfd_elf_symbol_refs_local_p (&h->root, info, 1);
+ if (local_p || r_type == R_MIPS_GOT_OFST)
+ break;
+ /* Fall through. */
+
case R_MIPS_CALL16:
case R_MIPS_GOT16:
case R_MIPS_GOT_DISP:
/* Find the index into the GOT where this value is located. */
if (!local_p)
{
- BFD_ASSERT (addend == 0);
+ /* GOT_PAGE may take a non-zero addend, that is ignored in a
+ GOT_PAGE relocation that decays to GOT_DISP because the
+ symbol turns out to be global. The addend is then added
+ as GOT_OFST. */
+ BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE);
g = mips_elf_global_got_index (elf_hash_table (info)->dynobj,
input_bfd,
(struct elf_link_hash_entry *) h);
if (! elf_hash_table(info)->dynamic_sections_created
|| (info->shared
&& (info->symbolic || h->root.dynindx == -1)
- && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ && h->root.def_regular))
{
/* This is a static link or a -Bsymbolic link. The
symbol is defined locally, or was forced to be local.
We must initialize this entry in the GOT. */
bfd *tmpbfd = elf_hash_table (info)->dynobj;
asection *sgot = mips_elf_got_section (tmpbfd, FALSE);
- MIPS_ELF_PUT_WORD (tmpbfd, symbol + addend, sgot->contents + g);
+ MIPS_ELF_PUT_WORD (tmpbfd, symbol, sgot->contents + g);
}
}
else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
return bfd_reloc_continue;
case R_MIPS_16:
- value = symbol + mips_elf_sign_extend (addend, 16);
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
if ((info->shared
|| (elf_hash_table (info)->dynamic_sections_created
&& h != NULL
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ && h->root.def_dynamic
+ && !h->root.def_regular))
&& r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0)
{
break;
case R_MIPS_PC32:
- case R_MIPS_PC64:
- case R_MIPS_GNU_REL_LO16:
value = symbol + addend - p;
value &= howto->dst_mask;
break;
case R_MIPS_GNU_REL16_S2:
- value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
overflowed_p = mips_elf_overflow_p (value, 18);
value = (value >> 2) & howto->dst_mask;
break;
- case R_MIPS_GNU_REL_HI16:
- /* Instead of subtracting 'p' here, we should be subtracting the
- equivalent value for the LO part of the reloc, since the value
- here is relative to that address. Because that's not easy to do,
- we adjust 'addend' in _bfd_mips_elf_relocate_section(). See also
- the comment there for more information. */
- value = mips_elf_high (addend + symbol - p);
- value &= howto->dst_mask;
- break;
-
case R_MIPS16_26:
/* The calculation for R_MIPS16_26 is just the same as for an
R_MIPS_26. It's only the storage of the relocated field into
R_MIPS_26 case here. */
case R_MIPS_26:
if (local_p)
- value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
+ value = ((addend | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
- value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+ value = (_bfd_mips_elf_sign_extend (addend, 28) + symbol) >> 2;
value &= howto->dst_mask;
break;
instruction. If the addend was separate, leave it alone,
otherwise we may lose significant bits. */
if (howto->partial_inplace)
- addend = mips_elf_sign_extend (addend, 16);
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
value = symbol + addend - gp;
/* If the symbol was local, any earlier relocatable links will
have adjusted its addend with the gp offset, so compensate
/* Fall through. */
case R_MIPS_GOT_DISP:
+ got_disp:
value = g;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
break;
case R_MIPS_PC16:
- value = mips_elf_sign_extend (addend, 16) + symbol - p;
+ value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
break;
case R_MIPS_GOT_PAGE:
+ /* GOT_PAGE relocations that reference non-local symbols decay
+ to GOT_DISP. The corresponding GOT_OFST relocation decays to
+ 0. */
+ if (! local_p)
+ goto got_disp;
value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
break;
case R_MIPS_GOT_OFST:
- mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
+ if (local_p)
+ mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
+ else
+ value = addend;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
/* Obtain the field relocated by RELOCATION. */
static bfd_vma
-mips_elf_obtain_contents (howto, relocation, input_bfd, contents)
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd *input_bfd;
- bfd_byte *contents;
+mips_elf_obtain_contents (reloc_howto_type *howto,
+ const Elf_Internal_Rela *relocation,
+ bfd *input_bfd, bfd_byte *contents)
{
bfd_vma x;
bfd_byte *location = contents + relocation->r_offset;
Returns FALSE if anything goes wrong. */
static bfd_boolean
-mips_elf_perform_relocation (info, howto, relocation, value, input_bfd,
- input_section, contents, require_jalx)
- struct bfd_link_info *info;
- reloc_howto_type *howto;
- const Elf_Internal_Rela *relocation;
- bfd_vma value;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- bfd_boolean require_jalx;
+mips_elf_perform_relocation (struct bfd_link_info *info,
+ reloc_howto_type *howto,
+ const Elf_Internal_Rela *relocation,
+ bfd_vma value, bfd *input_bfd,
+ asection *input_section, bfd_byte *contents,
+ bfd_boolean require_jalx)
{
bfd_vma x;
bfd_byte *location;
JALX is the 5-bit value 00011. X is 0 for jal, 1 for jalx.
Note that the immediate value in the first word is swapped.
- When producing a relocateable object file, R_MIPS16_26 is
+ When producing a relocatable object file, R_MIPS16_26 is
handled mostly like R_MIPS_26. In particular, the addend is
stored as a straight 26-bit value in a 32-bit instruction.
(gas makes life simpler for itself by never adjusting a
where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
((sub1 << 16) | sub2)).
- When producing a relocateable object file, the calculation is
+ When producing a relocatable object file, the calculation is
(((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
When producing a fully linked file, the calculation is
let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
- if (!info->relocateable)
+ if (!info->relocatable)
/* Shuffle the bits according to the formula above. */
value = (((value & 0x1f0000) << 5)
| ((value & 0x3e00000) >> 5)
if (!ok)
{
(*_bfd_error_handler)
- (_("%s: %s+0x%lx: jump to stub routine which is not jal"),
- bfd_archive_filename (input_bfd),
- input_section->name,
+ (_("%B: %A+0x%lx: jump to stub routine which is not jal"),
+ input_bfd,
+ input_section,
(unsigned long) relocation->r_offset);
bfd_set_error (bfd_error_bad_value);
return FALSE;
/* Returns TRUE if SECTION is a MIPS16 stub section. */
static bfd_boolean
-mips_elf_stub_section_p (abfd, section)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *section;
+mips_elf_stub_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
{
const char *name = bfd_get_section_name (abfd, section);
/* Add room for N relocations to the .rel.dyn section in ABFD. */
static void
-mips_elf_allocate_dynamic_relocations (abfd, n)
- bfd *abfd;
- unsigned int n;
+mips_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n)
{
asection *s;
s = mips_elf_rel_dyn_section (abfd, FALSE);
BFD_ASSERT (s != NULL);
- if (s->_raw_size == 0)
+ if (s->size == 0)
{
/* Make room for a null element. */
- s->_raw_size += MIPS_ELF_REL_SIZE (abfd);
+ s->size += MIPS_ELF_REL_SIZE (abfd);
++s->reloc_count;
}
- s->_raw_size += n * MIPS_ELF_REL_SIZE (abfd);
+ s->size += n * MIPS_ELF_REL_SIZE (abfd);
}
/* Create a rel.dyn relocation for the dynamic linker to resolve. REL
caller should store the result in place of the original addend. */
static bfd_boolean
-mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
- symbol, addendp, input_section)
- bfd *output_bfd;
- struct bfd_link_info *info;
- const Elf_Internal_Rela *rel;
- struct mips_elf_link_hash_entry *h;
- asection *sec;
- bfd_vma symbol;
- bfd_vma *addendp;
- asection *input_section;
+mips_elf_create_dynamic_relocation (bfd *output_bfd,
+ struct bfd_link_info *info,
+ const Elf_Internal_Rela *rel,
+ struct mips_elf_link_hash_entry *h,
+ asection *sec, bfd_vma symbol,
+ bfd_vma *addendp, asection *input_section)
{
Elf_Internal_Rela outrel[3];
bfd_boolean skip;
BFD_ASSERT (sreloc != NULL);
BFD_ASSERT (sreloc->contents != NULL);
BFD_ASSERT (sreloc->reloc_count * MIPS_ELF_REL_SIZE (output_bfd)
- < sreloc->_raw_size);
+ < sreloc->size);
skip = FALSE;
outrel[0].r_offset =
/* We begin by assuming that the offset for the dynamic relocation
is the same as for the original relocation. We'll adjust this
later to reflect the correct output offsets. */
- if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
+ if (input_section->sec_info_type != ELF_INFO_TYPE_STABS)
{
outrel[1].r_offset = rel[1].r_offset;
outrel[2].r_offset = rel[2].r_offset;
outrel[2].r_offset = outrel[0].r_offset;
/* If we didn't need the relocation at all, this value will be
-1. */
- if (outrel[0].r_offset == (bfd_vma) -1)
+ if (outrel[0].r_offset == MINUS_ONE)
skip = TRUE;
}
#endif
- if (outrel[0].r_offset == (bfd_vma) -1
- || outrel[0].r_offset == (bfd_vma) -2)
+ if (outrel[0].r_offset == MINUS_ONE)
+ /* The relocation field has been deleted. */
skip = TRUE;
+ else if (outrel[0].r_offset == MINUS_TWO)
+ {
+ /* The relocation field has been converted into a relative value of
+ some sort. Functions like _bfd_elf_write_section_eh_frame expect
+ the field to be fully relocated, so add in the symbol's value. */
+ skip = TRUE;
+ *addendp += symbol;
+ }
/* If we've decided to skip this relocation, just output an empty
record. Note that R_MIPS_NONE == 0, so that this call to memset
else
{
long indx;
- bfd_vma section_offset;
+ bfd_boolean defined_p;
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
if (h != NULL
- && (! info->symbolic || (h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
- {
- indx = h->root.dynindx;
+ && (! info->symbolic || !h->root.def_regular)
/* h->root.dynindx may be -1 if this symbol was marked to
become local. */
- if (indx == -1)
- indx = 0;
+ && h->root.dynindx != -1)
+ {
+ indx = h->root.dynindx;
+ if (SGI_COMPAT (output_bfd))
+ defined_p = h->root.def_regular;
+ else
+ /* ??? glibc's ld.so just adds the final GOT entry to the
+ relocation field. It therefore treats relocs against
+ defined symbols in the same way as relocs against
+ undefined symbols. */
+ defined_p = FALSE;
}
else
{
abort ();
}
- /* Figure out how far the target of the relocation is from
- the beginning of its section. */
- section_offset = symbol - sec->output_section->vma;
- /* The relocation we're building is section-relative.
- Therefore, the original addend must be adjusted by the
- section offset. */
- *addendp += section_offset;
- /* Now, the relocation is just against the section. */
- symbol = sec->output_section->vma;
+ /* Instead of generating a relocation using the section
+ symbol, we may as well make it a fully relative
+ relocation. We want to avoid generating relocations to
+ local symbols because we used to generate them
+ incorrectly, without adding the original symbol value,
+ which is mandated by the ABI for section symbols. In
+ order to give dynamic loaders and applications time to
+ phase out the incorrect use, we refrain from emitting
+ section-relative relocations. It's not like they're
+ useful, after all. This should be a bit more efficient
+ as well. */
+ /* ??? Although this behavior is compatible with glibc's ld.so,
+ the ABI says that relocations against STN_UNDEF should have
+ a symbol value of 0. Irix rld honors this, so relocations
+ against STN_UNDEF have no effect. */
+ if (!SGI_COMPAT (output_bfd))
+ indx = 0;
+ defined_p = TRUE;
}
/* If the relocation was previously an absolute relocation and
this symbol will not be referred to by the relocation, we must
adjust it by the value we give it in the dynamic symbol table.
Otherwise leave the job up to the dynamic linker. */
- if (!indx && r_type != R_MIPS_REL32)
+ if (defined_p && r_type != R_MIPS_REL32)
*addendp += symbol;
/* The relocation is always an REL32 relocation because we don't
know where the shared library will wind up at load-time. */
outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
R_MIPS_REL32);
- outrel[1].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
+ /* For strict adherence to the ABI specification, we should
+ generate a R_MIPS_64 relocation record by itself before the
+ _REL32/_64 record as well, such that the addend is read in as
+ a 64-bit value (REL32 is a 32-bit relocation, after all).
+ However, since none of the existing ELF64 MIPS dynamic
+ loaders seems to care, we don't waste space with these
+ artificial relocations. If this turns out to not be true,
+ mips_elf_allocate_dynamic_relocation() should be tweaked so
+ as to make room for a pair of dynamic relocations per
+ invocation if ABI_64_P, and here we should generate an
+ additional relocation record with R_MIPS_64 by itself for a
+ NULL symbol before this relocation record. */
+ outrel[1].r_info = ELF_R_INFO (output_bfd, 0,
ABI_64_P (output_bfd)
? R_MIPS_64
: R_MIPS_NONE);
- outrel[2].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
- R_MIPS_NONE);
+ outrel[2].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_NONE);
/* Adjust the output offset of the relocation to reference the
correct location in the output file. */
(output_bfd, &outrel[0],
(sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
- /* Record the index of the first relocation referencing H. This
- information is later emitted in the .msym section. */
- if (h != NULL
- && (h->min_dyn_reloc_index == 0
- || sreloc->reloc_count < h->min_dyn_reloc_index))
- h->min_dyn_reloc_index = sreloc->reloc_count;
-
/* We've now added another relocation. */
++sreloc->reloc_count;
/* Return the MACH for a MIPS e_flags value. */
unsigned long
-_bfd_elf_mips_mach (flags)
- flagword flags;
+_bfd_elf_mips_mach (flagword flags)
{
switch (flags & EF_MIPS_MACH)
{
case E_MIPS_ARCH_32R2:
return bfd_mach_mipsisa32r2;
break;
+
+ case E_MIPS_ARCH_64R2:
+ return bfd_mach_mipsisa64r2;
+ break;
}
}
/* Return printable name for ABI. */
static INLINE char *
-elf_mips_abi_name (abfd)
- bfd *abfd;
+elf_mips_abi_name (bfd *abfd)
{
flagword flags;
This is used for both the 32-bit and the 64-bit ABI. */
void
-_bfd_mips_elf_symbol_processing (abfd, asym)
- bfd *abfd;
- asymbol *asym;
+_bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
{
elf_symbol_type *elfsym;
asym->section = bfd_und_section_ptr;
break;
-#if 0 /* for SGI_COMPAT */
case SHN_MIPS_TEXT:
- asym->section = mips_elf_text_section_ptr;
+ {
+ asection *section = bfd_get_section_by_name (abfd, ".text");
+
+ BFD_ASSERT (SGI_COMPAT (abfd));
+ if (section != NULL)
+ {
+ asym->section = section;
+ /* MIPS_TEXT is a bit special, the address is not an offset
+ to the base of the .text section. So substract the section
+ base address to make it an offset. */
+ asym->value -= section->vma;
+ }
+ }
break;
case SHN_MIPS_DATA:
- asym->section = mips_elf_data_section_ptr;
+ {
+ asection *section = bfd_get_section_by_name (abfd, ".data");
+
+ BFD_ASSERT (SGI_COMPAT (abfd));
+ if (section != NULL)
+ {
+ asym->section = section;
+ /* MIPS_DATA is a bit special, the address is not an offset
+ to the base of the .data section. So substract the section
+ base address to make it an offset. */
+ asym->value -= section->vma;
+ }
+ }
break;
-#endif
}
}
\f
+/* There appears to be a bug in the MIPSpro linker that causes GOT_DISP
+ relocations against two unnamed section symbols to resolve to the
+ same address. For example, if we have code like:
+
+ lw $4,%got_disp(.data)($gp)
+ lw $25,%got_disp(.text)($gp)
+ jalr $25
+
+ then the linker will resolve both relocations to .data and the program
+ will jump there rather than to .text.
+
+ We can work around this problem by giving names to local section symbols.
+ This is also what the MIPSpro tools do. */
+
+bfd_boolean
+_bfd_mips_elf_name_local_section_symbols (bfd *abfd)
+{
+ return SGI_COMPAT (abfd);
+}
+\f
/* Work over a section just before writing it out. This routine is
used by both the 32-bit and the 64-bit ABI. FIXME: We recognize
sections that need the SHF_MIPS_GPREL flag by name; there has to be
a better way. */
bfd_boolean
-_bfd_mips_elf_section_processing (abfd, hdr)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
+_bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
{
if (hdr->sh_type == SHT_MIPS_REGINFO
&& hdr->sh_size > 0)
SEEK_SET) != 0)
return FALSE;
H_PUT_32 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
+ if (bfd_bwrite (buf, 4, abfd) != 4)
return FALSE;
}
SEEK_SET) != 0)
return FALSE;
H_PUT_64 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 8, abfd) != 8)
+ if (bfd_bwrite (buf, 8, abfd) != 8)
return FALSE;
}
else if (intopt.kind == ODK_REGINFO)
SEEK_SET) != 0)
return FALSE;
H_PUT_32 (abfd, elf_gp (abfd), buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
+ if (bfd_bwrite (buf, 4, abfd) != 4)
return FALSE;
}
l += intopt.size;
how to. */
bfd_boolean
-_bfd_mips_elf_section_from_shdr (abfd, hdr, name)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- const char *name;
+_bfd_mips_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
+ const char *name)
{
flagword flags = 0;
Elf32_External_RegInfo ext;
Elf32_RegInfo s;
- if (! bfd_get_section_contents (abfd, hdr->bfd_section, (PTR) &ext,
- (file_ptr) 0,
- (bfd_size_type) sizeof ext))
+ if (! bfd_get_section_contents (abfd, hdr->bfd_section,
+ &ext, 0, sizeof ext))
return FALSE;
bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
elf_gp (abfd) = s.ri_gp_value;
{
bfd_byte *contents, *l, *lend;
- contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+ contents = bfd_malloc (hdr->sh_size);
if (contents == NULL)
return FALSE;
if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
- (file_ptr) 0, hdr->sh_size))
+ 0, hdr->sh_size))
{
free (contents);
return FALSE;
used by both the 32-bit and the 64-bit ABI. */
bfd_boolean
-_bfd_mips_elf_fake_sections (abfd, hdr, sec)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- asection *sec;
+_bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
{
register const char *name;
if (strcmp (name, ".liblist") == 0)
{
hdr->sh_type = SHT_MIPS_LIBLIST;
- hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib);
+ hdr->sh_info = sec->size / sizeof (Elf32_Lib);
/* The sh_link field is set in final_write_processing. */
}
else if (strcmp (name, ".conflict") == 0)
hdr->sh_entsize = 8;
}
- /* The generic elf_fake_sections will set up REL_HDR using the
- default kind of relocations. But, we may actually need both
- kinds of relocations, so we set up the second header here.
-
- This is not necessary for the O32 ABI since that only uses Elf32_Rel
- relocations (cf. System V ABI, MIPS RISC Processor Supplement,
- 3rd Edition, p. 4-17). It breaks the IRIX 5/6 32-bit ld, since one
- of the resulting empty .rela.<section> sections starts with
- sh_offset == object size, and ld doesn't allow that. While the check
- is arguably bogus for empty or SHT_NOBITS sections, it can easily be
- avoided by not emitting those useless sections in the first place. */
- if (! SGI_COMPAT (abfd) && ! NEWABI_P(abfd)
- && (sec->flags & SEC_RELOC) != 0)
- {
- struct bfd_elf_section_data *esd;
- bfd_size_type amt = sizeof (Elf_Internal_Shdr);
-
- esd = elf_section_data (sec);
- BFD_ASSERT (esd->rel_hdr2 == NULL);
- esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
- if (!esd->rel_hdr2)
- return FALSE;
- _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, !sec->use_rela_p);
- }
+ /* The generic elf_fake_sections will set up REL_HDR using the default
+ kind of relocations. We used to set up a second header for the
+ non-default kind of relocations here, but only NewABI would use
+ these, and the IRIX ld doesn't like resulting empty RELA sections.
+ Thus we create those header only on demand now. */
return TRUE;
}
the .scommon section. */
bfd_boolean
-_bfd_mips_elf_section_from_bfd_section (abfd, sec, retval)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- int *retval;
+_bfd_mips_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, int *retval)
{
if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
{
file. We must handle the special MIPS section numbers here. */
bfd_boolean
-_bfd_mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
- bfd *abfd;
- struct bfd_link_info *info;
- const Elf_Internal_Sym *sym;
- const char **namep;
- flagword *flagsp ATTRIBUTE_UNUSED;
- asection **secp;
- bfd_vma *valp;
+_bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
+ Elf_Internal_Sym *sym, const char **namep,
+ flagword *flagsp ATTRIBUTE_UNUSED,
+ asection **secp, bfd_vma *valp)
{
if (SGI_COMPAT (abfd)
&& (abfd->flags & DYNAMIC) != 0
/* Mark __rld_obj_head as dynamic. */
bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, *namep, BSF_GLOBAL, *secp,
- (bfd_vma) *valp, (const char *) NULL, FALSE,
+ (info, abfd, *namep, BSF_GLOBAL, *secp, *valp, NULL, FALSE,
get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_OBJECT;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
mips_elf_hash_table (info)->use_rld_obj_head = TRUE;
also where we undo the increment of the value for a mips16 symbol. */
bfd_boolean
-_bfd_mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- const char *name ATTRIBUTE_UNUSED;
- Elf_Internal_Sym *sym;
- asection *input_sec;
+_bfd_mips_elf_link_output_symbol_hook
+ (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym,
+ asection *input_sec, struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
{
/* If we see a common symbol, which implies a relocatable link, then
if a symbol was small common in an input file, mark it as small
&& strcmp (input_sec->name, ".scommon") == 0)
sym->st_shndx = SHN_MIPS_SCOMMON;
- if (sym->st_other == STO_MIPS16
- && (sym->st_value & 1) != 0)
- --sym->st_value;
+ if (sym->st_other == STO_MIPS16)
+ sym->st_value &= ~1;
return TRUE;
}
/* Create dynamic sections when linking against a dynamic object. */
bfd_boolean
-_bfd_mips_elf_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+_bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
{
struct elf_link_hash_entry *h;
struct bfd_link_hash_entry *bh;
if (! mips_elf_rel_dyn_section (elf_hash_table (info)->dynobj, TRUE))
return FALSE;
- /* Create the .msym section on IRIX6. It is used by the dynamic
- linker to speed up dynamic relocations, and to avoid computing
- the ELF hash for symbols. */
- if (IRIX_COMPAT (abfd) == ict_irix6
- && !mips_elf_create_msym_section (abfd))
- return FALSE;
-
/* Create .stub section. */
if (bfd_get_section_by_name (abfd,
MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL)
{
bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr,
- (bfd_vma) 0, (const char *) NULL, FALSE,
- get_elf_backend_data (abfd)->collect, &bh)))
+ (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr, 0,
+ NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_SECTION;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Change alignments of some sections. */
s = bfd_get_section_by_name (abfd, ".hash");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynsym");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynstr");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".reginfo");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
}
if (!info->shared)
name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
bh = NULL;
if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
- (bfd_vma) 0, (const char *) NULL, FALSE,
- get_elf_backend_data (abfd)->collect, &bh)))
+ (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
+ NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_SECTION;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
if (! mips_elf_hash_table (info)->use_rld_obj_head)
name = SGI_COMPAT (abfd) ? "__rld_map" : "__RLD_MAP";
bh = NULL;
if (!(_bfd_generic_link_add_one_symbol
- (info, abfd, name, BSF_GLOBAL, s,
- (bfd_vma) 0, (const char *) NULL, FALSE,
+ (info, abfd, name, BSF_GLOBAL, s, 0, NULL, FALSE,
get_elf_backend_data (abfd)->collect, &bh)))
return FALSE;
h = (struct elf_link_hash_entry *) bh;
- h->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->non_elf = 0;
+ h->def_regular = 1;
h->type = STT_OBJECT;
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
}
allocate space in the global offset table. */
bfd_boolean
-_bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
+_bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
+ asection *sec, const Elf_Internal_Rela *relocs)
{
const char *name;
bfd *dynobj;
const Elf_Internal_Rela *rel_end;
asection *sgot;
asection *sreloc;
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
dynobj = elf_hash_table (info)->dynobj;
sizeof CALL_FP_STUB - 1) == 0)
continue;
- sec_relocs = (MNAME(abfd,_bfd_elf,link_read_relocs)
- (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory));
+ sec_relocs
+ = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+ info->keep_memory);
if (sec_relocs == NULL)
return FALSE;
else
symcount = symtab_hdr->sh_info;
amt = symcount * sizeof (asection *);
- n = (asection **) bfd_zalloc (abfd, amt);
+ n = bfd_zalloc (abfd, amt);
if (n == NULL)
return FALSE;
elf_tdata (abfd)->local_stubs = n;
else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
{
(*_bfd_error_handler)
- (_("%s: Malformed reloc detected for section %s"),
- bfd_archive_filename (abfd), name);
+ (_("%B: Malformed reloc detected for section %s"),
+ abfd, name);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
if (h == NULL)
{
(*_bfd_error_handler)
- (_("%s: CALL16 reloc at 0x%lx not against global symbol"),
- bfd_archive_filename (abfd), (unsigned long) rel->r_offset);
+ (_("%B: CALL16 reloc at 0x%lx not against global symbol"),
+ abfd, (unsigned long) rel->r_offset);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* We need a stub, not a plt entry for the undefined
function. But we record it as if it needs plt. See
- elf_adjust_dynamic_symbol in elflink.h. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ _bfd_elf_adjust_dynamic_symbol. */
+ h->needs_plt = 1;
h->type = STT_FUNC;
}
break;
+ case R_MIPS_GOT_PAGE:
+ /* If this is a global, overridable symbol, GOT_PAGE will
+ decay to GOT_DISP, so we'll need a GOT entry for it. */
+ if (h == NULL)
+ break;
+ else
+ {
+ struct mips_elf_link_hash_entry *hmips =
+ (struct mips_elf_link_hash_entry *) h;
+
+ while (hmips->root.root.type == bfd_link_hash_indirect
+ || hmips->root.root.type == bfd_link_hash_warning)
+ hmips = (struct mips_elf_link_hash_entry *)
+ hmips->root.root.u.i.link;
+
+ if (hmips->root.def_regular
+ && ! (info->shared && ! info->symbolic
+ && ! hmips->root.forced_local))
+ break;
+ }
+ /* Fall through. */
+
case R_MIPS_GOT16:
case R_MIPS_GOT_HI16:
case R_MIPS_GOT_LO16:
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MIPS_GNU_VTINHERIT:
- if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return FALSE;
break;
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_MIPS_GNU_VTENTRY:
- if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
return FALSE;
break;
case R_MIPS_CALL16:
case R_MIPS_CALL_HI16:
case R_MIPS_CALL_LO16:
+ case R_MIPS_JALR:
break;
}
return TRUE;
}
\f
+bfd_boolean
+_bfd_mips_relax_section (bfd *abfd, asection *sec,
+ struct bfd_link_info *link_info,
+ bfd_boolean *again)
+{
+ Elf_Internal_Rela *internal_relocs;
+ Elf_Internal_Rela *irel, *irelend;
+ Elf_Internal_Shdr *symtab_hdr;
+ bfd_byte *contents = NULL;
+ size_t extsymoff;
+ bfd_boolean changed_contents = FALSE;
+ bfd_vma sec_start = sec->output_section->vma + sec->output_offset;
+ Elf_Internal_Sym *isymbuf = NULL;
+
+ /* We are not currently changing any sizes, so only one pass. */
+ *again = FALSE;
+
+ if (link_info->relocatable)
+ return TRUE;
+
+ internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+ link_info->keep_memory);
+ if (internal_relocs == NULL)
+ return TRUE;
+
+ irelend = internal_relocs + sec->reloc_count
+ * get_elf_backend_data (abfd)->s->int_rels_per_ext_rel;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
+
+ for (irel = internal_relocs; irel < irelend; irel++)
+ {
+ bfd_vma symval;
+ bfd_signed_vma sym_offset;
+ unsigned int r_type;
+ unsigned long r_symndx;
+ asection *sym_sec;
+ unsigned long instruction;
+
+ /* Turn jalr into bgezal, and jr into beq, if they're marked
+ with a JALR relocation, that indicate where they jump to.
+ This saves some pipeline bubbles. */
+ r_type = ELF_R_TYPE (abfd, irel->r_info);
+ if (r_type != R_MIPS_JALR)
+ continue;
+
+ r_symndx = ELF_R_SYM (abfd, irel->r_info);
+ /* Compute the address of the jump target. */
+ if (r_symndx >= extsymoff)
+ {
+ struct mips_elf_link_hash_entry *h
+ = ((struct mips_elf_link_hash_entry *)
+ elf_sym_hashes (abfd) [r_symndx - extsymoff]);
+
+ while (h->root.root.type == bfd_link_hash_indirect
+ || h->root.root.type == bfd_link_hash_warning)
+ h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
+
+ /* If a symbol is undefined, or if it may be overridden,
+ skip it. */
+ if (! ((h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ && h->root.root.u.def.section)
+ || (link_info->shared && ! link_info->symbolic
+ && !h->root.forced_local))
+ continue;
+
+ sym_sec = h->root.root.u.def.section;
+ if (sym_sec->output_section)
+ symval = (h->root.root.u.def.value
+ + sym_sec->output_section->vma
+ + sym_sec->output_offset);
+ else
+ symval = h->root.root.u.def.value;
+ }
+ else
+ {
+ Elf_Internal_Sym *isym;
+
+ /* Read this BFD's symbols if we haven't done so already. */
+ if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+ {
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == NULL)
+ goto relax_return;
+ }
+
+ isym = isymbuf + r_symndx;
+ if (isym->st_shndx == SHN_UNDEF)
+ continue;
+ else if (isym->st_shndx == SHN_ABS)
+ sym_sec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ sym_sec = bfd_com_section_ptr;
+ else
+ sym_sec
+ = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ symval = isym->st_value
+ + sym_sec->output_section->vma
+ + sym_sec->output_offset;
+ }
+
+ /* Compute branch offset, from delay slot of the jump to the
+ branch target. */
+ sym_offset = (symval + irel->r_addend)
+ - (sec_start + irel->r_offset + 4);
+
+ /* Branch offset must be properly aligned. */
+ if ((sym_offset & 3) != 0)
+ continue;
+
+ sym_offset >>= 2;
+
+ /* Check that it's in range. */
+ if (sym_offset < -0x8000 || sym_offset >= 0x8000)
+ continue;
+
+ /* Get the section contents if we haven't done so already. */
+ if (contents == NULL)
+ {
+ /* Get cached copy if it exists. */
+ if (elf_section_data (sec)->this_hdr.contents != NULL)
+ contents = elf_section_data (sec)->this_hdr.contents;
+ else
+ {
+ if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+ goto relax_return;
+ }
+ }
+
+ instruction = bfd_get_32 (abfd, contents + irel->r_offset);
+
+ /* If it was jalr <reg>, turn it into bgezal $zero, <target>. */
+ if ((instruction & 0xfc1fffff) == 0x0000f809)
+ instruction = 0x04110000;
+ /* If it was jr <reg>, turn it into b <target>. */
+ else if ((instruction & 0xfc1fffff) == 0x00000008)
+ instruction = 0x10000000;
+ else
+ continue;
+
+ instruction |= (sym_offset & 0xffff);
+ bfd_put_32 (abfd, instruction, contents + irel->r_offset);
+ changed_contents = TRUE;
+ }
+
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
+ {
+ if (!changed_contents && !link_info->keep_memory)
+ free (contents);
+ else
+ {
+ /* Cache the section contents for elf_link_input_bfd. */
+ elf_section_data (sec)->this_hdr.contents = contents;
+ }
+ }
+ return TRUE;
+
+ relax_return:
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
+ free (contents);
+ return FALSE;
+}
+\f
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
understand. */
bfd_boolean
-_bfd_mips_elf_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
+_bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
- && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
- || h->weakdef != NULL
- || ((h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_REF_REGULAR) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+ && (h->needs_plt
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
/* If this symbol is defined in a dynamic object, we need to copy
any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
file. */
hmips = (struct mips_elf_link_hash_entry *) h;
- if (! info->relocateable
+ if (! info->relocatable
&& hmips->possibly_dynamic_relocs != 0
&& (h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ || !h->def_regular))
{
mips_elf_allocate_dynamic_relocations (dynobj,
hmips->possibly_dynamic_relocs);
/* For a function, create a stub, if allowed. */
if (! hmips->no_fn_stub
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ && h->needs_plt)
{
if (! elf_hash_table (info)->dynamic_sections_created)
return TRUE;
the symbol to the stub location. This is required to make
function pointers compare as equal between the normal
executable and the shared library. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ if (!h->def_regular)
{
/* We need .stub section. */
s = bfd_get_section_by_name (dynobj,
BFD_ASSERT (s != NULL);
h->root.u.def.section = s;
- h->root.u.def.value = s->_raw_size;
+ h->root.u.def.value = s->size;
/* XXX Write this stub address somewhere. */
- h->plt.offset = s->_raw_size;
+ h->plt.offset = s->size;
/* Make room for this stub code. */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+ s->size += MIPS_FUNCTION_STUB_SIZE;
/* The last half word of the stub will be filled with the index
of this symbol in .dynsym section. */
}
}
else if ((h->type == STT_FUNC)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0)
+ && !h->needs_plt)
{
/* This will set the entry for this symbol in the GOT to 0, and
the dynamic linker will take care of this. */
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
return TRUE;
}
check for any mips16 stub sections that we can discard. */
bfd_boolean
-_bfd_mips_elf_always_size_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
+_bfd_mips_elf_always_size_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
{
asection *ri;
/* The .reginfo section has a fixed size. */
ri = bfd_get_section_by_name (output_bfd, ".reginfo");
if (ri != NULL)
- bfd_set_section_size (output_bfd, ri,
- (bfd_size_type) sizeof (Elf32_External_RegInfo));
+ bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
- if (! (info->relocateable
+ if (! (info->relocatable
|| ! mips_elf_hash_table (info)->mips16_stubs_seen))
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
- mips_elf_check_mips16_stubs,
- (PTR) NULL);
+ mips_elf_check_mips16_stubs, NULL);
dynobj = elf_hash_table (info)->dynobj;
if (dynobj == NULL)
/* Relocatable links don't have it. */
return TRUE;
-
+
g = mips_elf_got_info (dynobj, &s);
if (s == NULL)
return TRUE;
{
if ((subsection->flags & SEC_ALLOC) == 0)
continue;
- loadable_size += ((subsection->_raw_size + 0xf)
+ loadable_size += ((subsection->size + 0xf)
&~ (bfd_size_type) 0xf);
}
}
local_gotno = (loadable_size >> 16) + 5;
g->local_gotno += local_gotno;
- s->_raw_size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
+ s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
g->global_gotno = i;
- s->_raw_size += i * MIPS_ELF_GOT_SIZE (output_bfd);
+ s->size += i * MIPS_ELF_GOT_SIZE (output_bfd);
- if (s->_raw_size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)
+ if (s->size > MIPS_ELF_GOT_MAX_SIZE (output_bfd)
&& ! mips_elf_multi_got (output_bfd, info, g, s, local_gotno))
return FALSE;
/* Set the sizes of the dynamic sections. */
bfd_boolean
-_bfd_mips_elf_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
+_bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *s;
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (! info->shared)
+ if (info->executable)
{
s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL);
- s->_raw_size
+ s->size
= strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
s->contents
= (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
if (strncmp (name, ".rel", 4) == 0)
{
- if (s->_raw_size == 0)
+ if (s->size == 0)
{
/* We only strip the section if the output section name
has the same name. Otherwise, there might be several
struct mips_got_info *g = gg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
unsigned int needed_relocs = 0;
-
+
if (gg->next)
{
set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
{
/* IRIX rld assumes that the function stub isn't at the end
of .text section. So put a dummy. XXX */
- s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+ s->size += MIPS_FUNCTION_STUB_SIZE;
}
else if (! info->shared
&& ! mips_elf_hash_table (info)->use_rld_obj_head
{
/* We add a room for __rld_map. It will be filled in by the
rtld to contain a pointer to the _r_debug structure. */
- s->_raw_size += 4;
+ s->size += 4;
}
else if (SGI_COMPAT (output_bfd)
&& strncmp (name, ".compact_rel", 12) == 0)
- s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
- else if (strcmp (name, ".msym") == 0)
- s->_raw_size = (sizeof (Elf32_External_Msym)
- * (elf_hash_table (info)->dynsymcount
- + bfd_count_sections (output_bfd)));
+ s->size += mips_elf_hash_table (info)->compact_rel_size;
else if (strncmp (name, ".init", 5) != 0)
{
/* It's not one of our sections, so don't allocate space. */
}
/* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
+ s->contents = bfd_zalloc (dynobj, s->size);
+ if (s->contents == NULL && s->size != 0)
{
bfd_set_error (bfd_error_no_memory);
return FALSE;
return FALSE;
}
- if (SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICTNO, 0))
- return FALSE;
- }
-
- if (SGI_COMPAT (output_bfd))
- {
- if (!MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLISTNO, 0))
- return FALSE;
- }
-
- if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
- {
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_CONFLICT, 0))
- return FALSE;
-
- s = bfd_get_section_by_name (dynobj, ".liblist");
- BFD_ASSERT (s != NULL);
-
- if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_LIBLIST, 0))
- return FALSE;
- }
-
if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_VERSION, 0))
return FALSE;
(dynobj, MIPS_ELF_OPTIONS_SECTION_NAME (dynobj)))
&& !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
return FALSE;
-
- if (bfd_get_section_by_name (dynobj, ".msym")
- && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_MSYM, 0))
- return FALSE;
}
return TRUE;
/* Relocate a MIPS ELF section. */
bfd_boolean
-_bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
+_bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
+ bfd *input_bfd, asection *input_section,
+ bfd_byte *contents, Elf_Internal_Rela *relocs,
+ Elf_Internal_Sym *local_syms,
+ asection **local_sections)
{
Elf_Internal_Rela *rel;
const Elf_Internal_Rela *relend;
bfd_vma addend = 0;
bfd_boolean use_saved_addend_p = FALSE;
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
bed = get_elf_backend_data (output_bfd);
relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
REL relocation. */
bfd_boolean rela_relocation_p = TRUE;
unsigned int r_type = ELF_R_TYPE (output_bfd, rel->r_info);
- const char * msg = (const char *) NULL;
+ const char *msg;
/* Find the relocation howto for this relocation. */
if (r_type == R_MIPS_64 && ! NEWABI_P (input_bfd))
addend = mips_elf_obtain_contents (howto, rel, input_bfd,
contents);
addend &= howto->src_mask;
- addend <<= howto->rightshift;
/* For some kinds of relocations, the ADDEND is a
combination of the addend stored in two different
relocations. */
if (r_type == R_MIPS_HI16
- || r_type == R_MIPS_GNU_REL_HI16
|| (r_type == R_MIPS_GOT16
&& mips_elf_local_relocation_p (input_bfd, rel,
local_sections, FALSE)))
bfd_vma l;
const Elf_Internal_Rela *lo16_relocation;
reloc_howto_type *lo16_howto;
- unsigned int lo;
/* The combined value is the sum of the HI16 addend,
left-shifted by sixteen bits, and the LO16
a `lui' of the HI16 value, and then an `addiu' of
the LO16 value.)
- Scan ahead to find a matching LO16 relocation. */
- if (r_type == R_MIPS_GNU_REL_HI16)
- lo = R_MIPS_GNU_REL_LO16;
- else
- lo = R_MIPS_LO16;
- lo16_relocation = mips_elf_next_relocation (input_bfd, lo,
+ Scan ahead to find a matching LO16 relocation.
+
+ According to the MIPS ELF ABI, the R_MIPS_LO16
+ relocation must be immediately following.
+ However, for the IRIX6 ABI, the next relocation
+ may be a composed relocation consisting of
+ several relocations for the same address. In
+ that case, the R_MIPS_LO16 relocation may occur
+ as one of these. We permit a similar extension
+ in general, as that is useful for GCC. */
+ lo16_relocation = mips_elf_next_relocation (input_bfd,
+ R_MIPS_LO16,
rel, relend);
if (lo16_relocation == NULL)
return FALSE;
/* Obtain the addend kept there. */
- lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, lo, FALSE);
+ lo16_howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd,
+ R_MIPS_LO16, FALSE);
l = mips_elf_obtain_contents (lo16_howto, lo16_relocation,
input_bfd, contents);
l &= lo16_howto->src_mask;
l <<= lo16_howto->rightshift;
- l = mips_elf_sign_extend (l, 16);
+ l = _bfd_mips_elf_sign_extend (l, 16);
addend <<= 16;
/* Compute the combined addend. */
addend += l;
-
- /* If PC-relative, subtract the difference between the
- address of the LO part of the reloc and the address of
- the HI part. The relocation is relative to the LO
- part, but mips_elf_calculate_relocation() doesn't
- know its address or the difference from the HI part, so
- we subtract that difference here. See also the
- comment in mips_elf_calculate_relocation(). */
- if (r_type == R_MIPS_GNU_REL_HI16)
- addend -= (lo16_relocation->r_offset - rel->r_offset);
}
else if (r_type == R_MIPS16_GPREL)
{
| ((addend & 0x7e00000) >> 16)
| (addend & 0x1f));
}
+ else
+ addend <<= howto->rightshift;
}
else
addend = rel->r_addend;
}
- if (info->relocateable)
+ if (info->relocatable)
{
Elf_Internal_Sym *sym;
unsigned long r_symndx;
they're against a section symbol, in which case we need
to adjust by the section offset, or unless they're GP
relative in which case we need to adjust by the amount
- that we're adjusting GP in this relocateable object. */
+ that we're adjusting GP in this relocatable object. */
if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
FALSE))
/* Adjust the addend appropriately. */
addend += local_sections[r_symndx]->output_offset;
- if (howto->partial_inplace)
+ if (rela_relocation_p)
+ /* If this is a RELA relocation, just update the addend. */
+ rel->r_addend = addend;
+ else
{
- /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
- then we only want to write out the high-order 16 bits.
- The subsequent R_MIPS_LO16 will handle the low-order bits.
- */
- if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
- || r_type == R_MIPS_GNU_REL_HI16)
+ if (r_type == R_MIPS_HI16
+ || r_type == R_MIPS_GOT16)
addend = mips_elf_high (addend);
else if (r_type == R_MIPS_HIGHER)
addend = mips_elf_higher (addend);
else if (r_type == R_MIPS_HIGHEST)
addend = mips_elf_highest (addend);
- }
+ else
+ addend >>= howto->rightshift;
- if (rela_relocation_p)
- /* If this is a RELA relocation, just update the addend.
- We have to cast away constness for REL. */
- rel->r_addend = addend;
- else
- {
- /* Otherwise, we have to write the value back out. Note
- that we use the source mask, rather than the
- destination mask because the place to which we are
- writing will be source of the addend in the final
- link. */
- addend >>= howto->rightshift;
+ /* We use the source mask, rather than the destination
+ mask because the place to which we are writing will be
+ source of the addend in the final link. */
addend &= howto->src_mask;
if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
else
use_saved_addend_p = FALSE;
- addend >>= howto->rightshift;
-
/* Figure out what value we are supposed to relocate. */
switch (mips_elf_calculate_relocation (output_bfd, input_bfd,
input_section, info, rel,
{
BFD_ASSERT (name != NULL);
if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
+ (info, NULL, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
return FALSE;
}
adjust it appropriately now. */
static void
-mips_elf_irix6_finish_dynamic_symbol (abfd, name, sym)
- bfd *abfd ATTRIBUTE_UNUSED;
- const char *name;
- Elf_Internal_Sym *sym;
+mips_elf_irix6_finish_dynamic_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *name, Elf_Internal_Sym *sym)
{
/* The linker script takes care of providing names and values for
these, but we must place them into the right sections. */
/* All of these symbols are given type STT_SECTION by the
IRIX6 linker. */
sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ sym->st_other = STO_PROTECTED;
/* The IRIX linker puts these symbols in special sections. */
if (i == 0)
dynamic sections here. */
bfd_boolean
-_bfd_mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+_bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
bfd *dynobj;
- bfd_vma gval;
asection *sgot;
- asection *smsym;
struct mips_got_info *g, *gg;
const char *name;
- struct mips_elf_link_hash_entry *mh;
dynobj = elf_hash_table (info)->dynobj;
- gval = sym->st_value;
- mh = (struct mips_elf_link_hash_entry *) h;
- if (h->plt.offset != (bfd_vma) -1)
+ if (h->plt.offset != MINUS_ONE)
{
asection *s;
bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub + 12);
- BFD_ASSERT (h->plt.offset <= s->_raw_size);
+ BFD_ASSERT (h->plt.offset <= s->size);
memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
/* Mark the symbol as undefined. plt.offset != -1 occurs
/* The run-time linker uses the st_value field of the symbol
to reset the global offset table entry for this external
to its stub address when unlinking a shared object. */
- gval = s->output_section->vma + s->output_offset + h->plt.offset;
- sym->st_value = gval;
+ sym->st_value = (s->output_section->vma + s->output_offset
+ + h->plt.offset);
}
BFD_ASSERT (h->dynindx != -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0);
+ || h->forced_local);
sgot = mips_elf_got_section (dynobj, FALSE);
BFD_ASSERT (sgot != NULL);
bfd_vma offset;
bfd_vma value;
- if (sym->st_value)
- value = sym->st_value;
- else
- {
- /* For an entity defined in a shared object, this will be
- NULL. (For functions in shared objects for
- which we have created stubs, ST_VALUE will be non-NULL.
- That's because such the functions are now no longer defined
- in a shared object.) */
-
- if ((info->shared && h->root.type == bfd_link_hash_undefined)
- || h->root.type == bfd_link_hash_undefweak)
- value = 0;
- else
- value = h->root.u.def.value;
- }
+ value = sym->st_value;
offset = mips_elf_global_got_index (dynobj, output_bfd, h);
MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
}
if (g->next && h->dynindx != -1)
{
struct mips_got_entry e, *p;
+ bfd_vma entry;
bfd_vma offset;
- bfd_vma value;
- Elf_Internal_Rela rel[3];
- bfd_vma addend = 0;
gg = g;
e.abfd = output_bfd;
e.symndx = -1;
e.d.h = (struct mips_elf_link_hash_entry *)h;
-
- if (info->shared
- || h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- value = 0;
- else if (sym->st_value)
- value = sym->st_value;
- else
- value = h->root.u.def.value;
-
- memset (rel, 0, sizeof (rel));
- rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_REL32);
for (g = g->next; g->next != gg; g = g->next)
{
&e)))
{
offset = p->gotidx;
- rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
-
- MIPS_ELF_PUT_WORD (output_bfd, value, sgot->contents + offset);
-
- if ((info->shared
- || (elf_hash_table (info)->dynamic_sections_created
- && p->d.h != NULL
- && ((p->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
- && ((p->d.h->root.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0)))
- && ! (mips_elf_create_dynamic_relocation
- (output_bfd, info, rel,
- e.d.h, NULL, value, &addend, sgot)))
- return FALSE;
- BFD_ASSERT (addend == 0);
+ if (info->shared
+ || (elf_hash_table (info)->dynamic_sections_created
+ && p->d.h != NULL
+ && p->d.h->root.def_dynamic
+ && !p->d.h->root.def_regular))
+ {
+ /* Create an R_MIPS_REL32 relocation for this entry. Due to
+ the various compatibility problems, it's easier to mock
+ up an R_MIPS_32 or R_MIPS_64 relocation and leave
+ mips_elf_create_dynamic_relocation to calculate the
+ appropriate addend. */
+ Elf_Internal_Rela rel[3];
+
+ memset (rel, 0, sizeof (rel));
+ if (ABI_64_P (output_bfd))
+ rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_64);
+ else
+ rel[0].r_info = ELF_R_INFO (output_bfd, 0, R_MIPS_32);
+ rel[0].r_offset = rel[1].r_offset = rel[2].r_offset = offset;
+
+ entry = 0;
+ if (! (mips_elf_create_dynamic_relocation
+ (output_bfd, info, rel,
+ e.d.h, NULL, sym->st_value, &entry, sgot)))
+ return FALSE;
+ }
+ else
+ entry = sym->st_value;
+ MIPS_ELF_PUT_WORD (output_bfd, entry, sgot->contents + offset);
}
}
}
- /* Create a .msym entry, if appropriate. */
- smsym = bfd_get_section_by_name (dynobj, ".msym");
- if (smsym)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = bfd_elf_hash (h->root.root.string);
- /* It is undocumented what the `1' indicates, but IRIX6 uses
- this value. */
- msym.ms_info = ELF32_MS_INFO (mh->min_dyn_reloc_index, 1);
- bfd_mips_elf_swap_msym_out
- (dynobj, &msym,
- ((Elf32_External_Msym *) smsym->contents) + h->dynindx);
- }
-
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
name = h->root.root.string;
if (strcmp (name, "_DYNAMIC") == 0
asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
BFD_ASSERT (s != NULL);
sym->st_value = s->output_section->vma + s->output_offset;
- bfd_put_32 (output_bfd, (bfd_vma) 0, s->contents);
+ bfd_put_32 (output_bfd, 0, s->contents);
if (mips_elf_hash_table (info)->rld_value == 0)
mips_elf_hash_table (info)->rld_value = sym->st_value;
}
}
/* If this is a mips16 symbol, force the value to be even. */
- if (sym->st_other == STO_MIPS16
- && (sym->st_value & 1) != 0)
- --sym->st_value;
+ if (sym->st_other == STO_MIPS16)
+ sym->st_value &= ~1;
return TRUE;
}
/* Finish up the dynamic sections. */
bfd_boolean
-_bfd_mips_elf_finish_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
- struct bfd_link_info *info;
+_bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *sdyn;
BFD_ASSERT (g != NULL);
for (b = sdyn->contents;
- b < sdyn->contents + sdyn->_raw_size;
+ b < sdyn->contents + sdyn->size;
b += MIPS_ELF_DYN_SIZE (dynobj))
{
Elf_Internal_Dyn dyn;
case DT_PLTGOT:
name = ".got";
- goto get_vma;
- case DT_MIPS_CONFLICT:
- name = ".conflict";
- goto get_vma;
- case DT_MIPS_LIBLIST:
- name = ".liblist";
- get_vma:
s = bfd_get_section_by_name (output_bfd, name);
BFD_ASSERT (s != NULL);
dyn.d_un.d_ptr = s->vma;
dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
break;
- case DT_MIPS_CONFLICTNO:
- name = ".conflict";
- elemsize = sizeof (Elf32_Conflict);
- goto set_elemno;
-
- case DT_MIPS_LIBLISTNO:
- name = ".liblist";
- elemsize = sizeof (Elf32_Lib);
- set_elemno:
- s = bfd_get_section_by_name (output_bfd, name);
- if (s != NULL)
- {
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
- }
- else
- dyn.d_un.d_val = 0;
- break;
-
case DT_MIPS_TIME_STAMP:
time ((time_t *) &dyn.d_un.d_val);
break;
s = bfd_get_section_by_name (output_bfd, name);
BFD_ASSERT (s != NULL);
- if (s->_cooked_size != 0)
- dyn.d_un.d_val = s->_cooked_size / elemsize;
- else
- dyn.d_un.d_val = s->_raw_size / elemsize;
+ dyn.d_un.d_val = s->size / elemsize;
break;
case DT_MIPS_HIPAGENO:
dyn.d_un.d_ptr = s->vma;
break;
- case DT_MIPS_MSYM:
- s = (bfd_get_section_by_name (output_bfd, ".msym"));
- dyn.d_un.d_ptr = s->vma;
+ case DT_RELSZ:
+ /* Reduce DT_RELSZ to account for any relocations we
+ decided not to make. This is for the n64 irix rld,
+ which doesn't seem to apply any relocations if there
+ are trailing null entries. */
+ s = mips_elf_rel_dyn_section (dynobj, FALSE);
+ dyn.d_un.d_val = (s->reloc_count
+ * (ABI_64_P (output_bfd)
+ ? sizeof (Elf64_Mips_External_Rel)
+ : sizeof (Elf32_External_Rel)));
break;
default:
/* The first entry of the global offset table will be filled at
runtime. The second entry will be used by some runtime loaders.
This isn't the case of IRIX rld. */
- if (sgot != NULL && sgot->_raw_size > 0)
+ if (sgot != NULL && sgot->size > 0)
{
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents);
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000,
+ MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents);
+ MIPS_ELF_PUT_WORD (output_bfd, 0x80000000,
sgot->contents + MIPS_ELF_GOT_SIZE (output_bfd));
}
{
bfd_vma index = g->next->local_gotno + g->next->global_gotno;
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0, sgot->contents
+ MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents
+ index++ * MIPS_ELF_GOT_SIZE (output_bfd));
- MIPS_ELF_PUT_WORD (output_bfd, (bfd_vma) 0x80000000, sgot->contents
+ MIPS_ELF_PUT_WORD (output_bfd, 0x80000000, sgot->contents
+ index++ * MIPS_ELF_GOT_SIZE (output_bfd));
if (! info->shared)
}
{
- asection *smsym;
asection *s;
Elf32_compact_rel cpt;
- /* ??? The section symbols for the output sections were set up in
- _bfd_elf_final_link. SGI sets the STT_NOTYPE attribute for these
- symbols. Should we do so? */
-
- smsym = bfd_get_section_by_name (dynobj, ".msym");
- if (smsym != NULL)
- {
- Elf32_Internal_Msym msym;
-
- msym.ms_hash_value = 0;
- msym.ms_info = ELF32_MS_INFO (0, 1);
-
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- long dynindx = elf_section_data (s)->dynindx;
-
- bfd_mips_elf_swap_msym_out
- (output_bfd, &msym,
- (((Elf32_External_Msym *) smsym->contents)
- + dynindx));
- }
- }
-
if (SGI_COMPAT (output_bfd))
{
/* Write .compact_rel section out. */
{
file_ptr dummy_offset;
- BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
- dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
+ BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE);
+ dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE;
memset (s->contents + dummy_offset, 0,
MIPS_FUNCTION_STUB_SIZE);
}
s = mips_elf_rel_dyn_section (dynobj, FALSE);
if (s != NULL
- && s->_raw_size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
+ && s->size > (bfd_vma)2 * MIPS_ELF_REL_SIZE (output_bfd))
{
reldyn_sorting_bfd = output_bfd;
if (ABI_64_P (output_bfd))
- qsort ((Elf64_External_Rel *) s->contents + 1,
- (size_t) s->reloc_count - 1,
+ qsort ((Elf64_External_Rel *) s->contents + 1, s->reloc_count - 1,
sizeof (Elf64_Mips_External_Rel), sort_dynamic_relocs_64);
else
- qsort ((Elf32_External_Rel *) s->contents + 1,
- (size_t) s->reloc_count - 1,
+ qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1,
sizeof (Elf32_External_Rel), sort_dynamic_relocs);
}
}
/* Set ABFD's EF_MIPS_ARCH and EF_MIPS_MACH flags. */
static void
-mips_set_isa_flags (abfd)
- bfd *abfd;
+mips_set_isa_flags (bfd *abfd)
{
flagword val;
break;
case bfd_mach_mips5000:
+ case bfd_mach_mips7000:
case bfd_mach_mips8000:
case bfd_mach_mips10000:
case bfd_mach_mips12000:
case bfd_mach_mipsisa32r2:
val = E_MIPS_ARCH_32R2;
break;
+
+ case bfd_mach_mipsisa64r2:
+ val = E_MIPS_ARCH_64R2;
+ break;
}
elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
elf_elfheader (abfd)->e_flags |= val;
number. This is used by both the 32-bit and the 64-bit ABI. */
void
-_bfd_mips_elf_final_write_processing (abfd, linker)
- bfd *abfd;
- bfd_boolean linker ATTRIBUTE_UNUSED;
+_bfd_mips_elf_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
{
unsigned int i;
Elf_Internal_Shdr **hdrpp;
segments. */
int
-_bfd_mips_elf_additional_program_headers (abfd)
- bfd *abfd;
+_bfd_mips_elf_additional_program_headers (bfd *abfd)
{
asection *s;
int ret = 0;
/* Modify the segment map for an IRIX5 executable. */
bfd_boolean
-_bfd_mips_elf_modify_segment_map (abfd)
- bfd *abfd;
+_bfd_mips_elf_modify_segment_map (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
asection *s;
struct elf_segment_map *m, **pm;
if (m == NULL)
{
amt = sizeof *m;
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
return FALSE;
/* For IRIX 6, we don't have .mdebug sections, nor does anything but
.dynamic end up in PT_DYNAMIC. However, we do have to insert a
- PT_OPTIONS segment immediately following the program header
+ PT_MIPS_OPTIONS segment immediately following the program header
table. */
if (NEWABI_P (abfd)
/* On non-IRIX6 new abi, we'll have already created a segment
{
struct elf_segment_map *options_segment;
- /* Usually, there's a program header table. But, sometimes
- there's not (like when running the `ld' testsuite). So,
- if there's no program header table, we just put the
- options segment at the end. */
- for (pm = &elf_tdata (abfd)->segment_map;
- *pm != NULL;
- pm = &(*pm)->next)
- if ((*pm)->p_type == PT_PHDR)
- break;
+ pm = &elf_tdata (abfd)->segment_map;
+ while (*pm != NULL
+ && ((*pm)->p_type == PT_PHDR
+ || (*pm)->p_type == PT_INTERP))
+ pm = &(*pm)->next;
amt = sizeof (struct elf_segment_map);
options_segment = bfd_zalloc (abfd, amt);
if (m == NULL)
{
amt = sizeof *m;
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
return FALSE;
unsigned int i, c;
struct elf_segment_map *n;
- low = 0xffffffff;
+ low = ~(bfd_vma) 0;
high = 0;
for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
{
if (low > s->vma)
low = s->vma;
- sz = s->_cooked_size;
- if (sz == 0)
- sz = s->_raw_size;
+ sz = s->size;
if (high < s->vma + sz)
high = s->vma + sz;
}
for (s = abfd->sections; s != NULL; s = s->next)
if ((s->flags & SEC_LOAD) != 0
&& s->vma >= low
- && ((s->vma
- + (s->_cooked_size !=
- 0 ? s->_cooked_size : s->_raw_size)) <= high))
+ && s->vma + s->size <= high)
++c;
amt = sizeof *n + (bfd_size_type) (c - 1) * sizeof (asection *);
- n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ n = bfd_zalloc (abfd, amt);
if (n == NULL)
return FALSE;
*n = *m;
{
if ((s->flags & SEC_LOAD) != 0
&& s->vma >= low
- && ((s->vma
- + (s->_cooked_size != 0 ?
- s->_cooked_size : s->_raw_size)) <= high))
+ && s->vma + s->size <= high)
{
n->sections[i] = s;
++i;
relocation. */
asection *
-_bfd_mips_elf_gc_mark_hook (sec, info, rel, h, sym)
- asection *sec;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+_bfd_mips_elf_gc_mark_hook (asection *sec,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
/* ??? Do mips16 stub sections need to be handled special? */
/* Update the got entry reference counts for the section being removed. */
bfd_boolean
-_bfd_mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+_bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
{
#if 0
Elf_Internal_Shdr *symtab_hdr;
_bfd_elf_link_hash_copy_indirect copy the flags for us. */
void
-_bfd_mips_elf_copy_indirect_symbol (bed, dir, ind)
- struct elf_backend_data *bed;
- struct elf_link_hash_entry *dir, *ind;
+_bfd_mips_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
{
struct mips_elf_link_hash_entry *dirmips, *indmips;
dirmips->possibly_dynamic_relocs += indmips->possibly_dynamic_relocs;
if (indmips->readonly_reloc)
dirmips->readonly_reloc = TRUE;
- if (dirmips->min_dyn_reloc_index == 0
- || (indmips->min_dyn_reloc_index != 0
- && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
- dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
if (indmips->no_fn_stub)
dirmips->no_fn_stub = TRUE;
}
void
-_bfd_mips_elf_hide_symbol (info, entry, force_local)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *entry;
- bfd_boolean force_local;
+_bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *entry,
+ bfd_boolean force_local)
{
bfd *dynobj;
asection *got;
h = (struct mips_elf_link_hash_entry *) entry;
if (h->forced_local)
return;
- h->forced_local = TRUE;
+ h->forced_local = force_local;
dynobj = elf_hash_table (info)->dynobj;
- got = mips_elf_got_section (dynobj, FALSE);
- g = mips_elf_section_data (got)->u.got_info;
-
- if (g->next)
+ if (dynobj != NULL && force_local)
{
- struct mips_got_entry e;
- struct mips_got_info *gg = g;
+ got = mips_elf_got_section (dynobj, FALSE);
+ g = mips_elf_section_data (got)->u.got_info;
- /* Since we're turning what used to be a global symbol into a
- local one, bump up the number of local entries of each GOT
- that had an entry for it. This will automatically decrease
- the number of global entries, since global_gotno is actually
- the upper limit of global entries. */
- e.abfd = dynobj;
- e.symndx = -1;
- e.d.h = h;
+ if (g->next)
+ {
+ struct mips_got_entry e;
+ struct mips_got_info *gg = g;
+
+ /* Since we're turning what used to be a global symbol into a
+ local one, bump up the number of local entries of each GOT
+ that had an entry for it. This will automatically decrease
+ the number of global entries, since global_gotno is actually
+ the upper limit of global entries. */
+ e.abfd = dynobj;
+ e.symndx = -1;
+ e.d.h = h;
- for (g = g->next; g != gg; g = g->next)
- if (htab_find (g->got_entries, &e))
- {
- BFD_ASSERT (g->global_gotno > 0);
- g->local_gotno++;
- g->global_gotno--;
- }
+ for (g = g->next; g != gg; g = g->next)
+ if (htab_find (g->got_entries, &e))
+ {
+ BFD_ASSERT (g->global_gotno > 0);
+ g->local_gotno++;
+ g->global_gotno--;
+ }
- /* If this was a global symbol forced into the primary GOT, we
- no longer need an entry for it. We can't release the entry
- at this point, but we must at least stop counting it as one
- of the symbols that required a forced got entry. */
- if (h->root.got.offset == 2)
+ /* If this was a global symbol forced into the primary GOT, we
+ no longer need an entry for it. We can't release the entry
+ at this point, but we must at least stop counting it as one
+ of the symbols that required a forced got entry. */
+ if (h->root.got.offset == 2)
+ {
+ BFD_ASSERT (gg->assigned_gotno > 0);
+ gg->assigned_gotno--;
+ }
+ }
+ else if (g->global_gotno == 0 && g->global_gotsym == NULL)
+ /* If we haven't got through GOT allocation yet, just bump up the
+ number of local entries, as this symbol won't be counted as
+ global. */
+ g->local_gotno++;
+ else if (h->root.got.offset == 1)
{
- BFD_ASSERT (gg->assigned_gotno > 0);
- gg->assigned_gotno--;
+ /* If we're past non-multi-GOT allocation and this symbol had
+ been marked for a global got entry, give it a local entry
+ instead. */
+ BFD_ASSERT (g->global_gotno > 0);
+ g->local_gotno++;
+ g->global_gotno--;
}
}
- else if (g->global_gotno == 0 && g->global_gotsym == NULL)
- /* If we haven't got through GOT allocation yet, just bump up the
- number of local entries, as this symbol won't be counted as
- global. */
- g->local_gotno++;
- else if (h->root.got.offset == 1)
- {
- /* If we're past non-multi-GOT allocation and this symbol had
- been marked for a global got entry, give it a local entry
- instead. */
- BFD_ASSERT (g->global_gotno > 0);
- g->local_gotno++;
- g->global_gotno--;
- }
_bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
}
#define PDR_SIZE 32
bfd_boolean
-_bfd_mips_elf_discard_info (abfd, cookie, info)
- bfd *abfd;
- struct elf_reloc_cookie *cookie;
- struct bfd_link_info *info;
+_bfd_mips_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
+ struct bfd_link_info *info)
{
asection *o;
bfd_boolean ret = FALSE;
o = bfd_get_section_by_name (abfd, ".pdr");
if (! o)
return FALSE;
- if (o->_raw_size == 0)
+ if (o->size == 0)
return FALSE;
- if (o->_raw_size % PDR_SIZE != 0)
+ if (o->size % PDR_SIZE != 0)
return FALSE;
if (o->output_section != NULL
&& bfd_is_abs_section (o->output_section))
return FALSE;
- tdata = bfd_zmalloc (o->_raw_size / PDR_SIZE);
+ tdata = bfd_zmalloc (o->size / PDR_SIZE);
if (! tdata)
return FALSE;
- cookie->rels = (MNAME(abfd,_bfd_elf,link_read_relocs)
- (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory));
+ cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+ info->keep_memory);
if (!cookie->rels)
{
free (tdata);
cookie->rel = cookie->rels;
cookie->relend = cookie->rels + o->reloc_count;
- for (i = 0, skip = 0; i < o->_raw_size; i ++)
+ for (i = 0, skip = 0; i < o->size / PDR_SIZE; i ++)
{
- if (MNAME(abfd,_bfd_elf,reloc_symbol_deleted_p) (i * PDR_SIZE, cookie))
+ if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
{
tdata[i] = 1;
skip ++;
if (skip != 0)
{
mips_elf_section_data (o)->u.tdata = tdata;
- o->_cooked_size = o->_raw_size - skip * PDR_SIZE;
+ o->size -= skip * PDR_SIZE;
ret = TRUE;
}
else
}
bfd_boolean
-_bfd_mips_elf_ignore_discarded_relocs (sec)
- asection *sec;
+_bfd_mips_elf_ignore_discarded_relocs (asection *sec)
{
if (strcmp (sec->name, ".pdr") == 0)
return TRUE;
}
bfd_boolean
-_bfd_mips_elf_write_section (output_bfd, sec, contents)
- bfd *output_bfd;
- asection *sec;
- bfd_byte *contents;
+_bfd_mips_elf_write_section (bfd *output_bfd, asection *sec,
+ bfd_byte *contents)
{
bfd_byte *to, *from, *end;
int i;
return FALSE;
to = contents;
- end = contents + sec->_raw_size;
+ end = contents + sec->size;
for (from = contents, i = 0;
from < end;
from += PDR_SIZE, i++)
to += PDR_SIZE;
}
bfd_set_section_contents (output_bfd, sec->output_section, contents,
- (file_ptr) sec->output_offset,
- sec->_cooked_size);
+ sec->output_offset, sec->size);
return TRUE;
}
\f
};
bfd_boolean
-_bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
- functionname_ptr, line_ptr)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- const char **filename_ptr;
- const char **functionname_ptr;
- unsigned int *line_ptr;
+_bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section,
+ asymbol **symbols, bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr)
{
asection *msec;
if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
filename_ptr, functionname_ptr,
- line_ptr,
- (unsigned) (ABI_64_P (abfd) ? 8 : 0),
+ line_ptr, ABI_64_P (abfd) ? 8 : 0,
&elf_tdata (abfd)->dwarf2_find_line_info))
return TRUE;
struct fdr *fdr_ptr;
bfd_size_type amt = sizeof (struct mips_elf_find_line);
- fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
+ fi = bfd_zalloc (abfd, amt);
if (fi == NULL)
{
msec->flags = origflags;
/* Swap in the FDR information. */
amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
- fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
+ fi->d.fdr = bfd_alloc (abfd, amt);
if (fi->d.fdr == NULL)
{
msec->flags = origflags;
fraw_end = (fraw_src
+ fi->d.symbolic_header.ifdMax * external_fdr_size);
for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
- (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+ (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
elf_tdata (abfd)->find_line_info = fi;
GP value in the section_processing routine. */
bfd_boolean
-_bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
+_bfd_mips_elf_set_section_contents (bfd *abfd, sec_ptr section,
+ const void *location,
+ file_ptr offset, bfd_size_type count)
{
if (strcmp (section->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
{
if (elf_section_data (section) == NULL)
{
bfd_size_type amt = sizeof (struct bfd_elf_section_data);
- section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
+ section->used_by_bfd = bfd_zalloc (abfd, amt);
if (elf_section_data (section) == NULL)
return FALSE;
}
c = mips_elf_section_data (section)->u.tdata;
if (c == NULL)
{
- bfd_size_type size;
-
- if (section->_cooked_size != 0)
- size = section->_cooked_size;
- else
- size = section->_raw_size;
- c = (bfd_byte *) bfd_zalloc (abfd, size);
+ c = bfd_zalloc (abfd, section->size);
if (c == NULL)
return FALSE;
mips_elf_section_data (section)->u.tdata = c;
}
- memcpy (c + offset, location, (size_t) count);
+ memcpy (c + offset, location, count);
}
return _bfd_elf_set_section_contents (abfd, section, location, offset,
MIPS relocations need to be handled specially. Sigh. */
bfd_byte *
-_bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
- data, relocateable, symbols)
- bfd *abfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- bfd_boolean relocateable;
- asymbol **symbols;
+_bfd_elf_mips_get_relocated_section_contents
+ (bfd *abfd,
+ struct bfd_link_info *link_info,
+ struct bfd_link_order *link_order,
+ bfd_byte *data,
+ bfd_boolean relocatable,
+ asymbol **symbols)
{
/* Get enough memory to hold the stuff */
bfd *input_bfd = link_order->u.indirect.section->owner;
asection *input_section = link_order->u.indirect.section;
+ bfd_size_type sz;
long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
arelent **reloc_vector = NULL;
if (reloc_size < 0)
goto error_return;
- reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
+ reloc_vector = bfd_malloc (reloc_size);
if (reloc_vector == NULL && reloc_size != 0)
goto error_return;
/* read in the section */
- if (!bfd_get_section_contents (input_bfd,
- input_section,
- (PTR) data,
- (file_ptr) 0,
- input_section->_raw_size))
+ sz = input_section->rawsize ? input_section->rawsize : input_section->size;
+ if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
goto error_return;
- /* We're not relaxing the section, so just copy the size info */
- input_section->_cooked_size = input_section->_raw_size;
- input_section->reloc_done = TRUE;
-
reloc_count = bfd_canonicalize_reloc (input_bfd,
input_section,
reloc_vector,
gp_found = 0;
}
/* end mips */
- for (parent = reloc_vector; *parent != (arelent *) NULL;
- parent++)
+ for (parent = reloc_vector; *parent != NULL; parent++)
{
- char *error_message = (char *) NULL;
+ char *error_message = NULL;
bfd_reloc_status_type r;
/* Specific to MIPS: Deal with relocation types that require
{
/* bypass special_function call */
r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent,
- input_section, relocateable,
- (PTR) data, gp);
+ input_section, relocatable,
+ data, gp);
goto skip_bfd_perform_relocation;
}
/* end mips specific stuff */
- r = bfd_perform_relocation (input_bfd,
- *parent,
- (PTR) data,
- input_section,
- relocateable ? abfd : (bfd *) NULL,
+ r = bfd_perform_relocation (input_bfd, *parent, data, input_section,
+ relocatable ? abfd : NULL,
&error_message);
skip_bfd_perform_relocation:
- if (relocateable)
+ if (relocatable)
{
asection *os = input_section->output_section;
goto error_return;
break;
case bfd_reloc_dangerous:
- BFD_ASSERT (error_message != (char *) NULL);
+ BFD_ASSERT (error_message != NULL);
if (!((*link_info->callbacks->reloc_dangerous)
(link_info, error_message, input_bfd, input_section,
(*parent)->address)))
break;
case bfd_reloc_overflow:
if (!((*link_info->callbacks->reloc_overflow)
- (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+ (link_info, NULL,
+ bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
(*parent)->howto->name, (*parent)->addend,
input_bfd, input_section, (*parent)->address)))
goto error_return;
/* Create a MIPS ELF linker hash table. */
struct bfd_link_hash_table *
-_bfd_mips_elf_link_hash_table_create (abfd)
- bfd *abfd;
+_bfd_mips_elf_link_hash_table_create (bfd *abfd)
{
struct mips_elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
- ret = (struct mips_elf_link_hash_table *) bfd_malloc (amt);
- if (ret == (struct mips_elf_link_hash_table *) NULL)
+ ret = bfd_malloc (amt);
+ if (ret == NULL)
return NULL;
if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
sections together, not write them all out sequentially. */
bfd_boolean
-_bfd_mips_elf_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+_bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
{
asection **secpp;
asection *o;
asection *rtproc_sec;
Elf32_RegInfo reginfo;
struct ecoff_debug_info debug;
- const struct ecoff_debug_swap *swap
- = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
HDRR *symhdr = &debug.symbolic_header;
- PTR mdebug_handle = NULL;
+ void *mdebug_handle = NULL;
asection *s;
EXTR esym;
unsigned int i;
scRData, scSData, scSBss, scBss
};
- /* If all the things we linked together were PIC, but we're
- producing an executable (rather than a shared object), then the
- resulting file is CPIC (i.e., it calls PIC code.) */
- if (!info->shared
- && !info->relocateable
- && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
- {
- elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
- elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
- }
-
/* We'd carefully arranged the dynamic symbol indices, and then the
generic size_dynamic_sections renumbered them out from under us.
Rather than trying somehow to prevent the renumbering, just do
bfd *dynobj;
asection *got;
struct mips_got_info *g;
+ bfd_size_type dynsecsymcount;
/* When we resort, we must tell mips_elf_sort_hash_table what
the lowest index it may use is. That's the number of section
adds these symbols when building a shared object. Note that
we count the sections after (possibly) removing the .options
section above. */
- if (! mips_elf_sort_hash_table (info, (info->shared
- ? bfd_count_sections (abfd) + 1
- : 1)))
+
+ dynsecsymcount = 0;
+ if (info->shared)
+ {
+ asection * p;
+
+ for (p = abfd->sections; p ; p = p->next)
+ if ((p->flags & SEC_EXCLUDE) == 0
+ && (p->flags & SEC_ALLOC) != 0
+ && !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
+ ++ dynsecsymcount;
+ }
+
+ if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
return FALSE;
/* Make sure we didn't grow the global .got region. */
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
- if (h != (struct bfd_link_hash_entry *) NULL
- && h->type == bfd_link_hash_defined)
+ if (h != NULL && h->type == bfd_link_hash_defined)
elf_gp (abfd) = (h->u.def.value
+ h->u.def.section->output_section->vma
+ h->u.def.section->output_offset);
- else if (info->relocateable)
+ else if (info->relocatable)
{
bfd_vma lo = MINUS_ONE;
/* Find the GP-relative section with the lowest offset. */
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ for (o = abfd->sections; o != NULL; o = o->next)
if (o->vma < lo
&& (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
lo = o->vma;
mdebug_sec = NULL;
gptab_data_sec = NULL;
gptab_bss_sec = NULL;
- for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ for (o = abfd->sections; o != NULL; o = o->next)
{
if (strcmp (o->name, ".reginfo") == 0)
{
/* We have found the .reginfo section in the output file.
Look through all the link_orders comprising it and merge
the information together. */
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
+ for (p = o->link_order_head; p != NULL; p = p->next)
{
asection *input_section;
bfd *input_bfd;
input_section = p->u.indirect.section;
input_bfd = input_section->owner;
- /* The linker emulation code has probably clobbered the
- size to be zero bytes. */
- if (input_section->_raw_size == 0)
- input_section->_raw_size = sizeof (Elf32_External_RegInfo);
-
if (! bfd_get_section_contents (input_bfd, input_section,
- (PTR) &ext,
- (file_ptr) 0,
- (bfd_size_type) sizeof ext))
+ &ext, 0, sizeof ext))
return FALSE;
bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);
}
/* Size has been set in _bfd_mips_elf_always_size_sections. */
- BFD_ASSERT(o->_raw_size == sizeof (Elf32_External_RegInfo));
+ BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
/* Skip this section later on (I don't think this currently
matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
+ o->link_order_head = NULL;
reginfo_sec = o;
}
debug.external_ext = debug.external_ext_end = NULL;
mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
- if (mdebug_handle == (PTR) NULL)
+ if (mdebug_handle == NULL)
return FALSE;
esym.jmptbl = 0;
if (s != NULL)
{
esym.asym.value = s->vma;
- last = s->vma + s->_raw_size;
+ last = s->vma + s->size;
}
else
esym.asym.value = last;
return FALSE;
}
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
+ for (p = o->link_order_head; p != NULL; p = p->next)
{
asection *input_section;
bfd *input_bfd;
input_swap = (get_elf_backend_data (input_bfd)
->elf_backend_ecoff_debug_swap);
- BFD_ASSERT (p->size == input_section->_raw_size);
+ BFD_ASSERT (p->size == input_section->size);
/* The ECOFF linking code expects that we have already
read in the debugging information and set up an
const char *name;
struct mips_elf_link_hash_entry *h;
- (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
+ (*input_swap->swap_ext_in) (input_bfd, eraw_src, &ext);
if (ext.asym.sc == scNil
|| ext.asym.sc == scUndefined
|| ext.asym.sc == scSUndefined)
einfo.swap = swap;
einfo.failed = FALSE;
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
- mips_elf_output_extsym,
- (PTR) &einfo);
+ mips_elf_output_extsym, &einfo);
if (einfo.failed)
return FALSE;
/* Set the size of the .mdebug section. */
- o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
+ o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
/* Skip this section later on (I don't think this currently
matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
+ o->link_order_head = NULL;
mdebug_sec = o;
}
information describing how the small data area would
change depending upon the -G switch. These sections
not used in executables files. */
- if (! info->relocateable)
+ if (! info->relocatable)
{
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
+ for (p = o->link_order_head; p != NULL; p = p->next)
{
asection *input_section;
/* Skip this section later on (I don't think this
currently matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
+ o->link_order_head = NULL;
/* Really remove the section. */
for (secpp = &abfd->sections;
/* Set up the first entry. */
c = 1;
amt = c * sizeof (Elf32_gptab);
- tab = (Elf32_gptab *) bfd_malloc (amt);
+ tab = bfd_malloc (amt);
if (tab == NULL)
return FALSE;
tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
tab[0].gt_header.gt_unused = 0;
/* Combine the input sections. */
- for (p = o->link_order_head;
- p != (struct bfd_link_order *) NULL;
- p = p->next)
+ for (p = o->link_order_head; p != NULL; p = p->next)
{
asection *input_section;
bfd *input_bfd;
/* Combine the gptab entries for this input section one
by one. We know that the input gptab entries are
sorted by ascending -G value. */
- size = bfd_section_size (input_bfd, input_section);
+ size = input_section->size;
last = 0;
for (gpentry = sizeof (Elf32_External_gptab);
gpentry < size;
unsigned int look;
if (! (bfd_get_section_contents
- (input_bfd, input_section, (PTR) &ext_gptab,
- (file_ptr) gpentry,
- (bfd_size_type) sizeof (Elf32_External_gptab))))
+ (input_bfd, input_section, &ext_gptab, gpentry,
+ sizeof (Elf32_External_gptab))))
{
free (tab);
return FALSE;
/* We need a new table entry. */
amt = (bfd_size_type) (c + 1) * sizeof (Elf32_gptab);
- new_tab = (Elf32_gptab *) bfd_realloc ((PTR) tab, amt);
+ new_tab = bfd_realloc (tab, amt);
if (new_tab == NULL)
{
free (tab);
/* Swap out the table. */
amt = (bfd_size_type) c * sizeof (Elf32_External_gptab);
- ext_tab = (Elf32_External_gptab *) bfd_alloc (abfd, amt);
+ ext_tab = bfd_alloc (abfd, amt);
if (ext_tab == NULL)
{
free (tab);
bfd_mips_elf32_swap_gptab_out (abfd, tab + j, ext_tab + j);
free (tab);
- o->_raw_size = c * sizeof (Elf32_External_gptab);
+ o->size = c * sizeof (Elf32_External_gptab);
o->contents = (bfd_byte *) ext_tab;
/* Skip this section later on (I don't think this currently
matters, but someday it might). */
- o->link_order_head = (struct bfd_link_order *) NULL;
+ o->link_order_head = NULL;
}
}
/* Invoke the regular ELF backend linker to do all the work. */
- if (!MNAME(abfd,bfd_elf,bfd_final_link) (abfd, info))
+ if (!bfd_elf_final_link (abfd, info))
return FALSE;
/* Now write out the computed sections. */
- if (reginfo_sec != (asection *) NULL)
+ if (reginfo_sec != NULL)
{
Elf32_External_RegInfo ext;
bfd_mips_elf32_swap_reginfo_out (abfd, ®info, &ext);
- if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext,
- (file_ptr) 0,
- (bfd_size_type) sizeof ext))
+ if (! bfd_set_section_contents (abfd, reginfo_sec, &ext, 0, sizeof ext))
return FALSE;
}
- if (mdebug_sec != (asection *) NULL)
+ if (mdebug_sec != NULL)
{
BFD_ASSERT (abfd->output_has_begun);
if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
}
- if (gptab_data_sec != (asection *) NULL)
+ if (gptab_data_sec != NULL)
{
if (! bfd_set_section_contents (abfd, gptab_data_sec,
gptab_data_sec->contents,
- (file_ptr) 0,
- gptab_data_sec->_raw_size))
+ 0, gptab_data_sec->size))
return FALSE;
}
- if (gptab_bss_sec != (asection *) NULL)
+ if (gptab_bss_sec != NULL)
{
if (! bfd_set_section_contents (abfd, gptab_bss_sec,
gptab_bss_sec->contents,
- (file_ptr) 0,
- gptab_bss_sec->_raw_size))
+ 0, gptab_bss_sec->size))
return FALSE;
}
{
if (! bfd_set_section_contents (abfd, rtproc_sec,
rtproc_sec->contents,
- (file_ptr) 0,
- rtproc_sec->_raw_size))
+ 0, rtproc_sec->size))
return FALSE;
}
}
static const struct mips_mach_extension mips_mach_extensions[] = {
/* MIPS64 extensions. */
+ { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
{ bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
/* MIPS V extensions. */
{ bfd_mach_mips5, bfd_mach_mips8000 },
{ bfd_mach_mips10000, bfd_mach_mips8000 },
{ bfd_mach_mips5000, bfd_mach_mips8000 },
+ { bfd_mach_mips7000, bfd_mach_mips8000 },
/* VR4100 extensions. */
{ bfd_mach_mips4120, bfd_mach_mips4100 },
/* Return true if bfd machine EXTENSION is an extension of machine BASE. */
static bfd_boolean
-mips_mach_extends_p (base, extension)
- unsigned long base, extension;
+mips_mach_extends_p (unsigned long base, unsigned long extension)
{
size_t i;
/* Return true if the given ELF header flags describe a 32-bit binary. */
static bfd_boolean
-mips_32bit_flags_p (flags)
- flagword flags;
+mips_32bit_flags_p (flagword flags)
{
return ((flags & EF_MIPS_32BITMODE) != 0
|| (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
object file when linking. */
bfd_boolean
-_bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
+_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
{
flagword old_flags;
flagword new_flags;
/* Check if we have the same endianess */
if (! _bfd_generic_verify_endian_match (ibfd, obfd))
- return FALSE;
+ {
+ (*_bfd_error_handler)
+ (_("%B: endianness incompatible with that of the selected emulation"),
+ ibfd);
+ return FALSE;
+ }
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
+ if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
+ {
+ (*_bfd_error_handler)
+ (_("%B: ABI is incompatible with that of the selected emulation"),
+ ibfd);
+ return FALSE;
+ }
+
new_flags = elf_elfheader (ibfd)->e_flags;
elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
old_flags = elf_elfheader (obfd)->e_flags;
new_flags &= ~EF_MIPS_XGOT;
old_flags &= ~EF_MIPS_XGOT;
+ /* MIPSpro generates ucode info in n64 objects. Again, we should
+ just be able to ignore this. */
+ new_flags &= ~EF_MIPS_UCODE;
+ old_flags &= ~EF_MIPS_UCODE;
+
if (new_flags == old_flags)
return TRUE;
which are automatically generated by gas. */
if (strcmp (sec->name, ".reginfo")
&& strcmp (sec->name, ".mdebug")
- && ((!strcmp (sec->name, ".text")
- || !strcmp (sec->name, ".data")
- || !strcmp (sec->name, ".bss"))
- && sec->_raw_size != 0))
+ && (sec->size != 0
+ || (strcmp (sec->name, ".text")
+ && strcmp (sec->name, ".data")
+ && strcmp (sec->name, ".bss"))))
{
null_input_bfd = FALSE;
break;
ok = TRUE;
- if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
+ if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
+ != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
{
- new_flags &= ~EF_MIPS_PIC;
- old_flags &= ~EF_MIPS_PIC;
(*_bfd_error_handler)
- (_("%s: linking PIC files with non-PIC files"),
- bfd_archive_filename (ibfd));
- ok = FALSE;
+ (_("%B: warning: linking PIC files with non-PIC files"),
+ ibfd);
+ ok = TRUE;
}
- if ((new_flags & EF_MIPS_CPIC) != (old_flags & EF_MIPS_CPIC))
- {
- new_flags &= ~EF_MIPS_CPIC;
- old_flags &= ~EF_MIPS_CPIC;
- (*_bfd_error_handler)
- (_("%s: linking abicalls files with non-abicalls files"),
- bfd_archive_filename (ibfd));
- ok = FALSE;
- }
+ if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
+ elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
+ if (! (new_flags & EF_MIPS_PIC))
+ elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
+
+ new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+ old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
/* Compare the ISAs. */
if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
{
(*_bfd_error_handler)
- (_("%s: linking 32-bit code with 64-bit code"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking 32-bit code with 64-bit code"),
+ ibfd);
ok = FALSE;
}
else if (!mips_mach_extends_p (bfd_get_mach (ibfd), bfd_get_mach (obfd)))
{
/* The ISAs aren't compatible. */
(*_bfd_error_handler)
- (_("%s: linking %s module with previous %s modules"),
- bfd_archive_filename (ibfd),
+ (_("%B: linking %s module with previous %s modules"),
+ ibfd,
bfd_printable_name (ibfd),
bfd_printable_name (obfd));
ok = FALSE;
!= elf_elfheader (obfd)->e_ident[EI_CLASS]))
{
(*_bfd_error_handler)
- (_("%s: ABI mismatch: linking %s module with previous %s modules"),
- bfd_archive_filename (ibfd),
+ (_("%B: ABI mismatch: linking %s module with previous %s modules"),
+ ibfd,
elf_mips_abi_name (ibfd),
elf_mips_abi_name (obfd));
ok = FALSE;
if (new_flags != old_flags)
{
(*_bfd_error_handler)
- (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
- bfd_archive_filename (ibfd), (unsigned long) new_flags,
+ (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
+ ibfd, (unsigned long) new_flags,
(unsigned long) old_flags);
ok = FALSE;
}
/* Function to keep MIPS specific file flags like as EF_MIPS_PIC. */
bfd_boolean
-_bfd_mips_elf_set_private_flags (abfd, flags)
- bfd *abfd;
- flagword flags;
+_bfd_mips_elf_set_private_flags (bfd *abfd, flagword flags)
{
BFD_ASSERT (!elf_flags_init (abfd)
|| elf_elfheader (abfd)->e_flags == flags);
}
bfd_boolean
-_bfd_mips_elf_print_private_bfd_data (abfd, ptr)
- bfd *abfd;
- PTR ptr;
+_bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
{
- FILE *file = (FILE *) ptr;
+ FILE *file = ptr;
BFD_ASSERT (abfd != NULL && ptr != NULL);
fprintf (file, _(" [mips64]"));
else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2)
fprintf (file, _(" [mips32r2]"));
+ else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
+ fprintf (file, _(" [mips64r2]"));
else
fprintf (file, _(" [unknown ISA]"));
return TRUE;
}
+
+struct bfd_elf_special_section const _bfd_mips_elf_special_sections[]=
+{
+ { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+ { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+ { ".lit4", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+ { ".lit8", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
+ { ".ucode", 6, 0, SHT_MIPS_UCODE, 0 },
+ { ".mdebug", 7, 0, SHT_MIPS_DEBUG, 0 },
+ { NULL, 0, 0, 0, 0 }
+};