X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-sparc.c;h=2118c7002726c466727d212ae4a904d56cad8e8a;hb=5dccc1ddaa1d8e543c1113a83df73c6d7e6973ec;hp=f759881276715987f7f94d6dc1c2caca766ddb09;hpb=5bc513b4fb70c1c265bd49b314dbe1f062797702;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index f759881276..2118c70027 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -1,5 +1,5 @@ /* SPARC-specific support for 32-bit ELF - Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -22,21 +22,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" -/* start-sanitize-v8plus */ #include "elf/sparc.h" -/* end-sanitize-v8plus */ -static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup +static reloc_howto_type *elf32_sparc_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); -static void elf_info_to_howto +static void elf32_sparc_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); static boolean elf32_sparc_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); static boolean elf32_sparc_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); -static boolean elf32_sparc_adjust_dynindx - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf32_sparc_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf32_sparc_relocate_section @@ -47,83 +43,91 @@ static boolean elf32_sparc_finish_dynamic_symbol Elf_Internal_Sym *)); static boolean elf32_sparc_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); -/* start-sanitize-v8plus */ -static boolean elf32_sparc_set_private_flags PARAMS ((bfd *, flagword)); -static boolean elf32_sparc_copy_private_bfd_data PARAMS ((bfd *, bfd *)); static boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *)); static boolean elf32_sparc_object_p PARAMS ((bfd *)); static void elf32_sparc_final_write_processing PARAMS ((bfd *, boolean)); -/* end-sanitize-v8plus */ - -enum reloc_type - { - R_SPARC_NONE = 0, - R_SPARC_8, R_SPARC_16, R_SPARC_32, - R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, - R_SPARC_WDISP30, R_SPARC_WDISP22, - R_SPARC_HI22, R_SPARC_22, - R_SPARC_13, R_SPARC_LO10, - R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, - R_SPARC_PC10, R_SPARC_PC22, - R_SPARC_WPLT30, - R_SPARC_COPY, - R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, - R_SPARC_RELATIVE, - R_SPARC_UA32, - R_SPARC_max - }; + +/* The relocation "howto" table. */ -#if 0 -static CONST char *CONST reloc_type_names[] = -{ - "R_SPARC_NONE", - "R_SPARC_8", "R_SPARC_16", "R_SPARC_32", - "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32", - "R_SPARC_WDISP30", "R_SPARC_WDISP22", - "R_SPARC_HI22", "R_SPARC_22", - "R_SPARC_13", "R_SPARC_LO10", - "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", - "R_SPARC_PC10", "R_SPARC_PC22", - "R_SPARC_WPLT30", - "R_SPARC_COPY", - "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", - "R_SPARC_RELATIVE", - "R_SPARC_UA32", -}; -#endif +static bfd_reloc_status_type sparc_elf_notsupported_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type sparc_elf_wdisp16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); -static reloc_howto_type elf_sparc_howto_table[] = +reloc_howto_type _bfd_sparc_elf_howto_table[] = { - HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_NONE", false,0,0x00000000,true), - HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_8", false,0,0x000000ff,true), - HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_16", false,0,0x0000ffff,true), - HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_32", false,0,0xffffffff,true), - HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_DISP8", false,0,0x000000ff,true), - HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_DISP16", false,0,0x0000ffff,true), - HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_DISP32", false,0,0x00ffffff,true), - HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_WDISP30", false,0,0x3fffffff,true), - HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_WDISP22", false,0,0x003fffff,true), - HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_HI22", false,0,0x003fffff,true), - HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_22", false,0,0x003fffff,true), - HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_13", false,0,0x00001fff,true), - HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_LO10", false,0,0x000003ff,true), - HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_GOT10", false,0,0x000003ff,true), - HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_GOT13", false,0,0x00001fff,true), - HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_GOT22", false,0,0x003fffff,true), - HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_PC10", false,0,0x000003ff,true), - HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,true), - HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x3fffffff,true), - HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_COPY", false,0,0x00000000,true), - HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,true), - HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,true), - HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,true), - HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc,"R_SPARC_UA32", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true), + HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true), + HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true), + HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true), + HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true), + HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true), + HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true), + HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true), + HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true), + HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true), + HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true), + HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true), + HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true), + HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true), + HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true), + HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true), + HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true), + HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true), + HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true), + HOWTO(R_SPARC_GLOB_DAT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true), + HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true), + HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true), + HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0x00000000,true), + HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true), + HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true), + HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true), + HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true), + HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true), + HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true), + HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true), + HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true), + /* These are for sparc64 in a 64 bit environment. + Values need to be here because the table is indexed by reloc number. */ + HOWTO(R_SPARC_64, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_64", false,0,0x00000000,true), + HOWTO(R_SPARC_OLO10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_OLO10", false,0,0x00000000,true), + HOWTO(R_SPARC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HH22", false,0,0x00000000,true), + HOWTO(R_SPARC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HM10", false,0,0x00000000,true), + HOWTO(R_SPARC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LM22", false,0,0x00000000,true), + HOWTO(R_SPARC_PC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HH22", false,0,0x00000000,true), + HOWTO(R_SPARC_PC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HM10", false,0,0x00000000,true), + HOWTO(R_SPARC_PC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_LM22", false,0,0x00000000,true), + /* End sparc64 in 64 bit environment values. + The following are for sparc64 in a 32 bit environment. */ + HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true), + HOWTO(R_SPARC_WDISP19, 2,2,19,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true), + HOWTO(R_SPARC_UNUSED_42, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UNUSED_42",false,0,0x00000000,true), + HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true), + HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true), + HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), + HOWTO(R_SPARC_REV32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_REV32", false,0,0xffffffff,true), }; +static reloc_howto_type elf32_sparc_vtinherit_howto = + HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,false,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", false,0, 0, false); +static reloc_howto_type elf32_sparc_vtentry_howto = + HOWTO (R_SPARC_GNU_VTENTRY, 0,2,0,false,0,complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_SPARC_GNU_VTENTRY", false,0,0, false); + struct elf_reloc_map { - unsigned char bfd_reloc_val; + bfd_reloc_code_real_type bfd_reloc_val; unsigned char elf_reloc_val; }; @@ -133,7 +137,7 @@ static CONST struct elf_reloc_map sparc_reloc_map[] = { BFD_RELOC_16, R_SPARC_16, }, { BFD_RELOC_8, R_SPARC_8 }, { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, - { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */ + { BFD_RELOC_CTOR, R_SPARC_32 }, { BFD_RELOC_32, R_SPARC_32 }, { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, { BFD_RELOC_HI22, R_SPARC_HI22 }, @@ -152,33 +156,155 @@ static CONST struct elf_reloc_map sparc_reloc_map[] = { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT }, { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE }, { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 }, + /* ??? Doesn't dwarf use this? */ /*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */ + {BFD_RELOC_SPARC_10, R_SPARC_10}, + {BFD_RELOC_SPARC_11, R_SPARC_11}, + {BFD_RELOC_SPARC_64, R_SPARC_64}, + {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10}, + {BFD_RELOC_SPARC_HH22, R_SPARC_HH22}, + {BFD_RELOC_SPARC_HM10, R_SPARC_HM10}, + {BFD_RELOC_SPARC_LM22, R_SPARC_LM22}, + {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22}, + {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10}, + {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22}, + {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16}, + {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19}, + {BFD_RELOC_SPARC_7, R_SPARC_7}, + {BFD_RELOC_SPARC_5, R_SPARC_5}, + {BFD_RELOC_SPARC_6, R_SPARC_6}, + {BFD_RELOC_SPARC_REV32, R_SPARC_REV32 }, + {BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT}, + {BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY}, }; static reloc_howto_type * -bfd_elf32_bfd_reloc_type_lookup (abfd, code) - bfd *abfd; +elf32_sparc_reloc_type_lookup (abfd, code) + bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { unsigned int i; - for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) + + switch (code) { - if (sparc_reloc_map[i].bfd_reloc_val == code) - return &elf_sparc_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; + case BFD_RELOC_VTABLE_INHERIT: + return &elf32_sparc_vtinherit_howto; + + case BFD_RELOC_VTABLE_ENTRY: + return &elf32_sparc_vtentry_howto; + + default: + for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) + { + if (sparc_reloc_map[i].bfd_reloc_val == code) + return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; + } } - return 0; + bfd_set_error (bfd_error_bad_value); + return NULL; } +/* We need to use ELF32_R_TYPE so we have our own copy of this function, + and elf64-sparc.c has its own copy. */ + static void -elf_info_to_howto (abfd, cache_ptr, dst) - bfd *abfd; +elf32_sparc_info_to_howto (abfd, cache_ptr, dst) + bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf_Internal_Rela *dst; { - BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max); - cache_ptr->howto = &elf_sparc_howto_table[ELF32_R_TYPE(dst->r_info)]; + switch (ELF32_R_TYPE(dst->r_info)) + { + case R_SPARC_GNU_VTINHERIT: + cache_ptr->howto = &elf32_sparc_vtinherit_howto; + break; + + case R_SPARC_GNU_VTENTRY: + cache_ptr->howto = &elf32_sparc_vtentry_howto; + break; + + default: + BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max_std); + cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)]; + } +} + +/* For unsupported relocs. */ + +static bfd_reloc_status_type +sparc_elf_notsupported_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd, + error_message) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc_entry ATTRIBUTE_UNUSED; + asymbol *symbol ATTRIBUTE_UNUSED; + PTR data ATTRIBUTE_UNUSED; + asection *input_section ATTRIBUTE_UNUSED; + bfd *output_bfd ATTRIBUTE_UNUSED; + char **error_message ATTRIBUTE_UNUSED; +{ + return bfd_reloc_notsupported; } +/* Handle the WDISP16 reloc. */ + +static bfd_reloc_status_type +sparc_elf_wdisp16_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message ATTRIBUTE_UNUSED; +{ + bfd_vma relocation; + bfd_vma x; + + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (output_bfd != NULL) + return bfd_reloc_continue; + + if (reloc_entry->address > input_section->_cooked_size) + return bfd_reloc_outofrange; + + relocation = (symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset); + relocation += reloc_entry->addend; + relocation -= (input_section->output_section->vma + + input_section->output_offset); + relocation -= reloc_entry->address; + + x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + x |= ((((relocation >> 2) & 0xc000) << 6) + | ((relocation >> 2) & 0x3fff)); + bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); + + if ((bfd_signed_vma) relocation < - 0x40000 + || (bfd_signed_vma) relocation > 0x3ffff) + return bfd_reloc_overflow; + else + return bfd_reloc_ok; +} /* Functions for the SPARC ELF linker. */ @@ -286,6 +412,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY)) || ! bfd_set_section_alignment (dynobj, srelgot, 2)) return false; @@ -294,12 +421,12 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got_offset != (bfd_vma) -1) + if (h->got.offset != (bfd_vma) -1) { /* We have already allocated space in the .got. */ break; } - h->got_offset = sgot->_raw_size; + h->got.offset = sgot->_raw_size; /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) @@ -345,6 +472,13 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) sgot->_raw_size += 4; + /* If the .got section is more than 0x1000 bytes, we add + 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 + bit relocations have a greater chance of working. */ + if (sgot->_raw_size >= 0x1000 + && elf_hash_table (info)->hgot->root.u.def.value == 0) + elf_hash_table (info)->hgot->root.u.def.value = 0x1000; + break; case R_SPARC_WPLT30: @@ -356,10 +490,11 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) if (h == NULL) { - /* It does not make sense to have a procedure linkage - table entry for a local symbol. */ - bfd_set_error (bfd_error_bad_value); - return false; + /* The Solaris native assembler will generate a WPLT30 + reloc for a local symbol if you assemble a call from + one section to another when using -K pic. We treat + it as WDISP30. */ + break; } /* Make sure this symbol is output as a dynamic symbol. */ @@ -384,7 +519,20 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) case R_SPARC_DISP32: case R_SPARC_WDISP30: case R_SPARC_WDISP22: - if (h == NULL) + case R_SPARC_WDISP19: + case R_SPARC_WDISP16: + /* If we are linking with -Bsymbolic, we do not need to copy + a PC relative reloc against a global symbol which is + defined in an object we are including in the link (i.e., + DEF_REGULAR is set). FIXME: At this point we have not + seen all the input files, so it is possible that + DEF_REGULAR is not set now but will be set later (it is + never cleared). This needs to be handled as in + elf32-i386.c. */ + if (h == NULL + || (info->symbolic + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0)) break; /* Fall through. */ case R_SPARC_8: @@ -395,8 +543,7 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) case R_SPARC_13: case R_SPARC_LO10: case R_SPARC_UA32: - if (info->shared - && (sec->flags & SEC_ALLOC) != 0) + if (info->shared) { /* When creating a shared object, we must copy these relocs into the output file. We create a reloc @@ -419,14 +566,15 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) sreloc = bfd_get_section_by_name (dynobj, name); if (sreloc == NULL) { + flagword flags; + sreloc = bfd_make_section (dynobj, name); + flags = (SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if ((sec->flags & SEC_ALLOC) != 0) + flags |= SEC_ALLOC | SEC_LOAD; if (sreloc == NULL - || ! bfd_set_section_flags (dynobj, sreloc, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_READONLY)) + || ! bfd_set_section_flags (dynobj, sreloc, flags) || ! bfd_set_section_alignment (dynobj, sreloc, 2)) return false; } @@ -437,6 +585,16 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) break; + case R_SPARC_GNU_VTINHERIT: + if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return false; + break; + + case R_SPARC_GNU_VTENTRY: + if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return false; + break; + default: break; } @@ -445,6 +603,114 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) return true; } +static asection * +elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym) + bfd *abfd; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + Elf_Internal_Rela *rel; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; +{ + + if (h != NULL) + { + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_SPARC_GNU_VTINHERIT: + case R_SPARC_GNU_VTENTRY: + break; + + default: + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + + default: + break; + } + } + } + else + { + if (!(elf_bad_symtab (abfd) + && ELF_ST_BIND (sym->st_info) != STB_LOCAL) + && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) + && sym->st_shndx != SHN_COMMON)) + { + return bfd_section_from_elf_index (abfd, sym->st_shndx); + } + } + + return NULL; +} + +/* Update the got entry reference counts for the section being removed. */ +static boolean +elf32_sparc_gc_sweep_hook (abfd, info, sec, relocs) + bfd *abfd; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + asection *sec; + const Elf_Internal_Rela *relocs; +{ + + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + bfd_signed_vma *local_got_refcounts; + const Elf_Internal_Rela *rel, *relend; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + local_got_refcounts = elf_local_got_refcounts (abfd); + + relend = relocs + sec->reloc_count; + for (rel = relocs; rel < relend; rel++) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_SPARC_GOT10: + case R_SPARC_GOT13: + case R_SPARC_GOT22: + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (h->got.refcount > 0) + h->got.refcount--; + } + else + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx]--; + } + break; + + case R_SPARC_PLT32: + case R_SPARC_HIPLT22: + case R_SPARC_LOPLT10: + case R_SPARC_PCPLT32: + case R_SPARC_PCPLT10: + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + if (h->plt.refcount > 0) + h->plt.refcount--; + } + break; + + default: + break; + } + + return true; +} + /* 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 @@ -475,18 +741,34 @@ elf32_sparc_adjust_dynamic_symbol (info, h) /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later - (although we could actually do it here). */ + (although we could actually do it here). The STT_NOTYPE + condition is a hack specifically for the Oracle libraries + delivered for Solaris; for some inexplicable reason, they define + some of their functions as STT_NOTYPE when they really should be + STT_FUNC. */ if (h->type == STT_FUNC - || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) + || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 + || (h->type == STT_NOTYPE + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && (h->root.u.def.section->flags & SEC_CODE) != 0)) { - if (! elf_hash_table (info)->dynamic_sections_created) + if (! elf_hash_table (info)->dynamic_sections_created + || ((!info->shared || info->symbolic || h->dynindx == -1) + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0)) { /* This case can occur if we saw a WPLT30 reloc in an input - file, but none of the input files were dynamic objects. - In such a case, we don't actually need to build a - procedure linkage table, and we can just do a WDISP30 - reloc instead. */ - BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); + file, but none of the input files were dynamic objects. + Or, when linking the main application or a -Bsymbolic + shared library against PIC code. Or when a global symbol + has been made private, e.g. via versioning. + + In these cases we know what value the symbol will resolve + to, so we don't actually need to build a procedure linkage + table, and we can just do a WDISP30 reloc instead. */ + + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; return true; } @@ -504,19 +786,19 @@ elf32_sparc_adjust_dynamic_symbol (info, h) return false; } - /* If this symbol is not defined in a regular file, and we are - not generating a shared library, then set the symbol to this - location in the .plt. This is required to make function - pointers compare as equal between the normal executable and - the shared library. */ - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - { - h->root.u.def.section = s; - h->root.u.def.value = s->_raw_size; - } + /* If this symbol is not defined in a regular file, and we are + not generating a shared library, then set the symbol to this + location in the .plt. This is required to make function + pointers compare as equal between the normal executable and + the shared library. */ + if (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + { + h->root.u.def.section = s; + h->root.u.def.value = s->_raw_size; + } - h->plt_offset = s->_raw_size; + h->plt.offset = s->_raw_size; /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; @@ -565,14 +847,11 @@ elf32_sparc_adjust_dynamic_symbol (info, h) s = bfd_get_section_by_name (dynobj, ".dynbss"); BFD_ASSERT (s != NULL); - /* If the symbol is currently defined in the .bss section of the - dynamic object, then it is OK to simply initialize it to zero. - If the symbol is in some other section, we must generate a - R_SPARC_COPY reloc to tell the dynamic linker to copy the initial - value out of the dynamic object and into the runtime process - image. We need to remember the offset into the .rel.bss section - we are going to use. */ - if ((h->root.u.def.section->flags & SEC_LOAD) != 0) + /* We must generate a R_SPARC_COPY reloc to tell the dynamic linker + to copy the initial value out of the dynamic object and into the + runtime process image. We need to remember the offset into the + .rel.bss section we are going to use. */ + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { asection *srel; @@ -661,7 +940,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info) const char *name; boolean strip; - if ((s->flags & SEC_IN_MEMORY) == 0) + if ((s->flags & SEC_LINKER_CREATED) == 0) continue; /* It's OK to base decisions on the section name, because none @@ -687,13 +966,17 @@ elf32_sparc_size_dynamic_sections (output_bfd, info) } else { + const char *outname; asection *target; /* If this relocation section applies to a read only section, then we probably need a DT_TEXTREL entry. */ - target = bfd_get_section_by_name (output_bfd, name + 5); + outname = bfd_get_section_name (output_bfd, + s->output_section); + target = bfd_get_section_by_name (output_bfd, outname + 5); if (target != NULL - && (target->flags & SEC_READONLY) != 0) + && (target->flags & SEC_READONLY) != 0 + && (target->flags & SEC_ALLOC) != 0) reltext = true; if (strcmp (name, ".rela.plt") == 0) @@ -713,15 +996,7 @@ elf32_sparc_size_dynamic_sections (output_bfd, info) if (strip) { - asection **spp; - - for (spp = &s->output_section->owner->sections; - *spp != s->output_section; - spp = &(*spp)->next) - ; - *spp = s->output_section->next; - --s->output_section->owner->section_count; - + _bfd_strip_section_from_output (s); continue; } @@ -744,12 +1019,10 @@ elf32_sparc_size_dynamic_sections (output_bfd, info) return false; } - if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)) - return false; - if (relplt) { - if (! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0) + if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0) + || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0) || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA) || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0)) return false; @@ -768,44 +1041,6 @@ elf32_sparc_size_dynamic_sections (output_bfd, info) } } - /* If we are generating a shared library, we generate a section - symbol for each output section. These are local symbols, which - means that they must come first in the dynamic symbol table. - That means we must increment the dynamic symbol index of every - other dynamic symbol. */ - if (info->shared) - { - int c, i; - - c = bfd_count_sections (output_bfd); - elf_link_hash_traverse (elf_hash_table (info), - elf32_sparc_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - - for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++) - { - elf_section_data (s)->dynindx = i; - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - } - } - - return true; -} - -/* Increment the index of a dynamic symbol by a given amount. Called - via elf_link_hash_traverse. */ - -static boolean -elf32_sparc_adjust_dynindx (h, cparg) - struct elf_link_hash_entry *h; - PTR cparg; -{ - int *cp = (int *) cparg; - - if (h->dynindx != -1) - h->dynindx += *cp; return true; } @@ -827,6 +1062,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; + bfd_vma got_base; asection *sgot; asection *splt; asection *sreloc; @@ -838,6 +1074,11 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); + if (elf_hash_table (info)->hgot == NULL) + got_base = 0; + else + got_base = elf_hash_table (info)->hgot->root.u.def.value; + sgot = NULL; splt = NULL; sreloc = NULL; @@ -856,12 +1097,17 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, bfd_reloc_status_type r; r_type = ELF32_R_TYPE (rel->r_info); - if (r_type < 0 || r_type >= (int) R_SPARC_max) + + if (r_type == R_SPARC_GNU_VTINHERIT + || r_type == R_SPARC_GNU_VTENTRY) + continue; + + if (r_type < 0 || r_type >= (int) R_SPARC_max_std) { bfd_set_error (bfd_error_bad_value); return false; } - howto = elf_sparc_howto_table + r_type; + howto = _bfd_sparc_elf_howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); @@ -899,22 +1145,27 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; if ((r_type == R_SPARC_WPLT30 - && h->plt_offset != (bfd_vma) -1) + && h->plt.offset != (bfd_vma) -1) || ((r_type == R_SPARC_GOT10 || r_type == R_SPARC_GOT13 || r_type == R_SPARC_GOT22) && elf_hash_table (info)->dynamic_sections_created && (! info->shared - || ! info->symbolic + || (! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) || (info->shared - && (input_section->flags & SEC_ALLOC) != 0 + && ((! info->symbolic && h->dynindx != -1) + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0) && (r_type == R_SPARC_8 || r_type == R_SPARC_16 || r_type == R_SPARC_32 @@ -923,6 +1174,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, || r_type == R_SPARC_DISP32 || r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WDISP22 + || r_type == R_SPARC_WDISP19 + || r_type == R_SPARC_WDISP16 || r_type == R_SPARC_HI22 || r_type == R_SPARC_22 || r_type == R_SPARC_13 @@ -945,7 +1198,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; - else if (info->shared && !info->symbolic) + else if (info->shared && !info->symbolic && !info->no_undefined) relocation = 0; else { @@ -974,20 +1227,21 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, { bfd_vma off; - off = h->got_offset; + off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); if (! elf_hash_table (info)->dynamic_sections_created || (info->shared - && info->symbolic + && (info->symbolic || h->dynindx == -1) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined - locally. We must initialize this entry in the - global offset table. Since the offset must - always be a multiple of 4, we use the least - significant bit to record whether we have + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of 4, we use the + least significant bit to record whether we have initialized it already. When doing a dynamic link, we create a .rela.got @@ -999,11 +1253,11 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, { bfd_put_32 (output_bfd, relocation, sgot->contents + off); - h->got_offset |= 1; + h->got.offset |= 1; } } - relocation = sgot->output_offset + off; + relocation = sgot->output_offset + off - got_base; } else { @@ -1048,7 +1302,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, local_got_offsets[r_symndx] |= 1; } - relocation = sgot->output_offset + off; + relocation = sgot->output_offset + off - got_base; } break; @@ -1056,9 +1310,15 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_WPLT30: /* Relocation is to the entry for this symbol in the procedure linkage table. */ - BFD_ASSERT (h != NULL); - if (h->plt_offset == (bfd_vma) -1) + /* The Solaris native assembler will generate a WPLT30 reloc + for a local symbol if you assemble a call from one + section to another when using -K pic. We treat it as + WDISP30. */ + if (h == NULL) + break; + + if (h->plt.offset == (bfd_vma) -1) { /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when @@ -1074,7 +1334,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (splt->output_section->vma + splt->output_offset - + h->plt_offset); + + h->plt.offset); break; case R_SPARC_PC10: @@ -1088,7 +1348,12 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_DISP32: case R_SPARC_WDISP30: case R_SPARC_WDISP22: - if (h == NULL) + case R_SPARC_WDISP19: + case R_SPARC_WDISP16: + if (h == NULL + || (info->symbolic + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0)) break; /* Fall through. */ case R_SPARC_8: @@ -1099,10 +1364,10 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_13: case R_SPARC_LO10: case R_SPARC_UA32: - if (info->shared - && (input_section->flags & SEC_ALLOC) != 0) + if (info->shared) { Elf_Internal_Rela outrel; + boolean skip; /* When generating a shared object, these relocations are copied into the output file to be resolved at run @@ -1128,10 +1393,35 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (sreloc != NULL); } - outrel.r_offset = (rel->r_offset - + input_section->output_section->vma - + input_section->output_offset); - if (h != NULL) + skip = false; + + if (elf_section_data (input_section)->stab_info == NULL) + outrel.r_offset = rel->r_offset; + else + { + bfd_vma off; + + off = (_bfd_stab_section_offset + (output_bfd, &elf_hash_table (info)->stab_info, + input_section, + &elf_section_data (input_section)->stab_info, + rel->r_offset)); + if (off == (bfd_vma) -1) + skip = true; + outrel.r_offset = off; + } + + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); + + if (skip) + memset (&outrel, 0, sizeof outrel); + /* h->dynindx may be -1 if the symbol was marked to + become local. */ + else if (h != NULL + && ((! info->symbolic && h->dynindx != -1) + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) { BFD_ASSERT (h->dynindx != -1); outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); @@ -1148,8 +1438,15 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - sym = local_syms + r_symndx; - sec = local_sections[r_symndx]; + if (h == NULL) + sec = local_sections[r_symndx]; + else + { + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || (h->root.type + == bfd_link_hash_defweak)); + sec = h->root.u.def.section; + } if (sec != NULL && bfd_is_abs_section (sec)) indx = 0; else if (sec == NULL || sec->owner == NULL) @@ -1163,12 +1460,30 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, osec = sec->output_section; indx = elf_section_data (osec)->dynindx; + + /* FIXME: we really should be able to link non-pic + shared libraries. */ if (indx == 0) - abort (); + { + BFD_FAIL (); + (*_bfd_error_handler) + (_("%s: probably compiled without -fPIC?"), + bfd_get_filename (input_bfd)); + bfd_set_error (bfd_error_bad_value); + return false; + } } outrel.r_info = ELF32_R_INFO (indx, r_type); - outrel.r_addend = relocation + rel->r_addend; + + /* For non-RELATIVE dynamic relocations, we keep the + same symbol, and so generally the same addend. But + we do need to adjust those relocations referencing + sections. */ + outrel.r_addend = rel->r_addend; + if (r_symndx < symtab_hdr->sh_info + && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + outrel.r_addend += sec->output_offset+sym->st_value; } } @@ -1179,17 +1494,55 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, ++sreloc->reloc_count; /* This reloc will be computed at runtime, so there's no - need to do anything now. */ - continue; + need to do anything now, unless this is a RELATIVE + reloc in an unallocated section. */ + if (skip + || (input_section->flags & SEC_ALLOC) != 0 + || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE) + continue; } + break; default: break; - } + } + + if (r_type == R_SPARC_WDISP16) + { + bfd_vma x; + + relocation += rel->r_addend; + relocation -= (input_section->output_section->vma + + input_section->output_offset); + relocation -= rel->r_offset; + + x = bfd_get_32 (input_bfd, contents + rel->r_offset); + x |= ((((relocation >> 2) & 0xc000) << 6) + | ((relocation >> 2) & 0x3fff)); + bfd_put_32 (input_bfd, x, contents + rel->r_offset); + + if ((bfd_signed_vma) relocation < - 0x40000 + || (bfd_signed_vma) relocation > 0x3ffff) + r = bfd_reloc_overflow; + else + r = bfd_reloc_ok; + } + else if (r_type == R_SPARC_REV32) + { + bfd_vma x; + + relocation = relocation + rel->r_addend; + + x = bfd_get_32 (input_bfd, contents + rel->r_offset); + x = x + relocation; + bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset); + r = bfd_reloc_ok; + } + else + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, rel->r_addend); - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, rel->r_offset, - relocation, rel->r_addend); if (r != bfd_reloc_ok) { @@ -1241,7 +1594,7 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) dynobj = elf_hash_table (info)->dynobj; - if (h->plt_offset != (bfd_vma) -1) + if (h->plt.offset != (bfd_vma) -1) { asection *splt; asection *srela; @@ -1258,24 +1611,24 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) /* Fill in the entry in the procedure linkage table. */ bfd_put_32 (output_bfd, - PLT_ENTRY_WORD0 + h->plt_offset, - splt->contents + h->plt_offset); + PLT_ENTRY_WORD0 + h->plt.offset, + splt->contents + h->plt.offset); bfd_put_32 (output_bfd, (PLT_ENTRY_WORD1 - + (((- (h->plt_offset + 4)) >> 2) & 0x3fffff)), - splt->contents + h->plt_offset + 4); + + (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)), + splt->contents + h->plt.offset + 4); bfd_put_32 (output_bfd, PLT_ENTRY_WORD2, - splt->contents + h->plt_offset + 8); + splt->contents + h->plt.offset + 8); /* Fill in the entry in the .rela.plt section. */ rela.r_offset = (splt->output_section->vma + splt->output_offset - + h->plt_offset); + + h->plt.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT); rela.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &rela, ((Elf32_External_Rela *) srela->contents - + h->plt_offset / PLT_ENTRY_SIZE - 4)); + + h->plt.offset / PLT_ENTRY_SIZE - 4)); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { @@ -1285,7 +1638,7 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) } } - if (h->got_offset != (bfd_vma) -1) + if (h->got.offset != (bfd_vma) -1) { asection *sgot; asection *srela; @@ -1294,27 +1647,26 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the global offset table. Set it up. */ - BFD_ASSERT (h->dynindx != -1); - sgot = bfd_get_section_by_name (dynobj, ".got"); srela = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (sgot != NULL && srela != NULL); rela.r_offset = (sgot->output_section->vma + sgot->output_offset - + (h->got_offset &~ 1)); + + (h->got.offset &~ 1)); /* If this is a -Bsymbolic link, and the symbol is defined - locally, we just want to emit a RELATIVE reloc. The entry in - the global offset table will already have been initialized in - the relocate_section function. */ + locally, we just want to emit a RELATIVE reloc. Likewise if + the symbol was forced to be local because of a version file. + The entry in the global offset table will already have been + initialized in the relocate_section function. */ if (info->shared - && info->symbolic + && (info->symbolic || h->dynindx == -1) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); else { - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); } @@ -1451,85 +1803,15 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - if (info->shared) - { - asection *sdynsym; - asection *s; - Elf_Internal_Sym sym; - - /* Set up the section symbols for the output sections. */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; - - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; - - sym.st_value = s->vma; - - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; - - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (PTR) (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - } - - /* Set the sh_info field of the output .dynsym section to the - index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - bfd_count_sections (output_bfd) + 1; - } - return true; } -/* start-sanitize-v8plus */ -/* Function to set e_flags. */ - -static boolean -elf32_sparc_set_private_flags (abfd, flags) - bfd *abfd; - flagword flags; -{ - /* Once the flags have been set, you (apparently) can't change them. */ - BFD_ASSERT (!elf_flags_init (abfd) - || elf_elfheader (abfd)->e_flags == flags); - - elf_elfheader (abfd)->e_flags = flags; - elf_flags_init (abfd) = true; - return true; -} - -/* Copy backend specific data from one object module to another. */ +/* Functions for dealing with the e_flags field. -static boolean -elf32_sparc_copy_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; -{ - /* This function is selected based on the input vector. We only - want to copy information over if the output BFD also uses Elf - format. */ - if (bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return true; - - /* Once the flags have been set, you (apparently) can't change them. */ - BFD_ASSERT (!elf_flags_init (obfd) - || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags); - - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; - elf_flags_init (obfd) = true; - return true; -} + We don't define set_private_flags or copy_private_bfd_data because + the only currently defined values are based on the bfd mach number, + so we use the latter instead and defer setting e_flags until the + file is written out. */ /* Merge backend specific data from an object file to the output object file when linking. */ @@ -1539,18 +1821,23 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd; { - flagword old_flags; - flagword new_flags; boolean error; + /* FIXME: This should not be static. */ + static unsigned long previous_ibfd_e_flags = (unsigned long) -1; - /* This function is selected based on the input vector. We only - want to copy information over if the output BFD also uses Elf - format. */ - if (bfd_get_flavour (obfd) != bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return true; error = false; +#if 0 + /* ??? The native linker doesn't do this so we can't (otherwise gcc would + have to know which linker is being used). Instead, the native linker + bumps up the architecture level when it has to. However, I still think + warnings like these are good, so it would be nice to have them turned on + by some option. */ + /* If the output machine is normal sparc, we can't allow v9 input files. */ if (bfd_get_mach (obfd) == bfd_mach_sparc && (bfd_get_mach (ibfd) == bfd_mach_sparc_v8plus @@ -1558,7 +1845,7 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) { error = true; (*_bfd_error_handler) - ("%s: compiled for a v8plus system and target is v8", + (_("%s: compiled for a v8plus system and target is v8"), bfd_get_filename (ibfd)); } /* If the output machine is v9, we can't allow v9+vis input files. */ @@ -1567,33 +1854,31 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) { error = true; (*_bfd_error_handler) - ("%s: compiled for a v8plusa system and target is v8plus", + (_("%s: compiled for a v8plusa system and target is v8plus"), bfd_get_filename (ibfd)); } - - new_flags = elf_elfheader (ibfd)->e_flags; - old_flags = elf_elfheader (obfd)->e_flags; - if (!elf_flags_init (obfd)) /* First call, no flags set */ +#else + if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9) { - elf_flags_init (obfd) = true; - elf_elfheader (obfd)->e_flags = new_flags; + error = true; + (*_bfd_error_handler) + (_("%s: compiled for a 64 bit system and target is 32 bit"), + bfd_get_filename (ibfd)); } - else if (new_flags == old_flags) /* Compatible flags are ok */ - ; - else /* Potentially incompatible flags */ - { - new_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1); - old_flags &= ~ (EF_SPARC_32PLUS | EF_SPARC_SUN_US1); + else if (bfd_get_mach (obfd) < bfd_get_mach (ibfd)) + bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd)); +#endif - /* Warn about any other mismatches */ - if (new_flags != old_flags) - { - error = true; - (*_bfd_error_handler) - ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)", - bfd_get_filename (ibfd), (long) new_flags, (long) old_flags); - } + if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA) + != previous_ibfd_e_flags) + && previous_ibfd_e_flags != (unsigned long) -1) + { + (*_bfd_error_handler) + (_("%s: linking little endian files with big endian files"), + bfd_get_filename (ibfd)); + error = true; } + previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA; if (error) { @@ -1611,7 +1896,19 @@ elf32_sparc_object_p (abfd) bfd *abfd; { if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) - return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v8plus); + { + if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plusa); + else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_v8plus); + else + return false; + } + else if (elf_elfheader (abfd)->e_flags & EF_SPARC_LEDATA) + return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, + bfd_mach_sparc_sparclite_le); else return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); } @@ -1622,27 +1919,41 @@ elf32_sparc_object_p (abfd) static void elf32_sparc_final_write_processing (abfd, linker) bfd *abfd; - boolean linker; + boolean linker ATTRIBUTE_UNUSED; { - if (bfd_get_mach (abfd) == bfd_mach_sparc_v8plus) + switch (bfd_get_mach (abfd)) { + case bfd_mach_sparc : + break; /* nothing to do */ + case bfd_mach_sparc_v8plus : elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; -#if 0 /* FIXME: Not sure how to handle EF_SPARC_32PLUS_US1 */ elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; -#endif elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS; + break; + case bfd_mach_sparc_v8plusa : + elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; + elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; + elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1; + break; + case bfd_mach_sparc_sparclite_le : + elf_elfheader (abfd)->e_machine = EM_SPARC; + elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA; + break; + default : + abort (); + break; } } -/* end-sanitize-v8plus */ #define TARGET_BIG_SYM bfd_elf32_sparc_vec #define TARGET_BIG_NAME "elf32-sparc" #define ELF_ARCH bfd_arch_sparc #define ELF_MACHINE_CODE EM_SPARC -/* start-sanitize-v8plus */ #define ELF_MACHINE_ALT1 EM_SPARC32PLUS -/* end-sanitize-v8plus */ #define ELF_MAXPAGESIZE 0x10000 + +#define bfd_elf32_bfd_reloc_type_lookup elf32_sparc_reloc_type_lookup +#define elf_info_to_howto elf32_sparc_info_to_howto #define elf_backend_create_dynamic_sections \ _bfd_elf_create_dynamic_sections #define elf_backend_check_relocs elf32_sparc_check_relocs @@ -1655,18 +1966,19 @@ elf32_sparc_final_write_processing (abfd, linker) elf32_sparc_finish_dynamic_symbol #define elf_backend_finish_dynamic_sections \ elf32_sparc_finish_dynamic_sections -/* start-sanitize-v8plus */ -#define bfd_elf32_bfd_set_private_flags elf32_sparc_set_private_flags -#define bfd_elf32_bfd_copy_private_bfd_data \ - elf32_sparc_copy_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data \ elf32_sparc_merge_private_bfd_data #define elf_backend_object_p elf32_sparc_object_p #define elf_backend_final_write_processing \ elf32_sparc_final_write_processing -/* end-sanitize-v8plus */ +#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook +#define elf_backend_gc_sweep_hook elf32_sparc_gc_sweep_hook + +#define elf_backend_can_gc_sections 1 #define elf_backend_want_got_plt 0 #define elf_backend_plt_readonly 0 #define elf_backend_want_plt_sym 1 +#define elf_backend_got_header_size 4 +#define elf_backend_plt_header_size (4*PLT_ENTRY_SIZE) #include "elf32-target.h"