mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 18:44:20 +08:00
Support for @GOTOFF in .long expressions.
This commit is contained in:
parent
bf62e5b49c
commit
f3c180aedc
@ -1,3 +1,19 @@
|
||||
2001-03-13 Alan Modra <alan@linuxcare.com.au>
|
||||
|
||||
* config/tc-i386.c (RELOC_ENUM): Define. Use throughout file.
|
||||
(NUM_FLAG_CODE): Define.
|
||||
(lex_got): New function.
|
||||
(got_reloc): New global var.
|
||||
(x86_cons_fix_new): New function.
|
||||
(x86_cons): New function.
|
||||
(i386_immediate): Use lex_got here, replacing inline code. Change
|
||||
"ignoring junk.." error message to "junk.."
|
||||
(i386_displacement): Likewise.
|
||||
* config/tc-i386.h (TC_PARSE_CONS_EXPRESSION): Define.
|
||||
(x86_cons): Declare.
|
||||
(TC_CONS_FIX_NEW): Define.
|
||||
(x86_cons_fix_new): Declare.
|
||||
|
||||
2001-03-12 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* config/tc-arm.c (md_begin): Always set machine type based on
|
||||
@ -6,10 +22,10 @@
|
||||
2001-03-07 Alan Modra <alan@linuxcare.com.au>
|
||||
|
||||
* config/tc-i386.c (struct _i386_insn): Rename disp_reloc to reloc.
|
||||
(md_assemble [smallest displacement]): Use correct field of i.op[]
|
||||
(md_assemble) <smallest displacement>: Use correct field of i.op[]
|
||||
union.
|
||||
(md_assemble [JumpInterSegment output]): Use correct i.disp_reloc[].
|
||||
(md_assemble [immediate output]): Likewise.
|
||||
<JumpInterSegment output>: Use correct i.disp_reloc[].
|
||||
<immediate output>: Likewise.
|
||||
|
||||
2001-03-06 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
|
@ -70,6 +70,9 @@ static void set_cpu_arch PARAMS ((int));
|
||||
#ifdef BFD_ASSEMBLER
|
||||
static bfd_reloc_code_real_type reloc
|
||||
PARAMS ((int, int, int, bfd_reloc_code_real_type));
|
||||
#define RELOC_ENUM enum bfd_reloc_code_real
|
||||
#else
|
||||
#define RELOC_ENUM int
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ARCH
|
||||
@ -117,11 +120,7 @@ struct _i386_insn
|
||||
#define Operand_PCrel 1
|
||||
|
||||
/* Relocation type for operand */
|
||||
#ifdef BFD_ASSEMBLER
|
||||
enum bfd_reloc_code_real reloc[MAX_OPERANDS];
|
||||
#else
|
||||
int reloc[MAX_OPERANDS];
|
||||
#endif
|
||||
RELOC_ENUM reloc[MAX_OPERANDS];
|
||||
|
||||
/* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
|
||||
the base index byte below. */
|
||||
@ -241,6 +240,7 @@ enum flag_code {
|
||||
CODE_32BIT,
|
||||
CODE_16BIT,
|
||||
CODE_64BIT };
|
||||
#define NUM_FLAG_CODE ((int) CODE_64BIT + 1)
|
||||
|
||||
static enum flag_code flag_code;
|
||||
static int use_rela_relocations = 0;
|
||||
@ -1546,11 +1546,7 @@ md_assemble (line)
|
||||
{
|
||||
union i386_op temp_op;
|
||||
unsigned int temp_type;
|
||||
#ifdef BFD_ASSEMBLER
|
||||
enum bfd_reloc_code_real temp_reloc;
|
||||
#else
|
||||
int temp_reloc;
|
||||
#endif
|
||||
RELOC_ENUM temp_reloc;
|
||||
int xchg1 = 0;
|
||||
int xchg2 = 0;
|
||||
|
||||
@ -3068,11 +3064,7 @@ md_assemble (line)
|
||||
Need a 32-bit fixup (don't support 8bit
|
||||
non-absolute imms). Try to support other
|
||||
sizes ... */
|
||||
#ifdef BFD_ASSEMBLER
|
||||
enum bfd_reloc_code_real reloc_type;
|
||||
#else
|
||||
int reloc_type;
|
||||
#endif
|
||||
RELOC_ENUM reloc_type;
|
||||
int size = 4;
|
||||
int sign = 0;
|
||||
|
||||
@ -3127,6 +3119,130 @@ md_assemble (line)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef LEX_AT
|
||||
static char *lex_got PARAMS ((RELOC_ENUM *, int *));
|
||||
|
||||
/* Parse operands of the form
|
||||
<symbol>@GOTOFF+<nnn>
|
||||
and similar .plt or .got references.
|
||||
|
||||
If we find one, set up the correct relocation in RELOC and copy the
|
||||
input string, minus the `@GOTOFF' into a malloc'd buffer for
|
||||
parsing by the calling routine. Return this buffer, and if ADJUST
|
||||
is non-null set it to the length of the string we removed from the
|
||||
input line. Otherwise return NULL. */
|
||||
static char *
|
||||
lex_got (reloc, adjust)
|
||||
RELOC_ENUM *reloc;
|
||||
int *adjust;
|
||||
{
|
||||
static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" };
|
||||
static const struct {
|
||||
const char *str;
|
||||
const RELOC_ENUM rel[NUM_FLAG_CODE];
|
||||
} gotrel[] = {
|
||||
{ "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } },
|
||||
{ "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } },
|
||||
{ "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } },
|
||||
{ "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } }
|
||||
};
|
||||
char *cp;
|
||||
unsigned int j;
|
||||
|
||||
for (cp = input_line_pointer; *cp != '@'; cp++)
|
||||
if (is_end_of_line[(unsigned char) *cp])
|
||||
return NULL;
|
||||
|
||||
for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen (gotrel[j].str);
|
||||
if (strncmp (cp + 1, gotrel[j].str, len) == 0)
|
||||
{
|
||||
if (gotrel[j].rel[(unsigned int) flag_code] != 0)
|
||||
{
|
||||
int first;
|
||||
char *tmpbuf;
|
||||
|
||||
*reloc = gotrel[j].rel[(unsigned int) flag_code];
|
||||
|
||||
if (GOT_symbol == NULL)
|
||||
GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
|
||||
|
||||
/* Replace the relocation token with ' ', so that
|
||||
errors like foo@GOTOFF1 will be detected. */
|
||||
first = cp - input_line_pointer;
|
||||
tmpbuf = xmalloc (strlen (input_line_pointer));
|
||||
memcpy (tmpbuf, input_line_pointer, first);
|
||||
tmpbuf[first] = ' ';
|
||||
strcpy (tmpbuf + first + 1, cp + 1 + len);
|
||||
if (adjust)
|
||||
*adjust = len;
|
||||
return tmpbuf;
|
||||
}
|
||||
|
||||
as_bad (_("@%s reloc is not supported in %s bit mode"),
|
||||
gotrel[j].str, mode_name[(unsigned int) flag_code]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Might be a symbol version string. Don't as_bad here. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* x86_cons_fix_new is called via the expression parsing code when a
|
||||
reloc is needed. We use this hook to get the correct .got reloc. */
|
||||
static RELOC_ENUM got_reloc = NO_RELOC;
|
||||
|
||||
void
|
||||
x86_cons_fix_new (frag, off, len, exp)
|
||||
fragS *frag;
|
||||
unsigned int off;
|
||||
unsigned int len;
|
||||
expressionS *exp;
|
||||
{
|
||||
RELOC_ENUM r = reloc (len, 0, 0, got_reloc);
|
||||
got_reloc = NO_RELOC;
|
||||
fix_new_exp (frag, off, len, exp, 0, r);
|
||||
}
|
||||
|
||||
void
|
||||
x86_cons (exp, size)
|
||||
expressionS *exp;
|
||||
int size;
|
||||
{
|
||||
if (size == 4)
|
||||
{
|
||||
/* Handle @GOTOFF and the like in an expression. */
|
||||
char *save;
|
||||
char *gotfree_input_line;
|
||||
int adjust;
|
||||
|
||||
save = input_line_pointer;
|
||||
gotfree_input_line = lex_got (&got_reloc, &adjust);
|
||||
if (gotfree_input_line)
|
||||
input_line_pointer = gotfree_input_line;
|
||||
|
||||
expression (exp);
|
||||
|
||||
if (gotfree_input_line)
|
||||
{
|
||||
/* expression () has merrily parsed up to the end of line,
|
||||
or a comma - in the wrong buffer. Transfer how far
|
||||
input_line_pointer has moved to the right buffer. */
|
||||
input_line_pointer = (save
|
||||
+ (input_line_pointer - gotfree_input_line)
|
||||
+ adjust);
|
||||
free (gotfree_input_line);
|
||||
}
|
||||
}
|
||||
else
|
||||
expression (exp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int i386_immediate PARAMS ((char *));
|
||||
|
||||
static int
|
||||
@ -3134,6 +3250,9 @@ i386_immediate (imm_start)
|
||||
char *imm_start;
|
||||
{
|
||||
char *save_input_line_pointer;
|
||||
#ifndef LEX_AT
|
||||
char *gotfree_input_line;
|
||||
#endif
|
||||
segT exp_seg = 0;
|
||||
expressionS *exp;
|
||||
|
||||
@ -3153,80 +3272,22 @@ i386_immediate (imm_start)
|
||||
input_line_pointer = imm_start;
|
||||
|
||||
#ifndef LEX_AT
|
||||
{
|
||||
/* We can have operands of the form
|
||||
<symbol>@GOTOFF+<nnn>
|
||||
Take the easy way out here and copy everything
|
||||
into a temporary buffer... */
|
||||
register char *cp;
|
||||
|
||||
cp = strchr (input_line_pointer, '@');
|
||||
if (cp != NULL)
|
||||
{
|
||||
char *tmpbuf;
|
||||
int len = 0;
|
||||
int first;
|
||||
|
||||
/* GOT relocations are not supported in 16 bit mode. */
|
||||
if (flag_code == CODE_16BIT)
|
||||
as_bad (_("GOT relocations not supported in 16 bit mode"));
|
||||
|
||||
if (GOT_symbol == NULL)
|
||||
GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
|
||||
|
||||
if (strncmp (cp + 1, "PLT", 3) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_PLT32;
|
||||
else
|
||||
i.reloc[this_operand] = BFD_RELOC_386_PLT32;
|
||||
len = 3;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOTOFF", 6) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
as_bad ("GOTOFF relocations are unsupported in 64bit mode.");
|
||||
i.reloc[this_operand] = BFD_RELOC_386_GOTOFF;
|
||||
len = 6;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOTPCREL", 8) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_GOTPCREL;
|
||||
else
|
||||
as_bad ("GOTPCREL relocations are supported only in 64bit mode.");
|
||||
len = 8;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOT", 3) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_GOT32;
|
||||
else
|
||||
i.reloc[this_operand] = BFD_RELOC_386_GOT32;
|
||||
len = 3;
|
||||
}
|
||||
else
|
||||
as_bad (_("bad reloc specifier in expression"));
|
||||
|
||||
/* Replace the relocation token with ' ', so that errors like
|
||||
foo@GOTOFF1 will be detected. */
|
||||
first = cp - input_line_pointer;
|
||||
tmpbuf = (char *) alloca (strlen (input_line_pointer));
|
||||
memcpy (tmpbuf, input_line_pointer, first);
|
||||
tmpbuf[first] = ' ';
|
||||
strcpy (tmpbuf + first + 1, cp + 1 + len);
|
||||
input_line_pointer = tmpbuf;
|
||||
}
|
||||
}
|
||||
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL);
|
||||
if (gotfree_input_line)
|
||||
input_line_pointer = gotfree_input_line;
|
||||
#endif
|
||||
|
||||
exp_seg = expression (exp);
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer)
|
||||
as_bad (_("ignoring junk `%s' after expression"), input_line_pointer);
|
||||
as_bad (_("junk `%s' after expression"), input_line_pointer);
|
||||
|
||||
input_line_pointer = save_input_line_pointer;
|
||||
#ifndef LEX_AT
|
||||
if (gotfree_input_line)
|
||||
free (gotfree_input_line);
|
||||
#endif
|
||||
|
||||
if (exp->X_op == O_absent || exp->X_op == O_big)
|
||||
{
|
||||
@ -3331,6 +3392,9 @@ i386_displacement (disp_start, disp_end)
|
||||
register expressionS *exp;
|
||||
segT exp_seg = 0;
|
||||
char *save_input_line_pointer;
|
||||
#ifndef LEX_AT
|
||||
char *gotfree_input_line;
|
||||
#endif
|
||||
int bigdisp = Disp32;
|
||||
|
||||
if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
|
||||
@ -3391,70 +3455,9 @@ i386_displacement (disp_start, disp_end)
|
||||
}
|
||||
#endif
|
||||
#ifndef LEX_AT
|
||||
{
|
||||
/* We can have operands of the form
|
||||
<symbol>@GOTOFF+<nnn>
|
||||
Take the easy way out here and copy everything
|
||||
into a temporary buffer... */
|
||||
register char *cp;
|
||||
|
||||
cp = strchr (input_line_pointer, '@');
|
||||
if (cp != NULL)
|
||||
{
|
||||
char *tmpbuf;
|
||||
int len = 0;
|
||||
int first;
|
||||
|
||||
/* GOT relocations are not supported in 16 bit mode. */
|
||||
if (flag_code == CODE_16BIT)
|
||||
as_bad (_("GOT relocations not supported in 16 bit mode"));
|
||||
|
||||
if (GOT_symbol == NULL)
|
||||
GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
|
||||
|
||||
if (strncmp (cp + 1, "PLT", 3) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_PLT32;
|
||||
else
|
||||
i.reloc[this_operand] = BFD_RELOC_386_PLT32;
|
||||
len = 3;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOTOFF", 6) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
as_bad ("GOTOFF relocation is not supported in 64bit mode.");
|
||||
i.reloc[this_operand] = BFD_RELOC_386_GOTOFF;
|
||||
len = 6;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOTPCREL", 8) == 0)
|
||||
{
|
||||
if (flag_code != CODE_64BIT)
|
||||
as_bad ("GOTPCREL relocation is supported only in 64bit mode.");
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_GOTPCREL;
|
||||
len = 8;
|
||||
}
|
||||
else if (strncmp (cp + 1, "GOT", 3) == 0)
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
i.reloc[this_operand] = BFD_RELOC_X86_64_GOT32;
|
||||
else
|
||||
i.reloc[this_operand] = BFD_RELOC_386_GOT32;
|
||||
len = 3;
|
||||
}
|
||||
else
|
||||
as_bad (_("bad reloc specifier in expression"));
|
||||
|
||||
/* Replace the relocation token with ' ', so that errors like
|
||||
foo@GOTOFF1 will be detected. */
|
||||
first = cp - input_line_pointer;
|
||||
tmpbuf = (char *) alloca (strlen (input_line_pointer));
|
||||
memcpy (tmpbuf, input_line_pointer, first);
|
||||
tmpbuf[first] = ' ';
|
||||
strcpy (tmpbuf + first + 1, cp + 1 + len);
|
||||
input_line_pointer = tmpbuf;
|
||||
}
|
||||
}
|
||||
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL);
|
||||
if (gotfree_input_line)
|
||||
input_line_pointer = gotfree_input_line;
|
||||
#endif
|
||||
|
||||
exp_seg = expression (exp);
|
||||
@ -3481,13 +3484,16 @@ i386_displacement (disp_start, disp_end)
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer)
|
||||
as_bad (_("ignoring junk `%s' after expression"),
|
||||
input_line_pointer);
|
||||
as_bad (_("junk `%s' after expression"), input_line_pointer);
|
||||
#if GCC_ASM_O_HACK
|
||||
RESTORE_END_STRING (disp_end + 1);
|
||||
#endif
|
||||
RESTORE_END_STRING (disp_end);
|
||||
input_line_pointer = save_input_line_pointer;
|
||||
#ifndef LEX_AT
|
||||
if (gotfree_input_line)
|
||||
free (gotfree_input_line);
|
||||
#endif
|
||||
|
||||
if (exp->X_op == O_absent || exp->X_op == O_big)
|
||||
{
|
||||
@ -3927,11 +3933,7 @@ md_estimate_size_before_relax (fragP, segment)
|
||||
/* Symbol is undefined in this segment, or we need to keep a
|
||||
reloc so that weak symbols can be overridden. */
|
||||
int size = (fragP->fr_subtype & CODE16) ? 2 : 4;
|
||||
#ifdef BFD_ASSEMBLER
|
||||
enum bfd_reloc_code_real reloc_type;
|
||||
#else
|
||||
int reloc_type;
|
||||
#endif
|
||||
RELOC_ENUM reloc_type;
|
||||
unsigned char *opcode;
|
||||
int old_fr_fix;
|
||||
|
||||
|
@ -155,6 +155,15 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
||||
|
||||
#endif /* ! BFD_ASSEMBLER */
|
||||
|
||||
#ifndef LEX_AT
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) x86_cons (EXP, NBYTES)
|
||||
extern void x86_cons PARAMS ((expressionS *, int));
|
||||
|
||||
#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) x86_cons_fix_new(FRAG, OFF, LEN, EXP)
|
||||
extern void x86_cons_fix_new
|
||||
PARAMS ((fragS *, unsigned int, unsigned int, expressionS *));
|
||||
#endif
|
||||
|
||||
#define TC_FORCE_RELOCATION(fixp) tc_i386_force_relocation(fixp)
|
||||
extern int tc_i386_force_relocation PARAMS ((struct fix *));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user