|
|
|
@ -756,6 +756,9 @@ struct elf_i386_link_hash_entry |
|
|
|
(GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) |
|
|
|
unsigned char tls_type; |
|
|
|
|
|
|
|
/* Symbol is referenced by R_386_GOTOFF relocation. */ |
|
|
|
unsigned int gotoff_ref : 1; |
|
|
|
|
|
|
|
/* Information about the GOT PLT entry. Filled when there are both
|
|
|
|
GOT and PLT relocations against the same function. */ |
|
|
|
union gotplt_union plt_got; |
|
|
|
@ -879,6 +882,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry, |
|
|
|
eh = (struct elf_i386_link_hash_entry *) entry; |
|
|
|
eh->dyn_relocs = NULL; |
|
|
|
eh->tls_type = GOT_UNKNOWN; |
|
|
|
eh->gotoff_ref = 0; |
|
|
|
eh->plt_got.offset = (bfd_vma) -1; |
|
|
|
eh->tlsdesc_got = (bfd_vma) -1; |
|
|
|
} |
|
|
|
@ -1022,13 +1026,28 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); |
|
|
|
if (!info->shared) |
|
|
|
htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss"); |
|
|
|
|
|
|
|
if (!htab->sdynbss |
|
|
|
|| (!info->shared && !htab->srelbss)) |
|
|
|
if (!htab->sdynbss) |
|
|
|
abort (); |
|
|
|
|
|
|
|
if (info->executable) |
|
|
|
{ |
|
|
|
/* Always allow copy relocs for building executables. */ |
|
|
|
asection *s = bfd_get_linker_section (dynobj, ".rel.bss"); |
|
|
|
if (s == NULL) |
|
|
|
{ |
|
|
|
const struct elf_backend_data *bed = get_elf_backend_data (dynobj); |
|
|
|
s = bfd_make_section_anyway_with_flags (dynobj, |
|
|
|
".rel.bss", |
|
|
|
(bed->dynamic_sec_flags |
|
|
|
| SEC_READONLY)); |
|
|
|
if (s == NULL |
|
|
|
|| ! bfd_set_section_alignment (dynobj, s, |
|
|
|
bed->s->log_file_align)) |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
htab->srelbss = s; |
|
|
|
} |
|
|
|
|
|
|
|
if (get_elf_i386_backend_data (dynobj)->is_vxworks |
|
|
|
&& !elf_vxworks_create_dynamic_sections (dynobj, info, |
|
|
|
&htab->srelplt2)) |
|
|
|
@ -1101,6 +1120,10 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info, |
|
|
|
eind->tls_type = GOT_UNKNOWN; |
|
|
|
} |
|
|
|
|
|
|
|
/* Copy gotoff_ref so that elf_i386_adjust_dynamic_symbol will
|
|
|
|
generate a R_386_COPY reloc. */ |
|
|
|
edir->gotoff_ref |= eind->gotoff_ref; |
|
|
|
|
|
|
|
if (ELIMINATE_COPY_RELOCS |
|
|
|
&& ind->root.type != bfd_link_hash_indirect |
|
|
|
&& dir->dynamic_adjusted) |
|
|
|
@ -1475,6 +1498,7 @@ elf_i386_check_relocs (bfd *abfd, |
|
|
|
unsigned int r_type; |
|
|
|
unsigned long r_symndx; |
|
|
|
struct elf_link_hash_entry *h; |
|
|
|
struct elf_i386_link_hash_entry *eh; |
|
|
|
Elf_Internal_Sym *isym; |
|
|
|
const char *name; |
|
|
|
bfd_boolean size_reloc; |
|
|
|
@ -1524,6 +1548,7 @@ elf_i386_check_relocs (bfd *abfd, |
|
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
|
|
} |
|
|
|
|
|
|
|
eh = (struct elf_i386_link_hash_entry *) h; |
|
|
|
if (h != NULL) |
|
|
|
{ |
|
|
|
/* Create the ifunc sections for static executables. If we
|
|
|
|
@ -1535,11 +1560,12 @@ elf_i386_check_relocs (bfd *abfd, |
|
|
|
default: |
|
|
|
break; |
|
|
|
|
|
|
|
case R_386_GOTOFF: |
|
|
|
eh->gotoff_ref = 1; |
|
|
|
case R_386_32: |
|
|
|
case R_386_PC32: |
|
|
|
case R_386_PLT32: |
|
|
|
case R_386_GOT32: |
|
|
|
case R_386_GOTOFF: |
|
|
|
if (htab->elf.dynobj == NULL) |
|
|
|
htab->elf.dynobj = abfd; |
|
|
|
if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) |
|
|
|
@ -1791,7 +1817,7 @@ do_size: |
|
|
|
relocations we need for this symbol. */ |
|
|
|
if (h != NULL) |
|
|
|
{ |
|
|
|
head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs; |
|
|
|
head = &eh->dyn_relocs; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
@ -2175,12 +2201,14 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
|
|
|
only references to the symbol are via the global offset table. |
|
|
|
For such cases we need not do anything here; the relocations will |
|
|
|
be handled correctly by relocate_section. */ |
|
|
|
if (info->shared) |
|
|
|
if (!info->executable) |
|
|
|
return TRUE; |
|
|
|
|
|
|
|
/* If there are no references to this symbol that do not use the
|
|
|
|
GOT, we don't need to generate a copy reloc. */ |
|
|
|
if (!h->non_got_ref) |
|
|
|
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy |
|
|
|
reloc. */ |
|
|
|
eh = (struct elf_i386_link_hash_entry *) h; |
|
|
|
if (!h->non_got_ref && !eh->gotoff_ref) |
|
|
|
return TRUE; |
|
|
|
|
|
|
|
/* If -z nocopyreloc was given, we won't generate them either. */ |
|
|
|
@ -2194,14 +2222,15 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
|
|
|
if (htab == NULL) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
/* If there aren't any dynamic relocs in read-only sections, then
|
|
|
|
we can keep the dynamic relocs and avoid the copy reloc. This |
|
|
|
doesn't work on VxWorks, where we can not have dynamic relocations |
|
|
|
(other than copy and jump slot relocations) in an executable. */ |
|
|
|
/* If there aren't any dynamic relocs in read-only sections nor
|
|
|
|
R_386_GOTOFF relocation, then we can keep the dynamic relocs and |
|
|
|
avoid the copy reloc. This doesn't work on VxWorks, where we can |
|
|
|
not have dynamic relocations (other than copy and jump slot |
|
|
|
relocations) in an executable. */ |
|
|
|
if (ELIMINATE_COPY_RELOCS |
|
|
|
&& !eh->gotoff_ref |
|
|
|
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks) |
|
|
|
{ |
|
|
|
eh = (struct elf_i386_link_hash_entry *) h; |
|
|
|
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
|
|
|
{ |
|
|
|
s = p->sec->output_section; |
|
|
|
@ -3718,7 +3747,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
|
|
|
symbol for shared library since it may not be local when |
|
|
|
used as function address or with copy relocation. We also |
|
|
|
need to make sure that a symbol is referenced locally. */ |
|
|
|
if (info->shared && h) |
|
|
|
if (!info->executable && h) |
|
|
|
{ |
|
|
|
if (!h->def_regular) |
|
|
|
{ |
|
|
|
@ -3746,8 +3775,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
|
|
|
bfd_set_error (bfd_error_bad_value); |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
else if (!info->executable |
|
|
|
&& !SYMBOL_REFERENCES_LOCAL (info, h) |
|
|
|
else if (!SYMBOL_REFERENCES_LOCAL (info, h) |
|
|
|
&& (h->type == STT_FUNC |
|
|
|
|| h->type == STT_OBJECT) |
|
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) |
|
|
|
|