From 53787b2316b0e9b4f166efc87f88748c46263096 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 29 Jan 1996 20:01:29 +0000 Subject: [PATCH] * elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when copying relocs into a shared object, treat a defined global symbol as a local symbol. * elf32-m68k.c (elf_m68k_relocate_section): Likewise. * elf32-mips.c (mips_elf_relocate_section): Likewise. * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. --- bfd/ChangeLog | 7 + bfd/elf32-i386.c | 26 ++- bfd/elf32-m68k.c | 24 +- bfd/elf32-mips.c | 552 +++++++++++++++++++++++++++------------------- bfd/elf32-sparc.c | 141 +++++------- 5 files changed, 433 insertions(+), 317 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cd48dd65546..f18d32e568e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -7,6 +7,13 @@ Mon Jan 29 14:27:24 1996 Kim Knuttila Mon Jan 29 13:06:28 1996 Ian Lance Taylor + * elf32-i386.c (elf_i386_relocate_section): If -Bsymbolic, when + copying relocs into a shared object, treat a defined global symbol + as a local symbol. + * elf32-m68k.c (elf_m68k_relocate_section): Likewise. + * elf32-mips.c (mips_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + * elflink.h (elf_link_add_object_symbols): Only set weakdef to a real defined symbol, not to a weak defined symbol. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 82f0ccded01..cb2a3dc75dc 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1,5 +1,5 @@ /* Intel 80386/80486-specific support for 32-bit ELF - Copyright 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -916,6 +916,9 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) || (info->shared + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0) && (r_type == R_386_32 || r_type == R_386_PC32) && (input_section->flags & SEC_ALLOC) != 0)) @@ -1100,9 +1103,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, case R_386_PC32: if (info->shared && (input_section->flags & SEC_ALLOC) != 0 - && (r_type != R_386_PC32 || h != NULL)) + && (r_type != R_386_PC32 + || (h != NULL + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) { Elf_Internal_Rel outrel; + boolean relocate; /* When generating a shared object, these relocations are copied into the output file to be resolved at run @@ -1134,15 +1142,23 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, if (r_type == R_386_PC32) { BFD_ASSERT (h != NULL && h->dynindx != -1); + relocate = false; outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32); } else { - if (h == NULL) - outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + if (h == NULL + || (info->symbolic + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) != 0)) + { + relocate = true; + outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + } else { BFD_ASSERT (h->dynindx != -1); + relocate = false; outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32); } } @@ -1157,7 +1173,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, not want to fiddle with the addend. Otherwise, we need to include the symbol value so that it becomes an addend for the dynamic reloc. */ - if (h != NULL) + if (! relocate) continue; } diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 35d6c097b24..d712569d391 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -1,5 +1,5 @@ /* Motorola 68k series support for 32-bit ELF - Copyright 1993 Free Software Foundation, Inc. + Copyright 1993, 1995, 1996 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -898,6 +898,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) || (info->shared + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0) && (input_section->flags & SEC_ALLOC) != 0 && (r_type == R_68K_8 || r_type == R_68K_16 @@ -1142,7 +1145,10 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_offset = (rel->r_offset + input_section->output_section->vma + input_section->output_offset); - if (h != NULL) + if (h != NULL + && (! info->symbolic + || (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); @@ -1159,11 +1165,15 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - sym = local_syms + r_symndx; - - BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); - - 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) diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index c254ecf8d76..b6c544a99ab 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -80,6 +80,10 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); static void mips_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *)); +static void bfd_mips_elf32_swap_gptab_in + PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *)); +static void bfd_mips_elf32_swap_gptab_out + PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *)); static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *)); static boolean mips_elf_object_p PARAMS ((bfd *)); static boolean mips_elf_create_procedure_table @@ -89,6 +93,9 @@ static int mips_elf_additional_program_headers PARAMS ((bfd *)); static boolean mips_elf_modify_segment_map PARAMS ((bfd *)); static void mips_elf_final_write_processing PARAMS ((bfd *, boolean)); +static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword)); +static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); +static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); static boolean mips_elf_section_from_shdr PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); static boolean mips_elf_fake_sections @@ -125,11 +132,32 @@ static boolean mips_elf_adjust_dynindx static boolean mips_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); +static boolean mips_elf_create_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_create_compact_rel_section + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_create_got_section + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_check_relocs + PARAMS ((bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *)); +static boolean mips_elf_adjust_dynamic_symbol + PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); +static boolean mips_elf_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_finish_dynamic_symbol + PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *)); +static boolean mips_elf_finish_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); static boolean mips_elf_add_symbol_hook PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, const char **, flagword *, asection **, bfd_vma *)); static bfd_reloc_status_type mips_elf_final_gp PARAMS ((bfd *, asymbol *, boolean, char **)); +static bfd_byte *elf32_mips_get_relocated_section_contents + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, boolean, asymbol **)); /* This is true for Irix 5 executables, false for normal MIPS ELF ABI executables. FIXME: At the moment, we default to always generating @@ -289,6 +317,11 @@ typedef struct #define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v)) #define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2) +static void bfd_elf32_swap_compact_rel_out + PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *)); +static void bfd_elf32_swap_crinfo_out + PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *)); + #define USE_REL 1 /* MIPS uses REL relocations instead of RELA */ enum reloc_type @@ -1327,7 +1360,7 @@ bfd_mips_elf32_swap_gptab_out (abfd, in, ex) static void bfd_elf32_swap_compact_rel_out (abfd, in, ex) bfd *abfd; - Elf32_compact_rel *in; + const Elf32_compact_rel *in; Elf32_External_compact_rel *ex; { bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1); @@ -1341,7 +1374,7 @@ bfd_elf32_swap_compact_rel_out (abfd, in, ex) static void bfd_elf32_swap_crinfo_out (abfd, in, ex) bfd *abfd; - Elf32_crinfo *in; + const Elf32_crinfo *in; Elf32_External_crinfo *ex; { unsigned long l; @@ -1968,8 +2001,7 @@ mips_elf_additional_program_headers (abfd) ++ret; } - if (bfd_get_section_by_name (abfd, ".interp") == NULL - && bfd_get_section_by_name (abfd, ".dynamic") != NULL + if (bfd_get_section_by_name (abfd, ".dynamic") != NULL && bfd_get_section_by_name (abfd, ".mdebug") != NULL) { /* We need a PT_MIPS_RTPROC segment. */ @@ -2409,6 +2441,8 @@ struct mips_elf_link_hash_table bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES]; /* The number of .rtproc entries. */ bfd_size_type procedure_count; + /* The size of the .compact_rel section (if SGI_COMPAT). */ + bfd_size_type compact_rel_size; }; /* Look up an entry in a MIPS ELF linker hash table. */ @@ -2494,6 +2528,7 @@ mips_elf_link_hash_table_create (abfd) for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++) ret->dynsym_sec_strindex[i] = (bfd_size_type) -1; ret->procedure_count = 0; + ret->compact_rel_size = 0; return &ret->root.root; } @@ -2512,6 +2547,15 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) asection **secp; bfd_vma *valp; { + if (SGI_COMPAT (abfd) + && (abfd->flags & DYNAMIC) != 0 + && strcmp (*namep, "_rld_new_interface") == 0) + { + /* Skip Irix 5 rld entry name. */ + *namep = NULL; + return true; + } + switch (sym->st_shndx) { case SHN_COMMON: @@ -2549,6 +2593,8 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) *secp = mips_elf_text_section_ptr; break; + case SHN_MIPS_ACOMMON: + /* Fall through. XXX Can we treat this as allocated data? */ case SHN_MIPS_DATA: /* This section is used in a shared object. */ if (mips_elf_data_section_ptr == NULL) @@ -3865,7 +3911,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* If this is HI16 or GOT16 with an associated LO16, adjust the addend accordingly. Otherwise, just relocate. */ - if ((r_type != R_MIPS_HI16 || r_type == R_MIPS_GOT16) + if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16) || (rel + 1) >= relend || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16) r = _bfd_relocate_contents (howto, input_bfd, @@ -3953,6 +3999,19 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = 0; else if (info->shared && ! info->symbolic) relocation = 0; + else if (strcmp (h->root.root.string, "_DYNAMIC_LINK") == 0) + { + /* If this is a dynamic link, we should have created + a _DYNAMIC_LINK symbol in + mips_elf_create_dynamic_sections. Otherwise, we + should define the symbol with a value of 0. + FIXME: It should probably get into the symbol + table somehow as well. */ + BFD_ASSERT (! info->shared); + BFD_ASSERT (bfd_get_section_by_name (output_bfd, + ".dynamic") == NULL); + relocation = 0; + } else { if (! ((*info->callbacks->undefined_symbol) @@ -4065,7 +4124,10 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, addend = bfd_get_32 (input_bfd, contents + rel->r_offset); - if (h != NULL) + if (h != NULL + && (! info->symbolic + || (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_MIPS_REL32); @@ -4075,11 +4137,15 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - sym = local_syms + r_symndx; - - BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); - - 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) @@ -4122,6 +4188,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32); else mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); + mips_elf_set_cr_dist2to (cptrel, 0); cptrel.konst = addend; cr = (scpt->contents @@ -4163,7 +4230,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, { case R_MIPS_26: mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD); - cptrel.konst = addend; + /* XXX How should we set dist2to in this case. */ + mips_elf_set_cr_dist2to (cptrel, 8); + cptrel.konst = addend + relocation; cr = scpt->contents + sizeof (Elf32_External_compact_rel); bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, ((Elf32_External_crinfo *) cr @@ -4176,6 +4245,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_MIPS_GPREL32: mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO); cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr; + mips_elf_set_cr_dist2to (cptrel, 4); cr = scpt->contents + sizeof (Elf32_External_compact_rel); bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, ((Elf32_External_crinfo *) cr @@ -4233,7 +4303,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1" /* Create dynamic sections when linking against a dynamic object. */ -static boolean mips_elf_create_got_section (bfd *, struct bfd_link_info *); static boolean mips_elf_create_dynamic_sections (abfd, info) @@ -4284,24 +4353,13 @@ mips_elf_create_dynamic_sections (abfd, info) h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; h->type = STT_SECTION; - if (info->shared - && ! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; - } - - /* Create .compact_rel section. */ - if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) - { - flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY; - - s = bfd_make_section (abfd, ".compact_rel"); - if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags) - || ! bfd_set_section_alignment (abfd, s, 2)) + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return false; } - s->_raw_size = sizeof (Elf32_compact_rel); + /* We need to create a .compact_rel section. */ + if (! mips_elf_create_compact_rel_section (abfd, info)) + return false; /* Change aligments of some sections. */ s = bfd_get_section_by_name (abfd, ".hash"); @@ -4321,9 +4379,51 @@ mips_elf_create_dynamic_sections (abfd, info) bfd_set_section_alignment (abfd, s, 4); } + if (!info->shared) + { + h = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr, + (bfd_vma) 0, (const char *) NULL, false, + get_elf_backend_data (abfd)->collect, + (struct bfd_link_hash_entry **) &h))) + return false; + h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; + h->type = STT_SECTION; + + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + return true; } +/* Create the .compact_rel section. */ + +static boolean +mips_elf_create_compact_rel_section (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + flagword flags; + register asection *s; + + if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) + { + flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY; + + s = bfd_make_section (abfd, ".compact_rel"); + if (s == NULL + || ! bfd_set_section_flags (abfd, s, flags) + || ! bfd_set_section_alignment (abfd, s, 2)) + return false; + + s->_raw_size = sizeof (Elf32_External_compact_rel); + } + + return true; +} + /* Create the .got section to hold the global offset table. */ static boolean @@ -4350,9 +4450,7 @@ mips_elf_create_got_section (abfd, info) /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the linker script because we don't want to define the symbol if we - are not creating a global offset table. XXX Should this be - defined at the start of the .got section, even if .got section is - accessed by using 16 bit signed offset? */ + are not creating a global offset table. */ h = NULL; if (! (_bfd_generic_link_add_one_symbol (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, @@ -4407,7 +4505,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs) const Elf_Internal_Rela *rel_end; asection *sgot; asection *sreloc; - asection *scpt; if (info->relocateable) return true; @@ -4419,10 +4516,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs) sgot = NULL; sreloc = NULL; - if (SGI_COMPAT (abfd) && dynobj != NULL) - scpt = bfd_get_section_by_name (dynobj, ".compact_rel"); - else - scpt = NULL; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -4577,19 +4670,21 @@ mips_elf_check_relocs (abfd, info, sec, relocs) } sreloc->_raw_size += sizeof (Elf32_External_Rel); - - if (scpt != NULL) - scpt->_raw_size += sizeof (Elf32_External_crinfo); } + if (SGI_COMPAT (abfd)) + mips_elf_hash_table (info)->compact_rel_size += + sizeof (Elf32_External_crinfo); + break; case R_MIPS_26: case R_MIPS_GPREL16: case R_MIPS_LITERAL: case R_MIPS_GPREL32: - if (scpt != NULL) - scpt->_raw_size += sizeof (Elf32_External_crinfo); + if (SGI_COMPAT (abfd)) + mips_elf_hash_table (info)->compact_rel_size += + sizeof (Elf32_External_crinfo); break; default: @@ -4800,9 +4895,10 @@ mips_elf_size_dynamic_sections (output_bfd, info) of .text section. So put a dummy. XXX */ s->_raw_size += MIPS_FUNCTION_STUB_SIZE; } - else if (strncmp (name, ".init", 5) != 0 - && (! SGI_COMPAT (output_bfd) - || strncmp (name, ".compact_rel", 12) != 0)) + else if (SGI_COMPAT (output_bfd) + && strncmp (name, ".compact_rel", 12) == 0) + s->_raw_size += mips_elf_hash_table (info)->compact_rel_size; + else if (strncmp (name, ".init", 5) != 0) { /* It's not one of our sections, so don't allocate space. */ continue; @@ -4872,7 +4968,7 @@ mips_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0)) return false; - if (bfd_get_section_by_name (dynobj, ".conflict")) + if (bfd_get_section_by_name (dynobj, ".conflict") != NULL) { if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0)) return false; @@ -4890,8 +4986,11 @@ mips_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0)) return false; +#if 0 + /* Time stamps in executable files are a bad idea. */ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0)) return false; +#endif #if 0 /* FIXME */ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0)) @@ -4932,74 +5031,76 @@ mips_elf_size_dynamic_sections (output_bfd, info) #endif } - /* 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. + /* If we use dynamic linking, 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) - { - const char * const *namep; - int c, i; - bfd_size_type strindex; - struct bfd_strtab_hash *dynstr; - struct mips_got_info *g; - - if (SGI_COMPAT (output_bfd)) - { - c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1; - elf_link_hash_traverse (elf_hash_table (info), - mips_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - - dynstr = elf_hash_table (info)->dynstr; - BFD_ASSERT (dynstr != NULL); - - for (i = 1, namep = mips_elf_dynsym_sec_names; - *namep != NULL; - i++, namep++) - { - s = bfd_get_section_by_name (output_bfd, *namep); - if (s != NULL) - elf_section_data (s)->dynindx = i; + { + const char * const *namep; + unsigned int c, i; + bfd_size_type strindex; + struct bfd_strtab_hash *dynstr; + struct mips_got_info *g; + + if (elf_hash_table (info)->dynamic_sections_created) + { + if (SGI_COMPAT (output_bfd)) + { + c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1; + elf_link_hash_traverse (elf_hash_table (info), + mips_elf_adjust_dynindx, + (PTR) &c); + elf_hash_table (info)->dynsymcount += c; + + dynstr = elf_hash_table (info)->dynstr; + BFD_ASSERT (dynstr != NULL); + + for (i = 1, namep = mips_elf_dynsym_sec_names; + *namep != NULL; + i++, namep++) + { + s = bfd_get_section_by_name (output_bfd, *namep); + if (s != NULL) + elf_section_data (s)->dynindx = i; - strindex = _bfd_stringtab_add (dynstr, *namep, true, false); - if (strindex == (bfd_size_type) -1) - return false; + strindex = _bfd_stringtab_add (dynstr, *namep, true, false); + if (strindex == (bfd_size_type) -1) + return false; - mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex; - } - } - else - { - c = bfd_count_sections (output_bfd); - elf_link_hash_traverse (elf_hash_table (info), - mips_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; + mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex; + } + } + else + { + c = bfd_count_sections (output_bfd); + elf_link_hash_traverse (elf_hash_table (info), + mips_elf_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. */ - } - } + 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. */ + } + } + } - s = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (s != NULL); - BFD_ASSERT (elf_section_data (s) != NULL); - g = (struct mips_got_info *) elf_section_data (s)->tdata; - BFD_ASSERT (g != NULL); + s = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (s != NULL); + BFD_ASSERT (elf_section_data (s) != NULL); + g = (struct mips_got_info *) elf_section_data (s)->tdata; + BFD_ASSERT (g != NULL); - /* If there are no global got symbols, fake the last symbol so for - safety. */ - if (g->global_gotsym) - g->global_gotsym += c; - else - g->global_gotsym = elf_hash_table (info)->dynsymcount - 1; - } + /* If there are no global got symbols, fake the last symbol so for + safety. */ + if (g->global_gotsym) + g->global_gotsym += c; + else + g->global_gotsym = elf_hash_table (info)->dynsymcount - 1; + } return true; } @@ -5012,7 +5113,7 @@ mips_elf_adjust_dynindx (h, cparg) struct elf_link_hash_entry *h; PTR cparg; { - int *cp = (int *) cparg; + unsigned int *cp = (unsigned int *) cparg; if (h->dynindx != -1) h->dynindx += *cp; @@ -5108,8 +5209,13 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym) if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) sym->st_shndx = SHN_ABS; - - if (SGI_COMPAT (output_bfd)) + else if (strcmp (name, "_DYNAMIC_LINK") == 0) + { + sym->st_shndx = SHN_ABS; + sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); + sym->st_value = 1; + } + else if (SGI_COMPAT (output_bfd)) { if (strcmp (name, "_gp_disp") == 0) { @@ -5132,8 +5238,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym) sym->st_value = mips_elf_hash_table (info)->procedure_count; sym->st_shndx = SHN_ABS; } - - if (sym->st_shndx != SHN_UNDEF) + else if (sym->st_shndx != SHN_UNDEF) { if (h->type == STT_FUNC) sym->st_shndx = SHN_MIPS_TEXT; @@ -5321,128 +5426,130 @@ mips_elf_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - if (info->shared) - { - asection *sdynsym; - asection *s; - unsigned int i; - bfd_vma last; - Elf_Internal_Sym sym; - long dindx; - const char *name; - const char * const * namep = mips_elf_dynsym_sec_names; - Elf32_compact_rel cpt; - - /* Set up the section symbols for the output sections. SGI set - STT_NOTYPE attribute for these symbols. Should we do so? */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - if (SGI_COMPAT (output_bfd)) - { - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); - sym.st_other = 0; - - i = 0; - while ((name = *namep++) != NULL) - { - s = bfd_get_section_by_name (output_bfd, name); - if (s) - { - sym.st_value = s->vma; - dindx = elf_section_data (s)->dynindx; - last = s->vma + s->_raw_size; - } - else - { - sym.st_value = last; - dindx++; - } - - sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO - ? SHN_MIPS_TEXT - : SHN_MIPS_DATA); - ++i; - sym.st_name = - mips_elf_hash_table (info)->dynsym_sec_strindex[dindx]; + { + asection *sdynsym; + asection *s; + unsigned int i; + bfd_vma last; + Elf_Internal_Sym sym; + long dindx; + const char *name; + const char * const * namep = mips_elf_dynsym_sec_names; + Elf32_compact_rel cpt; + + /* Set up the section symbols for the output sections. SGI sets + the STT_NOTYPE attribute for these symbols. Should we do so? */ + + sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); + if (sdynsym != NULL) + { + if (SGI_COMPAT (output_bfd)) + { + sym.st_size = 0; + sym.st_name = 0; + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); + sym.st_other = 0; - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (((Elf32_External_Sym *) - sdynsym->contents) - + dindx)); - } + i = 0; + while ((name = *namep++) != NULL) + { + s = bfd_get_section_by_name (output_bfd, name); + if (s != NULL) + { + sym.st_value = s->vma; + dindx = elf_section_data (s)->dynindx; + last = s->vma + s->_raw_size; + } + else + { + sym.st_value = last; + dindx++; + } - /* 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 = - SIZEOF_MIPS_DYNSYM_SECNAMES; - } - else - { - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; + sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO + ? SHN_MIPS_TEXT + : SHN_MIPS_DATA); + ++i; + sym.st_name = + mips_elf_hash_table (info)->dynsym_sec_strindex[dindx]; + + bfd_elf32_swap_symbol_out (output_bfd, &sym, + (((Elf32_External_Sym *) + sdynsym->contents) + + dindx)); + } - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; + /* 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 = + SIZEOF_MIPS_DYNSYM_SECNAMES; + } + else + { + sym.st_size = 0; + sym.st_name = 0; + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + sym.st_other = 0; - sym.st_value = s->vma; + for (s = output_bfd->sections; s != NULL; s = s->next) + { + int indx; - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; + sym.st_value = s->vma; - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - } + indx = elf_section_data (s)->this_idx; + BFD_ASSERT (indx > 0); + sym.st_shndx = indx; - /* 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; - } + bfd_elf32_swap_symbol_out (output_bfd, &sym, + (((Elf32_External_Sym *) + sdynsym->contents) + + elf_section_data (s)->dynindx)); + } - if (SGI_COMPAT (output_bfd)) - { - /* Write .compact_rel section out. */ - s = bfd_get_section_by_name (dynobj, ".compact_rel"); - BFD_ASSERT (s != NULL); + /* 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; + } + } - cpt.id1 = 1; - cpt.num = s->reloc_count; - cpt.id2 = 2; - cpt.offset = (s->output_section->filepos - + sizeof (Elf32_External_compact_rel)); - cpt.reserved0 = 0; - cpt.reserved1 = 0; - bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, - ((Elf32_External_compact_rel *) - s->contents)); - - /* Clean up a dummy stub function entry in .text. */ - s = bfd_get_section_by_name (dynobj, ".stub"); - if (s != NULL) - { - file_ptr dummy_offset; + if (SGI_COMPAT (output_bfd)) + { + /* Write .compact_rel section out. */ + s = bfd_get_section_by_name (dynobj, ".compact_rel"); + if (s != NULL) + { + cpt.id1 = 1; + cpt.num = s->reloc_count; + cpt.id2 = 2; + cpt.offset = (s->output_section->filepos + + sizeof (Elf32_External_compact_rel)); + cpt.reserved0 = 0; + cpt.reserved1 = 0; + bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, + ((Elf32_External_compact_rel *) + s->contents)); + + /* Clean up a dummy stub function entry in .text. */ + s = bfd_get_section_by_name (dynobj, ".stub"); + if (s != NULL) + { + file_ptr dummy_offset; - BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE); - dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE; - memset (s->contents + dummy_offset, 0, MIPS_FUNCTION_STUB_SIZE); - } - } + BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE); + dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE; + memset (s->contents + dummy_offset, 0, + MIPS_FUNCTION_STUB_SIZE); + } + } + } - /* Clean up a first relocation in .rel.dyn. */ - s = bfd_get_section_by_name (dynobj, ".rel.dyn"); - if (s) - memset (s->contents, 0, sizeof (Elf32_External_Rel)); - } + /* Clean up a first relocation in .rel.dyn. */ + s = bfd_get_section_by_name (dynobj, ".rel.dyn"); + if (s != NULL) + memset (s->contents, 0, sizeof (Elf32_External_Rel)); + } return true; } @@ -5712,7 +5819,6 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = #define bfd_elf32_bfd_merge_private_bfd_data \ mips_elf_merge_private_bfd_data #define bfd_elf32_bfd_set_private_flags mips_elf_set_private_flags -#define elf_backend_relocate_section mips_elf_relocate_section #define elf_backend_add_symbol_hook mips_elf_add_symbol_hook #define elf_backend_create_dynamic_sections \ mips_elf_create_dynamic_sections diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index f7598812767..b4327b7c54a 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -22,9 +22,7 @@ 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 PARAMS ((bfd *, bfd_reloc_code_real_type)); @@ -47,15 +45,11 @@ 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 { @@ -914,6 +908,9 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) || (info->shared + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0) && (input_section->flags & SEC_ALLOC) != 0 && (r_type == R_SPARC_8 || r_type == R_SPARC_16 @@ -1131,7 +1128,10 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_offset = (rel->r_offset + input_section->output_section->vma + input_section->output_offset); - if (h != NULL) + if (h != NULL + && (! info->symbolic + || (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 +1148,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) @@ -1491,45 +1498,13 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info) 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. */ - -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; +/* Functions for dealing with the e_flags field. - /* 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,8 +1514,6 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd; { - flagword old_flags; - flagword new_flags; boolean error; /* This function is selected based on the input vector. We only @@ -1551,6 +1524,13 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) 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 @@ -1570,30 +1550,17 @@ elf32_sparc_merge_private_bfd_data (ibfd, obfd) ("%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; - } - 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); - - /* 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); - } + error = true; + (*_bfd_error_handler) + ("%s: compiled for a 64 bit system and target is 32 bit", + bfd_get_filename (ibfd)); } + else if (bfd_get_mach (obfd) < bfd_get_mach (ibfd)) + bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd)); +#endif if (error) { @@ -1611,7 +1578,16 @@ 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 return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); } @@ -1624,24 +1600,30 @@ elf32_sparc_final_write_processing (abfd, linker) bfd *abfd; boolean linker; { - 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; + default : + abort (); } } -/* 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 elf_backend_create_dynamic_sections \ _bfd_elf_create_dynamic_sections @@ -1655,16 +1637,11 @@ 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_want_got_plt 0 #define elf_backend_plt_readonly 0 #define elf_backend_want_plt_sym 1 -- 2.30.2