0, /* dst_mask */
FALSE), /* pcrel_offset */
+ /* Marker relocs on inline plt call instructions. */
+ HOWTO (R_PPC_PLTSEQ,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLTSEQ", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_PPC_PLTCALL,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLTCALL", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
/* Computes the load module index of the load module that contains the
definition of its TLS sym. */
HOWTO (R_PPC_DTPMOD32,
case NT_PRPSINFO:
{
- char data[128];
+ char data[128] ATTRIBUTE_NONSTRING;
va_list ap;
va_start (ap, note_type);
memset (data, 0, sizeof (data));
strncpy (data + 32, va_arg (ap, const char *), 16);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+ DIAGNOSTIC_PUSH;
+ /* GCC 8.0 and 8.1 warn about 80 equals destination size with
+ -Wstringop-truncation:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
+ */
+ DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
+#endif
strncpy (data + 48, va_arg (ap, const char *), 80);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+ DIAGNOSTIC_POP;
+#endif
va_end (ap);
return elfcore_write_note (abfd, buf, bufsiz,
"CORE", note_type, data, sizeof (data));
/* The above field is also used to mark function symbols. In which
case TLS_TLS will be 0. */
#define PLT_IFUNC 2 /* STT_GNU_IFUNC. */
+#define PLT_KEEP 4 /* inline plt call requires plt entry. */
#define NON_GOT 256 /* local symbol plt, not stored. */
/* Nonzero if we have seen a small data relocation referring to this
elf_linker_section_t sdata[2];
asection *sbss;
asection *glink_eh_frame;
+ asection *pltlocal;
+ asection *relpltlocal;
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
asection *srelplt2;
/* Set if tls optimization is enabled. */
unsigned int do_tls_opt:1;
+ /* Set if inline plt calls should be converted to direct calls. */
+ unsigned int can_convert_all_inline_plt:1;
+
/* The size of PLT entries. */
int plt_entry_size;
/* The distance between adjacent PLT slots. */
/* Nonzero if this section has a call to __tls_get_addr. */
#define has_tls_get_addr_call sec_flg1
+ /* Flag set when PLTCALL relocs are detected. */
+#define has_pltcall sec_flg2
+
/* Get the PPC ELF linker hash table from a link_info structure. */
#define ppc_elf_hash_table(p) \
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
+ /* Local plt entries. */
+ flags = (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ htab->pltlocal = bfd_make_section_anyway_with_flags (abfd, ".branch_lt",
+ flags);
+ if (htab->pltlocal == NULL
+ || ! bfd_set_section_alignment (abfd, htab->pltlocal, 2))
+ return FALSE;
+
+ if (bfd_link_pic (info))
+ {
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ htab->relpltlocal
+ = bfd_make_section_anyway_with_flags (abfd, ".rela.branch_lt", flags);
+ if (htab->relpltlocal == NULL
+ || ! bfd_set_section_alignment (abfd, htab->relpltlocal, 2))
+ return FALSE;
+ }
+
if (!ppc_elf_create_linker_section (abfd, info, 0,
&htab->sdata[0]))
return FALSE;
*valp = sym->st_size;
}
- if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
- && (abfd->flags & DYNAMIC) == 0
- && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
- elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc;
-
return TRUE;
}
\f
|| r_type == R_PPC_VLE_REL24);
}
+/* Relocs on inline plt call sequence insns prior to the call. */
+
+static bfd_boolean
+is_plt_seq_reloc (enum elf_ppc_reloc_type r_type)
+{
+ return (r_type == R_PPC_PLT16_HA
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLTSEQ);
+}
+
static void
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
{
struct elf_link_hash_entry *h;
int tls_type;
struct plt_entry **ifunc;
+ struct plt_entry **pltent;
+ bfd_vma addend;
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
|| r_type == R_PPC_PLT16_HI
|| r_type == R_PPC_PLT16_HA)
{
- bfd_vma addend = 0;
+ addend = 0;
if (r_type == R_PPC_PLTREL24)
ppc_elf_tdata (abfd)->makes_plt_call = 1;
if (bfd_link_pic (info)
return FALSE;
break;
+ case R_PPC_PLTSEQ:
+ break;
+
case R_PPC_GOT_TLSLD16:
case R_PPC_GOT_TLSLD16_LO:
case R_PPC_GOT_TLSLD16_HI:
if (h == NULL)
break;
ppc_elf_tdata (abfd)->makes_plt_call = 1;
- /* Fall through */
+ goto pltentry;
+
+ case R_PPC_PLTCALL:
+ sec->has_pltcall = 1;
+ /* Fall through. */
case R_PPC_PLT32:
case R_PPC_PLTREL32:
case R_PPC_PLT16_LO:
case R_PPC_PLT16_HI:
case R_PPC_PLT16_HA:
+ pltentry:
#ifdef DEBUG
fprintf (stderr, "Reloc requires a PLT entry\n");
#endif
/* This symbol requires a procedure linkage table entry. */
if (h == NULL)
{
- if (ifunc == NULL)
- {
- /* It does not make sense to have a procedure linkage
- table entry for a non-ifunc local symbol. */
- info->callbacks->einfo
- /* xgettext:c-format */
- (_("%H: %s reloc against local symbol\n"),
- abfd, sec, rel->r_offset,
- ppc_elf_howto_table[r_type]->name);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
+ pltent = update_local_sym_info (abfd, symtab_hdr, r_symndx,
+ NON_GOT | PLT_KEEP);
+ if (pltent == NULL)
+ return FALSE;
}
else
{
- bfd_vma addend = 0;
-
- if (bfd_link_pic (info)
- && (r_type == R_PPC_PLTREL24
- || r_type == R_PPC_PLT16_LO
- || r_type == R_PPC_PLT16_HI
- || r_type == R_PPC_PLT16_HA))
- addend = rel->r_addend;
+ if (r_type != R_PPC_PLTREL24)
+ ppc_elf_hash_entry (h)->tls_mask |= PLT_KEEP;
h->needs_plt = 1;
- if (!update_plt_info (abfd, &h->plt.plist, got2, addend))
- return FALSE;
+ pltent = &h->plt.plist;
}
+ addend = 0;
+ if (bfd_link_pic (info)
+ && (r_type == R_PPC_PLTREL24
+ || r_type == R_PPC_PLT16_LO
+ || r_type == R_PPC_PLT16_HI
+ || r_type == R_PPC_PLT16_HA))
+ addend = rel->r_addend;
+ if (!update_plt_info (abfd, pltent, got2, addend))
+ return FALSE;
break;
/* The following relocations don't need to propagate the
\f
/* Warn for conflicting Tag_GNU_Power_ABI_FP attributes between IBFD
and OBFD, and merge non-conflicting ones. */
-void
+bfd_boolean
_bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
{
bfd *obfd = info->output_bfd;
obj_attribute *in_attr, *in_attrs;
obj_attribute *out_attr, *out_attrs;
+ bfd_boolean ret = TRUE;
in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
{
int in_fp = in_attr->i & 3;
int out_fp = out_attr->i & 3;
+ static bfd *last_fp, *last_ld;
if (in_fp == 0)
;
else if (out_fp == 0)
{
- out_attr->type = 1;
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i ^= in_fp;
+ last_fp = ibfd;
}
else if (out_fp != 2 && in_fp == 2)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses hard float, %pB uses soft float"), obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses hard float, %pB uses soft float"),
+ last_fp, ibfd);
+ ret = FALSE;
+ }
else if (out_fp == 2 && in_fp != 2)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses hard float, %pB uses soft float"), ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses hard float, %pB uses soft float"),
+ ibfd, last_fp);
+ ret = FALSE;
+ }
else if (out_fp == 1 && in_fp == 3)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses double-precision hard float, "
- "%pB uses single-precision hard float"), obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses double-precision hard float, "
+ "%pB uses single-precision hard float"), last_fp, ibfd);
+ ret = FALSE;
+ }
else if (out_fp == 3 && in_fp == 1)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses double-precision hard float, "
- "%pB uses single-precision hard float"), ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses double-precision hard float, "
+ "%pB uses single-precision hard float"), ibfd, last_fp);
+ ret = FALSE;
+ }
in_fp = in_attr->i & 0xc;
out_fp = out_attr->i & 0xc;
;
else if (out_fp == 0)
{
- out_attr->type = 1;
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i ^= in_fp;
+ last_ld = ibfd;
}
else if (out_fp != 2 * 4 && in_fp == 2 * 4)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses 64-bit long double, "
- "%pB uses 128-bit long double"), ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses 64-bit long double, "
+ "%pB uses 128-bit long double"), ibfd, last_ld);
+ ret = FALSE;
+ }
else if (in_fp != 2 * 4 && out_fp == 2 * 4)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses 64-bit long double, "
- "%pB uses 128-bit long double"), obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses 64-bit long double, "
+ "%pB uses 128-bit long double"), last_ld, ibfd);
+ ret = FALSE;
+ }
else if (out_fp == 1 * 4 && in_fp == 3 * 4)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses IBM long double, "
- "%pB uses IEEE long double"), ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses IBM long double, "
+ "%pB uses IEEE long double"), last_ld, ibfd);
+ ret = FALSE;
+ }
else if (out_fp == 3 * 4 && in_fp == 1 * 4)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses IBM long double, "
- "%pB uses IEEE long double"), obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses IBM long double, "
+ "%pB uses IEEE long double"), ibfd, last_ld);
+ ret = FALSE;
+ }
+ }
+
+ if (!ret)
+ {
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+ bfd_set_error (bfd_error_bad_value);
}
+ return ret;
}
/* Merge object attributes from IBFD into OBFD. Warn if
bfd *obfd;
obj_attribute *in_attr, *in_attrs;
obj_attribute *out_attr, *out_attrs;
+ bfd_boolean ret;
- _bfd_elf_ppc_merge_fp_attributes (ibfd, info);
+ if (!_bfd_elf_ppc_merge_fp_attributes (ibfd, info))
+ return FALSE;
obfd = info->output_bfd;
in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
merge non-conflicting ones. */
in_attr = &in_attrs[Tag_GNU_Power_ABI_Vector];
out_attr = &out_attrs[Tag_GNU_Power_ABI_Vector];
+ ret = TRUE;
if (in_attr->i != out_attr->i)
{
int in_vec = in_attr->i & 3;
int out_vec = out_attr->i & 3;
+ static bfd *last_vec;
if (in_vec == 0)
;
else if (out_vec == 0)
{
- out_attr->type = 1;
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i = in_vec;
+ last_vec = ibfd;
}
/* For now, allow generic to transition to AltiVec or SPE
without a warning. If GCC marked files with their stack
;
else if (out_vec == 1)
{
- out_attr->type = 1;
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i = in_vec;
+ last_vec = ibfd;
}
else if (out_vec < in_vec)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
- obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
+ last_vec, ibfd);
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+ ret = FALSE;
+ }
else if (out_vec > in_vec)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
- ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
+ ibfd, last_vec);
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+ ret = FALSE;
+ }
}
/* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes
{
int in_struct = in_attr->i & 3;
int out_struct = out_attr->i & 3;
+ static bfd *last_struct;
if (in_struct == 0 || in_struct == 3)
;
else if (out_struct == 0)
{
- out_attr->type = 1;
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
out_attr->i = in_struct;
+ last_struct = ibfd;
}
else if (out_struct < in_struct)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses r3/r4 for small structure returns, "
- "%pB uses memory"), obfd, ibfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses r3/r4 for small structure returns, "
+ "%pB uses memory"), last_struct, ibfd);
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+ ret = FALSE;
+ }
else if (out_struct > in_struct)
- _bfd_error_handler
- /* xgettext:c-format */
- (_("warning: %pB uses r3/r4 for small structure returns, "
- "%pB uses memory"), ibfd, obfd);
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB uses r3/r4 for small structure returns, "
+ "%pB uses memory"), ibfd, last_struct);
+ out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+ ret = FALSE;
+ }
+ }
+ if (!ret)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
/* Merge Tag_compatibility attributes and any common GNU ones. */
- _bfd_elf_merge_object_attributes (ibfd, info);
-
- return TRUE;
+ return _bfd_elf_merge_object_attributes (ibfd, info);
}
/* Merge backend specific data from an object file to the output
return TRUE;
}
\f
+/* Analyze inline PLT call relocations to see whether calls to locally
+ defined functions can be converted to direct calls. */
+
+bfd_boolean
+ppc_elf_inline_plt (struct bfd_link_info *info)
+{
+ struct ppc_elf_link_hash_table *htab;
+ bfd *ibfd;
+ asection *sec;
+ bfd_vma low_vma, high_vma, limit;
+
+ htab = ppc_elf_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
+ /* A bl insn can reach -0x2000000 to 0x1fffffc. The limit is
+ reduced somewhat to cater for possible stubs that might be added
+ between the call and its destination. */
+ limit = 0x1e00000;
+ low_vma = -1;
+ high_vma = 0;
+ for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
+ if ((sec->flags & (SEC_ALLOC | SEC_CODE)) == (SEC_ALLOC | SEC_CODE))
+ {
+ if (low_vma > sec->vma)
+ low_vma = sec->vma;
+ if (high_vma < sec->vma + sec->size)
+ high_vma = sec->vma + sec->size;
+ }
+
+ /* If a "bl" can reach anywhere in local code sections, then we can
+ convert all inline PLT sequences to direct calls when the symbol
+ is local. */
+ if (high_vma - low_vma < limit)
+ {
+ htab->can_convert_all_inline_plt = 1;
+ return TRUE;
+ }
+
+ /* Otherwise, go looking through relocs for cases where a direct
+ call won't reach. Mark the symbol on any such reloc to disable
+ the optimization and keep the PLT entry as it seems likely that
+ this will be better than creating trampolines. Note that this
+ will disable the optimization for all inline PLT calls to a
+ particular symbol, not just those that won't reach. The
+ difficulty in doing a more precise optimization is that the
+ linker needs to make a decision depending on whether a
+ particular R_PPC_PLTCALL insn can be turned into a direct
+ call, for each of the R_PPC_PLTSEQ and R_PPC_PLT16* insns in
+ the sequence, and there is nothing that ties those relocs
+ together except their symbol. */
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
+ {
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Sym *local_syms;
+
+ if (!is_ppc_elf (ibfd))
+ continue;
+
+ local_syms = NULL;
+ symtab_hdr = &elf_symtab_hdr (ibfd);
+
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ if (sec->has_pltcall
+ && !bfd_is_abs_section (sec->output_section))
+ {
+ Elf_Internal_Rela *relstart, *rel, *relend;
+
+ /* Read the relocations. */
+ relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
+ info->keep_memory);
+ if (relstart == NULL)
+ return FALSE;
+
+ relend = relstart + sec->reloc_count;
+ for (rel = relstart; rel < relend; )
+ {
+ enum elf_ppc_reloc_type r_type;
+ unsigned long r_symndx;
+ asection *sym_sec;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ unsigned char *tls_maskp;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type != R_PPC_PLTCALL)
+ continue;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (!get_sym_h (&h, &sym, &sym_sec, &tls_maskp, &local_syms,
+ r_symndx, ibfd))
+ {
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ if (local_syms != NULL
+ && symtab_hdr->contents != (unsigned char *) local_syms)
+ free (local_syms);
+ return FALSE;
+ }
+
+ if (sym_sec != NULL && sym_sec->output_section != NULL)
+ {
+ bfd_vma from, to;
+ if (h != NULL)
+ to = h->root.u.def.value;
+ else
+ to = sym->st_value;
+ to += (rel->r_addend
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ from = (rel->r_offset
+ + sec->output_offset
+ + sec->output_section->vma);
+ if (to - from + limit < 2 * limit)
+ *tls_maskp &= ~PLT_KEEP;
+ }
+ }
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ }
+
+ if (local_syms != NULL
+ && symtab_hdr->contents != (unsigned char *) local_syms)
+ {
+ if (!info->keep_memory)
+ free (local_syms);
+ else
+ symtab_hdr->contents = (unsigned char *) local_syms;
+ }
+ }
+
+ return TRUE;
+}
+
/* Set plt output section type, htab->tls_get_addr, and call the
generic ELF tls_setup function. */
case R_PPC_TLSGD:
case R_PPC_TLSLD:
+ if (rel + 1 < relend
+ && is_plt_seq_reloc (ELF32_R_TYPE (rel[1].r_info)))
+ {
+ if (pass != 0
+ && ELF32_R_TYPE (rel[1].r_info) != R_PPC_PLTSEQ)
+ {
+ r_type = ELF32_R_TYPE (rel[1].r_info);
+ r_symndx = ELF32_R_SYM (rel[1].r_info);
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ struct elf_link_hash_entry **sym_hashes;
+
+ sym_hashes = elf_sym_hashes (ibfd);
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ 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;
+ if (h != NULL)
+ {
+ struct plt_entry *ent = NULL;
+ bfd_vma addend = 0;
+
+ if (bfd_link_pic (info))
+ addend = rel->r_addend;
+ ent = find_plt_ent (&h->plt.plist,
+ got2, addend);
+ if (ent != NULL
+ && ent->plt.refcount > 0)
+ ent->plt.refcount -= 1;
+ }
+ }
+ }
+ continue;
+ }
expecting_tls_get_addr = 2;
tls_set = 0;
tls_clear = 0;
if (pass == 0)
{
if (!expecting_tls_get_addr
- || (expecting_tls_get_addr == 1
- && !sec->has_tls_get_addr_call))
+ || !sec->has_tls_get_addr_call)
continue;
if (rel + 1 < relend
bfd_vma addend = 0;
if (bfd_link_pic (info)
- && ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24)
+ && (ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24
+ || ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTCALL))
addend = rel[1].r_addend;
ent = find_plt_ent (&htab->tls_get_addr->plt.plist,
got2, addend);
if (ent->plt.refcount > 0)
break;
if (ent == NULL
- || (h->type != STT_GNU_IFUNC && local))
+ || (h->type != STT_GNU_IFUNC
+ && local
+ && (htab->can_convert_all_inline_plt
+ || (ppc_elf_hash_entry (h)->tls_mask
+ & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)))
{
/* A PLT entry is not required/allowed when:
&& !readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
- /* If we haven't seen a branch reloc then we don't need
- a plt entry. */
- if (!h->needs_plt)
+ /* If we haven't seen a branch reloc and the symbol
+ isn't an ifunc then we don't need a plt entry. */
+ if (!h->needs_plt && h->type != STT_GNU_IFUNC)
h->plt.plist = NULL;
}
else if (!bfd_link_pic (info))
sreloc->size += p->count * sizeof (Elf32_External_Rela);
}
- /* Handle PLT relocs. Done last, after dynindx has settled. */
+ /* Handle PLT relocs. Done last, after dynindx has settled.
+ We might need a PLT entry when the symbol
+ a) is dynamic, or
+ b) is an ifunc, or
+ c) has plt16 relocs and has been processed by adjust_dynamic_symbol, or
+ d) has plt16 relocs and we are linking statically. */
dyn = htab->elf.dynamic_sections_created && h->dynindx != -1;
- if (dyn || h->type == STT_GNU_IFUNC)
+ if (dyn
+ || h->type == STT_GNU_IFUNC
+ || (h->needs_plt && h->dynamic_adjusted)
+ || (h->needs_plt
+ && h->def_regular
+ && !htab->elf.dynamic_sections_created
+ && !htab->can_convert_all_inline_plt
+ && (ppc_elf_hash_entry (h)->tls_mask
+ & (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
{
struct plt_entry *ent;
bfd_boolean doneone = FALSE;
- bfd_vma plt_offset = 0, glink_offset = 0;
+ bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1;
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
asection *s = htab->elf.splt;
if (!dyn)
- s = htab->elf.iplt;
+ {
+ if (h->type == STT_GNU_IFUNC)
+ s = htab->elf.iplt;
+ else
+ s = htab->pltlocal;
+ }
if (htab->plt_type == PLT_NEW || !dyn)
{
}
ent->plt.offset = plt_offset;
- s = htab->glink;
- if (!doneone || bfd_link_pic (info))
- {
- glink_offset = s->size;
- s->size += GLINK_ENTRY_SIZE (htab, h);
- }
- if (!doneone
- && !bfd_link_pic (info)
- && h->def_dynamic
- && !h->def_regular)
+ if (s == htab->pltlocal)
+ ent->glink_offset = glink_offset;
+ else
{
- h->root.u.def.section = s;
- h->root.u.def.value = glink_offset;
- }
- ent->glink_offset = glink_offset;
+ s = htab->glink;
+ if (!doneone || bfd_link_pic (info))
+ {
+ glink_offset = s->size;
+ s->size += GLINK_ENTRY_SIZE (htab, h);
+ }
+ if (!doneone
+ && !bfd_link_pic (info)
+ && h->def_dynamic
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = glink_offset;
+ }
+ ent->glink_offset = glink_offset;
- if (htab->params->emit_stub_syms
- && !add_stub_sym (ent, h, info))
- return FALSE;
+ if (htab->params->emit_stub_syms
+ && !add_stub_sym (ent, h, info))
+ return FALSE;
+ }
}
else
{
if (!doneone)
{
if (!dyn)
- htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
+ {
+ if (h->type == STT_GNU_IFUNC)
+ {
+ s = htab->elf.irelplt;
+ s->size += sizeof (Elf32_External_Rela);
+ }
+ else if (bfd_link_pic (info))
+ {
+ s = htab->relpltlocal;
+ s->size += sizeof (Elf32_External_Rela);
+ }
+ }
else
{
htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
continue;
/* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */
- for (; local_plt < end_local_plt; ++local_plt)
+ lgot_masks = (char *) end_local_plt;
+ for (; local_plt < end_local_plt; ++local_plt, ++lgot_masks)
{
struct plt_entry *ent;
bfd_boolean doneone = FALSE;
- bfd_vma plt_offset = 0, glink_offset = 0;
+ bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1;
for (ent = *local_plt; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
{
- s = htab->elf.iplt;
+ if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
+ s = htab->elf.iplt;
+ else if (htab->can_convert_all_inline_plt
+ || (*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
+ {
+ ent->plt.offset = (bfd_vma) -1;
+ continue;
+ }
+ else
+ s = htab->pltlocal;
if (!doneone)
{
}
ent->plt.offset = plt_offset;
- s = htab->glink;
- if (!doneone || bfd_link_pic (info))
+ if (s != htab->pltlocal && (!doneone || bfd_link_pic (info)))
{
+ s = htab->glink;
glink_offset = s->size;
s->size += GLINK_ENTRY_SIZE (htab, NULL);
}
if (!doneone)
{
- htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
+ if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
+ {
+ s = htab->elf.irelplt;
+ s->size += sizeof (Elf32_External_Rela);
+ }
+ else if (bfd_link_pic (info))
+ {
+ s = htab->relpltlocal;
+ s->size += sizeof (Elf32_External_Rela);
+ }
doneone = TRUE;
}
}
comment below. */
}
else if (s == htab->elf.iplt
+ || s == htab->pltlocal
|| s == htab->glink
|| s == htab->glink_eh_frame
|| s == htab->elf.sgotplt
case R_PPC_REL24:
case R_PPC_LOCAL24PC:
case R_PPC_PLTREL24:
+ case R_PPC_PLTCALL:
max_branch_offset = 1 << 25;
break;
{
if (tsec != NULL)
;
- else if (isym->st_shndx == SHN_UNDEF)
- tsec = bfd_und_section_ptr;
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
+ continue;
toff = isym->st_value;
sym_type = ELF_ST_TYPE (isym->st_info);
if (tsec == isec)
continue;
+ /* toff is used for the symbol index when the symbol is
+ undefined and we're doing a relocatable link, so we can't
+ support addends. It would be possible to do so by
+ putting the addend in one_branch_fixup but addends on
+ branches are rare so it hardly seems worth supporting. */
+ if (bfd_link_relocatable (link_info)
+ && tsec == bfd_und_section_ptr
+ && r_type != R_PPC_PLTREL24
+ && irel->r_addend != 0)
+ continue;
+
/* There probably isn't any reason to handle symbols in
SEC_MERGE sections; SEC_MERGE doesn't seem a likely
attribute for a code section, and we are only looking at
a section symbol should not include the addend; Such an
access is presumed to be an offset from "sym"; The
location of interest is just "sym". */
- if (sym_type == STT_SECTION)
+ if (sym_type == STT_SECTION
+ && r_type != R_PPC_PLTREL24)
toff += irel->r_addend;
toff
elf_section_data (tsec)->sec_info,
toff);
- if (sym_type != STT_SECTION)
+ if (sym_type != STT_SECTION
+ && r_type != R_PPC_PLTREL24)
toff += irel->r_addend;
}
/* PLTREL24 addends are special. */
roff = irel->r_offset;
+ /* Avoid creating a lot of unnecessary fixups when
+ relocatable if the output section size is such that a
+ fixup can be created at final link.
+ The max_branch_offset adjustment allows for some number
+ of other fixups being needed at final link. */
+ if (bfd_link_relocatable (link_info)
+ && (isec->output_section->rawsize - (isec->output_offset + roff)
+ < max_branch_offset - (max_branch_offset >> 4)))
+ continue;
+
/* If the branch is in range, no need to do anything. */
if (tsec != bfd_und_section_ptr
&& (!bfd_link_relocatable (link_info)
unsigned long r_symndx;
bfd_vma relocation;
bfd_vma branch_bit, from;
- bfd_boolean unresolved_reloc;
+ bfd_boolean unresolved_reloc, save_unresolved_reloc;
bfd_boolean warned;
unsigned int tls_type, tls_mask, tls_gd;
struct plt_entry **ifunc, **plt_list;
unsigned int insn2;
bfd_vma offset = rel->r_offset;
+ if (is_plt_seq_reloc (ELF32_R_TYPE (rel[1].r_info)))
+ {
+ bfd_put_32 (input_bfd, NOP, contents + offset);
+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
+ break;
+ }
+
if ((tls_mask & TLS_TPRELGD) != 0)
{
/* IE */
{
unsigned int insn2;
+ if (is_plt_seq_reloc (ELF32_R_TYPE (rel[1].r_info)))
+ {
+ bfd_put_32 (input_bfd, NOP, contents + rel->r_offset);
+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
+ break;
+ }
+
for (r_symndx = 0;
r_symndx < symtab_hdr->sh_info;
r_symndx++)
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_REL14_BRNTAKEN:
{
- bfd_vma insn;
+ unsigned int insn;
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
insn &= ~BRANCH_PREDICT_BIT;
}
addend = rel->r_addend;
+ save_unresolved_reloc = unresolved_reloc;
howto = NULL;
if (r_type < R_PPC_max)
howto = ppc_elf_howto_table[r_type];
addend = 0;
break;
+ case R_PPC_PLTSEQ:
+ case R_PPC_PLTCALL:
case R_PPC_PLT16_LO:
case R_PPC_PLT16_HI:
case R_PPC_PLT16_HA:
- plt_list = ifunc;
+ plt_list = NULL;
if (h != NULL)
plt_list = &h->plt.plist;
+ else if (ifunc != NULL)
+ plt_list = ifunc;
+ else if (local_got_offsets != NULL)
+ {
+ struct plt_entry **local_plt;
+ local_plt = (struct plt_entry **) (local_got_offsets
+ + symtab_hdr->sh_info);
+ plt_list = local_plt + r_symndx;
+ }
unresolved_reloc = TRUE;
if (plt_list != NULL)
{
ent = find_plt_ent (plt_list, got2,
bfd_link_pic (info) ? addend : 0);
- if (ent != NULL)
+ if (ent != NULL && ent->plt.offset != (bfd_vma) -1)
{
+ asection *plt;
+
unresolved_reloc = FALSE;
- relocation = (htab->elf.splt->output_section->vma
- + htab->elf.splt->output_offset
+ plt = htab->elf.splt;
+ if (!htab->elf.dynamic_sections_created
+ || h == NULL
+ || h->dynindx == -1)
+ {
+ if (ifunc != NULL)
+ plt = htab->elf.iplt;
+ else
+ plt = htab->pltlocal;
+ }
+ relocation = (plt->output_section->vma
+ + plt->output_offset
+ ent->plt.offset);
if (bfd_link_pic (info))
{
goto copy_reloc;
}
+ switch (r_type)
+ {
+ default:
+ break;
+
+ case R_PPC_PLTCALL:
+ if (unresolved_reloc)
+ {
+ bfd_byte *p = contents + rel->r_offset;
+ unsigned int insn = bfd_get_32 (input_bfd, p);
+ insn &= 1;
+ bfd_put_32 (input_bfd, B | insn, p);
+ unresolved_reloc = save_unresolved_reloc;
+ r_type = R_PPC_REL24;
+ howto = ppc_elf_howto_table[r_type];
+ }
+ else if (htab->plt_type != PLT_NEW)
+ info->callbacks->einfo
+ (_("%P: %H: %s relocation unsupported for bss-plt\n"),
+ input_bfd, input_section, rel->r_offset,
+ howto->name);
+ break;
+
+ case R_PPC_PLTSEQ:
+ case R_PPC_PLT16_HA:
+ case R_PPC_PLT16_LO:
+ if (unresolved_reloc)
+ {
+ bfd_byte *p = contents + (rel->r_offset & ~3);
+ bfd_put_32 (input_bfd, NOP, p);
+ unresolved_reloc = FALSE;
+ r_type = R_PPC_NONE;
+ howto = ppc_elf_howto_table[r_type];
+ }
+ else if (htab->plt_type != PLT_NEW)
+ info->callbacks->einfo
+ (_("%P: %H: %s relocation unsupported for bss-plt\n"),
+ input_bfd, input_section, rel->r_offset,
+ howto->name);
+ break;
+ }
+
/* Do any further special processing. */
switch (r_type)
{
Elf_Internal_Rela rela;
bfd_byte *loc;
bfd_vma reloc_index;
+ asection *plt = htab->elf.splt;
+ asection *relplt = htab->elf.srelplt;
if (htab->plt_type == PLT_NEW
|| !htab->elf.dynamic_sections_created
{
bfd_put_32 (info->output_bfd,
plt_entry[0] | PPC_HA (got_offset),
- htab->elf.splt->contents + ent->plt.offset + 0);
+ plt->contents + ent->plt.offset + 0);
bfd_put_32 (info->output_bfd,
plt_entry[1] | PPC_LO (got_offset),
- htab->elf.splt->contents + ent->plt.offset + 4);
+ plt->contents + ent->plt.offset + 4);
}
else
{
bfd_put_32 (info->output_bfd,
plt_entry[0] | PPC_HA (got_loc),
- htab->elf.splt->contents + ent->plt.offset + 0);
+ plt->contents + ent->plt.offset + 0);
bfd_put_32 (info->output_bfd,
plt_entry[1] | PPC_LO (got_loc),
- htab->elf.splt->contents + ent->plt.offset + 4);
+ plt->contents + ent->plt.offset + 4);
}
bfd_put_32 (info->output_bfd, plt_entry[2],
- htab->elf.splt->contents + ent->plt.offset + 8);
+ plt->contents + ent->plt.offset + 8);
bfd_put_32 (info->output_bfd, plt_entry[3],
- htab->elf.splt->contents + ent->plt.offset + 12);
+ plt->contents + ent->plt.offset + 12);
/* This instruction is an immediate load. The value loaded is
the byte offset of the R_PPC_JMP_SLOT relocation from the
prescaled offset. */
bfd_put_32 (info->output_bfd,
plt_entry[4] | reloc_index,
- htab->elf.splt->contents + ent->plt.offset + 16);
+ plt->contents + ent->plt.offset + 16);
/* This instruction is a PC-relative branch whose target is
the start of the PLT section. The address of this branch
instruction is 20 bytes beyond the start of this PLT entry.
bfd_put_32 (info->output_bfd,
(plt_entry[5]
| (-(ent->plt.offset + 20) & 0x03fffffc)),
- htab->elf.splt->contents + ent->plt.offset + 20);
+ plt->contents + ent->plt.offset + 20);
bfd_put_32 (info->output_bfd, plt_entry[6],
- htab->elf.splt->contents + ent->plt.offset + 24);
+ plt->contents + ent->plt.offset + 24);
bfd_put_32 (info->output_bfd, plt_entry[7],
- htab->elf.splt->contents + ent->plt.offset + 28);
+ plt->contents + ent->plt.offset + 28);
/* Fill in the GOT entry corresponding to this PLT slot with
the address immediately after the "bctr" instruction
in this PLT entry. */
- bfd_put_32 (info->output_bfd,
- (htab->elf.splt->output_section->vma
- + htab->elf.splt->output_offset
- + ent->plt.offset + 16),
+ bfd_put_32 (info->output_bfd, (plt->output_section->vma
+ + plt->output_offset
+ + ent->plt.offset + 16),
htab->elf.sgotplt->contents + got_offset);
if (!bfd_link_pic (info))
* sizeof (Elf32_External_Rela));
/* Provide the @ha relocation for the first instruction. */
- rela.r_offset = (htab->elf.splt->output_section->vma
- + htab->elf.splt->output_offset
+ rela.r_offset = (plt->output_section->vma
+ + plt->output_offset
+ ent->plt.offset + 2);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
R_PPC_ADDR16_HA);
loc += sizeof (Elf32_External_Rela);
/* Provide the @l relocation for the second instruction. */
- rela.r_offset = (htab->elf.splt->output_section->vma
- + htab->elf.splt->output_offset
+ rela.r_offset = (plt->output_section->vma
+ + plt->output_offset
+ ent->plt.offset + 6);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
R_PPC_ADDR16_LO);
rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
+ got_offset);
-
+ rela.r_addend = 0;
}
else
{
- asection *splt = htab->elf.splt;
+ rela.r_addend = 0;
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- splt = htab->elf.iplt;
+ {
+ if (h->type == STT_GNU_IFUNC)
+ {
+ plt = htab->elf.iplt;
+ relplt = htab->elf.irelplt;
+ }
+ else
+ {
+ plt = htab->pltlocal;
+ relplt = bfd_link_pic (info) ? htab->relpltlocal : NULL;
+ }
+ if (h->def_regular
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ rela.r_addend = SYM_VAL (h);
+ }
- rela.r_offset = (splt->output_section->vma
- + splt->output_offset
- + ent->plt.offset);
- if (htab->plt_type == PLT_OLD
- || !htab->elf.dynamic_sections_created
- || h->dynindx == -1)
+ if (relplt == NULL)
{
- /* We don't need to fill in the .plt. The ppc dynamic
- linker will fill it in. */
+ loc = plt->contents + ent->plt.offset;
+ bfd_put_32 (info->output_bfd, rela.r_addend, loc);
}
else
{
- bfd_vma val = (htab->glink_pltresolve + ent->plt.offset
- + htab->glink->output_section->vma
- + htab->glink->output_offset);
- bfd_put_32 (info->output_bfd, val,
- splt->contents + ent->plt.offset);
- }
- }
+ rela.r_offset = (plt->output_section->vma
+ + plt->output_offset
+ + ent->plt.offset);
- /* Fill in the entry in the .rela.plt section. */
- rela.r_addend = 0;
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
- {
- BFD_ASSERT (h->type == STT_GNU_IFUNC
- && h->def_regular
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak));
- rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
- rela.r_addend = SYM_VAL (h);
+ if (htab->plt_type == PLT_OLD
+ || !htab->elf.dynamic_sections_created
+ || h->dynindx == -1)
+ {
+ /* We don't need to fill in the .plt. The ppc dynamic
+ linker will fill it in. */
+ }
+ else
+ {
+ bfd_vma val = (htab->glink_pltresolve + ent->plt.offset
+ + htab->glink->output_section->vma
+ + htab->glink->output_offset);
+ bfd_put_32 (info->output_bfd, val,
+ plt->contents + ent->plt.offset);
+ }
+ }
}
- else
- rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
+ if (relplt != NULL)
{
- loc = (htab->elf.irelplt->contents
- + (htab->elf.irelplt->reloc_count++
- * sizeof (Elf32_External_Rela)));
- htab->local_ifunc_resolver = 1;
- }
- else
- {
- loc = (htab->elf.srelplt->contents
- + reloc_index * sizeof (Elf32_External_Rela));
- if (h->type == STT_GNU_IFUNC && is_static_defined (h))
- htab->maybe_local_ifunc_resolver = 1;
+ /* Fill in the entry in the .rela.plt section. */
+ if (!htab->elf.dynamic_sections_created
+ || h->dynindx == -1)
+ {
+ if (h->type == STT_GNU_IFUNC)
+ rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
+ else
+ rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
+ loc = relplt->contents + (relplt->reloc_count++
+ * sizeof (Elf32_External_Rela));
+ htab->local_ifunc_resolver = 1;
+ }
+ else
+ {
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
+ loc = relplt->contents + (reloc_index
+ * sizeof (Elf32_External_Rela));
+ if (h->type == STT_GNU_IFUNC && is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
+ bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
}
- bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
doneone = TRUE;
}
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- plt = htab->elf.iplt;
+ {
+ if (h->type == STT_GNU_IFUNC)
+ plt = htab->elf.iplt;
+ else
+ break;
+ }
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
write_glink_stub (h, ent, plt, p, info);
if (sym_sec != NULL && sym_sec->output_section != NULL)
val += sym_sec->output_offset + sym_sec->output_section->vma;
- BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
-
- htab->local_ifunc_resolver = 1;
- plt = htab->elf.iplt;
- relplt = htab->elf.irelplt;
+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+ {
+ htab->local_ifunc_resolver = 1;
+ plt = htab->elf.iplt;
+ relplt = htab->elf.irelplt;
+ rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
+ }
+ else
+ {
+ plt = htab->pltlocal;
+ if (bfd_link_pic (info))
+ {
+ relplt = htab->relpltlocal;
+ rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
+ }
+ else
+ {
+ loc = plt->contents + ent->plt.offset;
+ bfd_put_32 (info->output_bfd, val, loc);
+ continue;
+ }
+ }
rela.r_offset = (ent->plt.offset
+ plt->output_offset
+ plt->output_section->vma);
- rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
rela.r_addend = val;
loc = relplt->contents + (relplt->reloc_count++
* sizeof (Elf32_External_Rela));
#define ELF_ARCH bfd_arch_powerpc
#define ELF_TARGET_ID PPC32_ELF_DATA
#define ELF_MACHINE_CODE EM_PPC
-#ifdef __QNXTARGET__
-#define ELF_MAXPAGESIZE 0x1000
-#define ELF_COMMONPAGESIZE 0x1000
-#else
#define ELF_MAXPAGESIZE 0x10000
-#define ELF_COMMONPAGESIZE 0x10000
-#endif
-#define ELF_MINPAGESIZE 0x1000
+#define ELF_COMMONPAGESIZE 0x1000
+#define ELF_RELROPAGESIZE ELF_MAXPAGESIZE
#define elf_info_to_howto ppc_elf_info_to_howto
#ifdef EM_CYGNUS_POWERPC