X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-mips.c;h=b17008eaaa42634f9fe4deb1f5ca3bfe54168768;hb=3a16a68c4f0cdabb4c9a77ffd7b70f2c78d54e98;hp=95eabc9a09544534707adbdcb1b2d7e130b6636c;hpb=c6e90b027b91f0b15fd90bcacfd602eca768e4d7;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 95eabc9a09..b17008eaaa 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1,6 +1,6 @@ /* MIPS-specific support for 32-bit ELF - Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003 Free Software Foundation, Inc. Most of the information added by Ian Lance Taylor, Cygnus Support, . @@ -47,12 +47,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ECOFF_SIGNED_32 #include "ecoffswap.h" +static bfd_reloc_status_type mips_elf_generic_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips_elf_hi16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips_elf_lo16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips_elf_got16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type gprel32_with_gp + PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR, + bfd_vma)); static bfd_reloc_status_type mips_elf_gprel32_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips32_64bit_reloc @@ -60,193 +65,46 @@ static bfd_reloc_status_type mips32_64bit_reloc static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); static reloc_howto_type *mips_elf32_rtype_to_howto - PARAMS ((unsigned int, boolean)); + PARAMS ((unsigned int, bfd_boolean)); static void mips_info_to_howto_rel - PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *)); + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); static void mips_info_to_howto_rela - PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); -static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *)); -static boolean mips_elf32_object_p PARAMS ((bfd *)); -static boolean mips_elf_is_local_label_name + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); +static bfd_boolean mips_elf_sym_is_global + PARAMS ((bfd *, asymbol *)); +static bfd_boolean mips_elf32_object_p + PARAMS ((bfd *)); +static bfd_boolean mips_elf_is_local_label_name PARAMS ((bfd *, const char *)); static bfd_reloc_status_type mips16_jump_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips16_gprel_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type mips_elf_final_gp - PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *)); -static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *)); -static boolean elf32_mips_grok_prstatus + PARAMS ((bfd *, asymbol *, bfd_boolean, char **, bfd_vma *)); +static bfd_boolean mips_elf_assign_gp + PARAMS ((bfd *, bfd_vma *)); +static bfd_boolean elf32_mips_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *)); -static boolean elf32_mips_grok_psinfo +static bfd_boolean elf32_mips_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *)); -static boolean elf32_mips_discard_info - PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *)); -static boolean elf32_mips_ignore_discarded_relocs - PARAMS ((asection *)); -static boolean elf32_mips_write_section - PARAMS ((bfd *, asection *, bfd_byte *)); static irix_compat_t elf32_mips_irix_compat PARAMS ((bfd *)); -extern const bfd_target bfd_elf32_tradbigmips_vec; -extern const bfd_target bfd_elf32_tradlittlemips_vec; +extern const bfd_target bfd_elf32_bigmips_vec; +extern const bfd_target bfd_elf32_littlemips_vec; /* Nonzero if ABFD is using the N32 ABI. */ - #define ABI_N32_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) -/* Nonzero if ABFD is using the 64-bit ABI. */ -#define ABI_64_P(abfd) \ - ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0) - -#define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd)) - /* Whether we are trying to be compatible with IRIX at all. */ #define SGI_COMPAT(abfd) \ (elf32_mips_irix_compat (abfd) != ict_none) -/* The size of an external REL relocation. */ -#define MIPS_ELF_REL_SIZE(abfd) \ - (get_elf_backend_data (abfd)->s->sizeof_rel) - /* The number of local .got entries we reserve. */ #define MIPS_RESERVED_GOTNO (2) -#if 0 -/* We no longer try to identify particular sections for the .dynsym - section. When we do, we wind up crashing if there are other random - sections with relocations. */ - -/* Names of sections which appear in the .dynsym section in an Irix 5 - executable. */ - -static const char * const mips_elf_dynsym_sec_names[] = -{ - ".text", - ".init", - ".fini", - ".data", - ".rodata", - ".sdata", - ".sbss", - ".bss", - NULL -}; - -#define SIZEOF_MIPS_DYNSYM_SECNAMES \ - (sizeof mips_elf_dynsym_sec_names / sizeof mips_elf_dynsym_sec_names[0]) - -/* The number of entries in mips_elf_dynsym_sec_names which go in the - text segment. */ - -#define MIPS_TEXT_DYNSYM_SECNO (3) - -#endif /* 0 */ - -/* The names of the runtime procedure table symbols used on Irix 5. */ - -static const char * const mips_elf_dynsym_rtproc_names[] = -{ - "_procedure_table", - "_procedure_string_table", - "_procedure_table_size", - NULL -}; - -/* These structures are used to generate the .compact_rel section on - Irix 5. */ - -typedef struct -{ - unsigned long id1; /* Always one? */ - unsigned long num; /* Number of compact relocation entries. */ - unsigned long id2; /* Always two? */ - unsigned long offset; /* The file offset of the first relocation. */ - unsigned long reserved0; /* Zero? */ - unsigned long reserved1; /* Zero? */ -} Elf32_compact_rel; - -typedef struct -{ - bfd_byte id1[4]; - bfd_byte num[4]; - bfd_byte id2[4]; - bfd_byte offset[4]; - bfd_byte reserved0[4]; - bfd_byte reserved1[4]; -} Elf32_External_compact_rel; - -typedef struct -{ - unsigned int ctype : 1; /* 1: long 0: short format. See below. */ - unsigned int rtype : 4; /* Relocation types. See below. */ - unsigned int dist2to : 8; - unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */ - unsigned long konst; /* KONST field. See below. */ - unsigned long vaddr; /* VADDR to be relocated. */ -} Elf32_crinfo; - -typedef struct -{ - unsigned int ctype : 1; /* 1: long 0: short format. See below. */ - unsigned int rtype : 4; /* Relocation types. See below. */ - unsigned int dist2to : 8; - unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */ - unsigned long konst; /* KONST field. See below. */ -} Elf32_crinfo2; - -typedef struct -{ - bfd_byte info[4]; - bfd_byte konst[4]; - bfd_byte vaddr[4]; -} Elf32_External_crinfo; - -typedef struct -{ - bfd_byte info[4]; - bfd_byte konst[4]; -} Elf32_External_crinfo2; - -/* These are the constants used to swap the bitfields in a crinfo. */ - -#define CRINFO_CTYPE (0x1) -#define CRINFO_CTYPE_SH (31) -#define CRINFO_RTYPE (0xf) -#define CRINFO_RTYPE_SH (27) -#define CRINFO_DIST2TO (0xff) -#define CRINFO_DIST2TO_SH (19) -#define CRINFO_RELVADDR (0x7ffff) -#define CRINFO_RELVADDR_SH (0) - -/* A compact relocation info has long (3 words) or short (2 words) - formats. A short format doesn't have VADDR field and relvaddr - fields contains ((VADDR - vaddr of the previous entry) >> 2). */ -#define CRF_MIPS_LONG 1 -#define CRF_MIPS_SHORT 0 - -/* There are 4 types of compact relocation at least. The value KONST - has different meaning for each type: - - (type) (konst) - CT_MIPS_REL32 Address in data - CT_MIPS_WORD Address in word (XXX) - CT_MIPS_GPHI_LO GP - vaddr - CT_MIPS_JMPAD Address to jump - */ - -#define CRT_MIPS_REL32 0xa -#define CRT_MIPS_WORD 0xb -#define CRT_MIPS_GPHI_LO 0xc -#define CRT_MIPS_JMPAD 0xd - -#define mips_elf_set_cr_format(x,format) ((x).ctype = (format)) -#define mips_elf_set_cr_type(x,type) ((x).rtype = (type)) -#define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v)) -#define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2) - /* 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) @@ -260,198 +118,198 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_NONE", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 16 bit relocation. */ HOWTO (R_MIPS_16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 32 bit relocation. */ HOWTO (R_MIPS_32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 32 bit symbol relative relocation. */ HOWTO (R_MIPS_REL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_REL32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 26 bit jump address. */ HOWTO (R_MIPS_26, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ /* This needs complex overflow detection, because the upper four bits must match the PC + 4. */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_26", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x03ffffff, /* src_mask */ 0x03ffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* High 16 bits of symbol value. */ HOWTO (R_MIPS_HI16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips_elf_hi16_reloc, /* special_function */ "R_MIPS_HI16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Low 16 bits of symbol value. */ HOWTO (R_MIPS_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips_elf_lo16_reloc, /* special_function */ "R_MIPS_LO16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* GP relative reference. */ HOWTO (R_MIPS_GPREL16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ _bfd_mips_elf32_gprel16_reloc, /* special_function */ "R_MIPS_GPREL16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Reference to literal section. */ HOWTO (R_MIPS_LITERAL, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ _bfd_mips_elf32_gprel16_reloc, /* special_function */ "R_MIPS_LITERAL", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Reference to global offset table. */ HOWTO (R_MIPS_GOT16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ mips_elf_got16_reloc, /* special_function */ "R_MIPS_GOT16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 16 bit PC relative reference. */ HOWTO (R_MIPS_PC16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_PC16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - true), /* pcrel_offset */ + TRUE), /* pcrel_offset */ /* 16 bit call through global offset table. */ HOWTO (R_MIPS_CALL16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 32 bit GP relative reference. */ HOWTO (R_MIPS_GPREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips_elf_gprel32_reloc, /* special_function */ "R_MIPS_GPREL32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* The remaining relocs are defined on Irix 5, although they are not defined by the ABI. */ @@ -464,15 +322,15 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 5, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 6, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SHIFT5", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x000007c0, /* src_mask */ 0x000007c0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 6 bit shift field. */ /* FIXME: This is not handled correctly; a special function is @@ -481,120 +339,120 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 6, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 6, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SHIFT6", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x000007c4, /* src_mask */ 0x000007c4, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 64 bit relocation. */ HOWTO (R_MIPS_64, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips32_64bit_reloc, /* special_function */ "R_MIPS_64", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Displacement in the global offset table. */ HOWTO (R_MIPS_GOT_DISP, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_DISP", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Displacement to page pointer in the global offset table. */ HOWTO (R_MIPS_GOT_PAGE, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_PAGE", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Offset from page pointer in the global offset table. */ HOWTO (R_MIPS_GOT_OFST, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_OFST", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* High 16 bits of displacement in global offset table. */ HOWTO (R_MIPS_GOT_HI16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_HI16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Low 16 bits of displacement in global offset table. */ HOWTO (R_MIPS_GOT_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_LO16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 64 bit subtraction. Used in the N32 ABI. */ HOWTO (R_MIPS_SUB, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SUB", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Used to cause the linker to insert and delete instructions? */ EMPTY_HOWTO (R_MIPS_INSERT_A), @@ -606,75 +464,75 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_HIGHER", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Get the highest value of a 64 bit addend. */ HOWTO (R_MIPS_HIGHEST, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_HIGHEST", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* High 16 bits of displacement in global offset table. */ HOWTO (R_MIPS_CALL_HI16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_HI16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Low 16 bits of displacement in global offset table. */ HOWTO (R_MIPS_CALL_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_LO16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Section displacement. */ HOWTO (R_MIPS_SCN_DISP, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SCN_DISP", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ EMPTY_HOWTO (R_MIPS_REL16), EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE), @@ -687,15 +545,15 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_JALR", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0x00000000, /* src_mask */ 0x00000000, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ }; /* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This @@ -705,15 +563,15 @@ static reloc_howto_type elf_mips_ctor64_howto = 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ mips32_64bit_reloc, /* special_function */ "R_MIPS_64", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false); /* pcrel_offset */ + FALSE); /* pcrel_offset */ /* The reloc used for the mips16 jump instruction. */ static reloc_howto_type elf_mips16_jump_howto = @@ -721,7 +579,7 @@ static reloc_howto_type elf_mips16_jump_howto = 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ /* This needs complex overflow @@ -729,10 +587,10 @@ static reloc_howto_type elf_mips16_jump_howto = bits must match the PC. */ mips16_jump_reloc, /* special_function */ "R_MIPS16_26", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x3ffffff, /* src_mask */ 0x3ffffff, /* dst_mask */ - false); /* pcrel_offset */ + FALSE); /* pcrel_offset */ /* The reloc used for the mips16 gprel instruction. */ static reloc_howto_type elf_mips16_gprel_howto = @@ -740,15 +598,15 @@ static reloc_howto_type elf_mips16_gprel_howto = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ mips16_gprel_reloc, /* special_function */ "R_MIPS16_GPREL", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x07ff001f, /* src_mask */ 0x07ff001f, /* dst_mask */ - false); /* pcrel_offset */ + FALSE); /* pcrel_offset */ /* GNU extensions for embedded-pic. */ /* High 16 bits of symbol value, pc-relative. */ @@ -757,15 +615,15 @@ static reloc_howto_type elf_mips_gnu_rel_hi16 = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips_elf_hi16_reloc, /* special_function */ "R_MIPS_GNU_REL_HI16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - true); /* pcrel_offset */ + TRUE); /* pcrel_offset */ /* Low 16 bits of symbol value, pc-relative. */ static reloc_howto_type elf_mips_gnu_rel_lo16 = @@ -773,15 +631,15 @@ static reloc_howto_type elf_mips_gnu_rel_lo16 = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ mips_elf_lo16_reloc, /* special_function */ "R_MIPS_GNU_REL_LO16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - true); /* pcrel_offset */ + TRUE); /* pcrel_offset */ /* 16 bit offset for pc-relative branches. */ static reloc_howto_type elf_mips_gnu_rel16_s2 = @@ -789,15 +647,15 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 = 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GNU_REL16_S2", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - true); /* pcrel_offset */ + TRUE); /* pcrel_offset */ /* 64 bit pc-relative. */ static reloc_howto_type elf_mips_gnu_pcrel64 = @@ -805,15 +663,15 @@ static reloc_howto_type elf_mips_gnu_pcrel64 = 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_PC64", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ - true); /* pcrel_offset */ + TRUE); /* pcrel_offset */ /* 32 bit pc-relative. */ static reloc_howto_type elf_mips_gnu_pcrel32 = @@ -821,15 +679,15 @@ static reloc_howto_type elf_mips_gnu_pcrel32 = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_PC32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - true); /* pcrel_offset */ + TRUE); /* pcrel_offset */ /* GNU extension to record C++ vtable hierarchy */ static reloc_howto_type elf_mips_gnu_vtinherit_howto = @@ -837,15 +695,15 @@ static reloc_howto_type elf_mips_gnu_vtinherit_howto = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_MIPS_GNU_VTINHERIT", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false); /* pcrel_offset */ + FALSE); /* pcrel_offset */ /* GNU extension to record C++ vtable member usage */ static reloc_howto_type elf_mips_gnu_vtentry_howto = @@ -853,15 +711,42 @@ static reloc_howto_type elf_mips_gnu_vtentry_howto = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_elf_rel_vtable_reloc_fn, /* special_function */ "R_MIPS_GNU_VTENTRY", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false); /* pcrel_offset */ + FALSE); /* pcrel_offset */ + +/* We use this instead of bfd_elf_generic_reloc because the latter + gets the handling of zero addends wrong. */ +static bfd_reloc_status_type +mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section, + output_bfd, error_message) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc_entry; + asymbol *symbol; + PTR data ATTRIBUTE_UNUSED; + asection *input_section; + bfd *output_bfd; + char **error_message ATTRIBUTE_UNUSED; +{ + /* If we're relocating, and this is an external symbol, we don't want + to change anything. */ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (symbol->flags & BSF_LOCAL) != 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + /* Just go on, nothing to see here. */ + return bfd_reloc_continue; +} /* Do a R_MIPS_HI16 relocation. This has to be done in combination with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to @@ -904,11 +789,11 @@ mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section, bfd_vma relocation; struct mips_hi16 *n; - /* If we're relocating, and this an external symbol, we don't want + /* If we're relocating, and this is an external symbol, we don't want to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (symbol->flags & BSF_LOCAL) != 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -918,21 +803,21 @@ mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section, if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) { - boolean relocateable; + bfd_boolean relocatable; bfd_vma gp; if (ret == bfd_reloc_undefined) abort (); if (output_bfd != NULL) - relocateable = true; + relocatable = TRUE; else { - relocateable = false; + relocatable = FALSE; output_bfd = symbol->section->output_section->owner; } - ret = mips_elf_final_gp (output_bfd, symbol, relocateable, + ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp); if (ret != bfd_reloc_ok) return ret; @@ -1002,41 +887,42 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section, unsigned long vallo; struct mips_hi16 *next; - /* Do the HI16 relocation. Note that we actually don't need - to know anything about the LO16 itself, except where to - find the low 16 bits of the addend needed by the LO16. */ - insn = bfd_get_32 (abfd, l->addr); - vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); - - /* The low order 16 bits are always treated as a signed - value. */ - vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000; - val = ((insn & 0xffff) << 16) + vallo; - val += l->addend; - - /* If PC-relative, we need to subtract out the address of the LO - half of the HI/LO. (The actual relocation is relative - to that instruction.) */ - if (reloc_entry->howto->pc_relative) - val -= reloc_entry->address; - - /* At this point, "val" has the value of the combined HI/LO - pair. If the low order 16 bits (which will be used for - the LO16 insn) are negative, then we will need an - adjustment for the high order 16 bits. */ - val += 0x8000; - val = (val >> 16) & 0xffff; - - insn &= ~ (bfd_vma) 0xffff; - insn |= val; - bfd_put_32 (abfd, (bfd_vma) insn, l->addr); - if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) { gp_disp_relent = *reloc_entry; reloc_entry = &gp_disp_relent; reloc_entry->addend = l->addend; } + else + { + /* Do the HI16 relocation. Note that we actually don't need + to know anything about the LO16 itself, except where to + find the low 16 bits of the addend needed by the LO16. */ + insn = bfd_get_32 (abfd, l->addr); + vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + /* The low order 16 bits are always treated as a signed + value. */ + vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000; + val = ((insn & 0xffff) << 16) + vallo; + val += l->addend; + + /* If PC-relative, we need to subtract out the address of the LO + half of the HI/LO. (The actual relocation is relative + to that instruction.) */ + if (reloc_entry->howto->pc_relative) + val -= reloc_entry->address; + + /* At this point, "val" has the value of the combined HI/LO + pair. If the low order 16 bits (which will be used for + the LO16 insn) are negative, then we will need an + adjustment for the high order 16 bits. */ + val += 0x8000; + val = (val >> 16) & 0xffff; + + insn &= ~ (bfd_vma) 0xffff; + insn |= val; + bfd_put_32 (abfd, (bfd_vma) insn, l->addr); + } next = l->next; free (l); @@ -1052,7 +938,7 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section, /* FIXME: Does this case ever occur? */ - ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp); + ret = mips_elf_final_gp (output_bfd, symbol, TRUE, error_message, &gp); if (ret != bfd_reloc_ok) return ret; @@ -1070,8 +956,8 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section, } /* Now do the LO16 reloc in the usual way. */ - return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message); + return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); } /* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset @@ -1099,30 +985,24 @@ mips_elf_got16_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd; char **error_message; { - /* If we're relocating, and this an external symbol, we don't want + /* If we're relocating, and this is an external symbol, we don't want to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (symbol->flags & BSF_LOCAL) != 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } - /* If we're relocating, and this is a local symbol, we can handle it - just like HI16. */ - if (output_bfd != (bfd *) NULL - && (symbol->flags & BSF_SECTION_SYM) != 0) - return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message); - - abort (); + return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); } -/* Set the GP value for OUTPUT_BFD. Returns false if this is a +/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a dangerous relocation. */ -static boolean +static bfd_boolean mips_elf_assign_gp (output_bfd, pgp) bfd *output_bfd; bfd_vma *pgp; @@ -1134,7 +1014,7 @@ mips_elf_assign_gp (output_bfd, pgp) /* If we've already figured out what GP will be, just return it. */ *pgp = _bfd_get_gp_value (output_bfd); if (*pgp) - return true; + return TRUE; count = bfd_get_symcount (output_bfd); sym = bfd_get_outsymbols (output_bfd); @@ -1164,28 +1044,28 @@ mips_elf_assign_gp (output_bfd, pgp) /* Only get the error once. */ *pgp = 4; _bfd_set_gp_value (output_bfd, *pgp); - return false; + return FALSE; } - return true; + return TRUE; } /* We have to figure out the gp value, so that we can adjust the symbol value correctly. We look up the symbol _gp in the output BFD. If we can't find it, we're stuck. We cache it in the ELF target data. We don't need to adjust the symbol value for an - external symbol if we are producing relocateable output. */ + external symbol if we are producing relocatable output. */ static bfd_reloc_status_type -mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp) +mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, pgp) bfd *output_bfd; asymbol *symbol; - boolean relocateable; + bfd_boolean relocatable; char **error_message; bfd_vma *pgp; { if (bfd_is_und_section (symbol->section) - && ! relocateable) + && ! relocatable) { *pgp = 0; return bfd_reloc_undefined; @@ -1193,10 +1073,10 @@ mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp) *pgp = _bfd_get_gp_value (output_bfd); if (*pgp == 0 - && (! relocateable + && (! relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)) { - if (relocateable) + if (relocatable) { /* Make up a value. */ *pgp = symbol->section->output_section->vma + 0x4000; @@ -1230,46 +1110,40 @@ _bfd_mips_elf32_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd; char **error_message; { - boolean relocateable; + bfd_boolean relocatable; bfd_reloc_status_type ret; bfd_vma gp; - /* If we're relocating, and this is an external symbol with no - addend, we don't want to change anything. We will only have an - addend if this is a newly created reloc, not read from an ELF - file. */ + /* If we're relocating, and this is an external symbol, we don't want + to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (symbol->flags & BSF_LOCAL) != 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (output_bfd != (bfd *) NULL) - relocateable = true; + relocatable = TRUE; else { - relocateable = false; + relocatable = FALSE; output_bfd = symbol->section->output_section->owner; } - ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, + ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp); if (ret != bfd_reloc_ok) return ret; return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, - input_section, relocateable, + input_section, relocatable, data, gp); } -/* Do a R_MIPS_GPREL32 relocation. Is this 32 bit value the offset - from the gp register? XXX */ - -static bfd_reloc_status_type gprel32_with_gp PARAMS ((bfd *, asymbol *, - arelent *, asection *, - boolean, PTR, bfd_vma)); +/* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must + become the offset from the gp register. */ static bfd_reloc_status_type mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section, @@ -1282,17 +1156,15 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd; char **error_message; { - boolean relocateable; + bfd_boolean relocatable; bfd_reloc_status_type ret; bfd_vma gp; - /* If we're relocating, and this is an external symbol with no - addend, we don't want to change anything. We will only have an - addend if this is a newly created reloc, not read from an ELF - file. */ + /* If we're relocating, and this is an external symbol, we don't want + to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (symbol->flags & BSF_LOCAL) != 0) { *error_message = (char *) _("32bits gp relative relocation occurs for an external symbol"); @@ -1300,38 +1172,35 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section, } if (output_bfd != (bfd *) NULL) - { - relocateable = true; - gp = _bfd_get_gp_value (output_bfd); - } + relocatable = TRUE; else { - relocateable = false; + relocatable = FALSE; output_bfd = symbol->section->output_section->owner; - - ret = mips_elf_final_gp (output_bfd, symbol, relocateable, - error_message, &gp); - if (ret != bfd_reloc_ok) - return ret; } + ret = mips_elf_final_gp (output_bfd, symbol, relocatable, + error_message, &gp); + if (ret != bfd_reloc_ok) + return ret; + return gprel32_with_gp (abfd, symbol, reloc_entry, input_section, - relocateable, data, gp); + relocatable, data, gp); } static bfd_reloc_status_type -gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data, +gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocatable, data, gp) bfd *abfd; asymbol *symbol; arelent *reloc_entry; asection *input_section; - boolean relocateable; + bfd_boolean relocatable; PTR data; bfd_vma gp; { bfd_vma relocation; - unsigned long val; + bfd_vma val; if (bfd_is_com_section (symbol->section)) relocation = 0; @@ -1344,27 +1213,25 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data, if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; - if (reloc_entry->howto->src_mask == 0) - { - /* This case arises with the 64-bit MIPS ELF ABI. */ - val = 0; - } - else - val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); - /* Set val to the offset into the section or symbol. */ - val += reloc_entry->addend; + val = reloc_entry->addend; + + if (reloc_entry->howto->partial_inplace) + val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); /* 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; - bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + reloc_entry->address); + if (reloc_entry->howto->partial_inplace) + bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); + else + reloc_entry->addend = val; - if (relocateable) + if (relocatable) reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; @@ -1390,8 +1257,8 @@ mips32_64bit_reloc (abfd, reloc_entry, symbol, data, input_section, unsigned long val; bfd_size_type addr; - r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message); + r = mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); if (r != bfd_reloc_continue) return r; @@ -1440,13 +1307,13 @@ mips16_jump_reloc (abfd, reloc_entry, symbol, data, input_section, /* FIXME. */ { - static boolean warned; + static bfd_boolean warned; if (! warned) (*_bfd_error_handler) (_("Linking mips16 objects into %s format is not supported"), bfd_get_target (input_section->output_section->owner)); - warned = true; + warned = TRUE; } return bfd_reloc_undefined; @@ -1465,33 +1332,33 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section, bfd *output_bfd; char **error_message; { - boolean relocateable; + bfd_boolean relocatable; bfd_reloc_status_type ret; bfd_vma gp; - unsigned short extend, insn; - unsigned long final; + unsigned short extend = 0; + unsigned short insn = 0; + bfd_signed_vma val; + bfd_vma relocation; - /* If we're relocating, and this is an external symbol with no - addend, we don't want to change anything. We will only have an - addend if this is a newly created reloc, not read from an ELF - file. */ + /* If we're relocating, and this is an external symbol, we don't want + to change anything. */ if (output_bfd != NULL && (symbol->flags & BSF_SECTION_SYM) == 0 - && reloc_entry->addend == 0) + && (symbol->flags & BSF_LOCAL) != 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (output_bfd != NULL) - relocateable = true; + relocatable = TRUE; else { - relocateable = false; + relocatable = FALSE; output_bfd = symbol->section->output_section->owner; } - ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, + ret = mips_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp); if (ret != bfd_reloc_ok) return ret; @@ -1499,47 +1366,70 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section, if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; - /* Pick up the mips16 extend instruction and the real instruction. */ - extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address); - insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2); - - /* Stuff the current addend back as a 32 bit value, do the usual - relocation, and then clean up. */ - bfd_put_32 (abfd, - (bfd_vma) (((extend & 0x1f) << 11) - | (extend & 0x7e0) - | (insn & 0x1f)), - (bfd_byte *) data + reloc_entry->address); - - ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, - input_section, relocateable, data, gp); - - final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); - bfd_put_16 (abfd, - (bfd_vma) ((extend & 0xf800) - | ((final >> 11) & 0x1f) - | (final & 0x7e0)), - (bfd_byte *) data + reloc_entry->address); - bfd_put_16 (abfd, - (bfd_vma) ((insn & 0xffe0) - | (final & 0x1f)), - (bfd_byte *) data + reloc_entry->address + 2); + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + + /* Set val to the offset into the section or symbol. */ + val = reloc_entry->addend; - return ret; + if (reloc_entry->howto->partial_inplace) + { + /* Pick up the mips16 extend instruction and the real instruction. */ + extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address); + insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2); + val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f); + } + + _bfd_mips_elf_sign_extend(val, 16); + + /* Adjust val for the final section location and GP value. If we + are producing relocatable output, we don't want to do this for + an external symbol. */ + if (! relocatable + || (symbol->flags & BSF_SECTION_SYM) != 0) + val += relocation - gp; + + if (reloc_entry->howto->partial_inplace) + { + bfd_put_16 (abfd, + (bfd_vma) ((extend & 0xf800) + | ((val >> 11) & 0x1f) + | (val & 0x7e0)), + (bfd_byte *) data + reloc_entry->address); + bfd_put_16 (abfd, + (bfd_vma) ((insn & 0xffe0) + | (val & 0x1f)), + (bfd_byte *) data + reloc_entry->address + 2); + } + else + reloc_entry->addend = val; + + if (relocatable) + reloc_entry->address += input_section->output_offset; + else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0)) + return bfd_reloc_overflow; + + return bfd_reloc_ok; } /* A mapping from BFD reloc types to MIPS ELF reloc types. */ struct elf_reloc_map { - bfd_reloc_code_real_type bfd_reloc_val; - enum elf_mips_reloc_type elf_reloc_val; + bfd_reloc_code_real_type bfd_val; + enum elf_mips_reloc_type elf_val; }; static const struct elf_reloc_map mips_reloc_map[] = { - { BFD_RELOC_NONE, R_MIPS_NONE, }, + { BFD_RELOC_NONE, R_MIPS_NONE }, { BFD_RELOC_16, R_MIPS_16 }, { BFD_RELOC_32, R_MIPS_32 }, + /* There is no BFD reloc for R_MIPS_REL32. */ { BFD_RELOC_64, R_MIPS_64 }, { BFD_RELOC_MIPS_JMP, R_MIPS_26 }, { BFD_RELOC_HI16_S, R_MIPS_HI16 }, @@ -1568,11 +1458,13 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) bfd_reloc_code_real_type code; { unsigned int i; + reloc_howto_type *howto_table = elf_mips_howto_table_rel; - for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++) + for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); + i++) { - if (mips_reloc_map[i].bfd_reloc_val == code) - return &elf_mips_howto_table_rel[(int) mips_reloc_map[i].elf_reloc_val]; + if (mips_reloc_map[i].bfd_val == code) + return &howto_table[(int) mips_reloc_map[i].elf_val]; } switch (code) @@ -1584,11 +1476,12 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) case BFD_RELOC_CTOR: /* We need to handle BFD_RELOC_CTOR specially. Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the - size of addresses on this architecture. */ - if (bfd_arch_bits_per_address (abfd) == 32) - return &elf_mips_howto_table_rel[(int) R_MIPS_32]; - else + size of addresses of the ABI. */ + if ((elf_elfheader (abfd)->e_flags & (E_MIPS_ABI_O64 + | E_MIPS_ABI_EABI64)) != 0) return &elf_mips_ctor64_howto; + else + return &howto_table[(int) R_MIPS_32]; case BFD_RELOC_MIPS16_JMP: return &elf_mips16_jump_howto; @@ -1611,61 +1504,51 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) } } -/* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure. */ +/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */ static reloc_howto_type * mips_elf32_rtype_to_howto (r_type, rela_p) unsigned int r_type; - boolean rela_p ATTRIBUTE_UNUSED; + bfd_boolean rela_p ATTRIBUTE_UNUSED; { switch (r_type) { case R_MIPS16_26: return &elf_mips16_jump_howto; - break; case R_MIPS16_GPREL: return &elf_mips16_gprel_howto; - break; case R_MIPS_GNU_VTINHERIT: return &elf_mips_gnu_vtinherit_howto; - break; case R_MIPS_GNU_VTENTRY: return &elf_mips_gnu_vtentry_howto; - break; case R_MIPS_GNU_REL_HI16: return &elf_mips_gnu_rel_hi16; - break; case R_MIPS_GNU_REL_LO16: return &elf_mips_gnu_rel_lo16; - break; case R_MIPS_GNU_REL16_S2: return &elf_mips_gnu_rel16_s2; - break; case R_MIPS_PC64: return &elf_mips_gnu_pcrel64; - break; case R_MIPS_PC32: return &elf_mips_gnu_pcrel32; - break; - default: BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); return &elf_mips_howto_table_rel[r_type]; } } -/* Given a MIPS Elf32_Internal_Rel, fill in an arelent structure. */ +/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */ static void mips_info_to_howto_rel (abfd, cache_ptr, dst) bfd *abfd; arelent *cache_ptr; - Elf32_Internal_Rel *dst; + Elf_Internal_Rela *dst; { unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); - cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, false); + cache_ptr->howto = mips_elf32_rtype_to_howto (r_type, FALSE); /* The addend for a GPREL16 or LITERAL relocation comes from the GP value for the object file. We get the addend now, rather than @@ -1677,21 +1560,18 @@ mips_info_to_howto_rel (abfd, cache_ptr, dst) cache_ptr->addend = elf_gp (abfd); } -/* Given a MIPS Elf32_Internal_Rela, fill in an arelent structure. */ +/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure. */ static void mips_info_to_howto_rela (abfd, cache_ptr, dst) bfd *abfd; arelent *cache_ptr; - Elf32_Internal_Rela *dst; + Elf_Internal_Rela *dst; { - /* Since an Elf32_Internal_Rel is an initial prefix of an - Elf32_Internal_Rela, we can just use mips_info_to_howto_rel - above. */ - mips_info_to_howto_rel (abfd, cache_ptr, (Elf32_Internal_Rel *) dst); + mips_info_to_howto_rel (abfd, cache_ptr, dst); /* If we ever need to do any extra processing with dst->r_addend - (the field omitted in an Elf32_Internal_Rel) we can do it here. */ + (the field omitted in an Elf_Internal_Rel) we can do it here. */ } /* Determine whether a symbol is global for the purposes of splitting @@ -1700,7 +1580,7 @@ mips_info_to_howto_rela (abfd, cache_ptr, dst) symbols. On most ELF targets the split is between static symbols and externally visible symbols. */ -static boolean +static bfd_boolean mips_elf_sym_is_global (abfd, sym) bfd *abfd ATTRIBUTE_UNUSED; asymbol *sym; @@ -1715,7 +1595,7 @@ mips_elf_sym_is_global (abfd, sym) /* Set the right machine number for a MIPS ELF file. */ -static boolean +static bfd_boolean mips_elf32_object_p (abfd) bfd *abfd; { @@ -1725,26 +1605,26 @@ mips_elf32_object_p (abfd) sorted correctly such that local symbols precede global symbols, and the sh_info field in the symbol table is not always right. */ if (SGI_COMPAT (abfd)) - elf_bad_symtab (abfd) = true; + elf_bad_symtab (abfd) = TRUE; + + if (ABI_N32_P (abfd)) + return FALSE; mach = _bfd_elf_mips_mach (elf_elfheader (abfd)->e_flags); bfd_default_set_arch_mach (abfd, bfd_arch_mips, mach); - if (ABI_N32_P (abfd)) - return false; - - return true; + return TRUE; } /* MIPS ELF local labels start with '$', not 'L'. */ -static boolean +static bfd_boolean mips_elf_is_local_label_name (abfd, name) bfd *abfd; const char *name; { if (name[0] == '$') - return true; + return TRUE; /* On Irix 6, the labels go back to starting with '.', so we accept the generic ELF local label syntax as well. */ @@ -1752,7 +1632,7 @@ mips_elf_is_local_label_name (abfd, name) } /* Support for core dump NOTE sections. */ -static boolean +static bfd_boolean elf32_mips_grok_prstatus (abfd, note) bfd *abfd; Elf_Internal_Note *note; @@ -1763,7 +1643,7 @@ elf32_mips_grok_prstatus (abfd, note) switch (note->descsz) { default: - return false; + return FALSE; case 256: /* Linux/MIPS */ /* pr_cursig */ @@ -1784,7 +1664,7 @@ elf32_mips_grok_prstatus (abfd, note) raw_size, note->descpos + offset); } -static boolean +static bfd_boolean elf32_mips_grok_psinfo (abfd, note) bfd *abfd; Elf_Internal_Note *note; @@ -1792,7 +1672,7 @@ elf32_mips_grok_psinfo (abfd, note) switch (note->descsz) { default: - return false; + return FALSE; case 128: /* Linux/MIPS elf_prpsinfo */ elf_tdata (abfd)->core_program @@ -1813,128 +1693,20 @@ elf32_mips_grok_psinfo (abfd, note) command[n - 1] = '\0'; } - return true; + return TRUE; } -#define PDR_SIZE 32 - -static boolean -elf32_mips_discard_info (abfd, cookie, info) - bfd *abfd; - struct elf_reloc_cookie *cookie; - struct bfd_link_info *info; -{ - asection *o; - struct elf_backend_data *bed = get_elf_backend_data (abfd); - boolean ret = false; - unsigned char *tdata; - size_t i, skip; - - o = bfd_get_section_by_name (abfd, ".pdr"); - if (! o) - return false; - if (o->_raw_size == 0) - return false; - if (o->_raw_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); - if (! tdata) - return false; - - cookie->rels = _bfd_elf32_link_read_relocs (abfd, o, (PTR) NULL, - (Elf_Internal_Rela *) NULL, - info->keep_memory); - if (!cookie->rels) - { - free (tdata); - return false; - } - - cookie->rel = cookie->rels; - cookie->relend = - cookie->rels + o->reloc_count * bed->s->int_rels_per_ext_rel; - - for (i = 0, skip = 0; i < o->_raw_size; i ++) - { - if (_bfd_elf32_reloc_symbol_deleted_p (i * PDR_SIZE, cookie)) - { - tdata[i] = 1; - skip ++; - } - } - - if (skip != 0) - { - elf_section_data (o)->tdata = tdata; - o->_cooked_size = o->_raw_size - skip * PDR_SIZE; - ret = true; - } - else - free (tdata); - - if (! info->keep_memory) - free (cookie->rels); - - return ret; -} - -static boolean -elf32_mips_ignore_discarded_relocs (sec) - asection *sec; -{ - if (strcmp (sec->name, ".pdr") == 0) - return true; - return false; -} - -static boolean -elf32_mips_write_section (output_bfd, sec, contents) - bfd *output_bfd; - asection *sec; - bfd_byte *contents; -{ - bfd_byte *to, *from, *end; - int i; - - if (strcmp (sec->name, ".pdr") != 0) - return false; - - if (elf_section_data (sec)->tdata == NULL) - return false; - - to = contents; - end = contents + sec->_raw_size; - for (from = contents, i = 0; - from < end; - from += PDR_SIZE, i++) - { - if (((unsigned char *)elf_section_data (sec)->tdata)[i] == 1) - continue; - if (to != from) - memcpy (to, from, PDR_SIZE); - to += PDR_SIZE; - } - bfd_set_section_contents (output_bfd, sec->output_section, contents, - (file_ptr) sec->output_offset, - sec->_cooked_size); - return true; -} - /* Depending on the target vector we generate some version of Irix executables or "normal" MIPS ELF ABI executables. */ static irix_compat_t elf32_mips_irix_compat (abfd) bfd *abfd; { - if ((abfd->xvec == &bfd_elf32_tradbigmips_vec) - || (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) - return ict_none; - else + if ((abfd->xvec == &bfd_elf32_bigmips_vec) + || (abfd->xvec == &bfd_elf32_littlemips_vec)) return ict_irix5; + else + return ict_none; } /* Given a data section and an in-memory embedded reloc section, store @@ -1944,7 +1716,7 @@ elf32_mips_irix_compat (abfd) after the add_symbols entry point has been called for all the objects, and before the final_link entry point is called. */ -boolean +bfd_boolean bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) bfd *abfd; struct bfd_link_info *info; @@ -1953,69 +1725,38 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) char **errmsg; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; - Elf32_External_Sym *free_extsyms = NULL; - Elf_External_Sym_Shndx *shndx_buf = NULL; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *p; - bfd_size_type amt; - BFD_ASSERT (! info->relocateable); + BFD_ASSERT (! info->relocatable); *errmsg = NULL; if (datasec->reloc_count == 0) - return true; + return TRUE; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Read this BFD's symbols if we haven't done so already, or get the cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - if (info->keep_memory) - extsyms = ((Elf32_External_Sym *) - bfd_alloc (abfd, symtab_hdr->sh_size)); - else - extsyms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_size)); - if (extsyms == NULL) - goto error_return; - if (! info->keep_memory) - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) - != symtab_hdr->sh_size)) - goto error_return; - if (info->keep_memory) - symtab_hdr->contents = (unsigned char *) extsyms; - } - - shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr; - if (shndx_hdr->sh_size != 0) + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + if (symtab_hdr->sh_info != 0) { - amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_return; - if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt) + 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 error_return; } /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf32_link_read_relocs + internal_relocs = (_bfd_elf_link_read_relocs (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! info->keep_memory) - free_relocs = internal_relocs; relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12); if (relsec->contents == NULL) @@ -2046,16 +1787,11 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) /* Get the target section referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf32_External_Sym *esym; - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; /* A local symbol. */ - esym = extsyms + ELF32_R_SYM (irel->r_info); - shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0); - bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym); - - targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + isym = isymbuf + ELF32_R_SYM (irel->r_info); + targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx); } else { @@ -2092,22 +1828,22 @@ bfd_mips_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) strncpy (p + 4, targetsec->output_section->name, 8); } - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); - return true; + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + return TRUE; error_return: - if (shndx_buf != NULL) - free (shndx_buf); - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); - return false; + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + return FALSE; } /* ECOFF swapping routines. These are used when dealing with the @@ -2159,9 +1895,9 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { a value of 0x1000, and we are compatible. */ #define ELF_MAXPAGESIZE 0x1000 -#define elf_backend_collect true -#define elf_backend_type_change_ok true -#define elf_backend_can_gc_sections true +#define elf_backend_collect TRUE +#define elf_backend_type_change_ok TRUE +#define elf_backend_can_gc_sections TRUE #define elf_info_to_howto mips_info_to_howto_rela #define elf_info_to_howto_rel mips_info_to_howto_rel #define elf_backend_sym_is_global mips_elf_sym_is_global @@ -2204,21 +1940,20 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap #define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO) -#define elf_backend_plt_header_size 0 #define elf_backend_may_use_rel_p 1 #define elf_backend_may_use_rela_p 0 #define elf_backend_default_use_rela_p 0 -#define elf_backend_sign_extend_vma true +#define elf_backend_sign_extend_vma TRUE -#define elf_backend_discard_info elf32_mips_discard_info +#define elf_backend_discard_info _bfd_mips_elf_discard_info #define elf_backend_ignore_discarded_relocs \ - elf32_mips_ignore_discarded_relocs -#define elf_backend_write_section elf32_mips_write_section + _bfd_mips_elf_ignore_discarded_relocs #define elf_backend_mips_irix_compat elf32_mips_irix_compat #define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto #define bfd_elf32_bfd_is_local_label_name \ mips_elf_is_local_label_name #define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line +#define bfd_elf32_new_section_hook _bfd_mips_elf_new_section_hook #define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents #define bfd_elf32_bfd_get_relocated_section_contents \ _bfd_elf_mips_get_relocated_section_contents