+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->_raw_size == 0)
+ s->_raw_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. */
+ plt_offset = (PLT_INITIAL_ENTRY_SIZE
+ + 8 * ((s->_raw_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->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = plt_offset;
+ }
+
+ h->plt_offset = plt_offset;
+
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+#if 0
+ /* 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 = bfd_get_section_by_name (dynobj, ".got.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += 4;
+#endif
+
+ /* We also need to make an entry in the .rela.plt section. */
+
+ s = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += sizeof (Elf32_External_Rela);
+
+ return true;
+ }
+
+ /* 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->weakdef != NULL)
+ {
+ BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+ || h->weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->weakdef->root.u.def.section;
+ h->root.u.def.value = h->weakdef->root.u.def.value;
+ 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;
+
+ /* 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. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynbss");
+ BFD_ASSERT (s != NULL);
+
+ /* If the symbol is currently defined in the .bss section of the
+ dynamic object, then it is OK to simply initialize it to zero.
+ If the symbol is in some other section, 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_LOAD) != 0)
+ {
+ asection *srel;
+
+ srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ BFD_ASSERT (srel != NULL);
+ srel->_raw_size += sizeof (Elf32_External_Rel);
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ }
+
+ /* 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 > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->_raw_size = BFD_ALIGN (s->_raw_size,
+ (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (! bfd_set_section_alignment (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->_raw_size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->_raw_size += h->size;
+
+ return true;
+}
+
+\f
+/* Increment the index of a dynamic symbol by a given amount. Called
+ via elf_link_hash_traverse. */
+
+static boolean
+ppc_elf_adjust_dynindx (h, cparg)
+ struct elf_link_hash_entry *h;
+ PTR cparg;
+{
+ int *cp = (int *) cparg;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp);
+#endif
+
+ if (h->dynindx != -1)
+ h->dynindx += *cp;
+
+ return true;
+}
+
+\f
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+ppc_elf_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean plt;
+ boolean relocs;
+ boolean reltext;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
+#endif
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* 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);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }