Better reloc support
This commit is contained in:
parent
cc47d19a93
commit
4ecbc1efea
@ -1,3 +1,12 @@
|
||||
Mon Sep 25 16:08:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* config/tc-ppc.c (ppc_elf_suffix): Lower case reloc before
|
||||
testing.
|
||||
(md_assemble): Be more robust in terms of relocations.
|
||||
(md_apply_fix3): Allow 14 bit relocs to be emitted for external
|
||||
symbols in addition to 26 bit relocs. Properly insert 26/14 bit
|
||||
reloc value fields into the instruction stream.
|
||||
|
||||
Mon Sep 25 00:23:16 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* config/tc-arm.c (md_atof): Output little endian constants in
|
||||
|
@ -560,26 +560,21 @@ ppc_elf_suffix (str_p)
|
||||
bfd_reloc_code_real_type reloc;
|
||||
};
|
||||
|
||||
char ident[20];
|
||||
char *str = *str_p;
|
||||
char *str2;
|
||||
int ch;
|
||||
int len;
|
||||
struct map_bfd *ptr;
|
||||
|
||||
static struct map_bfd mapping[] = {
|
||||
{ "GOT", 3, BFD_RELOC_PPC_TOC16 },
|
||||
{ "got", 3, BFD_RELOC_PPC_TOC16 },
|
||||
{ "L", 1, BFD_RELOC_LO16 },
|
||||
{ "l", 1, BFD_RELOC_LO16 },
|
||||
{ "HA", 2, BFD_RELOC_HI16_S },
|
||||
{ "ha", 2, BFD_RELOC_HI16_S },
|
||||
{ "H", 1, BFD_RELOC_HI16 },
|
||||
{ "h", 1, BFD_RELOC_HI16 },
|
||||
{ "SDAREL", 6, BFD_RELOC_GPREL16 },
|
||||
{ "sdarel", 6, BFD_RELOC_GPREL16 },
|
||||
{ "FIXUP", 5, BFD_RELOC_CTOR }, /* synonym for BFD_RELOC_32 that doesn't get */
|
||||
{ "fixup", 5, BFD_RELOC_CTOR }, /* warnings with -mrelocatable */
|
||||
{ "BRTAKEN", 7, BFD_RELOC_PPC_B16_BRTAKEN },
|
||||
{ "brtaken", 7, BFD_RELOC_PPC_B16_BRTAKEN },
|
||||
{ "BRNTAKEN", 8, BFD_RELOC_PPC_B16_BRNTAKEN },
|
||||
{ "brntaken", 8, BFD_RELOC_PPC_B16_BRNTAKEN },
|
||||
{ (char *)0, 0, BFD_RELOC_UNUSED }
|
||||
};
|
||||
@ -587,11 +582,17 @@ ppc_elf_suffix (str_p)
|
||||
if (*str++ != '@')
|
||||
return BFD_RELOC_UNUSED;
|
||||
|
||||
ch = *str;
|
||||
for (ch = *str, str2 = ident; str2 < ident + sizeof(ident) - 1 && isalpha (ch); ch = *++str)
|
||||
*str2++ = (islower (ch)) ? ch : tolower (ch);
|
||||
|
||||
*str2 = '\0';
|
||||
len = str2 - ident;
|
||||
|
||||
ch = ident[0];
|
||||
for (ptr = &mapping[0]; ptr->length > 0; ptr++)
|
||||
if (ch == ptr->string[0] && strncmp (str, ptr->string, ptr->length) == 0)
|
||||
if (ch == ptr->string[0] && len == ptr->length && memcmp (ident, ptr->string, ptr->length) == 0)
|
||||
{
|
||||
*str_p = str + ptr->length;
|
||||
*str_p = str;
|
||||
return ptr->reloc;
|
||||
}
|
||||
|
||||
@ -935,15 +936,21 @@ md_assemble (str)
|
||||
if (fixups[i].reloc != BFD_RELOC_UNUSED)
|
||||
{
|
||||
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
|
||||
int size = (!reloc_howto) ? 0 : bfd_get_reloc_size (reloc_howto);
|
||||
int offset = target_big_endian ? (4 - size) : 0;
|
||||
int size;
|
||||
int offset;
|
||||
fixS *fixP;
|
||||
|
||||
if (size > 4)
|
||||
if (!reloc_howto)
|
||||
abort ();
|
||||
|
||||
size = bfd_get_reloc_size (reloc_howto);
|
||||
offset = target_big_endian ? (4 - size) : 0;
|
||||
|
||||
if (size < 1 || size > 4)
|
||||
abort();
|
||||
|
||||
fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
|
||||
&fixups[i].exp, (reloc_howto && reloc_howto->pc_relative),
|
||||
&fixups[i].exp, reloc_howto->pc_relative,
|
||||
fixups[i].reloc);
|
||||
|
||||
/* Turn off complaints that the addend is too large for things like
|
||||
@ -2642,6 +2649,9 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
segT seg;
|
||||
{
|
||||
valueT value;
|
||||
char *where;
|
||||
unsigned long insn;
|
||||
unsigned long mask;
|
||||
|
||||
/* FIXME FIXME FIXME: The value we are passed in *valuep includes
|
||||
the symbol values. Since we are using BFD_ASSEMBLER, if we are
|
||||
@ -2681,8 +2691,6 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
{
|
||||
int opindex;
|
||||
const struct powerpc_operand *operand;
|
||||
char *where;
|
||||
unsigned long insn;
|
||||
|
||||
opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
|
||||
|
||||
@ -2735,17 +2743,24 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
We are only prepared to turn a few of the operands into
|
||||
relocs.
|
||||
FIXME: We need to handle the DS field at the very least.
|
||||
FIXME: Handling 16 bit branches would also be reasonable.
|
||||
FIXME: Selecting the reloc type is a bit haphazard; perhaps
|
||||
there should be a new field in the operand table. */
|
||||
if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
|
||||
&& operand->bits == 26
|
||||
&& operand->shift == 0)
|
||||
fixp->fx_r_type = BFD_RELOC_PPC_B26;
|
||||
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
|
||||
&& operand->bits == 16
|
||||
&& operand->shift == 0)
|
||||
fixp->fx_r_type = BFD_RELOC_PPC_B16;
|
||||
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
||||
&& operand->bits == 26
|
||||
&& operand->shift == 0)
|
||||
fixp->fx_r_type = BFD_RELOC_PPC_BA26;
|
||||
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
|
||||
&& operand->bits == 26
|
||||
&& operand->shift == 0)
|
||||
fixp->fx_r_type = BFD_RELOC_PPC_BA16;
|
||||
else if ((operand->flags & PPC_OPERAND_PARENS) != 0
|
||||
&& operand->bits == 16
|
||||
&& operand->shift == 0
|
||||
@ -2771,6 +2786,7 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
#ifdef OBJ_ELF
|
||||
ppc_elf_validate_fix (fixp, seg);
|
||||
#endif
|
||||
mask = 0;
|
||||
switch (fixp->fx_r_type)
|
||||
{
|
||||
case BFD_RELOC_32:
|
||||
@ -2795,24 +2811,52 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
if (fixp->fx_pcrel)
|
||||
abort ();
|
||||
|
||||
case BFD_RELOC_PPC_B16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
||||
value <<= 2;
|
||||
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
|
||||
value, 2);
|
||||
mask = 0xffff;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_8:
|
||||
if (fixp->fx_pcrel)
|
||||
abort ();
|
||||
|
||||
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
|
||||
value, 1);
|
||||
mask = 0xff;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_B16:
|
||||
case BFD_RELOC_PPC_B16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
||||
case BFD_RELOC_PPC_BA16:
|
||||
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
||||
mask = 0xfffc;
|
||||
break;
|
||||
|
||||
case BFD_RELOC_PPC_B26:
|
||||
case BFD_RELOC_PPC_BA26:
|
||||
mask = 0x3fffffc;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Fetch the instruction, insert the fully resolved operand
|
||||
value, and stuff the instruction back again. */
|
||||
if (mask != 0)
|
||||
{
|
||||
where = fixp->fx_frag->fr_literal + fixp->fx_where;
|
||||
if (target_big_endian)
|
||||
insn = bfd_getb32 ((unsigned char *) where);
|
||||
else
|
||||
insn = bfd_getl32 ((unsigned char *) where);
|
||||
|
||||
insn = (insn & ~mask) | (value & mask);
|
||||
|
||||
if (target_big_endian)
|
||||
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
|
||||
else
|
||||
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
|
Loading…
Reference in New Issue
Block a user