+
+ ppc_elf_maybe_strip_sdata_syms (&link_info);
+
+ if (RELAXATION_ENABLED)
+ params.branch_trampolines = 1;
+
+ /* Turn on relaxation if executable sections have addresses that
+ might make branches overflow. */
+ else if (!RELAXATION_DISABLED_BY_USER)
+ {
+ bfd_vma low = (bfd_vma) -1;
+ bfd_vma high = 0;
+ asection *o;
+
+ /* Run lang_size_sections (if not already done). */
+ prelim_size_sections ();
+
+ for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & (SEC_ALLOC | SEC_CODE)) != (SEC_ALLOC | SEC_CODE))
+ continue;
+ if (o->rawsize == 0)
+ continue;
+ if (low > o->vma)
+ low = o->vma;
+ if (high < o->vma + o->rawsize - 1)
+ high = o->vma + o->rawsize - 1;
+ }
+ if (high > low && high - low > (1 << 25) - 1)
+ params.branch_trampolines = 1;
+ }
+
+ if (params.branch_trampolines
+ || params.ppc476_workaround
+ || params.pic_fixup > 0)
+ ENABLE_RELAXATION;
+}
+
+/* Replaces default zero fill padding in executable sections with
+ "ba 0" instructions. This works around the ppc476 icache bug if we
+ have a function pointer tail call near the end of a page, some
+ small amount of padding, then the function called at the beginning
+ of the next page. If the "ba 0" is ever executed we should hit a
+ segv, so it's almost as good as an illegal instruction (zero). */
+
+static void
+no_zero_padding (lang_statement_union_type *l)
+{
+ if (l->header.type == lang_padding_statement_enum
+ && l->padding_statement.size != 0
+ && l->padding_statement.output_section != NULL
+ && (l->padding_statement.output_section->flags & SEC_CODE) != 0
+ && l->padding_statement.fill->size == 0)
+ {
+ struct _ppc_fill_type
+ {
+ size_t size;
+ unsigned char data[4];
+ };
+ static struct _ppc_fill_type fill_be = { 4, {0x48, 0, 0, 2} };
+ static struct _ppc_fill_type fill_le = { 4, {2, 0, 0, 0x48} };
+
+ if (bfd_big_endian (link_info.output_bfd))
+ l->padding_statement.fill = (struct _fill_type *) &fill_be;
+ else
+ l->padding_statement.fill = (struct _fill_type *) &fill_le;
+ }
+}
+
+static void
+ppc_finish (void)
+{
+ if (params.ppc476_workaround)
+ lang_for_each_statement (no_zero_padding);
+ if (!ppc_finish_symbols (&link_info))
+ einfo (_("%X%P: ppc_finish_symbols problem %E\n"));
+ finish_default ();