diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fd02d0b3ff..b68f7240cb 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,49 @@ 2001-09-29 Alan Modra + * elf-bfd.h (struct elf_link_local_dynamic_entry): Add init_refcount. + (struct elf_backend_data): Add can_refcount. + * elf.c (_bfd_elf_link_hash_newfunc): Get rid of a few casts. Set + got.refcount and plt.refcount from init_refcount. + (_bfd_elf_link_hash_table_init): Set up init_refcount. + (_bfd_elf_link_hash_copy_indirect): Reference got/plt.refcount + rather than got/plt.offset, and test for <= 0 rather than -1. + * elflink.h (size_dynamic_sections): Set init_refcount to -1. + * elfxx-target.h (elf_backend_can_refcount): Define. + (elfNN_bed): Init can_refcount. + * linker.c (_bfd_link_hash_newfunc): Get rid of a few casts. + (_bfd_generic_link_hash_newfunc): Likewise. + * elf32-cris.c (cris_elf_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * elf32-hppa.c (elf32_hppa_check_relocs): Modify for refcounts + starting from zero. + (elf32_hppa_copy_indirect_symbol): Make static to agree with + prototype. + (elf_backend_can_refcount): Define. + * elf32-i386.c (elf_i386_check_relocs): Modify for refcounts + starting from zero. + (allocate_dynrelocs): Set plt/got.offset rather than *.refcount. + (elf_i386_finish_dynamic_symbol): Expand SHN_UNDEF comment. + (elf_i386_finish_dynamic_sections): Use local var so line < 80 chars. + (elf_backend_can_refcount): Define. + (elf_i386_copy_indirect_symbol): Make static to agree with + prototype. Formatting fix. + * elf32-m68k.c (elf_m68k_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * elf32-ppc.c (ppc_elf_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * elf32-s390.c (elf_s390_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * elf64-s390.c (elf_s390_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * elf64-x86-64.c (elf64_x86_64_check_relocs): Modify for refcounts + starting from zero. + (elf_backend_can_refcount): Define. + * som.c (som_write_symbol_strings): Cast current_offset in bfd_seek call to match param type. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 6f0ae0ffd7..e1f38b9988 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfdlink.h" /* The number of entries in a section is its size divided by the size - of a single entry. This is normally only applicaable to reloc and + of a single entry. This is normally only applicable to reloc and symbol table sections. */ #define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_size / (shdr)->sh_entsize) @@ -223,33 +223,50 @@ struct elf_link_local_dynamic_entry struct elf_link_hash_table { struct bfd_link_hash_table root; + /* Whether we have created the special dynamic sections required when linking against or generating a shared object. */ boolean dynamic_sections_created; + /* The BFD used to hold special sections created by the linker. This will be the first BFD found which requires these sections to be created. */ bfd *dynobj; + + /* The value to use when initialising got.refcount/offset and + plt.refcount/offset in an elf_link_hash_entry. Set to zero when + the values are refcounts. Set to -1 in size_dynamic_sections + when the values may be offsets. */ + bfd_signed_vma init_refcount; + /* The number of symbols found in the link which must be put into the .dynsym section. */ bfd_size_type dynsymcount; + /* The string table of dynamic symbols, which becomes the .dynstr section. */ struct bfd_strtab_hash *dynstr; + /* The number of buckets in the hash table in the .hash section. This is based on the number of dynamic symbols. */ bfd_size_type bucketcount; + /* 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; + /* A pointer to information used to link stabs in sections. */ PTR stab_info; + /* A pointer to information used to merge SEC_MERGE sections. */ PTR merge_info; + /* A linked list of local symbols to be added to .dynsym. */ struct elf_link_local_dynamic_entry *dynlocal; + /* A linked list of DT_RPATH/DT_RUNPATH names found in dynamic objects included in the link. */ struct bfd_link_needed_list *runpath; @@ -726,6 +743,7 @@ struct elf_backend_data unsigned plt_not_loaded : 1; unsigned plt_alignment : 4; unsigned can_gc_sections : 1; + unsigned can_refcount : 1; unsigned want_got_sym : 1; unsigned want_dynbss : 1; }; diff --git a/bfd/elf.c b/bfd/elf.c index a6ceafbf19..2927d56724 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -944,31 +944,31 @@ _bfd_elf_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; - /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct elf_link_hash_entry *) NULL) - ret = ((struct elf_link_hash_entry *) - bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); - if (ret == (struct elf_link_hash_entry *) NULL) - return (struct bfd_hash_entry *) ret; + if (entry == NULL) + { + entry = bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry)); + if (entry == NULL) + return entry; + } /* Call the allocation method of the superclass. */ - ret = ((struct elf_link_hash_entry *) - _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, - table, string)); - if (ret != (struct elf_link_hash_entry *) NULL) + entry = _bfd_link_hash_newfunc (entry, table, string); + if (entry != NULL) { + struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; + struct elf_link_hash_table *htab = (struct elf_link_hash_table *) table; + /* Set local fields. */ ret->indx = -1; ret->size = 0; ret->dynindx = -1; ret->dynstr_index = 0; ret->weakdef = NULL; - ret->got.offset = (bfd_vma) -1; - ret->plt.offset = (bfd_vma) -1; - ret->linker_section_pointer = (elf_linker_section_pointers_t *)0; + ret->got.refcount = htab->init_refcount; + ret->plt.refcount = htab->init_refcount; + ret->linker_section_pointer = NULL; ret->verinfo.verdef = NULL; ret->vtable_entries_used = NULL; ret->vtable_entries_size = 0; @@ -982,7 +982,7 @@ _bfd_elf_link_hash_newfunc (entry, table, string) ret->elf_link_hash_flags = ELF_LINK_NON_ELF; } - return (struct bfd_hash_entry *) ret; + return entry; } /* Copy data from an indirect symbol to its direct symbol, hiding the @@ -1002,21 +1002,21 @@ _bfd_elf_link_hash_copy_indirect (dir, ind) | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF)); - /* Copy over the global and procedure linkage table offset entries. + /* Copy over the global and procedure linkage table refcount entries. These may have been already set up by a check_relocs routine. */ - if (dir->got.offset == (bfd_vma) -1) + if (dir->got.refcount <= 0) { - dir->got.offset = ind->got.offset; - ind->got.offset = (bfd_vma) -1; + dir->got.refcount = ind->got.refcount; + ind->got.refcount = 0; } - BFD_ASSERT (ind->got.offset == (bfd_vma) -1); + BFD_ASSERT (ind->got.refcount <= 0); - if (dir->plt.offset == (bfd_vma) -1) + if (dir->plt.refcount <= 0) { - dir->plt.offset = ind->plt.offset; - ind->plt.offset = (bfd_vma) -1; + dir->plt.refcount = ind->plt.refcount; + ind->plt.refcount = 0; } - BFD_ASSERT (ind->plt.offset == (bfd_vma) -1); + BFD_ASSERT (ind->plt.refcount <= 0); if (dir->dynindx == -1) { @@ -1053,6 +1053,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc) table->dynamic_sections_created = false; table->dynobj = NULL; + table->init_refcount = get_elf_backend_data (abfd)->can_refcount - 1; /* The first dynamic symbol is a dummy. */ table->dynsymcount = 1; table->dynstr = NULL; diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c index aca0852967..8178425918 100644 --- a/bfd/elf32-cris.c +++ b/bfd/elf32-cris.c @@ -2315,10 +2315,9 @@ cris_elf_check_relocs (abfd, info, sec, relocs) GOT entries. */ amt = symtab_hdr->sh_info + 1; amt *= sizeof (bfd_signed_vma); - local_got_refcounts = ((bfd_signed_vma *) bfd_alloc (abfd, amt)); + local_got_refcounts = ((bfd_signed_vma *) bfd_zalloc (abfd, amt)); if (local_got_refcounts == NULL) return false; - memset (local_got_refcounts, -1, (size_t) amt); local_got_refcounts++; elf_local_got_refcounts (abfd) = local_got_refcounts; @@ -2371,10 +2370,8 @@ cris_elf_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { @@ -2387,16 +2384,13 @@ cris_elf_check_relocs (abfd, info, sec, relocs) /* Allocate relocation space. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } - else - h->got.refcount++; + h->got.refcount++; } else { /* This is a global offset table entry for a local symbol. */ - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += 4; if (info->shared) { @@ -2406,8 +2400,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf32_External_Rela); } } - else - local_got_refcounts[r_symndx]++; + local_got_refcounts[r_symndx]++; } break; @@ -2440,10 +2433,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs) continue; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; break; case R_CRIS_8: @@ -2478,10 +2468,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs) /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; } /* If we are creating a shared library and this is not a local @@ -3013,6 +3000,7 @@ elf_cris_reloc_type_class (rela) #define elf_backend_check_relocs cris_elf_check_relocs #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_object_p cris_elf_object_p #define elf_backend_final_write_processing \ diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index b1ec63ca29..8b662ab6d7 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -1133,7 +1133,7 @@ elf32_hppa_create_dynamic_sections (abfd, info) /* Copy the extra info we tack onto an elf_link_hash_entry. */ -void +static void elf32_hppa_copy_indirect_symbol (dir, ind) struct elf_link_hash_entry *dir, *ind; { @@ -1359,10 +1359,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->elf.got.refcount == -1) - h->elf.got.refcount = 1; - else - h->elf.got.refcount += 1; + h->elf.got.refcount += 1; } else { @@ -1404,13 +1401,8 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) { if (h != NULL) { - if (h->elf.plt.refcount == -1) - { - h->elf.plt.refcount = 1; - h->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - } - else - h->elf.plt.refcount += 1; + h->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->elf.plt.refcount += 1; /* If this .plt entry is for a plabel, mark it so that adjust_dynamic_symbol will keep the entry @@ -3491,7 +3483,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Sym *local_syms; asection **local_sections; { - bfd *dynobj; bfd_vma *local_got_offsets; struct elf32_hppa_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; @@ -3501,7 +3492,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; htab = hppa_link_hash_table (info); - dynobj = htab->elf.dynobj; local_got_offsets = elf_local_got_offsets (input_bfd); rel = relocs; @@ -4019,10 +4009,8 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Sym *sym; { struct elf32_hppa_link_hash_table *htab; - bfd *dynobj; htab = hppa_link_hash_table (info); - dynobj = htab->elf.dynobj; if (h->plt.offset != (bfd_vma) -1) { @@ -4375,6 +4363,7 @@ elf32_hppa_elf_get_symbol_type (elf_sym, type) #define elf_backend_reloc_type_class elf32_hppa_reloc_type_class #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_plt_alignment 2 #define elf_backend_want_got_plt 0 #define elf_backend_plt_readonly 0 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index dbd137fa9e..192aa4e36e 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -44,8 +44,7 @@ static boolean create_got_section PARAMS((bfd *, struct bfd_link_info *)); static boolean elf_i386_create_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); -static void -elf_i386_copy_indirect_symbol +static void elf_i386_copy_indirect_symbol PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *)); static boolean elf_i386_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, @@ -629,7 +628,7 @@ elf_i386_create_dynamic_sections (dynobj, info) /* Copy the extra info we tack onto an elf_link_hash_entry. */ -void +static void elf_i386_copy_indirect_symbol (dir, ind) struct elf_link_hash_entry *dir, *ind; { @@ -703,10 +702,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs) /* This symbol requires a global offset table entry. */ if (h != NULL) { - if (h->got.refcount == -1) - h->got.refcount = 1; - else - h->got.refcount += 1; + h->got.refcount += 1; } else { @@ -754,13 +750,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs) if (h == NULL) continue; - if (h->plt.refcount == -1) - { - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - h->plt.refcount = 1; - } - else - h->plt.refcount += 1; + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount += 1; break; case R_386_32: @@ -777,10 +768,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs) /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount += 1; + h->plt.refcount += 1; } /* If we are creating a shared library, and this is a reloc @@ -1278,13 +1266,13 @@ allocate_dynrelocs (h, inf) } else { - h->plt.refcount = -1; + h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } } else { - h->plt.refcount = -1; + h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } @@ -1310,7 +1298,7 @@ allocate_dynrelocs (h, inf) htab->srelgot->_raw_size += sizeof (Elf32_External_Rel); } else - h->got.refcount = -1; + h->got.offset = (bfd_vma) -1; eh = (struct elf_i386_link_hash_entry *) h; if (eh->dyn_relocs == NULL) @@ -1648,7 +1636,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, asection **local_sections; { struct elf_i386_link_hash_table *htab; - bfd *dynobj; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; @@ -1656,7 +1643,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *relend; htab = elf_i386_hash_table (info); - dynobj = htab->elf.dynobj; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); @@ -2066,10 +2052,8 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym) Elf_Internal_Sym *sym; { struct elf_i386_link_hash_table *htab; - bfd *dynobj; htab = elf_i386_hash_table (info); - dynobj = htab->elf.dynobj; if (h->plt.offset != (bfd_vma) -1) { @@ -2141,7 +2125,10 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym) if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in - the .plt section. Leave the value alone. */ + the .plt section. Leave the value alone. This is a clue + for the dynamic linker, to make function pointer + comparisons work between an application and shared + library. */ sym->st_shndx = SHN_UNDEF; } } @@ -2265,6 +2252,7 @@ elf_i386_finish_dynamic_sections (output_bfd, info) for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; + asection *s; bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); @@ -2282,10 +2270,11 @@ elf_i386_finish_dynamic_sections (output_bfd, info) break; case DT_PLTRELSZ: - if (htab->srelplt->output_section->_cooked_size != 0) - dyn.d_un.d_val = htab->srelplt->output_section->_cooked_size; + s = htab->srelplt->output_section; + if (s->_cooked_size != 0) + dyn.d_un.d_val = s->_cooked_size; else - dyn.d_un.d_val = htab->srelplt->output_section->_raw_size; + dyn.d_un.d_val = s->_raw_size; break; case DT_RELSZ: @@ -2300,10 +2289,11 @@ elf_i386_finish_dynamic_sections (output_bfd, info) about changing the DT_REL entry. */ if (htab->srelplt != NULL) { - if (htab->srelplt->output_section->_cooked_size != 0) - dyn.d_un.d_val -= htab->srelplt->output_section->_cooked_size; + s = htab->srelplt->output_section; + if (s->_cooked_size != 0) + dyn.d_un.d_val -= s->_cooked_size; else - dyn.d_un.d_val -= htab->srelplt->output_section->_raw_size; + dyn.d_un.d_val -= s->_raw_size; } break; } @@ -2365,6 +2355,7 @@ elf_i386_finish_dynamic_sections (output_bfd, info) #define ELF_MAXPAGESIZE 0x1000 #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 80613f11e4..c3252240d2 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -534,10 +534,8 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { @@ -550,8 +548,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* Allocate relocation space. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } - else - h->got.refcount++; + h->got.refcount++; } else { @@ -563,16 +560,13 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts = ((bfd_signed_vma *) - bfd_alloc (abfd, size)); + bfd_zalloc (abfd, size)); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += 4; if (info->shared) { @@ -582,8 +576,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf32_External_Rela); } } - else - local_got_refcounts[r_symndx]++; + local_got_refcounts[r_symndx]++; } break; @@ -603,10 +596,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) continue; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; break; case R_68K_PLT8O: @@ -631,10 +621,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) } h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; break; case R_68K_PC8: @@ -662,10 +649,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; } break; } @@ -677,10 +661,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) { /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; } /* If we are creating a shared library, we need to copy the @@ -2357,6 +2338,7 @@ elf32_m68k_reloc_type_class (rela) #define elf_backend_reloc_type_class elf32_m68k_reloc_type_class #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index d770b2bf0f..f3143497c3 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -2184,7 +2184,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) @@ -2195,11 +2195,8 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) sgot->_raw_size += 4; /* Allocate relocation space. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); - - h->got.refcount = 1; } - else - h->got.refcount++; + h->got.refcount++; } else { @@ -2211,13 +2208,12 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts - = (bfd_signed_vma *) bfd_alloc (abfd, size); + = (bfd_signed_vma *) bfd_zalloc (abfd, size); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { sgot->_raw_size += 4; @@ -2226,11 +2222,8 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) dynamic linker can adjust this GOT entry. */ if (info->shared) srelgot->_raw_size += sizeof (Elf32_External_Rela); - - local_got_refcounts[r_symndx] = 1; } - else - local_got_refcounts[r_symndx]++; + local_got_refcounts[r_symndx]++; } break; @@ -2343,13 +2336,8 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return false; } - if (h->plt.refcount == -1) - { - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - h->plt.refcount = 1; - } - else - h->plt.refcount++; + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount++; break; /* The following relocations don't need to propagate the @@ -3821,6 +3809,7 @@ ppc_elf_grok_psinfo (abfd, note) #define elf_backend_plt_not_loaded 1 #define elf_backend_got_symbol_offset 4 #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_got_header_size 12 #define elf_backend_plt_header_size PLT_INITIAL_ENTRY_SIZE diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index 73db3f7854..c8f5a8f9f0 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -577,10 +577,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { @@ -591,8 +589,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) sgot->_raw_size += 4; srelgot->_raw_size += sizeof (Elf32_External_Rela); } - else - h->got.refcount += 1; + h->got.refcount += 1; } else { @@ -604,16 +601,13 @@ elf_s390_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts = (bfd_signed_vma *) - bfd_alloc (abfd, size); + bfd_zalloc (abfd, size); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += 4; if (info->shared) { @@ -623,8 +617,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf32_External_Rela); } } - else - local_got_refcounts[r_symndx] += 1; + local_got_refcounts[r_symndx] += 1; } break; @@ -642,13 +635,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (h == NULL) continue; - if (h->plt.refcount == -1) - { - h->plt.refcount = 1; - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - } - else - h->plt.refcount += 1; + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount += 1; break; case R_390_8: @@ -2164,6 +2152,7 @@ elf_s390_reloc_type_class (rela) #define ELF_MAXPAGESIZE 0x1000 #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 02a436fbaa..aeba8559ad 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -541,10 +541,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { @@ -555,8 +553,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) sgot->_raw_size += 8; srelgot->_raw_size += sizeof (Elf64_External_Rela); } - else - h->got.refcount += 1; + h->got.refcount += 1; } else { @@ -567,16 +564,13 @@ elf_s390_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info * sizeof (bfd_vma); local_got_refcounts = ((bfd_signed_vma *) - bfd_alloc (abfd, size)); + bfd_zalloc (abfd, size)); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += 8; if (info->shared) { @@ -586,9 +580,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf64_External_Rela); } } - else - local_got_refcounts[r_symndx] += 1; - + local_got_refcounts[r_symndx] += 1; } break; @@ -608,13 +600,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (h == NULL) continue; - if (h->plt.refcount == -1) - { - h->plt.refcount = 1; - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - } - else - h->plt.refcount += 1; + h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + h->plt.refcount += 1; break; case R_390_8: @@ -2162,6 +2149,7 @@ const struct elf_size_info s390_elf64_size_info = #define elf_backend_size_info s390_elf64_size_info #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index decd987019..321542165c 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -441,10 +441,8 @@ elf64_x86_64_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { @@ -455,8 +453,7 @@ elf64_x86_64_check_relocs (abfd, info, sec, relocs) sgot->_raw_size += GOT_ENTRY_SIZE; srelgot->_raw_size += sizeof (Elf64_External_Rela); } - else - h->got.refcount += 1; + h->got.refcount += 1; } else { @@ -468,16 +465,13 @@ elf64_x86_64_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts = ((bfd_signed_vma *) - bfd_alloc (abfd, size)); + bfd_zalloc (abfd, size)); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += GOT_ENTRY_SIZE; if (info->shared) { @@ -487,8 +481,7 @@ elf64_x86_64_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf64_External_Rela); } } - else - local_got_refcounts[r_symndx] += 1; + local_got_refcounts[r_symndx] += 1; } break; @@ -506,10 +499,7 @@ elf64_x86_64_check_relocs (abfd, info, sec, relocs) continue; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount += 1; + h->plt.refcount += 1; break; case R_X86_64_8: @@ -1959,6 +1949,7 @@ elf64_x86_64_reloc_type_class (rela) #define ELF_MAXPAGESIZE 0x100000 #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 diff --git a/bfd/elflink.h b/bfd/elflink.h index e38f0d50bd..73687fbd48 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -2920,6 +2920,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (! is_elf_hash_table (info)) return false; + /* Any syms created from now on start with -1 in + got.refcount/offset and plt.refcount/offset. */ + elf_hash_table (info)->init_refcount = -1; + /* The backend may have to create some sections regardless of whether we're dynamic or not. */ bed = get_elf_backend_data (output_bfd); diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index 257572d4dd..59da038917 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -102,6 +102,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef elf_backend_can_gc_sections #define elf_backend_can_gc_sections 0 #endif +#ifndef elf_backend_can_refcount +#define elf_backend_can_refcount 0 +#endif #ifndef elf_backend_want_got_sym #define elf_backend_want_got_sym 1 #endif @@ -459,6 +462,7 @@ static const struct elf_backend_data elfNN_bed = elf_backend_plt_not_loaded, elf_backend_plt_alignment, elf_backend_can_gc_sections, + elf_backend_can_refcount, elf_backend_want_dynbss, elf_backend_want_got_sym }; diff --git a/bfd/linker.c b/bfd/linker.c index 182786e361..e3828957da 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -445,28 +445,27 @@ _bfd_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct bfd_link_hash_entry *ret = (struct bfd_link_hash_entry *) entry; - /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct bfd_link_hash_entry *) NULL) - ret = ((struct bfd_link_hash_entry *) - bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry))); - if (ret == (struct bfd_link_hash_entry *) NULL) - return NULL; - - /* Call the allocation method of the superclass. */ - ret = ((struct bfd_link_hash_entry *) - bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); - - if (ret) + if (entry == NULL) { - /* Initialize the local fields. */ - ret->type = bfd_link_hash_new; - ret->next = NULL; + entry = bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)); + if (entry == NULL) + return entry; } - return (struct bfd_hash_entry *) ret; + /* Call the allocation method of the superclass. */ + entry = bfd_hash_newfunc (entry, table, string); + if (entry) + { + struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry; + + /* Initialize the local fields. */ + h->type = bfd_link_hash_new; + h->next = NULL; + } + + return entry; } /* Initialize a link hash table. The BFD argument is the one @@ -642,30 +641,29 @@ _bfd_generic_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct generic_link_hash_entry *ret = - (struct generic_link_hash_entry *) entry; - /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct generic_link_hash_entry *) NULL) - ret = ((struct generic_link_hash_entry *) - bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry))); - if (ret == (struct generic_link_hash_entry *) NULL) - return NULL; + if (entry == NULL) + { + entry = bfd_hash_allocate (table, + sizeof (struct generic_link_hash_entry)); + if (entry == NULL) + return entry; + } /* Call the allocation method of the superclass. */ - ret = ((struct generic_link_hash_entry *) - _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, - table, string)); - - if (ret) + entry = _bfd_link_hash_newfunc (entry, table, string); + if (entry) { + struct generic_link_hash_entry *ret; + /* Set local fields. */ + ret = (struct generic_link_hash_entry *) entry; ret->written = false; ret->sym = NULL; } - return (struct bfd_hash_entry *) ret; + return entry; } /* Create an generic link hash table. */