Fix Label1 - Label2 relocartions for ELF targets

This commit is contained in:
Nick Clifton
1999-02-09 15:49:01 +00:00
parent 8aad4bd619
commit b8d4b00e93
2 changed files with 337 additions and 359 deletions

View File

@ -1,3 +1,8 @@
1999-02-09 Nick Clifton <nickc@cygnus.com>
* config/tc-arm.c (md_apply_fix3): Fix handling of label1 - label2
relocations for ELF targets.
1999-02-08 Nick Clifton <nickc@cygnus.com> 1999-02-08 Nick Clifton <nickc@cygnus.com>
* configure.in: Add support for StrongARM target. * configure.in: Add support for StrongARM target.

View File

@ -36,14 +36,6 @@
#include "elf/arm.h" #include "elf/arm.h"
#endif #endif
/* ??? This is currently unused. */
#ifdef __STDC__
#define internalError() \
as_fatal (_("ARM Internal Error, line %d, %s"), __LINE__, __FILE__)
#else
#define internalError() as_fatal (_("ARM Internal Error"))
#endif
/* Types of processor to assemble for. */ /* Types of processor to assemble for. */
#define ARM_1 0x00000001 #define ARM_1 0x00000001
#define ARM_2 0x00000002 #define ARM_2 0x00000002
@ -751,8 +743,7 @@ struct thumb_opcode
CONST char * template; /* Basic string to match */ CONST char * template; /* Basic string to match */
unsigned long value; /* Basic instruction code */ unsigned long value; /* Basic instruction code */
int size; int size;
/* Function to call to parse args */ void (* parms) PARAMS ((char *)); /* Function to call to parse args */
void (*parms) PARAMS ((char *));
}; };
static CONST struct thumb_opcode tinsns[] = static CONST struct thumb_opcode tinsns[] =
@ -975,7 +966,7 @@ add_to_lit_pool ()
} }
/* Can't use symbol_new here, so have to create a symbol and then at /* Can't use symbol_new here, so have to create a symbol and then at
a later date assign it a value. Thats what these functions do */ a later date assign it a value. Thats what these functions do. */
static void static void
symbol_locate (symbolP, name, segment, valu, frag) symbol_locate (symbolP, name, segment, valu, frag)
symbolS * symbolP; symbolS * symbolP;
@ -1008,9 +999,7 @@ symbol_locate (symbolP, name, segment, valu, frag)
symbolP->sy_frag = frag; symbolP->sy_frag = frag;
/* /* Link to end of symbol chain. */
* Link to end of symbol chain.
*/
{ {
extern int symbol_table_frozen; extern int symbol_table_frozen;
if (symbol_table_frozen) if (symbol_table_frozen)
@ -1099,7 +1088,9 @@ s_even (ignore)
{ {
if (!need_pass_2) /* Never make frag if expect extra pass. */ if (!need_pass_2) /* Never make frag if expect extra pass. */
frag_align (1, 0, 0); frag_align (1, 0, 0);
record_alignment (now_seg, 1); record_alignment (now_seg, 1);
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
} }
@ -1135,6 +1126,7 @@ s_ltorg (internal)
symbol_table_insert (current_poolP); symbol_table_insert (current_poolP);
ARM_SET_THUMB (current_poolP, thumb_mode); ARM_SET_THUMB (current_poolP, thumb_mode);
#if defined OBJ_COFF || defined OBJ_ELF #if defined OBJ_COFF || defined OBJ_ELF
ARM_SET_INTERWORK (current_poolP, support_interwork); ARM_SET_INTERWORK (current_poolP, support_interwork);
#endif #endif
@ -1147,20 +1139,6 @@ s_ltorg (internal)
current_poolP = NULL; current_poolP = NULL;
} }
#if 0 /* not used */
static void
arm_align (power, fill)
int power;
int fill;
{
/* Only make a frag if we HAVE to ... */
if (power && !need_pass_2)
frag_align (power, fill, 0);
record_alignment (now_seg, power);
}
#endif
static void static void
s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */ s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
int unused; int unused;
@ -1962,7 +1940,8 @@ my_get_float_expression (str)
LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE words[MAX_LITTLENUMS];
char * save_in; char * save_in;
expressionS exp; expressionS exp;
int i, j; int i;
int j;
memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE)); memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
/* Look for a raw floating point number */ /* Look for a raw floating point number */
@ -4953,8 +4932,8 @@ md_atof (type, litP, sizeP)
return 0; return 0;
} }
/* We have already put the pipeline compensation in the instruction */ /* The knowledge of the PC's pipeline offset is built into the relocs
for the ELF port and into the insns themselves for the COFF port. */
long long
md_pcrel_from (fixP) md_pcrel_from (fixP)
fixS * fixP; fixS * fixP;
@ -4962,7 +4941,7 @@ md_pcrel_from (fixP)
if ( fixP->fx_addsy if ( fixP->fx_addsy
&& S_GET_SEGMENT (fixP->fx_addsy) == undefined_section && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
&& fixP->fx_subsy == NULL) && fixP->fx_subsy == NULL)
return 0; /* HACK */ return 0;
if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD)) if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
{ {
@ -5048,7 +5027,8 @@ arm_psr_parse (ccp)
register char ** ccp; register char ** ccp;
{ {
char * start = * ccp; char * start = * ccp;
char c, *p; char c;
char * p;
CONST struct asm_psr * psr; CONST struct asm_psr * psr;
p = start; p = start;
@ -5238,20 +5218,15 @@ md_apply_fix3 (fixP, val, seg)
break; break;
case BFD_RELOC_ARM_PCREL_BRANCH: case BFD_RELOC_ARM_PCREL_BRANCH:
newval = md_chars_to_number (buf, INSN_SIZE);
#ifdef OBJ_ELF #ifdef OBJ_ELF
if (target_oabi) newval &= 0xff000000;
value = (value >> 2) & 0x00ffffff; if (! target_oabi)
else
value = fixP->fx_offset; value = fixP->fx_offset;
else
#else #else
value = (value >> 2) & 0x00ffffff; value = (value >> 2) & 0x00ffffff;
#endif #endif
newval = md_chars_to_number (buf, INSN_SIZE);
#ifdef OBJ_ELF
if (!target_oabi)
newval = (newval & 0xff000000);
#endif
newval = (newval & 0xff000000);
value = (value + (newval & 0x00ffffff)) & 0x00ffffff; value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
newval = value | (newval & 0xff000000); newval = value | (newval & 0xff000000);
md_number_to_chars (buf, newval, INSN_SIZE); md_number_to_chars (buf, newval, INSN_SIZE);
@ -5337,17 +5312,14 @@ md_apply_fix3 (fixP, val, seg)
case BFD_RELOC_RVA: case BFD_RELOC_RVA:
case BFD_RELOC_32: case BFD_RELOC_32:
#ifndef OBJ_ELF
if (fixP->fx_done || fixP->fx_pcrel) if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 4); md_number_to_chars (buf, value, 4);
#else #ifdef OBJ_ELF
if (!target_oabi) else if (!target_oabi)
{ {
value = fixP->fx_offset; value = fixP->fx_offset;
md_number_to_chars (buf, value, 4); md_number_to_chars (buf, value, 4);
} }
else if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 4);
#endif #endif
break; break;
@ -5647,7 +5619,7 @@ md_estimate_size_before_relax (fragP, segtype)
segT segtype; segT segtype;
{ {
as_fatal (_("md_estimate_size_before_relax\n")); as_fatal (_("md_estimate_size_before_relax\n"));
return (1); return 1;
} }
static void static void
@ -5685,14 +5657,16 @@ md_assemble (str)
char * str; char * str;
{ {
char c; char c;
char *p, *q, *start; char * p;
char * q;
char * start;
/* Align the instruction */ /* Align the instruction.
/* this may not be the right thing to do but ... */ This may not be the right thing to do but ... */
/* arm_align (2, 0); */ /* arm_align (2, 0); */
listing_prev_line (); /* Defined in listing.h */ listing_prev_line (); /* Defined in listing.h */
/* Align the previous label if needed */ /* Align the previous label if needed. */
if (last_label_seen != NULL) if (last_label_seen != NULL)
{ {
last_label_seen->sy_frag = frag_now; last_label_seen->sy_frag = frag_now;
@ -5706,8 +5680,8 @@ md_assemble (str)
if (*str == ' ') if (*str == ' ')
str++; /* Skip leading white space */ str++; /* Skip leading white space */
/* scan up to the end of the op-code, which must end in white space or /* Scan up to the end of the op-code, which must end in white space or
end of string */ end of string. */
for (start = p = str; *p != '\0'; p++) for (start = p = str; *p != '\0'; p++)
if (*p == ' ') if (*p == ' ')
break; break;
@ -5958,6 +5932,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
* -mapcs-float Pass floats in float regs * -mapcs-float Pass floats in float regs
* -mapcs-reentrant Position independent code * -mapcs-reentrant Position independent code
* -mthumb-interwork Code supports Arm/Thumb interworking * -mthumb-interwork Code supports Arm/Thumb interworking
* -moabi Old ELF ABI
*/ */
CONST char * md_shortopts = "m:"; CONST char * md_shortopts = "m:";
@ -6014,10 +5989,12 @@ md_parse_option (c, arg)
cpu_variant &= ~FPU_ALL; cpu_variant &= ~FPU_ALL;
break; break;
#ifdef OBJ_ELF
case 'o': case 'o':
if (!strcmp (str, "oabi")) if (!strcmp (str, "oabi"))
target_oabi = true; target_oabi = true;
break; break;
#endif
case 't': case 't':
/* Limit assembler to generating only Thumb instructions: */ /* Limit assembler to generating only Thumb instructions: */
@ -6283,6 +6260,11 @@ _("\
_("\ _("\
-mapcs-reentrant the code is position independent/reentrant\n")); -mapcs-reentrant the code is position independent/reentrant\n"));
#endif #endif
#ifdef OBJ_ELF
fprintf (fp,
_("\
-moabi support the old ELF ABI\n"));
#endif
#ifdef ARM_BI_ENDIAN #ifdef ARM_BI_ENDIAN
fprintf (fp, fprintf (fp,
_("\ _("\
@ -6358,7 +6340,9 @@ arm_frob_label (sym)
symbolS * sym; symbolS * sym;
{ {
last_label_seen = sym; last_label_seen = sym;
ARM_SET_THUMB (sym, thumb_mode); ARM_SET_THUMB (sym, thumb_mode);
#if defined OBJ_COFF || defined OBJ_ELF #if defined OBJ_COFF || defined OBJ_ELF
ARM_SET_INTERWORK (sym, support_interwork); ARM_SET_INTERWORK (sym, support_interwork);
#endif #endif
@ -6379,10 +6363,6 @@ arm_frob_label (sym)
/* Adjust the symbol table. This marks Thumb symbols as distinct from /* Adjust the symbol table. This marks Thumb symbols as distinct from
ARM ones. */ ARM ones. */
#ifdef OBJ_ELF
#define S_GET_STORAGE_CLASS(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_info)
#define S_SET_STORAGE_CLASS(S,V) (elf_symbol ((S)->bsym)->internal_elf_sym.st_info = (V))
#endif
void void
arm_adjust_symtab () arm_adjust_symtab ()
{ {
@ -6403,7 +6383,8 @@ arm_adjust_symtab ()
else if (S_GET_STORAGE_CLASS (sym) == C_EXT) else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC); S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
else else
as_bad (_("%s: unexpected function type: %d"), S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym)); as_bad (_("%s: unexpected function type: %d"),
S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
} }
else switch (S_GET_STORAGE_CLASS (sym)) else switch (S_GET_STORAGE_CLASS (sym))
{ {
@ -6425,11 +6406,7 @@ arm_adjust_symtab ()
coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF; coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF;
} }
#endif #endif
}
#ifdef OBJ_ELF #ifdef OBJ_ELF
void
armelf_adjust_symtab ()
{
symbolS * sym; symbolS * sym;
elf_symbol_type * elf_sym; elf_symbol_type * elf_sym;
char bind; char bind;
@ -6444,24 +6421,11 @@ armelf_adjust_symtab ()
bind = ELF_ST_BIND (elf_sym); bind = ELF_ST_BIND (elf_sym);
elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC); elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC);
} }
} }
} }
}
#endif
#ifdef OBJ_ELF
void
armelf_frob_symbol (symp, puntp)
symbolS *symp;
int *puntp;
{
elf_frob_symbol (symp, puntp);
}
#endif #endif
}
int int
arm_data_in_code () arm_data_in_code ()
{ {
@ -6472,6 +6436,7 @@ arm_data_in_code ()
*input_line_pointer = 0; *input_line_pointer = 0;
return 1; return 1;
} }
return 0; return 0;
} }
@ -6489,62 +6454,6 @@ arm_canonicalize_symbol_name (name)
return name; return name;
} }
#ifdef OBJ_ELF
/* Relocations against Thumb function names must be left unadjusted,
so that the linker can use this information to correctly set the
bottom bit of their addresses. The MIPS version of this function
also prevents relocations that are mips-16 specific, but I do not
know why it does this.
FIXME:
There is one other problem that ought to be addressed here, but
which currently is not: Taking the address of a label (rather
than a function) and then later jumping to that address. Such
address also ought to have their bottom bit set (assuming that
they reside in Thumb code), but at the moment they will not. */
boolean
arm_fix_adjustable (fixP)
fixS *fixP;
{
if (fixP->fx_addsy == NULL)
return 1;
/* Prevent all adjustments to global symbols. */
if (S_IS_EXTERN (fixP->fx_addsy))
return 0;
if (S_IS_WEAK (fixP->fx_addsy))
return 0;
if (THUMB_IS_FUNC (fixP->fx_addsy)
&& fixP->fx_subsy == NULL)
return 0;
/* We need the symbol name for the VTABLE entries */
if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0;
return 1;
}
#endif /* OBJ_ELF */
#ifdef OBJ_ELF
int
elf32_arm_force_relocation (fixp)
struct fix *fixp;
{
if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 1;
if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
return 1;
return 0;
}
#endif
boolean boolean
arm_validate_fix (fixP) arm_validate_fix (fixP)
@ -6566,6 +6475,47 @@ arm_validate_fix (fixP)
return false; return false;
} }
#ifdef OBJ_ELF
/* Relocations against Thumb function names must be left unadjusted,
so that the linker can use this information to correctly set the
bottom bit of their addresses. The MIPS version of this function
also prevents relocations that are mips-16 specific, but I do not
know why it does this.
FIXME:
There is one other problem that ought to be addressed here, but
which currently is not: Taking the address of a label (rather
than a function) and then later jumping to that address. Such
addresses also ought to have their bottom bit set (assuming that
they reside in Thumb code), but at the moment they will not. */
boolean
arm_fix_adjustable (fixP)
fixS * fixP;
{
if (fixP->fx_addsy == NULL)
return 1;
/* Prevent all adjustments to global symbols. */
if (S_IS_EXTERN (fixP->fx_addsy))
return 0;
if (S_IS_WEAK (fixP->fx_addsy))
return 0;
if (THUMB_IS_FUNC (fixP->fx_addsy)
&& fixP->fx_subsy == NULL)
return 0;
/* We need the symbol name for the VTABLE entries */
if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0;
return 1;
}
const char * const char *
elf32_arm_target_format () elf32_arm_target_format ()
{ {
@ -6580,3 +6530,26 @@ elf32_arm_target_format ()
else else
return "elf32-littlearm"; return "elf32-littlearm";
} }
void
armelf_frob_symbol (symp, puntp)
symbolS * symp;
int * puntp;
{
elf_frob_symbol (symp, puntp);
}
int
arm_force_relocation (fixp)
struct fix * fixp;
{
if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
return 1;
return 0;
}
#endif /* OBJ_ELF */