+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ }
+
+ if (locsyms != NULL
+ && (symtab_hdr->contents != (unsigned char *) locsyms))
+ {
+ if (!info->keep_memory)
+ free (locsyms);
+ else
+ symtab_hdr->contents = (unsigned char *) locsyms;
+ }
+ }
+ return TRUE;
+}
+\f
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static bfd_boolean
+ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ struct ppc_elf_link_hash_table *htab;
+ asection *s;
+ unsigned int power_of_two;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n",
+ h->root.root.string);
+#endif
+
+ /* Make sure we know what is going on here. */
+ htab = ppc_elf_hash_table (info);
+ BFD_ASSERT (htab->elf.dynobj != NULL
+ && (h->needs_plt
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
+
+ /* Deal with function syms. */
+ if (h->type == STT_FUNC
+ || h->needs_plt)
+ {
+ /* Clear procedure linkage table information for any symbol that
+ won't need a .plt entry. */
+ if (h->plt.refcount <= 0
+ || SYMBOL_CALLS_LOCAL (info, h)
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak))
+ {
+ /* A PLT entry is not required/allowed when:
+
+ 1. We are not using ld.so; because then the PLT entry
+ can't be set up, so we can't use one. In this case,
+ ppc_elf_adjust_dynamic_symbol won't even be called.
+
+ 2. GC has rendered the entry unused.
+
+ 3. We know for certain that a call to this symbol
+ will go to this object, or will remain undefined. */
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+ return TRUE;
+ }
+ else
+ h->plt.offset = (bfd_vma) -1;
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->u.weakdef != NULL)
+ {
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ if (ELIMINATE_COPY_RELOCS)
+ h->non_got_ref = h->u.weakdef->non_got_ref;
+ return TRUE;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ 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)
+ 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)
+ return TRUE;
+
+ if (ELIMINATE_COPY_RELOCS)
+ {
+ struct ppc_elf_dyn_relocs *p;
+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ s = p->sec->output_section;
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ break;
+ }
+
+ /* If we didn't find any dynamic relocs in read-only sections, then
+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
+ if (p == NULL)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+ }
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable.
+
+ Of course, if the symbol is sufficiently small, we must instead
+ allocate it in .sbss. FIXME: It would be better to do this if and
+ only if there were actually SDAREL relocs for that symbol. */
+
+ if (h->size <= elf_gp_size (htab->elf.dynobj))
+ s = htab->dynsbss;
+ else
+ s = htab->dynbss;
+ BFD_ASSERT (s != NULL);
+
+ /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
+ copy the initial value out of the dynamic object and into the
+ runtime process image. We need to remember the offset into the
+ .rela.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ asection *srel;
+
+ if (h->size <= elf_gp_size (htab->elf.dynobj))
+ srel = htab->relsbss;
+ else
+ srel = htab->relbss;
+ BFD_ASSERT (srel != NULL);
+ srel->size += sizeof (Elf32_External_Rela);
+ h->needs_copy = 1;
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 4)
+ power_of_two = 4;
+
+ /* Apply the required alignment. */
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
+ {
+ if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two))
+ return FALSE;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->size += h->size;
+
+ return TRUE;
+}
+\f
+/* Allocate space in associated reloc sections for dynamic relocs. */
+
+static bfd_boolean
+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+{
+ struct bfd_link_info *info = inf;
+ struct ppc_elf_link_hash_entry *eh;
+ struct ppc_elf_link_hash_table *htab;
+ struct ppc_elf_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ /* When warning symbols are created, they **replace** the "real"
+ entry in the hash table, thus we never get to see the real
+ symbol in a hash traversal. So look at it now. */
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ htab = ppc_elf_hash_table (info);
+ if (htab->elf.dynamic_sections_created
+ && h->plt.refcount > 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ if (info->shared
+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
+ {
+ asection *s = htab->plt;
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->size == 0)
+ s->size += PLT_INITIAL_ENTRY_SIZE;
+
+ /* The PowerPC PLT is actually composed of two parts, the
+ first part is 2 words (for a load and a jump), and then
+ there is a remaining word available at the end. */
+ h->plt.offset = (PLT_INITIAL_ENTRY_SIZE
+ + (PLT_SLOT_SIZE
+ * ((s->size - PLT_INITIAL_ENTRY_SIZE)
+ / PLT_ENTRY_SIZE)));
+
+ /* 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 in the .plt. This is required to make
+ function pointers compare as equal between the normal
+ executable and the shared library. */
+ if (! info->shared
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = h->plt.offset;
+ }
+
+ /* Make room for this entry. After the 8192nd entry, room
+ for two entries is allocated. */
+ s->size += PLT_ENTRY_SIZE;
+ if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
+ > PLT_NUM_SINGLE_ENTRIES)
+ s->size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .rela.plt section. */
+ htab->relplt->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+
+ eh = (struct ppc_elf_link_hash_entry *) h;
+ if (eh->elf.got.refcount > 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (eh->elf.dynindx == -1
+ && !eh->elf.forced_local)
+ {
+ if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf))
+ return FALSE;
+ }
+
+ if (eh->tls_mask == (TLS_TLS | TLS_LD)
+ && !eh->elf.def_dynamic)
+ /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */
+ eh->elf.got.offset = (bfd_vma) -1;
+ else
+ {
+ bfd_boolean dyn;
+ eh->elf.got.offset = htab->got->size;
+ if ((eh->tls_mask & TLS_TLS) != 0)
+ {
+ if ((eh->tls_mask & TLS_LD) != 0)
+ htab->got->size += 8;
+ if ((eh->tls_mask & TLS_GD) != 0)
+ htab->got->size += 8;
+ if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ htab->got->size += 4;
+ if ((eh->tls_mask & TLS_DTPREL) != 0)
+ htab->got->size += 4;
+ }
+ else
+ htab->got->size += 4;
+ dyn = htab->elf.dynamic_sections_created;
+ if ((info->shared
+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
+ && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
+ || eh->elf.root.type != bfd_link_hash_undefweak))
+ {
+ /* All the entries we allocated need relocs. */
+ htab->relgot->size
+ += ((htab->got->size - eh->elf.got.offset) / 4
+ * sizeof (Elf32_External_Rela));
+ /* Except LD only needs one. */
+ if ((eh->tls_mask & TLS_LD) != 0)
+ htab->relgot->size -= sizeof (Elf32_External_Rela);
+ }
+ }
+ }
+ else
+ eh->elf.got.offset = (bfd_vma) -1;
+
+ if (eh->dyn_relocs == NULL)
+ return TRUE;
+
+ /* In the shared -Bsymbolic case, discard space allocated for
+ dynamic pc-relative 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. */
+
+ if (info->shared)
+ {
+ /* Relocs that use pc_count are those that appear on a call insn,
+ or certain REL relocs (see MUST_BE_DYN_RELOC) that can be
+ generated via assembly. We want calls to protected symbols to
+ resolve directly to the function rather than going via the plt.
+ If people want function pointer comparisons to work as expected
+ then they should avoid writing weird assembly. */
+ if (SYMBOL_CALLS_LOCAL (info, h))
+ {
+ struct ppc_elf_dyn_relocs **pp;
+
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ p->count -= p->pc_count;
+ p->pc_count = 0;
+ if (p->count == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+ }
+
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility. */
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak)
+ eh->dyn_relocs = NULL;
+
+ /* Make sure undefined weak symbols are output as a dynamic symbol
+ in PIEs. */
+ if (info->pie
+ && eh->dyn_relocs != NULL
+ && h->dynindx == -1
+ && h->root.type == bfd_link_hash_undefweak
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+ }
+ else if (ELIMINATE_COPY_RELOCS)
+ {
+ /* For the non-shared case, discard space for relocs against
+ symbols which turn out to need copy relocs or are not
+ dynamic. */
+
+ if (!h->non_got_ref
+ && h->def_dynamic
+ && !h->def_regular)
+ {
+ /* 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->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ /* If that succeeded, we know we'll be keeping all the
+ relocs. */
+ if (h->dynindx != -1)
+ goto keep;
+ }
+
+ eh->dyn_relocs = NULL;
+
+ keep: ;
+ }
+
+ /* Finally, allocate space. */
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *sreloc = elf_section_data (p->sec)->sreloc;
+ sreloc->size += p->count * sizeof (Elf32_External_Rela);
+ }
+
+ return TRUE;
+}
+
+/* Find any dynamic relocs that apply to read-only sections. */
+
+static bfd_boolean
+readonly_dynrelocs (struct elf_link_hash_entry *h, void *info)
+{
+ struct ppc_elf_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL
+ && ((s->flags & (SEC_READONLY | SEC_ALLOC))
+ == (SEC_READONLY | SEC_ALLOC)))
+ {
+ ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
+{
+ struct ppc_elf_link_hash_table *htab;
+ asection *s;
+ bfd_boolean relocs;
+ bfd *ibfd;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
+#endif
+
+ htab = ppc_elf_hash_table (info);
+ BFD_ASSERT (htab->elf.dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (info->executable)
+ {
+ s = bfd_get_section_by_name (htab->elf.dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = htab->got->size;
+ htab->got->size += 8;
+ if (info->shared)
+ htab->relgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
+ /* Set up .got offsets for local syms, and space for local dynamic
+ relocs. */
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ {
+ bfd_signed_vma *local_got;
+ bfd_signed_vma *end_local_got;
+ char *lgot_masks;
+ bfd_size_type locsymcount;
+ Elf_Internal_Shdr *symtab_hdr;
+ asection *srel;
+
+ if (!is_ppc_elf_target (ibfd->xvec))
+ continue;
+
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ {
+ struct ppc_elf_dyn_relocs *p;
+
+ for (p = ((struct ppc_elf_dyn_relocs *)
+ elf_section_data (s)->local_dynrel);
+ p != NULL;
+ p = p->next)
+ {
+ if (!bfd_is_abs_section (p->sec)
+ && bfd_is_abs_section (p->sec->output_section))
+ {
+ /* Input section has been discarded, either because
+ it is a copy of a linkonce section or due to
+ linker script /DISCARD/, so we'll be discarding
+ the relocs too. */
+ }
+ else if (p->count != 0)
+ {
+ elf_section_data (p->sec)->sreloc->size
+ += p->count * sizeof (Elf32_External_Rela);
+ if ((p->sec->output_section->flags
+ & (SEC_READONLY | SEC_ALLOC))
+ == (SEC_READONLY | SEC_ALLOC))
+ info->flags |= DF_TEXTREL;
+ }
+ }
+ }
+
+ local_got = elf_local_got_refcounts (ibfd);
+ if (!local_got)
+ continue;
+
+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+ locsymcount = symtab_hdr->sh_info;
+ end_local_got = local_got + locsymcount;
+ lgot_masks = (char *) end_local_got;
+ s = htab->got;
+ srel = htab->relgot;
+ for (; local_got < end_local_got; ++local_got, ++lgot_masks)
+ if (*local_got > 0)
+ {
+ if (*lgot_masks == (TLS_TLS | TLS_LD))
+ {
+ /* If just an LD reloc, we'll just use
+ htab->tlsld_got.offset. */
+ if (htab->tlsld_got.offset == (bfd_vma) -1)
+ {
+ htab->tlsld_got.offset = s->size;
+ s->size += 8;
+ if (info->shared)
+ srel->size += sizeof (Elf32_External_Rela);
+ }
+ *local_got = (bfd_vma) -1;
+ }
+ else
+ {
+ *local_got = s->size;
+ if ((*lgot_masks & TLS_TLS) != 0)
+ {
+ if ((*lgot_masks & TLS_GD) != 0)
+ s->size += 8;
+ if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ s->size += 4;
+ if ((*lgot_masks & TLS_DTPREL) != 0)
+ s->size += 4;
+ }
+ else
+ s->size += 4;
+ if (info->shared)
+ srel->size += ((s->size - *local_got) / 4
+ * sizeof (Elf32_External_Rela));
+ }
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
+
+ /* Allocate space for global sym dynamic relocs. */
+ elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
+
+ /* We've now determined the sizes of the various dynamic sections.
+ Allocate memory for them. */
+ relocs = FALSE;
+ for (s = htab->elf.dynobj->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LINKER_CREATED) == 0)
+ continue;
+
+ if (s == htab->plt
+ || s == htab->got
+ || s == htab->sbss)
+ {
+ /* Strip this section if we don't need it; see the
+ comment below. */
+ }
+ else if (s == htab->sdata[0].section
+ || s == htab->sdata[1].section)
+ {
+ /* Strip these too. */
+ }
+ else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
+ {
+ if (s->size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ }
+ else
+ {
+ /* Remember whether there are any relocation sections. */
+ relocs = TRUE;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (s->size == 0)
+ {
+ _bfd_strip_section_from_output (info, s);
+ continue;
+ }
+
+ if (s == htab->sbss)
+ continue;
+
+ /* Allocate memory for the section contents. */
+ s->contents = bfd_zalloc (htab->elf.dynobj, s->size);
+ if (s->contents == NULL)
+ return FALSE;
+ }
+
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in ppc_elf_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+#define add_dynamic_entry(TAG, VAL) \
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
+
+ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+ }
+
+ if (htab->plt != NULL && htab->plt->size != 0)
+ {
+ if (!add_dynamic_entry (DT_PLTGOT, 0)
+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || !add_dynamic_entry (DT_JMPREL, 0))
+ return FALSE;
+ }
+
+ if (relocs)
+ {
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
+ return FALSE;
+ }
+
+ /* If any dynamic relocs apply to a read-only section, then we
+ need a DT_TEXTREL entry. */
+ if ((info->flags & DF_TEXTREL) == 0)
+ elf_link_hash_traverse (elf_hash_table (info), readonly_dynrelocs,
+ info);