* elf32-i386.c (struct elf_i386_pcrel_relocs_copied): Rename to

elf_i386_dyn_relocs.  Update comment.
	(struct elf_i386_link_hash_entry): Rename pcrel_relocs_copied to
	dyn_relocs.
	(elf_i386_adjust_dynamic_symbol): Remove a BFD_ASSERT, change
	others to aborts.
	(allocate_plt_and_got_and_discard_relocs): Replace BFD_ASSERT with
	abort.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_finish_dynamic_symbol): Likewise.
	(elf_i386_finish_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.  Tidy R_386_GOT32 and error
	handling code.
This commit is contained in:
Alan Modra 2001-06-23 10:03:53 +00:00
parent 12d0ee4aca
commit ffb2e45bfb
2 changed files with 108 additions and 95 deletions

View File

@ -1,5 +1,19 @@
2001-06-23 Alan Modra <amodra@bigpond.net.au> 2001-06-23 Alan Modra <amodra@bigpond.net.au>
* elf32-i386.c (struct elf_i386_pcrel_relocs_copied): Rename to
elf_i386_dyn_relocs. Update comment.
(struct elf_i386_link_hash_entry): Rename pcrel_relocs_copied to
dyn_relocs.
(elf_i386_adjust_dynamic_symbol): Remove a BFD_ASSERT, change
others to aborts.
(allocate_plt_and_got_and_discard_relocs): Replace BFD_ASSERT with
abort.
(elf_i386_size_dynamic_sections): Likewise.
(elf_i386_finish_dynamic_symbol): Likewise.
(elf_i386_finish_dynamic_sections): Likewise.
(elf_i386_relocate_section): Likewise. Tidy R_386_GOT32 and error
handling code.
Avoid creating COPY relocs if possible. Avoid creating COPY relocs if possible.
* elf32-i386.c (elf_i386_check_relocs): Tweak condition under * elf32-i386.c (elf_i386_check_relocs): Tweak condition under
which .got created. Mark symbols used by R_386_32 and R_386_PC32 which .got created. Mark symbols used by R_386_32 and R_386_PC32

View File

@ -357,18 +357,15 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
}; };
/* The i386 linker needs to keep track of the number of relocs that it /* The i386 linker needs to keep track of the number of relocs that it
decides to copy in check_relocs for each symbol. This is so that decides to copy as dynamic relocs in check_relocs for each symbol.
it can discard PC relative relocs if it doesn't need them when This is so that it can later discard them if they are found to be
linking with -Bsymbolic. We store the information in a field unnecessary. We store the information in a field extending the
extending the regular ELF linker hash table. */ regular ELF linker hash table. */
/* This structure keeps track of the number of PC relative relocs we struct elf_i386_dyn_relocs
have copied for a given symbol. */
struct elf_i386_pcrel_relocs_copied
{ {
/* Next section. */ /* Next section. */
struct elf_i386_pcrel_relocs_copied *next; struct elf_i386_dyn_relocs *next;
/* A section in dynobj. */ /* A section in dynobj. */
asection *section; asection *section;
/* Number of relocs copied in this section. */ /* Number of relocs copied in this section. */
@ -382,7 +379,7 @@ struct elf_i386_link_hash_entry
struct elf_link_hash_entry root; struct elf_link_hash_entry root;
/* Number of PC relative relocs copied for this symbol. */ /* Number of PC relative relocs copied for this symbol. */
struct elf_i386_pcrel_relocs_copied *pcrel_relocs_copied; struct elf_i386_dyn_relocs *dyn_relocs;
}; };
/* i386 ELF linker hash table. */ /* i386 ELF linker hash table. */
@ -432,7 +429,7 @@ elf_i386_link_hash_newfunc (entry, table, string)
table, string)); table, string));
if (ret != (struct elf_i386_link_hash_entry *) NULL) if (ret != (struct elf_i386_link_hash_entry *) NULL)
{ {
ret->pcrel_relocs_copied = NULL; ret->dyn_relocs = NULL;
} }
return (struct bfd_hash_entry *) ret; return (struct bfd_hash_entry *) ret;
@ -784,22 +781,22 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
&& ELF32_R_TYPE (rel->r_info) == R_386_PC32)) && ELF32_R_TYPE (rel->r_info) == R_386_PC32))
{ {
struct elf_i386_link_hash_entry *eh; struct elf_i386_link_hash_entry *eh;
struct elf_i386_pcrel_relocs_copied *p; struct elf_i386_dyn_relocs *p;
eh = (struct elf_i386_link_hash_entry *) h; eh = (struct elf_i386_link_hash_entry *) h;
for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) for (p = eh->dyn_relocs; p != NULL; p = p->next)
if (p->section == sreloc) if (p->section == sreloc)
break; break;
if (p == NULL) if (p == NULL)
{ {
p = ((struct elf_i386_pcrel_relocs_copied *) p = ((struct elf_i386_dyn_relocs *)
bfd_alloc (dynobj, sizeof *p)); bfd_alloc (dynobj, sizeof *p));
if (p == NULL) if (p == NULL)
return false; return false;
p->next = eh->pcrel_relocs_copied; p->next = eh->dyn_relocs;
eh->pcrel_relocs_copied = p; eh->dyn_relocs = p;
p->section = sreloc; p->section = sreloc;
p->count = 0; p->count = 0;
} }
@ -968,17 +965,6 @@ elf_i386_adjust_dynamic_symbol (info, h)
htab = elf_i386_hash_table (info); htab = elf_i386_hash_table (info);
dynobj = htab->root.dynobj; dynobj = htab->root.dynobj;
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
|| h->weakdef != NULL
|| ((h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)));
/* If this is a function, put it in the procedure linkage table. We /* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later, will fill in the contents of the procedure linkage table later,
when we know the address of the .got section. */ when we know the address of the .got section. */
@ -1055,7 +1041,8 @@ elf_i386_adjust_dynamic_symbol (info, h)
same memory location for the variable. */ same memory location for the variable. */
s = htab->sdynbss; s = htab->sdynbss;
BFD_ASSERT (s != NULL); if (s == NULL)
abort ();
/* We must generate a R_386_COPY reloc to tell the dynamic linker to /* We must generate a R_386_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the copy the initial value out of the dynamic object and into the
@ -1066,7 +1053,8 @@ elf_i386_adjust_dynamic_symbol (info, h)
asection *srel; asection *srel;
srel = htab->srelbss; srel = htab->srelbss;
BFD_ASSERT (srel != NULL); if (srel == NULL)
abort ();
srel->_raw_size += sizeof (Elf32_External_Rel); srel->_raw_size += sizeof (Elf32_External_Rel);
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
} }
@ -1132,7 +1120,8 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
&& h->plt.refcount > 0) && h->plt.refcount > 0)
{ {
s = htab->splt; s = htab->splt;
BFD_ASSERT (s != NULL); if (s == NULL)
abort ();
/* If this is the first .plt entry, make room for the special /* If this is the first .plt entry, make room for the special
first entry. */ first entry. */
@ -1159,14 +1148,16 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
/* We also need to make an entry in the .got.plt section, which /* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */ will be placed in the .got section by the linker script. */
s = htab->sgotplt; s = htab->sgotplt;
BFD_ASSERT (s != NULL); if (s == NULL)
abort ();
s->_raw_size += 4; s->_raw_size += 4;
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
{ {
/* We also need to make an entry in the .rel.plt section. */ /* We also need to make an entry in the .rel.plt section. */
s = htab->srelplt; s = htab->srelplt;
BFD_ASSERT (s != NULL); if (s == NULL)
abort ();
s->_raw_size += sizeof (Elf32_External_Rel); s->_raw_size += sizeof (Elf32_External_Rel);
} }
} }
@ -1206,10 +1197,10 @@ allocate_plt_and_got_and_discard_relocs (h, inf)
|| h->dynindx == -1))) || h->dynindx == -1)))
{ {
struct elf_i386_link_hash_entry *eh; struct elf_i386_link_hash_entry *eh;
struct elf_i386_pcrel_relocs_copied *c; struct elf_i386_dyn_relocs *c;
eh = (struct elf_i386_link_hash_entry *) h; eh = (struct elf_i386_link_hash_entry *) h;
for (c = eh->pcrel_relocs_copied; c != NULL; c = c->next) for (c = eh->dyn_relocs; c != NULL; c = c->next)
c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel); c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel);
} }
@ -1232,7 +1223,8 @@ elf_i386_size_dynamic_sections (output_bfd, info)
htab = elf_i386_hash_table (info); htab = elf_i386_hash_table (info);
dynobj = htab->root.dynobj; dynobj = htab->root.dynobj;
BFD_ASSERT (dynobj != NULL); if (dynobj == NULL)
abort ();
if (htab->root.dynamic_sections_created) if (htab->root.dynamic_sections_created)
{ {
@ -1240,7 +1232,8 @@ elf_i386_size_dynamic_sections (output_bfd, info)
if (! info->shared) if (! info->shared)
{ {
s = bfd_get_section_by_name (dynobj, ".interp"); s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL); if (s == NULL)
abort ();
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
} }
@ -1453,6 +1446,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym; Elf_Internal_Sym *sym;
asection *sec; asection *sec;
bfd_vma off;
bfd_vma relocation; bfd_vma relocation;
bfd_reloc_status_type r; bfd_reloc_status_type r;
unsigned int indx; unsigned int indx;
@ -1514,6 +1508,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
while (h->root.type == bfd_link_hash_indirect while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
relocation = 0; relocation = 0;
if (h->root.type == bfd_link_hash_defined if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak) || h->root.type == bfd_link_hash_defweak)
@ -1591,16 +1586,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
case R_386_GOT32: case R_386_GOT32:
/* Relocation is to the entry for this symbol in the global /* Relocation is to the entry for this symbol in the global
offset table. */ offset table. */
BFD_ASSERT (htab->sgot != NULL); if (htab->sgot == NULL)
abort ();
if (h != NULL) if (h != NULL)
{ {
bfd_vma off;
boolean dyn; boolean dyn;
off = h->got.offset; off = h->got.offset;
BFD_ASSERT (off != (bfd_vma) -1);
dyn = htab->root.dynamic_sections_created; dyn = htab->root.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared || (info->shared
@ -1630,15 +1623,11 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
h->got.offset |= 1; h->got.offset |= 1;
} }
} }
relocation = htab->sgot->output_offset + off;
} }
else else
{ {
bfd_vma off; if (local_got_offsets == NULL)
abort ();
BFD_ASSERT (local_got_offsets != NULL
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
off = local_got_offsets[r_symndx]; off = local_got_offsets[r_symndx];
@ -1658,7 +1647,8 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
Elf_Internal_Rel outrel; Elf_Internal_Rel outrel;
srelgot = htab->srelgot; srelgot = htab->srelgot;
BFD_ASSERT (srelgot != NULL); if (srelgot == NULL)
abort ();
outrel.r_offset = (htab->sgot->output_section->vma outrel.r_offset = (htab->sgot->output_section->vma
+ htab->sgot->output_offset + htab->sgot->output_offset
@ -1673,10 +1663,12 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
local_got_offsets[r_symndx] |= 1; local_got_offsets[r_symndx] |= 1;
} }
relocation = htab->sgot->output_offset + off;
} }
if (off >= (bfd_vma) -2)
abort ();
relocation = htab->sgot->output_offset + off;
break; break;
case R_386_GOTOFF: case R_386_GOTOFF:
@ -1689,7 +1681,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
permitted by the ABI, we might have to change this permitted by the ABI, we might have to change this
calculation. */ calculation. */
relocation -= htab->sgot->output_section->vma; relocation -= htab->sgot->output_section->vma;
break; break;
case R_386_GOTPC: case R_386_GOTPC:
@ -1718,7 +1709,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
relocation = (htab->splt->output_section->vma relocation = (htab->splt->output_section->vma
+ htab->splt->output_offset + htab->splt->output_offset
+ h->plt.offset); + h->plt.offset);
break; break;
case R_386_32: case R_386_32:
@ -1764,19 +1754,22 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
name + 4) != 0) name + 4) != 0)
{ {
if (input_bfd->my_archive) if (input_bfd->my_archive)
(*_bfd_error_handler) (_("%s(%s): bad relocation section name `%s\'"), (*_bfd_error_handler)\
bfd_get_filename (input_bfd->my_archive), (_("%s(%s): bad relocation section name `%s\'"),
bfd_get_filename (input_bfd), bfd_get_filename (input_bfd->my_archive),
name); bfd_get_filename (input_bfd),
name);
else else
(*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"), (*_bfd_error_handler)
bfd_get_filename (input_bfd), (_("%s: bad relocation section name `%s\'"),
name); bfd_get_filename (input_bfd),
name);
return false; return false;
} }
sreloc = bfd_get_section_by_name (dynobj, name); sreloc = bfd_get_section_by_name (dynobj, name);
BFD_ASSERT (sreloc != NULL); if (sreloc == NULL)
abort ();
} }
skip = false; skip = false;
@ -1855,36 +1848,38 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
contents, rel->r_offset, contents, rel->r_offset,
relocation, (bfd_vma) 0); relocation, (bfd_vma) 0);
if (r != bfd_reloc_ok) switch (r)
{ {
switch (r) case bfd_reloc_ok:
{ break;
default:
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
{
const char *name;
if (h != NULL) case bfd_reloc_overflow:
name = h->root.root.string; {
else const char *name;
{
name = bfd_elf_string_from_elf_section (input_bfd, if (h != NULL)
symtab_hdr->sh_link, name = h->root.root.string;
sym->st_name); else
if (name == NULL) {
return false; name = bfd_elf_string_from_elf_section (input_bfd,
if (*name == '\0') symtab_hdr->sh_link,
name = bfd_section_name (input_bfd, sec); sym->st_name);
} if (name == NULL)
if (! ((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
return false; return false;
if (*name == '\0')
name = bfd_section_name (input_bfd, sec);
} }
break; if (! ((*info->callbacks->reloc_overflow)
} (info, name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
return false;
}
break;
default:
case bfd_reloc_outofrange:
abort ();
break;
} }
} }
@ -1916,10 +1911,11 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
/* This symbol has an entry in the procedure linkage table. Set /* This symbol has an entry in the procedure linkage table. Set
it up. */ it up. */
BFD_ASSERT (h->dynindx != -1 if (h->dynindx == -1
&& htab->splt != NULL || htab->splt == NULL
&& htab->sgotplt != NULL || htab->sgotplt == NULL
&& htab->srelplt != NULL); || htab->srelplt == NULL)
abort ();
/* Get the index in the procedure linkage table which /* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol corresponds to this symbol. This is the index of this symbol
@ -1988,7 +1984,8 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
/* This symbol has an entry in the global offset table. Set it /* This symbol has an entry in the global offset table. Set it
up. */ up. */
BFD_ASSERT (htab->sgot != NULL && htab->srelgot != NULL); if (htab->sgot == NULL || htab->srelgot == NULL)
abort ();
rel.r_offset = (htab->sgot->output_section->vma rel.r_offset = (htab->sgot->output_section->vma
+ htab->sgot->output_offset + htab->sgot->output_offset
@ -2028,10 +2025,11 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
/* This symbol needs a copy reloc. Set it up. */ /* This symbol needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1 if (h->dynindx == -1
&& (h->root.type == bfd_link_hash_defined || (h->root.type != bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak) && h->root.type != bfd_link_hash_defweak)
&& htab->srelbss != NULL); || htab->srelbss == NULL)
abort ();
rel.r_offset = (h->root.u.def.value rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma + h->root.u.def.section->output_section->vma
@ -2070,7 +2068,8 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
{ {
Elf32_External_Dyn *dyncon, *dynconend; Elf32_External_Dyn *dyncon, *dynconend;
BFD_ASSERT (sdyn != NULL && htab->sgot != NULL); if (sdyn == NULL || htab->sgot == NULL)
abort ();
dyncon = (Elf32_External_Dyn *) sdyn->contents; dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);