Index: bfd/elf32-vax.c |
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c |
index 84ec972563f328974ba7fdc3c1cc62173cb7ac62..d6ae14e132caa81c5b3e6f93e634ea794668902d 100644 |
--- a/bfd/elf32-vax.c |
+++ b/bfd/elf32-vax.c |
@@ -465,7 +465,7 @@ elf_vax_link_hash_table_create (bfd *abfd) |
struct elf_link_hash_table *ret; |
bfd_size_type amt = sizeof (struct elf_link_hash_table); |
- ret = bfd_malloc (amt); |
+ ret = bfd_zmalloc (amt); |
if (ret == NULL) |
return NULL; |
@@ -585,20 +585,22 @@ elf_vax_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, |
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; |
+ |
+ /* PR15323, ref flags aren't set for references in the same |
+ object. */ |
+ h->root.non_ir_ref = 1; |
} |
switch (ELF32_R_TYPE (rel->r_info)) |
{ |
case R_VAX_GOT32: |
BFD_ASSERT (h != NULL); |
- if (h->forced_local |
- || h == elf_hash_table (info)->hgot |
- || h == elf_hash_table (info)->hplt) |
- break; |
/* If this is a local symbol, we resolve it directly without |
creating a global offset table entry. */ |
- if (h == NULL || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) |
+ if (h->forced_local |
+ || h == elf_hash_table (info)->hgot |
+ || h == elf_hash_table (info)->hplt) |
break; |
/* This symbol requires a global offset table entry. */ |
@@ -668,11 +670,11 @@ elf_vax_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, |
never referenced by a dynamic object, in which case we |
don't need to generate a procedure linkage table entry |
after all. */ |
+ BFD_ASSERT (h != NULL); |
/* If this is a local symbol, we resolve it directly without |
creating a procedure linkage table entry. */ |
- BFD_ASSERT (h != NULL); |
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT || h->forced_local) |
+ if (h->forced_local) |
break; |
h->needs_plt = 1; |
@@ -910,9 +912,8 @@ elf_vax_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, asection *sec, |
understand. */ |
static bfd_boolean |
-elf_vax_adjust_dynamic_symbol (info, h) |
- struct bfd_link_info *info; |
- struct elf_link_hash_entry *h; |
+elf_vax_adjust_dynamic_symbol (struct bfd_link_info *info, |
+ struct elf_link_hash_entry *h) |
{ |
bfd *dynobj; |
asection *s; |
@@ -933,39 +934,21 @@ elf_vax_adjust_dynamic_symbol (info, h) |
if (h->type == STT_FUNC |
|| h->needs_plt) |
{ |
- if (! info->shared |
- && !h->def_dynamic |
- && !h->ref_dynamic |
- /* We must always create the plt entry if it was referenced |
- by a PLTxxO relocation. In this case we already recorded |
- it as a dynamic symbol. */ |
- && h->dynindx == -1) |
+ if (h->plt.refcount <= 0 |
+ || SYMBOL_CALLS_LOCAL (info, h) |
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
+ && h->root.type == bfd_link_hash_undefweak)) |
{ |
/* This case can occur if we saw a PLTxx reloc in an input |
file, but the symbol was never referred to by a dynamic |
- object. In such a case, we don't actually need to build |
- a procedure linkage table, and we can just do a PCxx |
- reloc instead. */ |
- BFD_ASSERT (h->needs_plt); |
+ object, or if all references were garbage collected. In |
+ such a case, we don't actually need to build a procedure |
+ linkage table, and we can just do a PCxx reloc instead. */ |
h->plt.offset = (bfd_vma) -1; |
- return TRUE; |
- } |
- |
- /* GC may have rendered this entry unused. */ |
- if (h->plt.refcount <= 0) |
- { |
h->needs_plt = 0; |
- h->plt.offset = (bfd_vma) -1; |
return TRUE; |
} |
- /* Make sure this symbol is output as a dynamic symbol. */ |
- if (h->dynindx == -1) |
- { |
- if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
- return FALSE; |
- } |
- |
s = bfd_get_linker_section (dynobj, ".plt"); |
BFD_ASSERT (s != NULL); |
@@ -1065,6 +1048,59 @@ elf_vax_adjust_dynamic_symbol (info, h) |
return _bfd_elf_adjust_dynamic_copy (h, s); |
} |
+/* This function is called via elf_link_hash_traverse. It resets GOT |
+ and PLT (.GOT) reference counts back to -1 so normal PC32 relocation |
+ will be done. */ |
+ |
+static bfd_boolean |
+elf_vax_discard_got_entries (struct elf_link_hash_entry *h, |
+ void *infoptr ATTRIBUTE_UNUSED) |
+{ |
+ h->got.refcount = -1; |
+ h->plt.refcount = -1; |
+ |
+ return TRUE; |
+} |
+ |
+/* Discard unused dynamic data if this is a static link. */ |
+ |
+static bfd_boolean |
+elf_vax_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
+ struct bfd_link_info *info) |
+{ |
+ bfd *dynobj; |
+ asection *s; |
+ |
+ dynobj = elf_hash_table (info)->dynobj; |
+ |
+ if (dynobj && !elf_hash_table (info)->dynamic_sections_created) |
+ { |
+ /* We may have created entries in the .rela.got and .got sections. |
+ However, if we are not creating the dynamic sections, we will |
+ not actually use these entries. Reset the size of .rela.got |
+ and .got, which will cause them to get stripped from the output |
+ file below. */ |
+ s = bfd_get_linker_section (dynobj, ".rela.got"); |
+ if (s != NULL) |
+ s->size = 0; |
+ s = bfd_get_linker_section (dynobj, ".got.plt"); |
+ if (s != NULL) |
+ s->size = 0; |
+ s = bfd_get_linker_section (dynobj, ".got"); |
+ if (s != NULL) |
+ s->size = 0; |
+ } |
+ |
+ /* If this is a static link, we need to discard all the got entries we've |
+ recorded. */ |
+ if (!dynobj || !elf_hash_table (info)->dynamic_sections_created) |
+ elf_link_hash_traverse (elf_hash_table (info), |
+ elf_vax_discard_got_entries, |
+ info); |
+ |
+ return TRUE; |
+} |
+ |
/* Set the sizes of the dynamic sections. */ |
static bfd_boolean |
@@ -1090,23 +1126,6 @@ elf_vax_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
} |
} |
- else |
- { |
- /* We may have created entries in the .rela.got and .got sections. |
- However, if we are not creating the dynamic sections, we will |
- not actually use these entries. Reset the size of .rela.got |
- and .got, which will cause it to get stripped from the output |
- file below. */ |
- s = bfd_get_linker_section (dynobj, ".rela.got"); |
- if (s != NULL) |
- s->size = 0; |
- s = bfd_get_linker_section (dynobj, ".got.plt"); |
- if (s != NULL) |
- s->size = 0; |
- s = bfd_get_linker_section (dynobj, ".got"); |
- if (s != NULL) |
- s->size = 0; |
- } |
/* If this is a -Bsymbolic shared link, then we need to discard all PC |
relative relocs against symbols defined in a regular object. We |
@@ -1117,9 +1136,9 @@ elf_vax_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
elf_vax_discard_copies, |
NULL); |
- /* If this is a -Bsymbolic shared link or a static link, we need to |
- discard all the got entries we've recorded. Otherwise, we need to |
- instantiate (allocate space for them). */ |
+ /* If this is a -Bsymbolic shared link, we need to discard all the got |
+ entries we've recorded. Otherwise, we need to instantiate (allocate |
+ space for them). */ |
elf_link_hash_traverse (elf_hash_table (info), |
elf_vax_instantiate_got_entries, |
info); |
@@ -1275,12 +1294,12 @@ elf_vax_discard_copies (struct elf_vax_link_hash_entry *h, |
return TRUE; |
} |
-/* This function is called via elf_link_hash_traverse. It looks for entries |
- that have GOT or PLT (.GOT) references. If creating a static object or a |
- shared object with -Bsymbolic, it resets the reference count back to 0 |
- and sets the offset to -1 so normal PC32 relocation will be done. If |
- creating a shared object or executable, space in the .got and .rela.got |
- will be reserved for the symbol. */ |
+/* This function is called via elf_link_hash_traverse. It looks for |
+ entries that have GOT or PLT (.GOT) references. If creating a shared |
+ object with -Bsymbolic, or the symbol has been forced local, then it |
+ resets the reference count back to -1 so normal PC32 relocation will |
+ be done. Otherwise space in the .got and .rela.got will be reserved |
+ for the symbol. */ |
static bfd_boolean |
elf_vax_instantiate_got_entries (struct elf_link_hash_entry *h, void * infoptr) |
@@ -1295,25 +1314,18 @@ elf_vax_instantiate_got_entries (struct elf_link_hash_entry *h, void * infoptr) |
return TRUE; |
dynobj = elf_hash_table (info)->dynobj; |
- if (dynobj == NULL) |
- return TRUE; |
+ BFD_ASSERT (dynobj != NULL); |
sgot = bfd_get_linker_section (dynobj, ".got"); |
srelgot = bfd_get_linker_section (dynobj, ".rela.got"); |
- if (!elf_hash_table (info)->dynamic_sections_created |
- || (info->shared && info->symbolic) |
- || h->forced_local) |
+ if (SYMBOL_REFERENCES_LOCAL (info, h)) |
{ |
- h->got.refcount = 0; |
- h->got.offset = (bfd_vma) -1; |
- h->plt.refcount = 0; |
- h->plt.offset = (bfd_vma) -1; |
+ h->got.refcount = -1; |
+ h->plt.refcount = -1; |
} |
else if (h->got.refcount > 0) |
{ |
- bfd_boolean dyn; |
- |
/* Make sure this symbol is output as a dynamic symbol. */ |
if (h->dynindx == -1) |
{ |
@@ -1321,15 +1333,9 @@ elf_vax_instantiate_got_entries (struct elf_link_hash_entry *h, void * infoptr) |
return FALSE; |
} |
- dyn = elf_hash_table (info)->dynamic_sections_created; |
/* Allocate space in the .got and .rela.got sections. */ |
- if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
- && (info->shared |
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) |
- { |
- sgot->size += 4; |
- srelgot->size += sizeof (Elf32_External_Rela); |
- } |
+ sgot->size += 4; |
+ srelgot->size += sizeof (Elf32_External_Rela); |
} |
return TRUE; |
@@ -1402,12 +1408,12 @@ elf_vax_relocate_section (bfd *output_bfd, |
else |
{ |
bfd_boolean unresolved_reloc; |
- bfd_boolean warned; |
+ bfd_boolean warned, ignored; |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
r_symndx, symtab_hdr, sym_hashes, |
h, sec, relocation, |
- unresolved_reloc, warned); |
+ unresolved_reloc, warned, ignored); |
if ((h->root.type == bfd_link_hash_defined |
|| h->root.type == bfd_link_hash_defweak) |
@@ -1454,17 +1460,14 @@ elf_vax_relocate_section (bfd *output_bfd, |
case R_VAX_GOT32: |
/* Relocation is to the address of the entry for this symbol |
in the global offset table. */ |
+ |
+ /* Resolve a GOTxx reloc against a local symbol directly, |
+ without using the global offset table. */ |
if (h == NULL |
- || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
- || h->got.offset == (bfd_vma) -1 |
- || h->forced_local) |
+ || h->got.offset == (bfd_vma) -1) |
break; |
- /* Relocation is the offset of the entry for this symbol in |
- the global offset table. */ |
- |
{ |
- bfd_boolean dyn; |
bfd_vma off; |
if (sgot == NULL) |
@@ -1473,37 +1476,10 @@ elf_vax_relocate_section (bfd *output_bfd, |
BFD_ASSERT (sgot != NULL); |
} |
- BFD_ASSERT (h != NULL); |
off = h->got.offset; |
- BFD_ASSERT (off != (bfd_vma) -1); |
BFD_ASSERT (off < sgot->size); |
- dyn = elf_hash_table (info)->dynamic_sections_created; |
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
- || (info->shared |
- && SYMBOL_REFERENCES_LOCAL (info, h))) |
- { |
- /* The symbol was forced to be local |
- because of a version file.. We must initialize |
- this entry in the global offset table. Since |
- the offset must always be a multiple of 4, we |
- use the least significant bit to record whether |
- we have initialized it already. |
- |
- When doing a dynamic link, we create a .rela.got |
- relocation entry to initialize the value. This |
- is done in the finish_dynamic_symbol routine. */ |
- if ((off & 1) != 0) |
- off &= ~1; |
- else |
- { |
- bfd_put_32 (output_bfd, relocation + rel->r_addend, |
- sgot->contents + off); |
- h->got.offset |= 1; |
- } |
- } else { |
- bfd_put_32 (output_bfd, rel->r_addend, sgot->contents + off); |
- } |
+ bfd_put_32 (output_bfd, rel->r_addend, sgot->contents + off); |
relocation = sgot->output_offset + off; |
/* The GOT relocation uses the addend. */ |
@@ -1530,19 +1506,9 @@ elf_vax_relocate_section (bfd *output_bfd, |
/* Resolve a PLTxx reloc against a local symbol directly, |
without using the procedure linkage table. */ |
if (h == NULL |
- || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
- || h->forced_local) |
+ || h->plt.offset == (bfd_vma) -1) |
break; |
- if (h->plt.offset == (bfd_vma) -1 |
- || !elf_hash_table (info)->dynamic_sections_created) |
- { |
- /* We didn't make a PLT entry for this symbol. This |
- happens when statically linking PIC code, or when |
- using -Bsymbolic. */ |
- break; |
- } |
- |
if (splt == NULL) |
{ |
splt = bfd_get_linker_section (dynobj, ".plt"); |
@@ -1877,25 +1843,10 @@ elf_vax_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, |
rela.r_offset = (sgot->output_section->vma |
+ sgot->output_offset |
- + (h->got.offset &~ 1)); |
- |
- /* If the symbol was forced to be local because of a version file |
- locally we just want to emit a RELATIVE reloc. The entry in |
- the global offset table will already have been initialized in |
- the relocate_section function. */ |
- if (info->shared |
- && h->dynindx == -1 |
- && h->def_regular) |
- { |
- rela.r_info = ELF32_R_INFO (0, R_VAX_RELATIVE); |
- } |
- else |
- { |
- rela.r_info = ELF32_R_INFO (h->dynindx, R_VAX_GLOB_DAT); |
- } |
+ + h->got.offset); |
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_VAX_GLOB_DAT); |
rela.r_addend = bfd_get_signed_32 (output_bfd, |
- (sgot->contents |
- + (h->got.offset & ~1))); |
+ sgot->contents + h->got.offset); |
loc = srela->contents; |
loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); |
@@ -1926,7 +1877,7 @@ elf_vax_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, |
} |
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ |
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
+ if (h == elf_hash_table (info)->hdynamic |
|| h == elf_hash_table (info)->hgot) |
sym->st_shndx = SHN_ABS; |
@@ -2038,13 +1989,16 @@ elf_vax_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); |
} |
- elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; |
+ if (elf_section_data (sgot->output_section) != NULL) |
+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; |
return TRUE; |
} |
static enum elf_reloc_type_class |
-elf_vax_reloc_type_class (const Elf_Internal_Rela *rela) |
+elf_vax_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, |
+ const asection *rel_sec ATTRIBUTE_UNUSED, |
+ const Elf_Internal_Rela *rela) |
{ |
switch ((int) ELF32_R_TYPE (rela->r_info)) |
{ |
@@ -2080,6 +2034,8 @@ elf_vax_plt_sym_val (bfd_vma i, const asection *plt, |
#define elf_backend_check_relocs elf_vax_check_relocs |
#define elf_backend_adjust_dynamic_symbol \ |
elf_vax_adjust_dynamic_symbol |
+#define elf_backend_always_size_sections \ |
+ elf_vax_always_size_sections |
#define elf_backend_size_dynamic_sections \ |
elf_vax_size_dynamic_sections |
#define elf_backend_init_index_section _bfd_elf_init_1_index_section |