Merge from (binutils-2.9.1 based) gnu/dist/gas.

This commit is contained in:
tv 2000-08-10 18:47:29 +00:00
parent 7e11855e83
commit d977b907c5
5 changed files with 413 additions and 18 deletions

View File

@ -34,7 +34,7 @@
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
@ -2960,8 +2960,10 @@ load_expression (targreg, exp, pbasereg, poffset, explicit_reloc)
/* XXX: Disable this .got minimizing optimization so that we can get
better instruction offset knowledge in the compiler. This happens
very infrequently anyway. */
if (1 || (!range_signed_32 (addend)
&& (alpha_noat_on || targreg == AXP_REG_AT)))
/* XXX: This causes addends to be added to ELF_LITERALs, which
do not yet work. Reverted for NetBSD. */
if (!range_signed_32 (addend)
&& (alpha_noat_on || targreg == AXP_REG_AT))
{
newtok[1] = *exp;
addend = 0;
@ -5610,11 +5612,7 @@ alpha_align (n, pfill, label, force)
if (n > 2
&& (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
{
static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
static char const nopunop[8] = {
0x1f, 0x04, 0xff, 0x47,
0x00, 0x00, 0xe0, 0x2f
};
static char const nop[4] = { 0x1f, 0x04, 0xff, 0x47 };
/* First, make sure we're on a four-byte boundary, in case
someone has been putting .byte values into the text
@ -5623,10 +5621,7 @@ alpha_align (n, pfill, label, force)
with proper alignment. */
if (alpha_current_align < 2)
frag_align (2, 0, 0);
if (alpha_current_align < 3)
frag_align_pattern (3, unop, sizeof unop, 0);
if (n > 3)
frag_align_pattern (n, nopunop, sizeof nopunop, 0);
frag_align_pattern (n, nop, sizeof nop, 0);
}
else
frag_align (n, 0, 0);

View File

@ -36,6 +36,10 @@
#include "elf/arm.h"
#endif
/* Parser fixup to handle complicated __GLOBAL_OFFSET_TABLE_ expressions */
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES)\
parse_cons_expression_arm(EXP)
/* Types of processor to assemble for. */
#define ARM_1 0x00000001
#define ARM_2 0x00000002
@ -95,12 +99,13 @@
static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
static int target_oabi = 0;
static boolean pic_code = false;
#if defined OBJ_COFF || defined OBJ_ELF
/* Flags stored in private area of BFD structure */
static boolean uses_apcs_26 = false;
static boolean support_interwork = false;
static boolean uses_apcs_float = false;
static boolean pic_code = false;
#endif
/* This array holds the chars that always start a comment. If the
@ -936,6 +941,10 @@ static void s_code PARAMS ((int));
static void s_force_thumb PARAMS ((int));
static void s_thumb_func PARAMS ((int));
static void s_thumb_set PARAMS ((int));
static void s_cons PARAMS ((int));
static void s_type PARAMS ((int));
static void s_weak PARAMS ((int));
static void s_size PARAMS ((int));
static void arm_s_text PARAMS ((int));
static void arm_s_data PARAMS ((int));
#ifdef OBJ_ELF
@ -970,7 +979,9 @@ CONST pseudo_typeS md_pseudo_table[] =
{ "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 },
#else
{ "word", cons, 4},
{ "word", s_cons, 4},
{ "type", s_type, 4},
{ "weak", s_weak, 4},
#endif
{ "extend", float_cons, 'x' },
{ "ldouble", float_cons, 'x' },
@ -5980,6 +5991,14 @@ tc_gen_reloc (section, fixp)
}
case BFD_RELOC_32:
if (pic_code && fixp->fx_pcrel == 0 && fixp->fx_addsy != NULL)
{
if (section == text_section)
code = BFD_RELOC_ARM_GOT32;
else
code = fixp->fx_r_type;
break;
}
if (fixp->fx_pcrel)
{
code = BFD_RELOC_32_PCREL;
@ -5987,6 +6006,11 @@ tc_gen_reloc (section, fixp)
}
case BFD_RELOC_ARM_PCREL_BRANCH:
if (pic_code)
{
code = BFD_RELOC_ARM_JMPSLOT;
break;
}
case BFD_RELOC_RVA:
case BFD_RELOC_THUMB_PCREL_BRANCH9:
case BFD_RELOC_THUMB_PCREL_BRANCH12:
@ -6030,6 +6054,12 @@ tc_gen_reloc (section, fixp)
fixp->fx_r_type);
return NULL;
case BFD_RELOC_ARM_GOTPC:
assert(fixp->fx_pcrel != 0);
code = fixp->fx_r_type;
code = BFD_RELOC_32_PCREL;
break;
default:
{
char * type;
@ -6779,11 +6809,9 @@ md_parse_option (c, arg)
}
break;
#if defined OBJ_ELF || defined OBJ_COFF
case 'k':
pic_code = 1;
break;
#endif
default:
return 0;
@ -7044,6 +7072,306 @@ arm_canonicalize_symbol_name (name)
return name;
}
/* Treat expressions starting __GLOBAL_OFFSET_TABLE_ + as special. Evaluate
* RHS first.
*
* XXX - This is a complete hack. No idea what the *right* way to do this
* is.
*
* This is probably no longer needed with gcc 2.8+
*/
void
parse_cons_expression_arm(exp)
expressionS *exp;
{
static const char* got = GLOBAL_OFFSET_TABLE_NAME;
static int strlen_got = 0;
static char* line_space = NULL; /* Horrible hack because I'm not sure that
free() is okay to call at the end of
this fn */
char *tmp_line_pointer;
char *eol_pointer;
char *rhs;
char *saved_line_pointer;
expressionS right;
char c;
symbolS *symbolP; /* points to symbol */
char *name; /* points to name of symbol */
segT segment;
if (strlen_got == 0)
strlen_got = strlen(got);
if (strncmp(input_line_pointer, got, strlen_got) != 0)
{
/* Not a GOT expression, proceed as normal. */
expression(exp);
return;
}
saved_line_pointer = input_line_pointer;
name = input_line_pointer;
c = get_symbol_end();
symbolP = symbol_find_or_make (name);
segment = S_GET_SEGMENT (symbolP);
if (segment == undefined_section)
{
exp->X_op = O_symbol;
exp->X_add_symbol = symbolP;
exp->X_add_number = 0;
}
*input_line_pointer = c;
SKIP_WHITESPACE();
if (*input_line_pointer == '+')
++input_line_pointer;
expression(&right);
input_line_pointer = saved_line_pointer + strlen_got;
SKIP_WHITESPACE();
if (*input_line_pointer != '+' && *input_line_pointer != '-')
{
/* Not an operator we can deal with. */
input_line_pointer = saved_line_pointer;
expression(exp);
return;
}
/* Shut your eyes - you don't want to see this bit.
* Build a buffer to hold a munged input line and
* hand that on to the generic expression parser.
*/
rhs = input_line_pointer + 1;
while (*input_line_pointer != '\n' && *input_line_pointer != '\0' &&
*input_line_pointer != ';')
input_line_pointer++;
eol_pointer = input_line_pointer;
if (line_space != NULL)
free (line_space);
input_line_pointer = line_space = malloc(eol_pointer -
saved_line_pointer + 3);
strncpy (input_line_pointer, saved_line_pointer, rhs - saved_line_pointer);
input_line_pointer[rhs - saved_line_pointer] = '\0';
strcat (input_line_pointer, "(");
strncat (input_line_pointer, rhs, eol_pointer - rhs);
input_line_pointer[eol_pointer - saved_line_pointer + 1] = 0;
strcat (input_line_pointer, ")");
/* Okay, you can open your eyes again now. */
expression(exp);
/* XXX - Hack to check whether any pointers are left referring to the
* line_space buffer
* Note: free() to be moved down here if this turns out to be safe.
*/
while(input_line_pointer > line_space)
{
input_line_pointer--;
input_line_pointer[0] = 'X';
}
*input_line_pointer = '\0';
/* Restore the input_line_pointer to point to where the caller expects it to be and exit. */
input_line_pointer = eol_pointer;
}
/*
* Called to deal with an expression part of an .word instruction
* i.e.
* .word <expression>
*
* This is an expression that could have a GOT reference of the form
* __GLOBAL_OFFSET_TABLE + . - (L2 + 4)
*
* This is something that the expression parser cannot handle
* We need to perform the . - (L2 + 4) part first as this resolves
* to an absolute.
*/
static void
s_cons(size)
int size;
{
#if 0
if (pic_code)
abort(); /* Whoops */
#endif
cons (size);
}
/*
* This fix_new is called by cons via TC_CONS_FIX_NEW
*
* We check the expression to see if it is of the form
* __GLOBAL_OFFSET_TABLE + ???
* If it is then this is a PC relative reference to the GOT.
* i.e.
* ldr sl, L1
* add sl, pc, sl
* L2:
* ...
* L1:
* .word __GLOBAL_OFFSET_TABLE + (. - (L2 + 4))
*
* In this case use a reloc type BFD_RELOC_ARM_GOTPC instead of the
* normal BFD_RELOC_{16,32,64}
*/
void
cons_fix_new_arm(frag, where, size, exp)
fragS *frag;
int where;
int size;
expressionS *exp;
{
bfd_reloc_code_real_type type;
int pcrel = 0;
/* Pick a reloc ...
*
* @@ Should look at CPU word size.
*/
switch (size)
{
case 2:
type = BFD_RELOC_16;
break;
case 4:
default:
type = BFD_RELOC_32;
break;
case 8:
type = BFD_RELOC_64;
break;
}
/* Look for possible GOTPC reloc */
/*
* Look for pic assembler and 'undef symbol + expr symbol' expression
* and a 32 bit size
*/
if (pic_code != 0 && size == 4 && exp->X_op == O_add
&& exp->X_add_symbol
&& S_GET_SEGMENT (exp->X_add_symbol) == undefined_section
&& exp->X_op_symbol
&& S_GET_SEGMENT (exp->X_op_symbol) == expr_section)
{
/*
* This could be it
* Is the primary symbol name "__GLOBAL_OFFSET_TABLE" ?
*/
if (strcmp (S_GET_NAME(exp->X_add_symbol),
GLOBAL_OFFSET_TABLE_NAME) == 0)
{
type = BFD_RELOC_ARM_GOTPC;
pcrel = 1;
}
}
fix_new_exp (frag, where, (int) size, exp, pcrel, type);
}
#define AUX_OBJECT 1
#define AUX_FUNCTION 2
static void
s_type(a)
int a;
{
/* Strip out the section name */
char *symbol_name, *symbol_name_end;
char *type_name, *type_name_end;
char c;
register symbolS *symbolP;
unsigned int len;
symbol_name = input_line_pointer;
c = get_symbol_end ();
symbol_name_end = input_line_pointer;
input_line_pointer++;
len = symbol_name_end - symbol_name;
SKIP_WHITESPACE ();
if (c == ',')
{
/* Allow some leeway here, as .type has used several different
characters at different times. `%' is the current favourite
and this is what gcc 2.8 outputs, but `@' is traditional on
other machines and there was a time when `#' got used by some
people. */
if (input_line_pointer[0] == '#' || input_line_pointer[0] == '@'
|| input_line_pointer[0] == '%')
++input_line_pointer;
if (strncmp (input_line_pointer, "object", 6) == 0)
{
symbolP = symbol_find_or_make (symbol_name);
S_SET_OTHER (symbolP, S_GET_OTHER(symbolP) | AUX_OBJECT);
input_line_pointer += 6;
}
else
if (strncmp (input_line_pointer, "function", 8) == 0)
{
symbolP = symbol_find_or_make (symbol_name);
S_SET_OTHER (symbolP, S_GET_OTHER(symbolP) | AUX_FUNCTION);
input_line_pointer += 8;
}
}
demand_empty_rest_of_line ();
}
#define BIND_WEAK 0x20
static void
s_weak(a)
int a;
{
char *name;
int c;
symbolS *symbolP;
do
{
name = input_line_pointer;
c = get_symbol_end ();
symbolP = symbol_find_or_make (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
S_SET_OTHER(symbolP, S_GET_OTHER(symbolP) | BIND_WEAK);
/*
* Anything declared weak becomes global.
* Not sure why but this is required to work with the netbsd linker
* The NetBSD assembler does this.
*/
if (c == ',')
{
input_line_pointer++;
SKIP_WHITESPACE ();
if (*input_line_pointer == '\n')
c = '\n';
}
}
while (c == ',');
demand_empty_rest_of_line ();
}
boolean
arm_validate_fix (fixP)
fixS * fixP;

View File

@ -178,6 +178,18 @@ void armelf_frob_symbol PARAMS ((symbolS *, int *));
#define LOCAL_LABEL_PREFIX '.'
#endif
extern boolean pic_code;
/* This expression evaluates to false if the relocation is for a local
object for which we still want to do the relocation at runtime.
True if we are willing to perform this relocation while building
the .o file.
If the reloc is against an externally visible symbol, then the
a.out assembler should not do the relocation if generating PIC */
#define obj_relocate_extern (!pic_code)
/* This expression evaluates to false if the relocation is for a local object
for which we still want to do the relocation at runtime. True if we
are willing to perform this relocation while building the .o file.
@ -207,5 +219,8 @@ void armelf_frob_symbol PARAMS ((symbolS *, int *));
#else
#define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
#endif
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES)\
parse_cons_expression_arm(EXP)
/* end of tc-arm.h */

View File

@ -143,7 +143,7 @@ const char extra_symbol_chars[] = "*%-(";
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */
#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (TE_LINUX) && !defined(TE_FreeBSD))
#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD))
/* Putting '/' here makes it impossible to use the divide operator.
However, we need it for compatibility with SVR4 systems. */
const char comment_chars[] = "#/";
@ -2789,6 +2789,7 @@ i386_displacement (disp_start, disp_end)
exp_seg = expression (exp);
#if !(defined(TE_NetBSD) && defined(OBJ_AOUT)) /* XXX */
#ifdef BFD_ASSEMBLER
/* We do this to make sure that the section symbol is in
the symbol table. We will ultimately change the relocation
@ -2803,6 +2804,7 @@ i386_displacement (disp_start, disp_end)
exp->X_op_symbol = GOT_symbol;
i.disp_reloc[this_operand] = BFD_RELOC_32;
}
#endif
#endif
SKIP_WHITESPACE ();
@ -3974,6 +3976,40 @@ md_apply_fix3 (fixP, valp, seg)
/* Fix a few things - the dynamic linker expects certain values here,
and we must not dissappoint it. */
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
if (fixP->fx_r_type == BFD_RELOC_32
&& GOT_symbol
&& fixP->fx_addsy == GOT_symbol)
{
fixP->fx_r_type = BFD_RELOC_386_GOTPC;
value += 1;
}
else if ((fixP->fx_r_type == BFD_RELOC_32)
&& aout_pic_flag
&& (fixP->fx_addsy != NULL)
&& ((fixP->fx_addsy->bsym->flags & BSF_GLOBAL) != 0))
{
if (!bfd_is_com_section(bfd_get_section(fixP->fx_addsy->bsym)))
value = fixP->fx_offset - bfd_asymbol_value(fixP->fx_addsy->bsym);
}
switch(fixP->fx_r_type) {
case BFD_RELOC_386_PLT32:
break;
case BFD_RELOC_386_GOT32:
value = fixP->fx_offset;
break;
case BFD_RELOC_386_GOTPC:
value -= (fixP->fx_where + fixP->fx_frag->fr_address + 1);
break;
case BFD_RELOC_386_GOTOFF:
value = fixP->fx_offset;
break;
default:
break;
}
#endif
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& fixP->fx_addsy)
@ -4196,7 +4232,7 @@ parse_register (reg_string, end_op)
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
CONST char *md_shortopts = "kmVQ:sq";
#else
CONST char *md_shortopts = "m";
CONST char *md_shortopts = "mkK";
#endif
struct option md_longopts[] = {
{NULL, no_argument, NULL, 0}
@ -4239,6 +4275,12 @@ md_parse_option (c, arg)
fewer checks. */
break;
#endif
#ifdef OBJ_AOUT
case 'k':
case 'K':
aout_pic_flag = 1;
break;
#endif
default:
return 0;
@ -4393,6 +4435,17 @@ tc_gen_reloc (section, fixp)
switch (fixp->fx_r_type)
{
case BFD_RELOC_386_PLT32:
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
/* XXX */
if (fixp->fx_addsy != NULL)
{
asection *sec;
sec = bfd_get_section (fixp->fx_addsy->bsym);
if (strcmp(sec->name, ".text") == 0)
return 0;
}
#endif
/* FALLTHROUGH */
case BFD_RELOC_386_GOT32:
case BFD_RELOC_386_GOTOFF:
case BFD_RELOC_386_GOTPC:

View File

@ -426,8 +426,12 @@ sib_byte;
/* The name of the global offset table generated by the compiler. Allow
this to be overridden if need be. */
#ifndef GLOBAL_OFFSET_TABLE_NAME
#if defined(TE_NetBSD) && defined(OBJ_AOUT)
#define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
#else
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
#endif
#endif
#ifdef BFD_ASSEMBLER
void i386_validate_fix PARAMS ((struct fix *));