From 19bfbcbecf49abb63d85b0244dc10770e3b4ac9a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Apr 1996 19:57:33 +0000 Subject: [PATCH] * elf-bfd.h (struct elf_link_hash_table): Add hgot field. * elf.c (_bfd_elf_link_hash_table_init): Initialize hgot field. * elflink.c (_bfd_elf_create_got_section): Store the _GLOBAL_OFFSET_TABLE_ hash table entry in the hgot field. * elf32-sparc.c (elf32_sparc_check_relocs): If the size of the global offset table goes over 0x1000, set the value of _GLOBAL_OFFSET_TABLE_ to 0x1000 into the section. (elf32_sparc_relocate_section): Subtract the offset of _GLOBAL_OFFSET_TABLE_ when handling GOT relocations. PR 9323. --- bfd/ChangeLog | 10 ++ bfd/elf-bfd.h | 21 ++-- bfd/elf.c | 7 +- bfd/elf32-sparc.c | 303 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 258 insertions(+), 83 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 42953608aa7..9de2eec07e7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,15 @@ Tue Apr 2 00:33:18 1996 Ian Lance Taylor + * elf-bfd.h (struct elf_link_hash_table): Add hgot field. + * elf.c (_bfd_elf_link_hash_table_init): Initialize hgot field. + * elflink.c (_bfd_elf_create_got_section): Store the + _GLOBAL_OFFSET_TABLE_ hash table entry in the hgot field. + * elf32-sparc.c (elf32_sparc_check_relocs): If the size of the + global offset table goes over 0x1000, set the value of + _GLOBAL_OFFSET_TABLE_ to 0x1000 into the section. + (elf32_sparc_relocate_section): Subtract the offset of + _GLOBAL_OFFSET_TABLE_ when handling GOT relocations. + * elfcode.h: Don't include . Mon Apr 1 10:39:24 1996 Jeffrey A Law (law@cygnus.com) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b6060634eb5..987425ea7eb 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -126,6 +126,10 @@ struct elf_link_hash_entry #define ELF_LINK_HASH_NEEDS_COPY 040 /* Symbol needs a procedure linkage table entry. */ #define ELF_LINK_HASH_NEEDS_PLT 0100 + /* Symbol appears in a non-ELF input file. */ +#define ELF_LINK_NON_ELF 0200 + /* Note: If you add more flags, you must change the type of + elf_link_hash_flags. */ }; /* ELF linker hash table. */ @@ -152,6 +156,8 @@ struct elf_link_hash_table /* A linked list of DT_NEEDED names found in dynamic objects included in the link. */ struct bfd_link_needed_list *needed; + /* The _GLOBAL_OFFSET_TABLE_ symbol. */ + struct elf_link_hash_entry *hgot; }; /* Look up an entry in an ELF linker hash table. */ @@ -446,9 +452,6 @@ struct elf_backend_data unsigned want_got_plt : 1; unsigned plt_readonly : 1; unsigned want_plt_sym : 1; - - /* Put ELF and program headers in the first loadable segment. */ - unsigned want_hdr_in_seg : 1; }; /* Information stored for each BFD section in an ELF file. This @@ -578,9 +581,13 @@ struct elf_obj_tdata /* The linker ELF emulation code needs to let the backend ELF linker know what filename should be used for a dynamic object if the - dynamic object is found using a search. This field is used to - hold that information. */ - const char *dt_needed_name; + dynamic object is found using a search. The emulation code then + sometimes needs to know what name was actually used. Until the + file has been added to the linker symbol table, this field holds + the name the linker wants. After it has been added, it holds the + name actually used, which will be the DT_SONAME entry if there is + one. */ + const char *dt_name; /* Irix 5 often screws up the symbol table, sorting local symbols after global symbols. This flag is set if the symbol table in @@ -624,7 +631,7 @@ struct elf_obj_tdata #define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes) #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got_offsets) #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers) -#define elf_dt_needed_name(bfd) (elf_tdata(bfd) -> dt_needed_name) +#define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name) #define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) #define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init) #define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n]) diff --git a/bfd/elf.c b/bfd/elf.c index fdc16d9091e..6ede06aec84 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -583,6 +583,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc) table->dynstr = NULL; table->bucketcount = 0; table->needed = NULL; + table->hgot = NULL; return _bfd_link_hash_table_init (&table->root, abfd, newfunc); } @@ -2078,11 +2079,9 @@ assign_file_positions_for_segments (abfd) if (i == 0) abort (); p->p_memsz += adjust; + off += adjust; if ((flags & SEC_LOAD) != 0) - { - p->p_filesz += adjust; - off += adjust; - } + p->p_filesz += adjust; } } diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index b4327b7c54a..3e2343cc221 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "elf-bfd.h" #include "elf/sparc.h" -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 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); @@ -50,70 +50,86 @@ static boolean elf32_sparc_object_p PARAMS ((bfd *)); static void elf32_sparc_final_write_processing PARAMS ((bfd *, boolean)); - -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 - }; - -#if 0 -static CONST char *CONST reloc_type_names[] = + +/* The howto table and associated functions. + ??? elf64-sparc.c has its own copy for the moment to ease transition + since some of the relocation values have changed. At some point we'll + want elf64-sparc.c to switch over and use this table. + ??? Do we want to recognize (or flag as errors) some of the 64 bit entries + if the target is elf32-sparc. +*/ + +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 **)); + +reloc_howto_type _bfd_sparc_elf_howto_table[] = { - "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", -}; + 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), + /* ??? If we need to handle R_SPARC_64 then we need (figuratively) + --enable-64-bit-bfd. That causes objdump to print address as 64 bits + which we really don't want on an elf32-sparc system. There may be other + consequences which we may not want (at least not until it's proven they're + necessary) so for now these are only enabled ifdef BFD64. */ +#ifdef BFD64 + HOWTO(R_SPARC_64, 0,4,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", false,0,~ (bfd_vma) 0, true), + /* ??? These don't make sense except in 64 bit systems so they're disabled + ifndef BFD64 too (for now). */ + HOWTO(R_SPARC_OLO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false,0,0x000003ff,true), + HOWTO(R_SPARC_HH22, 42,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true), + HOWTO(R_SPARC_HM10, 32,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true), + HOWTO(R_SPARC_LM22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true), + HOWTO(R_SPARC_PC_HH22, 42,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true), + HOWTO(R_SPARC_PC_HM10, 32,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true), + HOWTO(R_SPARC_PC_LM22, 10,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true), +#else + 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), #endif - -static reloc_howto_type elf_sparc_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_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,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true), + HOWTO(R_SPARC_GLOB_JMP, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",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), }; struct elf_reloc_map { @@ -127,6 +143,8 @@ 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 }, + /* ??? This might cause us to need separate functions in elf{32,64}-sparc.c + (we could still have just one table), but is this reloc ever used? */ { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */ { BFD_RELOC_32, R_SPARC_32 }, { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, @@ -146,11 +164,28 @@ 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_GLOB_JMP, R_SPARC_GLOB_JMP}, + {BFD_RELOC_SPARC_7, R_SPARC_7}, + {BFD_RELOC_SPARC_5, R_SPARC_5}, + {BFD_RELOC_SPARC_6, R_SPARC_6}, }; static reloc_howto_type * -bfd_elf32_bfd_reloc_type_lookup (abfd, code) +elf32_sparc_reloc_type_lookup (abfd, code) bfd *abfd; bfd_reloc_code_real_type code; { @@ -158,11 +193,14 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) { if (sparc_reloc_map[i].bfd_reloc_val == code) - return &elf_sparc_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; + return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; } return 0; } +/* 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; @@ -170,9 +208,85 @@ elf_info_to_howto (abfd, cache_ptr, dst) 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)]; + 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; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + 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; +{ + 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, (char *) data + reloc_entry->address); + x |= ((((relocation >> 2) & 0xc000) << 6) + | ((relocation >> 2) & 0x3fff)); + bfd_put_32 (abfd, x, (char *) 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. */ @@ -339,6 +453,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: @@ -378,6 +499,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) case R_SPARC_DISP32: case R_SPARC_WDISP30: case R_SPARC_WDISP22: + case R_SPARC_WDISP19: + case R_SPARC_WDISP16: if (h == NULL) break; /* Fall through. */ @@ -821,6 +944,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; @@ -832,6 +956,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; @@ -855,7 +984,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, 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); @@ -893,6 +1022,9 @@ 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) { @@ -920,6 +1052,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 @@ -1000,7 +1134,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, } } - relocation = sgot->output_offset + off; + relocation = sgot->output_offset + off - got_base; } else { @@ -1045,7 +1179,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; @@ -1085,6 +1219,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_DISP32: case R_SPARC_WDISP30: case R_SPARC_WDISP22: + case R_SPARC_WDISP19: + case R_SPARC_WDISP16: if (h == NULL) break; /* Fall through. */ @@ -1194,9 +1330,30 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, break; } - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, rel->r_offset, - relocation, rel->r_addend); + if (r_type != R_SPARC_WDISP16) + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, rel->r_addend); + else + { + 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; + } if (r != bfd_reloc_ok) { @@ -1625,6 +1782,8 @@ elf32_sparc_final_write_processing (abfd, linker) #define ELF_MACHINE_CODE EM_SPARC #define ELF_MACHINE_ALT1 EM_SPARC32PLUS #define ELF_MAXPAGESIZE 0x10000 + +#define bfd_elf32_bfd_reloc_type_lookup elf32_sparc_reloc_type_lookup #define elf_backend_create_dynamic_sections \ _bfd_elf_create_dynamic_sections #define elf_backend_check_relocs elf32_sparc_check_relocs -- 2.30.2