const Elf_Internal_Rela *));
static boolean elf_i386_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean allocate_plt_and_got
+static boolean allocate_plt_and_got_and_discard_relocs
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_i386_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
-static boolean discard_copies
- PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_i386_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
};
/* 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
- it can discard PC relative relocs if it doesn't need them when
- linking with -Bsymbolic. We store the information in a field
- extending the regular ELF linker hash table. */
-
-/* This structure keeps track of the number of PC relative relocs we
- have copied for a given symbol. */
+ decides to copy as dynamic relocs in check_relocs for each symbol.
+ This is so that it can later discard them if they are found to be
+ unnecessary. We store the information in a field extending the
+ regular ELF linker hash table. */
-struct elf_i386_pcrel_relocs_copied
+struct elf_i386_dyn_relocs
{
/* Next section. */
- struct elf_i386_pcrel_relocs_copied *next;
+ struct elf_i386_dyn_relocs *next;
/* A section in dynobj. */
asection *section;
/* Number of relocs copied in this section. */
struct elf_link_hash_entry root;
/* 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. */
table, string));
if (ret != (struct elf_i386_link_hash_entry *) NULL)
{
- ret->pcrel_relocs_copied = NULL;
+ ret->dyn_relocs = NULL;
}
return (struct bfd_hash_entry *) ret;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
/* Some relocs require a global offset table. */
- if (dynobj == NULL)
+ if (htab->sgot == NULL)
{
switch (ELF32_R_TYPE (rel->r_info))
{
case R_386_GOT32:
case R_386_GOTOFF:
case R_386_GOTPC:
- elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (dynobj == NULL)
+ htab->root.dynobj = dynobj = abfd;
if (!create_got_section (dynobj, info))
return false;
break;
if (h != NULL)
{
if (h->got.refcount == -1)
- {
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
- {
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
- }
- h->got.refcount = 1;
- }
+ h->got.refcount = 1;
else
h->got.refcount += 1;
}
else
{
- /* This is a global offset table entry for a local symbol. */
+ /* This is a global offset table entry for a local symbol. */
if (local_got_refcounts == NULL)
{
size_t size;
case R_386_PLT32:
/* This symbol requires a procedure linkage table entry. We
- actually build the entry in adjust_dynamic_symbol,
- because this might be a case of linking PIC code which is
- never referenced by a dynamic object, in which case we
- don't need to generate a procedure linkage table entry
- after all. */
+ actually build the entry in adjust_dynamic_symbol,
+ because this might be a case of linking PIC code which is
+ never referenced by a dynamic object, in which case we
+ don't need to generate a procedure linkage table entry
+ after all. */
/* If this is a local symbol, we resolve it directly without
- creating a procedure linkage table entry. */
+ creating a procedure linkage table entry. */
if (h == NULL)
continue;
case R_386_32:
case R_386_PC32:
- if (h != NULL)
+ if (h != NULL && !info->shared)
{
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
- if (!info->shared)
- {
- /* 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;
- }
+ /* If this reloc is in a read-only section, we might
+ need a copy reloc. */
+ if ((sec->flags & SEC_READONLY) != 0)
+ h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+ /* 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;
}
/* If we are creating a shared library, and this is a reloc
storing information in the relocs_copied field of the hash
table entry. A similar situation occurs when creating
shared libraries and symbol visibility changes render the
- symbol local. */
- if (info->shared
- && (sec->flags & SEC_ALLOC) != 0
- && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
- || (h != NULL
- && (! info->symbolic
- || h->root.type == bfd_link_hash_defweak
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ symbol local.
+ If on the other hand, we are creating an executable, we
+ may need to keep relocations for symbols satisfied by a
+ dynamic library if we manage to avoid copy relocs for the
+ symbol. */
+ if ((info->shared
+ && (sec->flags & SEC_ALLOC) != 0
+ && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
+ || (h != NULL
+ && (! info->symbolic
+ || h->root.type == bfd_link_hash_defweak
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ || (!info->shared
+ && (sec->flags & SEC_ALLOC) != 0
+ && h != NULL
+ && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+ && (h->root.type == bfd_link_hash_defweak
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
{
- /* When creating a shared object, we must copy these
- reloc types into the output file. We create a reloc
- section in dynobj and make room for this reloc. */
+ /* We must copy these reloc types into the output file.
+ Create a reloc section in dynobj and make room for
+ this reloc. */
+ if (dynobj == NULL)
+ htab->root.dynobj = dynobj = abfd;
+
if (sreloc == NULL)
{
const char *name;
that this function is only called if we are using an
elf_i386 linker hash table, which means that h is
really a pointer to an elf_i386_link_hash_entry. */
- if (h != NULL
- && ELF32_R_TYPE (rel->r_info) == R_386_PC32)
+ if (!info->shared
+ || (h != NULL
+ && ELF32_R_TYPE (rel->r_info) == R_386_PC32))
{
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;
- 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)
break;
if (p == NULL)
{
- p = ((struct elf_i386_pcrel_relocs_copied *)
+ p = ((struct elf_i386_dyn_relocs *)
bfd_alloc (dynobj, sizeof *p));
if (p == NULL)
return false;
- p->next = eh->pcrel_relocs_copied;
- eh->pcrel_relocs_copied = p;
+ p->next = eh->dyn_relocs;
+ eh->dyn_relocs = p;
p->section = sreloc;
p->count = 0;
}
htab = elf_i386_hash_table (info);
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
will fill in the contents of the procedure linkage table later,
when we know the address of the .got section. */
linkage table, and we can just do a PC32 reloc instead. */
h->plt.refcount = (bfd_vma) -1;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- return true;
- }
-
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
- {
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
- return false;
}
return true;
same memory location for the variable. */
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
copy the initial value out of the dynamic object and into the
asection *srel;
srel = htab->srelbss;
- BFD_ASSERT (srel != NULL);
+ if (srel == NULL)
+ abort ();
srel->_raw_size += sizeof (Elf32_External_Rel);
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
}
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
/* Allocate space in .plt, .got and associated reloc sections for
- global syms. */
+ global syms. Also discards space allocated for relocs in the
+ check_relocs function that we subsequently have found to be
+ unneeded. */
static boolean
-allocate_plt_and_got (h, inf)
+allocate_plt_and_got_and_discard_relocs (h, inf)
struct elf_link_hash_entry *h;
PTR inf;
{
struct bfd_link_info *info;
struct elf_i386_link_hash_table *htab;
asection *s;
+ struct elf_i386_link_hash_entry *eh;
if (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
if (htab->root.dynamic_sections_created
&& h->plt.refcount > 0)
{
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
s = htab->splt;
- BFD_ASSERT (s != NULL);
+ if (s == NULL)
+ abort ();
/* If this is the first .plt entry, make room for the special
first entry. */
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
s = htab->sgotplt;
- BFD_ASSERT (s != NULL);
+ if (s == NULL)
+ abort ();
s->_raw_size += 4;
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
{
/* We also need to make an entry in the .rel.plt section. */
s = htab->srelplt;
- BFD_ASSERT (s != NULL);
+ if (s == NULL)
+ abort ();
s->_raw_size += sizeof (Elf32_External_Rel);
}
}
{
boolean dyn;
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
s = htab->sgot;
h->got.offset = s->_raw_size;
s->_raw_size += 4;
else
h->got.offset = (bfd_vma) -1;
+ /* In the shared -Bsymbolic case, discard space allocated for
+ dynamic relocs against symbols which turn out to be defined
+ in regular objects. For the normal shared case, discard space
+ for relocs that have become local due to symbol visibility
+ changes. For the non-shared case, discard space for symbols
+ which turn out to need copy relocs or are not dynamic. */
+
+ eh = (struct elf_i386_link_hash_entry *) h;
+ if (eh->dyn_relocs == NULL)
+ return true;
+
+ if (!info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined))
+ {
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ /* If that succeeded, we know we'll be keeping all the relocs. */
+ if (h->dynindx != -1)
+ return true;
+ }
+
+ if (!info->shared
+ || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+ || info->symbolic)))
+ {
+ struct elf_i386_dyn_relocs *c;
+
+ for (c = eh->dyn_relocs; c != NULL; c = c->next)
+ c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel);
+ }
+
return true;
}
asection *s;
boolean relocs;
boolean reltext;
+ bfd *i;
htab = elf_i386_hash_table (info);
dynobj = htab->root.dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if (dynobj == NULL)
+ abort ();
if (htab->root.dynamic_sections_created)
{
- bfd *i;
-
/* Set the contents of the .interp section to the interpreter. */
if (! info->shared)
{
s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
+ if (s == NULL)
+ abort ();
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
+ }
- /* Set up .got offsets for local syms. */
- for (i = info->input_bfds; i; i = i->link_next)
- {
- bfd_signed_vma *local_got;
- bfd_signed_vma *end_local_got;
- bfd_size_type locsymcount;
- Elf_Internal_Shdr *symtab_hdr;
- asection *srel;
+ /* Set up .got offsets for local syms. */
+ for (i = info->input_bfds; i; i = i->link_next)
+ {
+ bfd_signed_vma *local_got;
+ bfd_signed_vma *end_local_got;
+ bfd_size_type locsymcount;
+ Elf_Internal_Shdr *symtab_hdr;
+ asection *srel;
- if (bfd_get_flavour (i) != bfd_target_elf_flavour)
- continue;
+ if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ continue;
- local_got = elf_local_got_refcounts (i);
- if (!local_got)
- continue;
+ local_got = elf_local_got_refcounts (i);
+ if (!local_got)
+ continue;
- symtab_hdr = &elf_tdata (i)->symtab_hdr;
- locsymcount = symtab_hdr->sh_info;
- end_local_got = local_got + locsymcount;
- s = htab->sgot;
- srel = htab->srelgot;
- for (; local_got < end_local_got; ++local_got)
+ symtab_hdr = &elf_tdata (i)->symtab_hdr;
+ locsymcount = symtab_hdr->sh_info;
+ end_local_got = local_got + locsymcount;
+ s = htab->sgot;
+ srel = htab->srelgot;
+ for (; local_got < end_local_got; ++local_got)
+ {
+ if (*local_got > 0)
{
- if (*local_got > 0)
- {
- *local_got = s->_raw_size;
- s->_raw_size += 4;
- if (info->shared)
- srel->_raw_size += sizeof (Elf32_External_Rel);
- }
- else
- *local_got = (bfd_vma) -1;
+ *local_got = s->_raw_size;
+ s->_raw_size += 4;
+ if (info->shared)
+ srel->_raw_size += sizeof (Elf32_External_Rel);
}
+ else
+ *local_got = (bfd_vma) -1;
}
}
- /* Allocate global sym .plt and .got entries. */
+ /* Allocate global sym .plt and .got entries. Also discard all
+ unneeded relocs. */
elf_link_hash_traverse (&htab->root,
- allocate_plt_and_got,
+ allocate_plt_and_got_and_discard_relocs,
(PTR) info);
- /* If this is a -Bsymbolic shared link, then we need to discard all
- PC relative relocs against symbols defined in a regular object.
- We allocated space for them in the check_relocs routine, but we
- will not fill them in in the relocate_section routine. */
- if (info->shared)
- elf_link_hash_traverse (&htab->root,
- discard_copies,
- (PTR) info);
-
- /* The check_relocs and adjust_dynamic_symbol entry points have
- determined the sizes of the various dynamic sections. Allocate
- memory for them. */
+ /* We now have determined the sizes of the various dynamic sections.
+ Allocate memory for them. */
relocs = false;
reltext = false;
for (s = dynobj->sections; s != NULL; s = s->next)
asection *target;
/* Remember whether there are any reloc sections other
- than .rel.plt. */
+ than .rel.plt. */
if (s != htab->srelplt)
{
const char *outname;
return true;
}
-/* This function is called via elf_link_hash_traverse if we are
- creating a shared object. In the -Bsymbolic case, it discards the
- space allocated to copy PC relative relocs against symbols which
- are defined in regular objects. For the normal non-symbolic case,
- we also discard space for relocs that have become local due to
- symbol visibility changes. We allocated space for them in the
- check_relocs routine, but we won't fill them in in the
- relocate_section routine. */
-
-static boolean
-discard_copies (h, inf)
- struct elf_link_hash_entry *h;
- PTR inf;
-{
- struct elf_i386_pcrel_relocs_copied *s;
- struct bfd_link_info *info;
- struct elf_i386_link_hash_entry *eh;
-
- info = (struct bfd_link_info *) inf;
- eh = (struct elf_i386_link_hash_entry *) h;
-
- /* If a symbol has been forced local or we have found a regular
- definition for the symbolic link case, then we won't be needing
- any relocs. */
- if ((eh->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- && ((eh->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
- || info->symbolic))
- {
- for (s = eh->pcrel_relocs_copied; s != NULL; s = s->next)
- s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
- }
-
- return true;
-}
-
/* Relocate an i386 ELF section. */
static boolean
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
asection *sec;
+ bfd_vma off;
bfd_vma relocation;
+ boolean unresolved_reloc;
bfd_reloc_status_type r;
unsigned int indx;
h = NULL;
sym = NULL;
sec = NULL;
+ unresolved_reloc = false;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
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;
+
relocation = 0;
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
- if (r_type == R_386_GOTPC
- || (r_type == R_386_PLT32
- && htab->splt != NULL
- && h->plt.offset != (bfd_vma) -1)
- || (r_type == R_386_GOT32
- && (WILL_CALL_FINISH_DYNAMIC_SYMBOL
- (htab->root.dynamic_sections_created, info, h))
- && !(info->shared
- && (info->symbolic
- || h->dynindx == -1
- || (h->elf_link_hash_flags
- & ELF_LINK_FORCED_LOCAL))
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR)))
- || (info->shared
- && ((! info->symbolic && h->dynindx != -1)
- || (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
- /* DWARF will emit R_386_32 relocations in its
- sections against symbols defined externally
- in shared libraries. We can't do anything
- with them here. */
- || ((input_section->flags & SEC_DEBUGGING) != 0
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
- /* In these cases, we don't need the relocation
- value. We check specially because in some
- obscure cases sec->output_section will be NULL. */
- ;
- else if (sec->output_section == NULL)
- (*_bfd_error_handler)
- (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
- bfd_get_filename (input_bfd),
- bfd_get_section_name (input_bfd, input_section),
- (long) rel->r_offset,
- h->root.root.string);
+ if (sec->output_section == NULL)
+ /* Set a flag that will be cleared later if we find a
+ relocation value for this symbol. output_section
+ is typically NULL for symbols satisfied by a shared
+ library. */
+ unresolved_reloc = true;
else
relocation = (h->root.u.def.value
+ sec->output_section->vma
case R_386_GOT32:
/* Relocation is to the entry for this symbol in the global
offset table. */
- BFD_ASSERT (htab->sgot != NULL);
+ if (htab->sgot == NULL)
+ abort ();
if (h != NULL)
{
- bfd_vma off;
boolean dyn;
off = h->got.offset;
- BFD_ASSERT (off != (bfd_vma) -1);
-
dyn = htab->root.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared
h->got.offset |= 1;
}
}
-
- relocation = htab->sgot->output_offset + off;
+ else
+ unresolved_reloc = false;
}
else
{
- bfd_vma off;
-
- BFD_ASSERT (local_got_offsets != NULL
- && local_got_offsets[r_symndx] != (bfd_vma) -1);
+ if (local_got_offsets == NULL)
+ abort ();
off = local_got_offsets[r_symndx];
/* The offset must always be a multiple of 4. We use
- the least significant bit to record whether we have
- already generated the necessary reloc. */
+ the least significant bit to record whether we have
+ already generated the necessary reloc. */
if ((off & 1) != 0)
off &= ~1;
else
Elf_Internal_Rel outrel;
srelgot = htab->srelgot;
- BFD_ASSERT (srelgot != NULL);
+ if (srelgot == NULL)
+ abort ();
outrel.r_offset = (htab->sgot->output_section->vma
+ htab->sgot->output_offset
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;
case R_386_GOTOFF:
permitted by the ABI, we might have to change this
calculation. */
relocation -= htab->sgot->output_section->vma;
-
break;
case R_386_GOTPC:
/* Use global offset table as symbol value. */
relocation = htab->sgot->output_section->vma;
+ unresolved_reloc = false;
break;
case R_386_PLT32:
procedure linkage table. */
/* Resolve a PLT32 reloc against a local symbol directly,
- without using the procedure linkage table. */
+ without using the procedure linkage table. */
if (h == NULL)
break;
|| htab->splt == NULL)
{
/* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code, or when
- using -Bsymbolic. */
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
break;
}
relocation = (htab->splt->output_section->vma
+ htab->splt->output_offset
+ h->plt.offset);
-
+ unresolved_reloc = false;
break;
case R_386_32:
case R_386_PC32:
- if (info->shared
- && (input_section->flags & SEC_ALLOC) != 0
- && (r_type != R_386_PC32
- || (h != NULL
- && h->dynindx != -1
- && (! info->symbolic
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ if ((info->shared
+ && (input_section->flags & SEC_ALLOC) != 0
+ && (r_type != R_386_PC32
+ || (h != NULL
+ && h->dynindx != -1
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ || (!info->shared
+ && (input_section->flags & SEC_ALLOC) != 0
+ && h != NULL
+ && h->dynindx != -1
+ && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+ && ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_undefined)))
{
Elf_Internal_Rel outrel;
boolean skip, relocate;
name + 4) != 0)
{
if (input_bfd->my_archive)
- (*_bfd_error_handler) (_("%s(%s): bad relocation section name `%s\'"),
- bfd_get_filename (input_bfd->my_archive),
- bfd_get_filename (input_bfd),
- name);
+ (*_bfd_error_handler)\
+ (_("%s(%s): bad relocation section name `%s\'"),
+ bfd_get_filename (input_bfd->my_archive),
+ bfd_get_filename (input_bfd),
+ name);
else
- (*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"),
- bfd_get_filename (input_bfd),
- name);
+ (*_bfd_error_handler)
+ (_("%s: bad relocation section name `%s\'"),
+ bfd_get_filename (input_bfd),
+ name);
return false;
}
sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
+ if (sreloc == NULL)
+ abort ();
}
skip = false;
bfd_vma off;
off = (_bfd_stab_section_offset
- (output_bfd, &elf_hash_table (info)->stab_info,
- input_section,
+ (output_bfd, htab->root.stab_info, input_section,
&elf_section_data (input_section)->stab_info,
rel->r_offset));
if (off == (bfd_vma) -1)
memset (&outrel, 0, sizeof outrel);
relocate = false;
}
- else if (r_type == R_386_PC32)
+ else if (h != NULL
+ && h->dynindx != -1
+ && (r_type == R_386_PC32
+ || !info->shared
+ || !info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+
{
- BFD_ASSERT (h != NULL && h->dynindx != -1);
relocate = false;
- outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
}
else
{
- /* h->dynindx may be -1 if this symbol was marked to
- become local. */
- if (h == NULL
- || ((info->symbolic || h->dynindx == -1)
- && (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);
- }
+ /* This symbol is local, or marked to become local. */
+ relocate = true;
+ outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
}
bfd_elf32_swap_reloc_out (output_bfd, &outrel,
break;
}
+ /* FIXME: Why do we allow debugging sections to escape this error?
+ More importantly, why do we not emit dynamic relocs for
+ R_386_32 above in debugging sections (which are ! SEC_ALLOC)?
+ If we had emitted the dynamic reloc, we could remove the
+ fudge here. */
+ if (unresolved_reloc
+ && !(info->shared
+ && (input_section->flags & SEC_DEBUGGING) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+ (*_bfd_error_handler)
+ (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ bfd_get_filename (input_bfd),
+ bfd_get_section_name (input_bfd, input_section),
+ (long) rel->r_offset,
+ h->root.root.string);
+
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
relocation, (bfd_vma) 0);
- if (r != bfd_reloc_ok)
+ switch (r)
{
- switch (r)
- {
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
+ case bfd_reloc_ok:
+ break;
+
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
{
- const char *name;
-
- if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (name == NULL)
- return false;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
- }
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
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;
}
}
/* This symbol has an entry in the procedure linkage table. Set
it up. */
- BFD_ASSERT (h->dynindx != -1
- && htab->splt != NULL
- && htab->sgotplt != NULL
- && htab->srelplt != NULL);
+ if (h->dynindx == -1
+ || htab->splt == NULL
+ || htab->sgotplt == NULL
+ || htab->srelplt == NULL)
+ abort ();
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol
/* This symbol has an entry in the global offset table. Set it
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
+ htab->sgot->output_offset
/* This symbol needs a copy reloc. Set it up. */
- BFD_ASSERT (h->dynindx != -1
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && htab->srelbss != NULL);
+ if (h->dynindx == -1
+ || (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ || htab->srelbss == NULL)
+ abort ();
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
htab = elf_i386_hash_table (info);
dynobj = htab->root.dynobj;
-
- BFD_ASSERT (htab->sgot != NULL);
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (htab->root.dynamic_sections_created)
{
Elf32_External_Dyn *dyncon, *dynconend;
- BFD_ASSERT (sdyn != NULL);
+ if (sdyn == NULL || htab->sgot == NULL)
+ abort ();
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
}
}
- /* Fill in the first three entries in the global offset table. */
- if (htab->sgotplt->_raw_size > 0)
+ if (htab->sgotplt)
{
- bfd_put_32 (output_bfd,
- (sdyn == NULL ? (bfd_vma) 0
- : sdyn->output_section->vma + sdyn->output_offset),
- htab->sgotplt->contents);
- bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 4);
- bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
- }
-
- elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
+ /* Fill in the first three entries in the global offset table. */
+ if (htab->sgotplt->_raw_size > 0)
+ {
+ bfd_put_32 (output_bfd,
+ (sdyn == NULL ? (bfd_vma) 0
+ : sdyn->output_section->vma + sdyn->output_offset),
+ htab->sgotplt->contents);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 4);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
+ }
+ elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
+ }
return true;
}
#define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook
#define elf_backend_relocate_section elf_i386_relocate_section
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
-#define elf_backend_fake_sections elf_i386_fake_sections
+#define elf_backend_fake_sections elf_i386_fake_sections
#include "elf32-target.h"