#endif
#ifdef OBJ_ELF
-static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **));
+static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *));
static void ppc_elf_cons PARAMS ((int));
static void ppc_elf_rdata PARAMS ((int));
static void ppc_elf_lcomm PARAMS ((int));
static struct hash_control *ppc_macro_hash;
#ifdef OBJ_ELF
-/* Whether to warn about non PC relative relocations that aren't
- in the .got2 section. */
-static boolean mrelocatable = false;
+/* What type of shared library support to use */
+static enum { SHLIB_NONE, SHLIB_PIC, SHILB_MRELOCATABLE } shlib = SHLIB_NONE;
/* Flags to set in the elf header */
static flagword ppc_flags = 0;
/* Recognize -K PIC */
if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0)
{
- mrelocatable = true;
+ shlib = SHLIB_PIC;
ppc_flags |= EF_PPC_RELOCATABLE_LIB;
}
else
/* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */
else if (strcmp (arg, "relocatable") == 0)
{
- mrelocatable = true;
+ shlib = SHILB_MRELOCATABLE;
ppc_flags |= EF_PPC_RELOCATABLE;
}
else if (strcmp (arg, "relocatable-lib") == 0)
{
- mrelocatable = true;
+ shlib = SHILB_MRELOCATABLE;
ppc_flags |= EF_PPC_RELOCATABLE_LIB;
}
#ifdef OBJ_ELF
/* Parse @got, etc. and return the desired relocation. */
static bfd_reloc_code_real_type
-ppc_elf_suffix (str_p)
+ppc_elf_suffix (str_p, exp_p)
char **str_p;
+ expressionS *exp_p;
{
struct map_bfd {
char *string;
for (ptr = &mapping[0]; ptr->length > 0; ptr++)
if (ch == ptr->string[0] && len == ptr->length && memcmp (ident, ptr->string, ptr->length) == 0)
{
+ /* Now check for identifier@suffix+constant */
+ if (*str == '-' || *str == '+')
+ {
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
+
+ input_line_pointer = str;
+ expression (&new_exp);
+ if (new_exp.X_op == O_constant)
+ {
+ exp_p->X_add_number += new_exp.X_add_number;
+ str = input_line_pointer;
+ }
+
+ if (&input_line_pointer != str_p)
+ input_line_pointer = orig_line;
+ }
+
*str_p = str;
return ptr->reloc;
}
expression (&exp);
if (exp.X_op == O_symbol
&& *input_line_pointer == '@'
- && (reloc = ppc_elf_suffix (&input_line_pointer)) != BFD_RELOC_UNUSED)
+ && (reloc = ppc_elf_suffix (&input_line_pointer, &exp)) != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
int size = bfd_get_reloc_size (reloc_howto);
fixS *fixp;
segT seg;
{
- if (mrelocatable
- && !fixp->fx_done
- && !fixp->fx_pcrel
- && fixp->fx_r_type <= BFD_RELOC_UNUSED
- && fixp->fx_r_type != BFD_RELOC_16_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_32_BASEREL
- && fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
- && fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
- && fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
- && strcmp (segment_name (seg), ".got2") != 0
- && strcmp (segment_name (seg), ".dtors") != 0
- && strcmp (segment_name (seg), ".ctors") != 0
- && strcmp (segment_name (seg), ".fixup") != 0
- && strcmp (segment_name (seg), ".stab") != 0
- && strcmp (segment_name (seg), ".gcc_except_table") != 0
- && strcmp (segment_name (seg), ".ex_shared") != 0)
+ if (fixp->fx_done || fixp->fx_pcrel)
+ return;
+
+ switch (shlib)
{
- if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
- || fixp->fx_r_type != BFD_RELOC_CTOR)
+ case SHLIB_NONE:
+ case SHLIB_PIC:
+ return;
+
+ case SHILB_MRELOCATABLE:
+ if (fixp->fx_r_type <= BFD_RELOC_UNUSED
+ && fixp->fx_r_type != BFD_RELOC_16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
+ && fixp->fx_r_type != BFD_RELOC_32_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
+ && strcmp (segment_name (seg), ".got2") != 0
+ && strcmp (segment_name (seg), ".dtors") != 0
+ && strcmp (segment_name (seg), ".ctors") != 0
+ && strcmp (segment_name (seg), ".fixup") != 0
+ && strcmp (segment_name (seg), ".stab") != 0
+ && strcmp (segment_name (seg), ".gcc_except_table") != 0
+ && strcmp (segment_name (seg), ".ex_shared") != 0)
{
- as_bad_where (fixp->fx_file, fixp->fx_line,
- "Relocation cannot be done when using -mrelocatable");
+ if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
+ || fixp->fx_r_type != BFD_RELOC_CTOR)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Relocation cannot be done when using -mrelocatable");
+ }
}
+ return;
}
}
#endif /* OBJ_ELF */
/* Allow @HA, @L, @H on constants. */
char *orig_str = str;
- if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
+ if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
switch (reloc)
{
default:
(char *) NULL, 0);
}
#ifdef OBJ_ELF
- else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
+ else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
{
/* For the absoulte forms of branchs, convert the PC relative form back into
the absolute. */