0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- TRUE, /* pc_relative */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
Elf_Internal_Shdr *shdr,
asection *asect)
{
- if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
- shdr->sh_flags |= SHF_EXCLUDE;
-
if ((asect->flags & SEC_SORT_ENTRIES) != 0)
shdr->sh_type = SHT_ORDERED;
apuinfo_list;
static apuinfo_list *head;
-
+static bfd_boolean apuinfo_set;
static void
apuinfo_list_init (void)
{
head = NULL;
+ apuinfo_set = FALSE;
}
static void
{
bfd *ibfd;
asection *asec;
- char *buffer;
- unsigned num_input_sections;
- bfd_size_type output_section_size;
+ char *buffer = NULL;
+ bfd_size_type largest_input_size = 0;
unsigned i;
- unsigned num_entries;
- unsigned long offset;
unsigned long length;
const char *error_message = NULL;
if (link_info == NULL)
return;
- /* Scan the input bfds, looking for apuinfo sections. */
- num_input_sections = 0;
- output_section_size = 0;
-
- for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
- {
- asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
- if (asec)
- {
- ++ num_input_sections;
- output_section_size += asec->size;
- }
- }
-
- /* We need at least one input sections
- in order to make merging worthwhile. */
- if (num_input_sections < 1)
- return;
-
- /* Just make sure that the output section exists as well. */
- asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
- if (asec == NULL)
- return;
-
- /* Allocate a buffer for the contents of the input sections. */
- buffer = bfd_malloc (output_section_size);
- if (buffer == NULL)
- return;
-
- offset = 0;
apuinfo_list_init ();
/* Read in the input sections contents. */
for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
{
unsigned long datum;
- char *ptr;
asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
if (asec == NULL)
continue;
+ error_message = _("corrupt %s section in %B");
length = asec->size;
- if (length < 24)
+ if (length < 20)
+ goto fail;
+
+ apuinfo_set = TRUE;
+ if (largest_input_size < asec->size)
{
- error_message = _("corrupt or empty %s section in %B");
- goto fail;
+ if (buffer)
+ free (buffer);
+ largest_input_size = asec->size;
+ buffer = bfd_malloc (largest_input_size);
+ if (!buffer)
+ return;
}
if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
- || (bfd_bread (buffer + offset, length, ibfd) != length))
+ || (bfd_bread (buffer, length, ibfd) != length))
{
error_message = _("unable to read in %s section from %B");
goto fail;
}
- /* Process the contents of the section. */
- ptr = buffer + offset;
- error_message = _("corrupt %s section in %B");
-
/* Verify the contents of the header. Note - we have to
extract the values this way in order to allow for a
host whose endian-ness is different from the target. */
- datum = bfd_get_32 (ibfd, ptr);
+ datum = bfd_get_32 (ibfd, buffer);
if (datum != sizeof APUINFO_LABEL)
goto fail;
- datum = bfd_get_32 (ibfd, ptr + 8);
+ datum = bfd_get_32 (ibfd, buffer + 8);
if (datum != 0x2)
goto fail;
- if (strcmp (ptr + 12, APUINFO_LABEL) != 0)
+ if (strcmp (buffer + 12, APUINFO_LABEL) != 0)
goto fail;
/* Get the number of bytes used for apuinfo entries. */
- datum = bfd_get_32 (ibfd, ptr + 4);
+ datum = bfd_get_32 (ibfd, buffer + 4);
if (datum + 20 != length)
goto fail;
- /* Make sure that we do not run off the end of the section. */
- if (offset + length > output_section_size)
- goto fail;
-
/* Scan the apuinfo section, building a list of apuinfo numbers. */
for (i = 0; i < datum; i += 4)
- apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + i));
-
- /* Update the offset. */
- offset += length;
+ apuinfo_list_add (bfd_get_32 (ibfd, buffer + 20 + i));
}
error_message = NULL;
- /* Compute the size of the output section. */
- num_entries = apuinfo_list_length ();
- output_section_size = 20 + num_entries * 4;
+ if (apuinfo_set)
+ {
+ /* Compute the size of the output section. */
+ unsigned num_entries = apuinfo_list_length ();
- asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+ /* Set the output section size, if it exists. */
+ asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
- if (! bfd_set_section_size (abfd, asec, output_section_size))
- ibfd = abfd,
- error_message = _("warning: unable to set size of %s section in %B");
+ if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4))
+ {
+ ibfd = abfd;
+ error_message = _("warning: unable to set size of %s section in %B");
+ }
+ }
fail:
- free (buffer);
+ if (buffer)
+ free (buffer);
if (error_message)
(*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME);
asection *asec,
bfd_byte *contents ATTRIBUTE_UNUSED)
{
- return (apuinfo_list_length ()
- && strcmp (asec->name, APUINFO_SECTION_NAME) == 0);
+ return apuinfo_set && strcmp (asec->name, APUINFO_SECTION_NAME) == 0;
}
/* Finally we can generate the output section. */
if (asec == NULL)
return;
- if (apuinfo_list_length () == 0)
+ if (!apuinfo_set)
return;
length = asec->size;
/* The bfd that forced an old-style PLT. */
bfd *old_bfd;
-
+
/* TLS local dynamic got entry handling. */
union {
bfd_signed_vma refcount;
struct sym_cache sym_cache;
};
+/* Rename some of the generic section flags to better document how they
+ are used here. */
+
+/* Nonzero if this section has TLS related relocations. */
+#define has_tls_reloc sec_flg0
+
+/* Nonzero if this section has a call to __tls_get_addr. */
+#define has_tls_get_addr_call sec_flg1
+
/* Get the PPC ELF linker hash table from a link_info structure. */
#define ppc_elf_hash_table(p) \
*valp = sym->st_size;
}
- if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+ if ((abfd->flags & DYNAMIC) == 0
+ && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
return TRUE;
(_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd);
else if (out_attr->i == 1 && in_attr->i == 3)
_bfd_error_handler
- (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
+ (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
obfd, ibfd);
else if (out_attr->i == 3 && in_attr->i == 1)
_bfd_error_handler
- (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
+ (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
ibfd, obfd);
else if (out_attr->i == 3 && in_attr->i == 2)
_bfd_error_handler
- (_("Warning: %B uses soft float, %B uses single-precision hard float"),
+ (_("Warning: %B uses soft float, %B uses single-precision hard float"),
ibfd, obfd);
else if (out_attr->i == 2 && (in_attr->i == 1 || in_attr->i == 3))
_bfd_error_handler
}
else
{
- Elf_Internal_Sym *sym;
bfd_signed_vma *lgot_refs;
struct plt_entry **local_plt;
char *lgot_masks;
return FALSE;
}
}
- sym = locsyms + r_symndx;
lgot_refs = elf_local_got_refcounts (ibfd);
if (lgot_refs == NULL)
abort ();
/* If this symbol is not defined in a regular
file, and we are not generating a shared
- library, then set the symbol to this location
+ library, then set the symbol to this location
in the .plt. This is to avoid text
relocations, and is required to make
function pointers compare as equal between
struct ppc_elf_link_hash_table *htab;
bfd_size_type trampoff;
asection *got2;
+ bfd_boolean maybe_pasted;
*again = FALSE;
anyway. */
if (link_info->relocatable && link_info->shared)
return TRUE;
-
+
trampoff = (isec->size + 3) & (bfd_vma) -4;
+ maybe_pasted = (strcmp (isec->output_section->name, ".init") == 0
+ || strcmp (isec->output_section->name, ".fini") == 0);
/* Space for a branch around any trampolines. */
- trampoff += 4;
+ if (maybe_pasted)
+ trampoff += 4;
symtab_hdr = &elf_symtab_hdr (abfd);
{
const int *stub;
bfd_byte *dest;
- bfd_vma val;
int i, size;
do
goto error_return;
isec->size = (isec->size + 3) & (bfd_vma) -4;
- /* Branch around the trampolines. */
- val = B + trampoff - isec->size;
dest = contents + isec->size;
+ /* Branch around the trampolines. */
+ if (maybe_pasted)
+ {
+ bfd_vma val = B + trampoff - isec->size;
+ bfd_put_32 (abfd, val, dest);
+ dest += 4;
+ }
isec->size = trampoff;
- bfd_put_32 (abfd, val, dest);
- dest += 4;
if (link_info->shared)
{
Elf_Internal_Rela *new_relocs = bfd_malloc ((changes + isec->reloc_count)
* sizeof (*new_relocs));
unsigned ix;
-
+
if (!new_relocs)
goto error_return;
memcpy (new_relocs, internal_relocs,
irel++;
}
}
-
+
return TRUE;
error_return:
}
skip = 0;
- outrel.r_offset =
- _bfd_elf_section_offset (output_bfd, info, input_section,
- rel->r_offset);
+ outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
+ input_section,
+ rel->r_offset);
if (outrel.r_offset == (bfd_vma) -1
|| outrel.r_offset == (bfd_vma) -2)
skip = (int) outrel.r_offset;
{
bfd_vma got_offset;
const bfd_vma *plt_entry;
-
+
/* The first three entries in .got.plt are reserved. */
got_offset = (reloc_index + 3) * 4;
low-order 16 bits of the load instruction. */
/* NOTE: It appears that this is now an index rather than a
prescaled offset. */
- bfd_put_32 (output_bfd,
+ bfd_put_32 (output_bfd,
plt_entry[4] | reloc_index,
htab->plt->contents + ent->plt.offset + 16);
/* This instruction is a PC-relative branch whose target is
The address is encoded in bits 6-29, inclusive. The value
stored is right-shifted by two bits, permitting a 26-bit
offset. */
- bfd_put_32 (output_bfd,
- (plt_entry[5]
+ bfd_put_32 (output_bfd,
+ (plt_entry[5]
| (-(ent->plt.offset + 20) & 0x03fffffc)),
htab->plt->contents + ent->plt.offset + 20);
bfd_put_32 (output_bfd, plt_entry[6],
relocation. */
sym->st_shndx = (_bfd_elf_section_from_bfd_section
(output_bfd, htab->glink->output_section));
- sym->st_value = (ent->glink_offset +
- htab->glink->output_offset
+ sym->st_value = (ent->glink_offset
+ + htab->glink->output_offset
+ htab->glink->output_section->vma);
}
doneone = TRUE;
dynobj = elf_hash_table (info)->dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (htab->is_vxworks)
- splt = bfd_get_section_by_name (dynobj, ".plt");
+ splt = bfd_get_section_by_name (dynobj, ".plt");
else
splt = NULL;
if (splt && splt->size > 0)
{
/* Use the right PLT. */
- static const bfd_vma *plt_entry = NULL;
- plt_entry = info->shared ?
- ppc_elf_vxworks_pic_plt0_entry : ppc_elf_vxworks_plt0_entry;
+ const bfd_vma *plt_entry = (info->shared
+ ? ppc_elf_vxworks_pic_plt0_entry
+ : ppc_elf_vxworks_plt0_entry);
if (!info->shared)
{
rela.r_addend = 0;
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
loc += sizeof (Elf32_External_Rela);
-
+
/* Output the @l relocation for the second instruction. */
rela.r_offset = (htab->plt->output_section->vma
+ htab->plt->output_offset