+ 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. */
+ struct plt_entry *ent;
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->plt.refcount > 0)
+ break;
+ if (ent == NULL
+ || 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.plist = NULL;
+ h->needs_plt = 0;
+ }
+ return TRUE;
+ }
+ else
+ h->plt.plist = NULL;
+
+ /* 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 we didn't find any dynamic relocs in read-only sections, then we'll
+ be keeping the dynamic relocs and avoiding the copy reloc. We can't
+ do this if there are any small data relocations. */
+ if (ELIMINATE_COPY_RELOCS
+ && !ppc_elf_hash_entry (h)->has_sda_refs)
+ {
+ 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 (p == NULL)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+ }
+
+ if (h->size == 0)
+ {
+ (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
+ h->root.root.string);
+ 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 referenced using SDAREL relocs, we
+ must instead allocate it in .sbss. */
+
+ if (ppc_elf_hash_entry (h)->has_sda_refs)
+ 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 (ppc_elf_hash_entry (h)->has_sda_refs)
+ 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 NEED contiguous space in .got, and return the offset.
+ Handles allocation of the got header when crossing 32k. */
+
+static bfd_vma
+allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
+{
+ bfd_vma where;
+ unsigned int max_before_header = 32768;
+
+ if (htab->old_plt)
+ max_before_header = 32764;
+
+ if (htab->is_vxworks)
+ {
+ where = htab->got->size;
+ htab->got->size += need;
+ }
+ else if (need <= htab->got_gap)
+ {
+ where = max_before_header - htab->got_gap;
+ htab->got_gap -= need;
+ }
+ else
+ {
+ if (htab->got->size + need > max_before_header
+ && htab->got->size <= max_before_header)
+ {
+ htab->got_gap = max_before_header - htab->got->size;
+ htab->got->size = max_before_header + htab->got_header_size;
+ }
+ where = htab->got->size;
+ htab->got->size += need;
+ }
+ return where;
+}
+
+/* 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)
+ {
+ struct plt_entry *ent;
+ bfd_boolean doneone = FALSE;
+ bfd_vma plt_offset = 0, glink_offset = 0;
+
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->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 (!(htab->old_plt || htab->is_vxworks))
+ {
+ if (!doneone)
+ {
+ plt_offset = s->size;
+ s->size += 4;
+ }
+ ent->plt.offset = plt_offset;
+
+ s = htab->glink;
+ if (!doneone || info->shared || info->pie)
+ {
+ glink_offset = s->size;
+ s->size += GLINK_ENTRY_SIZE;
+ }
+ if (!doneone
+ && !info->shared
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = glink_offset;
+ }
+ ent->glink_offset = glink_offset;
+ }
+ else
+ {
+ if (!doneone)
+ {
+ /* If this is the first .plt entry, make room
+ for the special first entry. */
+ if (s->size == 0)
+ s->size += htab->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. */
+ plt_offset = (htab->plt_initial_entry_size
+ + (htab->plt_slot_size
+ * ((s->size
+ - htab->plt_initial_entry_size)
+ / htab->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 = plt_offset;
+ }
+
+ /* Make room for this entry. */
+ s->size += htab->plt_entry_size;
+ /* After the 8192nd entry, room for two entries
+ is allocated. */
+ if (!htab->is_vxworks
+ && (s->size - htab->plt_initial_entry_size)
+ / htab->plt_entry_size
+ > PLT_NUM_SINGLE_ENTRIES)
+ s->size += htab->plt_entry_size;
+ }
+ ent->plt.offset = plt_offset;
+ }
+
+ /* We also need to make an entry in the .rela.plt section. */
+ if (!doneone)
+ {
+ htab->relplt->size += sizeof (Elf32_External_Rela);
+
+ if (htab->is_vxworks)
+ {
+ /* Allocate space for the unloaded relocations. */
+ if (!info->shared)
+ {
+ if (ent->plt.offset
+ == (bfd_vma) htab->plt_initial_entry_size)
+ {
+ htab->srelplt2->size
+ += sizeof (Elf32_External_Rela)
+ * VXWORKS_PLTRESOLVE_RELOCS;
+ }
+
+ htab->srelplt2->size
+ += sizeof (Elf32_External_Rela)
+ * VXWORKS_PLT_NON_JMP_SLOT_RELOCS;
+ }
+
+ /* Every PLT entry has an associated GOT entry in
+ .got.plt. */
+ htab->sgotplt->size += 4;
+ }
+ doneone = TRUE;
+ }
+ }
+ else
+ ent->plt.offset = (bfd_vma) -1;
+
+ if (!doneone)
+ {
+ h->plt.plist = NULL;
+ h->needs_plt = 0;
+ }
+ }
+ }
+ else
+ {
+ h->plt.plist = NULL;
+ 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;
+ unsigned int need = 0;
+ if ((eh->tls_mask & TLS_TLS) != 0)
+ {
+ if ((eh->tls_mask & TLS_LD) != 0)
+ need += 8;
+ if ((eh->tls_mask & TLS_GD) != 0)
+ need += 8;
+ if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ need += 4;
+ if ((eh->tls_mask & TLS_DTPREL) != 0)
+ need += 4;
+ }
+ else
+ need += 4;
+ eh->elf.got.offset = allocate_got (htab, need);
+ 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.
+ Except LD only needs one. */
+ if ((eh->tls_mask & TLS_LD) != 0)
+ need -= 4;
+ htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
+ }
+ }
+ 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->old_plt)
+ htab->got_header_size = 16;
+ else
+ htab->got_header_size = 12;
+
+ /* 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;
+
+ 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;
+ 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. */
+ htab->tlsld_got.refcount += 1;
+ *local_got = (bfd_vma) -1;
+ }
+ else
+ {
+ unsigned int need = 0;
+ if ((*lgot_masks & TLS_TLS) != 0)
+ {
+ if ((*lgot_masks & TLS_GD) != 0)
+ need += 8;
+ if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ need += 4;
+ if ((*lgot_masks & TLS_DTPREL) != 0)
+ need += 4;
+ }
+ else
+ need += 4;
+ *local_got = allocate_got (htab, need);
+ if (info->shared)
+ htab->relgot->size += (need
+ * (sizeof (Elf32_External_Rela) / 4));
+ }
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
+
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = allocate_got (htab, 8);
+ if (info->shared)
+ htab->relgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
+ if (htab->is_vxworks)
+ {
+ /* Save the PLT symbol in the hash table for easy access.
+ Mark GOT and PLT syms as having relocations; they might not,
+ but we won't know for sure until we build the GOT in
+ finish_dynamic_symbol. */
+
+ if (htab->elf.hgot)
+ htab->elf.hgot->indx = -2;
+ htab->hplt = elf_link_hash_lookup (elf_hash_table (info),
+ "_PROCEDURE_LINKAGE_TABLE_",
+ FALSE, FALSE, FALSE);
+ if (htab->hplt)
+ htab->hplt->indx = -2;
+ /* If the PLT is executable then give the symbol function type. */
+ if (htab->hplt && htab->plt->flags & SEC_CODE)
+ htab->hplt->type = STT_FUNC;
+ }
+
+ /* Allocate space for global sym dynamic relocs. */
+ elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
+
+ if (htab->got != NULL && !htab->is_vxworks)
+ {
+ unsigned int g_o_t = 32768;
+
+ /* If we haven't allocated the header, do so now. When we get here,
+ for old plt/got the got size will be 0 to 32764 (not allocated),
+ or 32780 to 65536 (header allocated). For new plt/got, the
+ corresponding ranges are 0 to 32768 and 32780 to 65536. */
+ if (htab->got->size <= 32768)
+ {
+ g_o_t = htab->got->size;
+ if (htab->old_plt)
+ g_o_t += 4;
+ htab->got->size += htab->got_header_size;
+ }
+
+ htab->elf.hgot->root.u.def.value = g_o_t;
+ }
+
+ if (htab->glink != NULL && htab->glink->size != 0)
+ {
+ htab->glink_pltresolve = htab->glink->size;
+ /* Space for the branch table. */
+ htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4;
+ /* Pad out to align the start of PLTresolve. */
+ htab->glink->size += -htab->glink->size & 15;
+ htab->glink->size += GLINK_PLTRESOLVE;
+ }
+
+ /* 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)
+ {
+ bfd_boolean strip_section = TRUE;
+
+ if ((s->flags & SEC_LINKER_CREATED) == 0)
+ continue;
+
+ if (s == htab->plt
+ || s == htab->glink
+ || s == htab->got
+ || s == htab->sgotplt
+ || s == htab->sbss
+ || s == htab->dynbss
+ || s == htab->dynsbss)
+ {
+ /* We'd like to strip these sections if they aren't needed, but if
+ we've exported dynamic symbols from them we must leave them.
+ It's too late to tell BFD to get rid of the symbols. */
+ if ((s == htab->plt || s == htab->got) && htab->hplt != NULL)
+ strip_section = FALSE;
+ /* 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)
+ {
+ /* 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 && strip_section)
+ {
+ /* 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. */
+ s->flags |= SEC_EXCLUDE;
+ continue;
+ }
+
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
+ 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 (htab->glink != NULL && htab->glink->size != 0)
+ {
+ if (!add_dynamic_entry (DT_PPC_GOT, 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);
+
+ if ((info->flags & DF_TEXTREL) != 0)
+ {
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
+ return FALSE;
+ }
+ }
+#undef add_dynamic_entry
+
+ return TRUE;
+}
+\f
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+static const int shared_stub_entry[] =
+ {
+ 0x7c0802a6, /* mflr 0 */
+ 0x429f0005, /* bcl 20, 31, .Lxxx */
+ 0x7d6802a6, /* mflr 11 */
+ 0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */
+ 0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */
+ 0x7c0803a6, /* mtlr 0 */
+ 0x7d6903a6, /* mtctr 11 */
+ 0x4e800420, /* bctr */
+ };
+
+static const int stub_entry[] =
+ {
+ 0x3d600000, /* lis 11,xxx@ha */
+ 0x396b0000, /* addi 11,11,xxx@l */
+ 0x7d6903a6, /* mtctr 11 */
+ 0x4e800420, /* bctr */
+ };
+
+static bfd_boolean
+ppc_elf_relax_section (bfd *abfd,
+ asection *isec,
+ struct bfd_link_info *link_info,
+ bfd_boolean *again)
+{
+ struct one_fixup
+ {
+ struct one_fixup *next;
+ asection *tsec;
+ bfd_vma toff;
+ bfd_vma trampoff;
+ };
+
+ Elf_Internal_Shdr *symtab_hdr;
+ bfd_byte *contents = NULL;
+ Elf_Internal_Sym *isymbuf = NULL;
+ Elf_Internal_Rela *internal_relocs = NULL;
+ Elf_Internal_Rela *irel, *irelend;
+ struct one_fixup *fixups = NULL;
+ bfd_boolean changed;
+ struct ppc_elf_link_hash_table *htab;
+ bfd_size_type trampoff;
+ asection *got2;
+
+ *again = FALSE;
+
+ /* Nothing to do if there are no relocations, and no need to do
+ anything with non-alloc sections. */
+ if ((isec->flags & SEC_ALLOC) == 0
+ || (isec->flags & SEC_RELOC) == 0
+ || isec->reloc_count == 0)
+ return TRUE;
+
+ trampoff = (isec->size + 3) & (bfd_vma) -4;
+ /* Space for a branch around any trampolines. */
+ trampoff += 4;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+ /* Get a copy of the native relocations. */
+ internal_relocs = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL,
+ link_info->keep_memory);
+ if (internal_relocs == NULL)
+ goto error_return;
+
+ htab = ppc_elf_hash_table (link_info);
+ got2 = bfd_get_section_by_name (abfd, ".got2");
+
+ irelend = internal_relocs + isec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++)
+ {
+ unsigned long r_type = ELF32_R_TYPE (irel->r_info);
+ bfd_vma symaddr, reladdr, toff, roff;
+ asection *tsec;
+ struct one_fixup *f;
+ size_t insn_offset = 0;
+ bfd_vma max_branch_offset, val;
+ bfd_byte *hit_addr;
+ unsigned long t0;
+ unsigned char sym_type;
+
+ switch (r_type)
+ {
+ case R_PPC_REL24:
+ case R_PPC_LOCAL24PC:
+ case R_PPC_PLTREL24:
+ max_branch_offset = 1 << 25;
+ break;
+
+ case R_PPC_REL14:
+ case R_PPC_REL14_BRTAKEN:
+ case R_PPC_REL14_BRNTAKEN:
+ max_branch_offset = 1 << 15;
+ break;
+
+ default:
+ continue;
+ }
+
+ /* Get the value of the symbol referred to by the reloc. */
+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+ {
+ /* A local symbol. */
+ Elf_Internal_Sym *isym;
+
+ /* Read this BFD's local symbols. */
+ if (isymbuf == NULL)
+ {
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == 0)
+ goto error_return;
+ }
+ isym = isymbuf + ELF32_R_SYM (irel->r_info);
+ if (isym->st_shndx == SHN_UNDEF)
+ continue; /* We can't do anything with undefined symbols. */
+ else if (isym->st_shndx == SHN_ABS)
+ tsec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ tsec = bfd_com_section_ptr;
+ else
+ tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+
+ toff = isym->st_value;
+ sym_type = ELF_ST_TYPE (isym->st_info);
+ }
+ else
+ {
+ /* Global symbol handling. */
+ unsigned long indx;
+ struct elf_link_hash_entry *h;
+
+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+ h = elf_sym_hashes (abfd)[indx];
+
+ 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;
+
+ tsec = NULL;
+ toff = 0;
+ if (r_type == R_PPC_PLTREL24
+ && htab->plt != NULL)
+ {
+ struct plt_entry *ent = find_plt_ent (h, got2, irel->r_addend);
+
+ if (ent != NULL)
+ {
+ if (!htab->old_plt)
+ {
+ tsec = htab->glink;
+ toff = ent->glink_offset;
+ }
+ else
+ {
+ tsec = htab->plt;
+ toff = ent->plt.offset;
+ }
+ }
+ }
+ if (tsec != NULL)
+ ;
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ tsec = h->root.u.def.section;
+ toff = h->root.u.def.value;
+ }
+ else
+ continue;