Bring the binutils_2_13_20021110 snap version of this to the HEAD branch.
This commit is contained in:
parent
8d7f2d507e
commit
613e6f63e2
@ -108,8 +108,10 @@ static void output_insn PARAMS ((void));
|
||||
static void output_branch PARAMS ((void));
|
||||
static void output_jump PARAMS ((void));
|
||||
static void output_interseg_jump PARAMS ((void));
|
||||
static void output_imm PARAMS ((void));
|
||||
static void output_disp PARAMS ((void));
|
||||
static void output_imm PARAMS ((fragS *insn_start_frag,
|
||||
offsetT insn_start_off));
|
||||
static void output_disp PARAMS ((fragS *insn_start_frag,
|
||||
offsetT insn_start_off));
|
||||
#ifndef I386COFF
|
||||
static void s_bss PARAMS ((int));
|
||||
#endif
|
||||
@ -439,7 +441,7 @@ const pseudo_typeS md_pseudo_table[] =
|
||||
{"code64", set_code_flag, CODE_64BIT},
|
||||
{"intel_syntax", set_intel_syntax, 1},
|
||||
{"att_syntax", set_intel_syntax, 0},
|
||||
{"file", dwarf2_directive_file, 0},
|
||||
{"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
|
||||
{"loc", dwarf2_directive_loc, 0},
|
||||
{0, 0, 0}
|
||||
};
|
||||
@ -1134,21 +1136,6 @@ pt (t)
|
||||
|
||||
#endif /* DEBUG386 */
|
||||
|
||||
int
|
||||
tc_i386_force_relocation (fixp)
|
||||
struct fix *fixp;
|
||||
{
|
||||
#ifdef BFD_ASSEMBLER
|
||||
if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|
||||
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
|
||||
return 1;
|
||||
return 0;
|
||||
#else
|
||||
/* For COFF. */
|
||||
return fixp->fx_r_type == 7;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BFD_ASSEMBLER
|
||||
static bfd_reloc_code_real_type reloc
|
||||
PARAMS ((int, int, int, bfd_reloc_code_real_type));
|
||||
@ -1205,9 +1192,12 @@ reloc (size, pcrel, sign, other)
|
||||
|
||||
int
|
||||
tc_i386_fix_adjustable (fixP)
|
||||
fixS *fixP;
|
||||
fixS *fixP ATTRIBUTE_UNUSED;
|
||||
{
|
||||
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
|
||||
if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
|
||||
return 1;
|
||||
|
||||
/* Prevent all adjustments to global symbols, or else dynamic
|
||||
linking will not work correctly. */
|
||||
if (S_IS_EXTERNAL (fixP->fx_addsy)
|
||||
@ -1218,28 +1208,47 @@ tc_i386_fix_adjustable (fixP)
|
||||
&& (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0
|
||||
&& fixP->fx_pcrel))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* adjust_reloc_syms doesn't know about the GOT. */
|
||||
if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_PLT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_GOT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GD
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_IE
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LE
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
|
||||
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|
||||
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
#define reloc(SIZE,PCREL,SIGN,OTHER) 0
|
||||
#define BFD_RELOC_8 0
|
||||
#define BFD_RELOC_16 0
|
||||
#define BFD_RELOC_32 0
|
||||
#define BFD_RELOC_8_PCREL 0
|
||||
#define BFD_RELOC_16_PCREL 0
|
||||
#define BFD_RELOC_32_PCREL 0
|
||||
#define BFD_RELOC_386_PLT32 0
|
||||
#define BFD_RELOC_386_GOT32 0
|
||||
#define BFD_RELOC_386_GOTOFF 0
|
||||
#define BFD_RELOC_386_TLS_GD 0
|
||||
#define BFD_RELOC_386_TLS_LDM 0
|
||||
#define BFD_RELOC_386_TLS_LDO_32 0
|
||||
#define BFD_RELOC_386_TLS_IE_32 0
|
||||
#define BFD_RELOC_386_TLS_IE 0
|
||||
#define BFD_RELOC_386_TLS_GOTIE 0
|
||||
#define BFD_RELOC_386_TLS_LE_32 0
|
||||
#define BFD_RELOC_386_TLS_LE 0
|
||||
#define BFD_RELOC_X86_64_PLT32 0
|
||||
#define BFD_RELOC_X86_64_GOT32 0
|
||||
#define BFD_RELOC_X86_64_GOTPCREL 0
|
||||
@ -1318,11 +1327,19 @@ md_assemble (line)
|
||||
if (!match_template ())
|
||||
return;
|
||||
|
||||
/* Undo SYSV386_COMPAT brokenness when in Intel mode. See i386.h */
|
||||
if (SYSV386_COMPAT
|
||||
&& intel_syntax
|
||||
&& (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
|
||||
i.tm.base_opcode ^= FloatR;
|
||||
if (intel_syntax)
|
||||
{
|
||||
/* Undo SYSV386_COMPAT brokenness when in Intel mode. See i386.h */
|
||||
if (SYSV386_COMPAT
|
||||
&& (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
|
||||
i.tm.base_opcode ^= FloatR;
|
||||
|
||||
/* Zap movzx and movsx suffix. The suffix may have been set from
|
||||
"word ptr" or "byte ptr" on the source operand, but we'll use
|
||||
the suffix later to choose the destination register. */
|
||||
if ((i.tm.base_opcode & ~9) == 0x0fb6)
|
||||
i.suffix = 0;
|
||||
}
|
||||
|
||||
if (i.tm.opcode_modifier & FWait)
|
||||
if (!add_prefix (FWAIT_OPCODE))
|
||||
@ -2210,18 +2227,6 @@ process_suffix ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For movzx and movsx, need to check the register type. */
|
||||
if (intel_syntax
|
||||
&& (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe)
|
||||
&& i.suffix == BYTE_MNEM_SUFFIX)
|
||||
{
|
||||
unsigned int prefix = DATA_PREFIX_OPCODE;
|
||||
|
||||
if ((i.op[1].regs->reg_type & Reg16) != 0)
|
||||
if (!add_prefix (prefix))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
|
||||
{
|
||||
/* It's not a byte, select word/dword operation. */
|
||||
@ -2237,8 +2242,10 @@ process_suffix ()
|
||||
size prefix, except for instructions that will ignore this
|
||||
prefix anyway. */
|
||||
if (i.suffix != QWORD_MNEM_SUFFIX
|
||||
&& (i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
|
||||
&& !(i.tm.opcode_modifier & IgnoreSize))
|
||||
&& !(i.tm.opcode_modifier & IgnoreSize)
|
||||
&& ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
|
||||
|| (flag_code == CODE_64BIT
|
||||
&& (i.tm.opcode_modifier & JumpByte))))
|
||||
{
|
||||
unsigned int prefix = DATA_PREFIX_OPCODE;
|
||||
if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
|
||||
@ -2248,25 +2255,11 @@ process_suffix ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i.suffix != QWORD_MNEM_SUFFIX && (flag_code == CODE_64BIT)
|
||||
&& !(i.tm.opcode_modifier & IgnoreSize)
|
||||
&& (i.tm.opcode_modifier & JumpByte))
|
||||
{
|
||||
if (!add_prefix (ADDR_PREFIX_OPCODE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set mode64 for an operand. */
|
||||
if (i.suffix == QWORD_MNEM_SUFFIX
|
||||
&& flag_code == CODE_64BIT
|
||||
&& (i.tm.opcode_modifier & NoRex64) == 0)
|
||||
{
|
||||
i.rex |= REX_MODE64;
|
||||
if (flag_code < CODE_64BIT)
|
||||
{
|
||||
as_bad (_("64bit operations available only in 64bit modes."));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
i.rex |= REX_MODE64;
|
||||
|
||||
/* Size floating point instruction. */
|
||||
if (i.suffix == LONG_MNEM_SUFFIX)
|
||||
@ -2600,9 +2593,8 @@ process_operands ()
|
||||
else if (i.tm.opcode_modifier & Modrm)
|
||||
{
|
||||
/* The opcode is completed (modulo i.tm.extension_opcode which
|
||||
must be put into the modrm byte).
|
||||
Now, we make the modrm & index base bytes based on all the
|
||||
info we've collected. */
|
||||
must be put into the modrm byte). Now, we make the modrm and
|
||||
index base bytes based on all the info we've collected. */
|
||||
|
||||
default_seg = build_modrm_byte ();
|
||||
}
|
||||
@ -2629,12 +2621,14 @@ process_operands ()
|
||||
default_seg = &ds;
|
||||
}
|
||||
|
||||
/* If a segment was explicitly specified,
|
||||
and the specified segment is not the default,
|
||||
use an opcode prefix to select it.
|
||||
If we never figured out what the default segment is,
|
||||
then default_seg will be zero at this point,
|
||||
and the specified segment prefix will always be used. */
|
||||
if (i.tm.base_opcode == 0x8d /* lea */ && i.seg[0] && !quiet_warnings)
|
||||
as_warn (_("segment override on `lea' is ineffectual"));
|
||||
|
||||
/* If a segment was explicitly specified, and the specified segment
|
||||
is not the default, use an opcode prefix to select it. If we
|
||||
never figured out what the default segment is, then default_seg
|
||||
will be zero at this point, and the specified segment prefix will
|
||||
always be used. */
|
||||
if ((i.seg[0]) && (i.seg[0] != default_seg))
|
||||
{
|
||||
if (!add_prefix (i.seg[0]->seg_prefix))
|
||||
@ -2985,6 +2979,7 @@ output_jump ()
|
||||
{
|
||||
char *p;
|
||||
int size;
|
||||
fixS *fixP;
|
||||
|
||||
if (i.tm.opcode_modifier & JumpByte)
|
||||
{
|
||||
@ -3035,8 +3030,14 @@ output_jump ()
|
||||
p = frag_more (1 + size);
|
||||
*p++ = i.tm.base_opcode;
|
||||
|
||||
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
|
||||
i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
|
||||
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
|
||||
i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
|
||||
|
||||
/* All jumps handled here are signed, but don't use a signed limit
|
||||
check for 32 and 16 bit jumps as we want to allow wrap around at
|
||||
4G and 64k respectively. */
|
||||
if (size == 1)
|
||||
fixP->fx_signed = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3103,14 +3104,21 @@ output_interseg_jump ()
|
||||
md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
output_insn ()
|
||||
{
|
||||
fragS *insn_start_frag;
|
||||
offsetT insn_start_off;
|
||||
|
||||
/* Tie dwarf2 debug info to the address at the start of the insn.
|
||||
We can't do this after the insn has been output as the current
|
||||
frag may have been closed off. eg. by frag_var. */
|
||||
dwarf2_emit_insn (0);
|
||||
|
||||
insn_start_frag = frag_now;
|
||||
insn_start_off = frag_now_fix ();
|
||||
|
||||
/* Output jumps. */
|
||||
if (i.tm.opcode_modifier & Jump)
|
||||
output_branch ();
|
||||
@ -3181,10 +3189,10 @@ output_insn ()
|
||||
}
|
||||
|
||||
if (i.disp_operands)
|
||||
output_disp ();
|
||||
output_disp (insn_start_frag, insn_start_off);
|
||||
|
||||
if (i.imm_operands)
|
||||
output_imm ();
|
||||
output_imm (insn_start_frag, insn_start_off);
|
||||
}
|
||||
|
||||
#ifdef DEBUG386
|
||||
@ -3196,7 +3204,9 @@ output_insn ()
|
||||
}
|
||||
|
||||
static void
|
||||
output_disp ()
|
||||
output_disp (insn_start_frag, insn_start_off)
|
||||
fragS *insn_start_frag;
|
||||
offsetT insn_start_off;
|
||||
{
|
||||
char *p;
|
||||
unsigned int n;
|
||||
@ -3226,6 +3236,7 @@ output_disp ()
|
||||
}
|
||||
else
|
||||
{
|
||||
RELOC_ENUM reloc_type;
|
||||
int size = 4;
|
||||
int sign = 0;
|
||||
int pcrel = (i.flags[n] & Operand_PCrel) != 0;
|
||||
@ -3268,16 +3279,50 @@ output_disp ()
|
||||
}
|
||||
|
||||
p = frag_more (size);
|
||||
reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
|
||||
#ifdef BFD_ASSEMBLER
|
||||
if (reloc_type == BFD_RELOC_32
|
||||
&& GOT_symbol
|
||||
&& GOT_symbol == i.op[n].disps->X_add_symbol
|
||||
&& (i.op[n].disps->X_op == O_symbol
|
||||
|| (i.op[n].disps->X_op == O_add
|
||||
&& ((symbol_get_value_expression
|
||||
(i.op[n].disps->X_op_symbol)->X_op)
|
||||
== O_subtract))))
|
||||
{
|
||||
offsetT add;
|
||||
|
||||
if (insn_start_frag == frag_now)
|
||||
add = (p - frag_now->fr_literal) - insn_start_off;
|
||||
else
|
||||
{
|
||||
fragS *fr;
|
||||
|
||||
add = insn_start_frag->fr_fix - insn_start_off;
|
||||
for (fr = insn_start_frag->fr_next;
|
||||
fr && fr != frag_now; fr = fr->fr_next)
|
||||
add += fr->fr_fix;
|
||||
add += p - frag_now->fr_literal;
|
||||
}
|
||||
|
||||
/* We don't support dynamic linking on x86-64 yet. */
|
||||
if (flag_code == CODE_64BIT)
|
||||
abort ();
|
||||
reloc_type = BFD_RELOC_386_GOTPC;
|
||||
i.op[n].disps->X_add_number += add;
|
||||
}
|
||||
#endif
|
||||
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
|
||||
i.op[n].disps, pcrel,
|
||||
reloc (size, pcrel, sign, i.reloc[n]));
|
||||
i.op[n].disps, pcrel, reloc_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
output_imm ()
|
||||
output_imm (insn_start_frag, insn_start_off)
|
||||
fragS *insn_start_frag;
|
||||
offsetT insn_start_off;
|
||||
{
|
||||
char *p;
|
||||
unsigned int n;
|
||||
@ -3330,6 +3375,48 @@ output_imm ()
|
||||
p = frag_more (size);
|
||||
reloc_type = reloc (size, 0, sign, i.reloc[n]);
|
||||
#ifdef BFD_ASSEMBLER
|
||||
/* This is tough to explain. We end up with this one if we
|
||||
* have operands that look like
|
||||
* "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal here is to
|
||||
* obtain the absolute address of the GOT, and it is strongly
|
||||
* preferable from a performance point of view to avoid using
|
||||
* a runtime relocation for this. The actual sequence of
|
||||
* instructions often look something like:
|
||||
*
|
||||
* call .L66
|
||||
* .L66:
|
||||
* popl %ebx
|
||||
* addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
|
||||
*
|
||||
* The call and pop essentially return the absolute address
|
||||
* of the label .L66 and store it in %ebx. The linker itself
|
||||
* will ultimately change the first operand of the addl so
|
||||
* that %ebx points to the GOT, but to keep things simple, the
|
||||
* .o file must have this operand set so that it generates not
|
||||
* the absolute address of .L66, but the absolute address of
|
||||
* itself. This allows the linker itself simply treat a GOTPC
|
||||
* relocation as asking for a pcrel offset to the GOT to be
|
||||
* added in, and the addend of the relocation is stored in the
|
||||
* operand field for the instruction itself.
|
||||
*
|
||||
* Our job here is to fix the operand so that it would add
|
||||
* the correct offset so that %ebx would point to itself. The
|
||||
* thing that is tricky is that .-.L66 will point to the
|
||||
* beginning of the instruction, so we need to further modify
|
||||
* the operand so that it will point to itself. There are
|
||||
* other cases where you have something like:
|
||||
*
|
||||
* .long $_GLOBAL_OFFSET_TABLE_+[.-.L66]
|
||||
*
|
||||
* and here no correction would be required. Internally in
|
||||
* the assembler we treat operands of this form as not being
|
||||
* pcrel since the '.' is explicitly mentioned, and I wonder
|
||||
* whether it would simplify matters to do it this way. Who
|
||||
* knows. In earlier versions of the PIC patches, the
|
||||
* pcrel_adjust field was used to store the correction, but
|
||||
* since the expression is not pcrel, I felt it would be
|
||||
* confusing to do it this way. */
|
||||
|
||||
if (reloc_type == BFD_RELOC_32
|
||||
&& GOT_symbol
|
||||
&& GOT_symbol == i.op[n].imms->X_add_symbol
|
||||
@ -3339,11 +3426,26 @@ output_imm ()
|
||||
(i.op[n].imms->X_op_symbol)->X_op)
|
||||
== O_subtract))))
|
||||
{
|
||||
offsetT add;
|
||||
|
||||
if (insn_start_frag == frag_now)
|
||||
add = (p - frag_now->fr_literal) - insn_start_off;
|
||||
else
|
||||
{
|
||||
fragS *fr;
|
||||
|
||||
add = insn_start_frag->fr_fix - insn_start_off;
|
||||
for (fr = insn_start_frag->fr_next;
|
||||
fr && fr != frag_now; fr = fr->fr_next)
|
||||
add += fr->fr_fix;
|
||||
add += p - frag_now->fr_literal;
|
||||
}
|
||||
|
||||
/* We don't support dynamic linking on x86-64 yet. */
|
||||
if (flag_code == CODE_64BIT)
|
||||
abort ();
|
||||
reloc_type = BFD_RELOC_386_GOTPC;
|
||||
i.op[n].imms->X_add_number += 3;
|
||||
i.op[n].imms->X_add_number += add;
|
||||
}
|
||||
#endif
|
||||
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
|
||||
@ -3375,10 +3477,18 @@ lex_got (reloc, adjust)
|
||||
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 } }
|
||||
{ "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 } },
|
||||
{ "TLSGD", { BFD_RELOC_386_TLS_GD, 0, 0 } },
|
||||
{ "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0, 0 } },
|
||||
{ "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, 0, 0 } },
|
||||
{ "TPOFF", { BFD_RELOC_386_TLS_LE_32, 0, 0 } },
|
||||
{ "NTPOFF", { BFD_RELOC_386_TLS_LE, 0, 0 } },
|
||||
{ "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, 0, 0 } },
|
||||
{ "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0, 0 } },
|
||||
{ "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0, 0 } },
|
||||
{ "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } }
|
||||
};
|
||||
char *cp;
|
||||
unsigned int j;
|
||||
@ -3561,6 +3671,7 @@ i386_immediate (imm_start)
|
||||
#ifdef BFD_ASSEMBLER
|
||||
&& OUTPUT_FLAVOR == bfd_target_aout_flavour
|
||||
#endif
|
||||
&& exp_seg != absolute_section
|
||||
&& exp_seg != text_section
|
||||
&& exp_seg != data_section
|
||||
&& exp_seg != bss_section
|
||||
@ -3775,10 +3886,15 @@ i386_displacement (disp_start, disp_end)
|
||||
#ifdef BFD_ASSEMBLER
|
||||
&& OUTPUT_FLAVOR == bfd_target_aout_flavour
|
||||
#endif
|
||||
&& exp_seg != absolute_section
|
||||
&& exp_seg != text_section
|
||||
&& exp_seg != data_section
|
||||
&& exp_seg != bss_section
|
||||
&& exp_seg != undefined_section)
|
||||
&& exp_seg != undefined_section
|
||||
#ifdef BFD_ASSEMBLER
|
||||
&& !bfd_is_com_section (exp_seg)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef BFD_ASSEMBLER
|
||||
as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
|
||||
@ -4204,8 +4320,9 @@ md_estimate_size_before_relax (fragP, segment)
|
||||
shared library. */
|
||||
if (S_GET_SEGMENT (fragP->fr_symbol) != segment
|
||||
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
|
||||
|| S_IS_EXTERNAL (fragP->fr_symbol)
|
||||
|| S_IS_WEAK (fragP->fr_symbol)
|
||||
|| (OUTPUT_FLAVOR == bfd_target_elf_flavour
|
||||
&& (S_IS_EXTERNAL (fragP->fr_symbol)
|
||||
|| S_IS_WEAK (fragP->fr_symbol)))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@ -4262,11 +4379,14 @@ md_estimate_size_before_relax (fragP, segment)
|
||||
case COND_JUMP:
|
||||
if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
|
||||
{
|
||||
fixS *fixP;
|
||||
|
||||
fragP->fr_fix += 1;
|
||||
fix_new (fragP, old_fr_fix, 1,
|
||||
fragP->fr_symbol,
|
||||
fragP->fr_offset, 1,
|
||||
BFD_RELOC_8_PCREL);
|
||||
fixP = fix_new (fragP, old_fr_fix, 1,
|
||||
fragP->fr_symbol,
|
||||
fragP->fr_offset, 1,
|
||||
BFD_RELOC_8_PCREL);
|
||||
fixP->fx_signed = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4452,12 +4572,12 @@ md_apply_fix3 (fixP, valP, seg)
|
||||
/* The fix we're to put in. */
|
||||
fixS *fixP;
|
||||
/* Pointer to the value of the bits. */
|
||||
valueT * valP;
|
||||
valueT *valP;
|
||||
/* Segment fix is from. */
|
||||
segT seg ATTRIBUTE_UNUSED;
|
||||
{
|
||||
char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
|
||||
valueT value = * valP;
|
||||
valueT value = *valP;
|
||||
|
||||
#if defined (BFD_ASSEMBLER) && !defined (TE_Mach)
|
||||
if (fixP->fx_pcrel)
|
||||
@ -4479,15 +4599,16 @@ md_apply_fix3 (fixP, valP, seg)
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a hack. There should be a better way to handle this.
|
||||
This covers for the fact that bfd_install_relocation will
|
||||
subtract the current location (for partial_inplace, PC relative
|
||||
relocations); see more below. */
|
||||
if ((fixP->fx_r_type == BFD_RELOC_32_PCREL
|
||||
|| fixP->fx_r_type == BFD_RELOC_16_PCREL
|
||||
|| fixP->fx_r_type == BFD_RELOC_8_PCREL)
|
||||
&& fixP->fx_addsy && !use_rela_relocations)
|
||||
if (fixP->fx_pcrel
|
||||
&& (fixP->fx_r_type == BFD_RELOC_32_PCREL
|
||||
|| fixP->fx_r_type == BFD_RELOC_16_PCREL
|
||||
|| fixP->fx_r_type == BFD_RELOC_8_PCREL)
|
||||
&& !use_rela_relocations)
|
||||
{
|
||||
/* This is a hack. There should be a better way to handle this.
|
||||
This covers for the fact that bfd_install_relocation will
|
||||
subtract the current location (for partial_inplace, PC relative
|
||||
relocations); see more below. */
|
||||
#ifndef OBJ_AOUT
|
||||
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
|
||||
#ifdef TE_PE
|
||||
@ -4538,55 +4659,16 @@ md_apply_fix3 (fixP, valP, seg)
|
||||
runtime we merely add the offset to the actual PLT entry. */
|
||||
value = -4;
|
||||
break;
|
||||
case BFD_RELOC_386_GOTPC:
|
||||
|
||||
/* This is tough to explain. We end up with this one if we have
|
||||
* operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal
|
||||
* here is to obtain the absolute address of the GOT, and it is strongly
|
||||
* preferable from a performance point of view to avoid using a runtime
|
||||
* relocation for this. The actual sequence of instructions often look
|
||||
* something like:
|
||||
*
|
||||
* call .L66
|
||||
* .L66:
|
||||
* popl %ebx
|
||||
* addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx
|
||||
*
|
||||
* The call and pop essentially return the absolute address of
|
||||
* the label .L66 and store it in %ebx. The linker itself will
|
||||
* ultimately change the first operand of the addl so that %ebx points to
|
||||
* the GOT, but to keep things simple, the .o file must have this operand
|
||||
* set so that it generates not the absolute address of .L66, but the
|
||||
* absolute address of itself. This allows the linker itself simply
|
||||
* treat a GOTPC relocation as asking for a pcrel offset to the GOT to be
|
||||
* added in, and the addend of the relocation is stored in the operand
|
||||
* field for the instruction itself.
|
||||
*
|
||||
* Our job here is to fix the operand so that it would add the correct
|
||||
* offset so that %ebx would point to itself. The thing that is tricky is
|
||||
* that .-.L66 will point to the beginning of the instruction, so we need
|
||||
* to further modify the operand so that it will point to itself.
|
||||
* There are other cases where you have something like:
|
||||
*
|
||||
* .long $_GLOBAL_OFFSET_TABLE_+[.-.L66]
|
||||
*
|
||||
* and here no correction would be required. Internally in the assembler
|
||||
* we treat operands of this form as not being pcrel since the '.' is
|
||||
* explicitly mentioned, and I wonder whether it would simplify matters
|
||||
* to do it this way. Who knows. In earlier versions of the PIC patches,
|
||||
* the pcrel_adjust field was used to store the correction, but since the
|
||||
* expression is not pcrel, I felt it would be confusing to do it this
|
||||
* way. */
|
||||
|
||||
value -= 1;
|
||||
break;
|
||||
case BFD_RELOC_386_GOT32:
|
||||
case BFD_RELOC_386_TLS_GD:
|
||||
case BFD_RELOC_386_TLS_LDM:
|
||||
case BFD_RELOC_386_TLS_IE_32:
|
||||
case BFD_RELOC_386_TLS_IE:
|
||||
case BFD_RELOC_386_TLS_GOTIE:
|
||||
case BFD_RELOC_X86_64_GOT32:
|
||||
value = 0; /* Fully resolved at runtime. No addend. */
|
||||
break;
|
||||
case BFD_RELOC_386_GOTOFF:
|
||||
case BFD_RELOC_X86_64_GOTPCREL:
|
||||
break;
|
||||
|
||||
case BFD_RELOC_VTABLE_INHERIT:
|
||||
case BFD_RELOC_VTABLE_ENTRY:
|
||||
@ -4597,11 +4679,11 @@ md_apply_fix3 (fixP, valP, seg)
|
||||
break;
|
||||
}
|
||||
#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */
|
||||
* valP = value;
|
||||
*valP = value;
|
||||
#endif /* defined (BFD_ASSEMBLER) && !defined (TE_Mach) */
|
||||
|
||||
/* Are we finished with this relocation now? */
|
||||
if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
|
||||
if (fixP->fx_addsy == NULL)
|
||||
fixP->fx_done = 1;
|
||||
#ifdef BFD_ASSEMBLER
|
||||
else if (use_rela_relocations)
|
||||
@ -4879,7 +4961,7 @@ i386_target_format ()
|
||||
{
|
||||
if (flag_code == CODE_64BIT)
|
||||
use_rela_relocations = 1;
|
||||
return flag_code == CODE_64BIT ? "elf64-x86-64" : "elf32-i386";
|
||||
return flag_code == CODE_64BIT ? "elf64-x86-64" : ELF_TARGET_FORMAT;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
@ -5049,6 +5131,14 @@ tc_gen_reloc (section, fixp)
|
||||
case BFD_RELOC_386_GOT32:
|
||||
case BFD_RELOC_386_GOTOFF:
|
||||
case BFD_RELOC_386_GOTPC:
|
||||
case BFD_RELOC_386_TLS_GD:
|
||||
case BFD_RELOC_386_TLS_LDM:
|
||||
case BFD_RELOC_386_TLS_LDO_32:
|
||||
case BFD_RELOC_386_TLS_IE_32:
|
||||
case BFD_RELOC_386_TLS_IE:
|
||||
case BFD_RELOC_386_TLS_GOTIE:
|
||||
case BFD_RELOC_386_TLS_LE_32:
|
||||
case BFD_RELOC_386_TLS_LE:
|
||||
case BFD_RELOC_X86_64_32S:
|
||||
case BFD_RELOC_RVA:
|
||||
case BFD_RELOC_VTABLE_ENTRY:
|
||||
@ -5114,10 +5204,7 @@ tc_gen_reloc (section, fixp)
|
||||
if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
|
||||
rel->address = fixp->fx_offset;
|
||||
|
||||
if (fixp->fx_pcrel)
|
||||
rel->addend = fixp->fx_addnumber;
|
||||
else
|
||||
rel->addend = 0;
|
||||
rel->addend = 0;
|
||||
}
|
||||
/* Use the rela in 64bit mode. */
|
||||
else
|
||||
|
@ -102,13 +102,20 @@ extern unsigned long i386_mach PARAMS ((void));
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386"
|
||||
#endif
|
||||
|
||||
#ifdef TE_FreeBSD
|
||||
#define ELF_TARGET_FORMAT "elf32-i386-freebsd"
|
||||
#endif
|
||||
#ifndef ELF_TARGET_FORMAT
|
||||
#define ELF_TARGET_FORMAT "elf32-i386"
|
||||
#endif
|
||||
|
||||
#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
|
||||
|| defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
|
||||
extern const char *i386_target_format PARAMS ((void));
|
||||
#define TARGET_FORMAT i386_target_format ()
|
||||
#else
|
||||
#ifdef OBJ_ELF
|
||||
#define TARGET_FORMAT "elf32-i386"
|
||||
#define TARGET_FORMAT ELF_TARGET_FORMAT
|
||||
#endif
|
||||
#ifdef OBJ_AOUT
|
||||
#define TARGET_FORMAT AOUT_TARGET_FORMAT
|
||||
@ -120,6 +127,8 @@ extern const char *i386_target_format PARAMS ((void));
|
||||
extern void i386_elf_emit_arch_note PARAMS ((void));
|
||||
#endif
|
||||
|
||||
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
|
||||
|
||||
#else /* ! BFD_ASSEMBLER */
|
||||
|
||||
/* COFF STUFF */
|
||||
@ -135,7 +144,7 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
||||
|
||||
#ifdef TE_GO32
|
||||
/* DJGPP now expects some sections to be 2**4 aligned. */
|
||||
#define SUB_SEGMENT_ALIGN(SEG) \
|
||||
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \
|
||||
((strcmp (obj_segment_name (SEG), ".text") == 0 \
|
||||
|| strcmp (obj_segment_name (SEG), ".data") == 0 \
|
||||
|| strcmp (obj_segment_name (SEG), ".bss") == 0 \
|
||||
@ -145,7 +154,7 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
||||
? 4 \
|
||||
: 2)
|
||||
#else
|
||||
#define SUB_SEGMENT_ALIGN(SEG) 2
|
||||
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 2
|
||||
#endif
|
||||
|
||||
#define TC_RVA_RELOC 7
|
||||
@ -173,8 +182,15 @@ 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 *));
|
||||
#ifdef BFD_ASSEMBLER
|
||||
#define TC_FORCE_RELOCATION(FIXP) \
|
||||
((FIXP)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \
|
||||
|| (FIXP)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
|
||||
#else
|
||||
/* For COFF. */
|
||||
#define TC_FORCE_RELOCATION(FIXP) \
|
||||
((FIXP)->fx_r_type == 7)
|
||||
#endif
|
||||
|
||||
#ifdef BFD_ASSEMBLER
|
||||
#define NO_RELOC BFD_RELOC_NONE
|
||||
|
Loading…
Reference in New Issue
Block a user