diff options
Diffstat (limited to 'binutils-2.25/gas/config/tc-i386.c')
-rw-r--r-- | binutils-2.25/gas/config/tc-i386.c | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/binutils-2.25/gas/config/tc-i386.c b/binutils-2.25/gas/config/tc-i386.c index 6f7a1ae..97e326c 100644 --- a/binutils-2.25/gas/config/tc-i386.c +++ b/binutils-2.25/gas/config/tc-i386.c @@ -2830,6 +2830,7 @@ static bfd_reloc_code_real_type reloc (unsigned int size, int pcrel, int sign, + int bnd_prefix, bfd_reloc_code_real_type other) { if (other != NO_RELOC) @@ -2842,6 +2843,9 @@ reloc (unsigned int size, case BFD_RELOC_X86_64_GOT32: return BFD_RELOC_X86_64_GOT64; break; + case BFD_RELOC_X86_64_GOTPLT64: + return BFD_RELOC_X86_64_GOTPLT64; + break; case BFD_RELOC_X86_64_PLTOFF64: return BFD_RELOC_X86_64_PLTOFF64; break; @@ -2905,7 +2909,9 @@ reloc (unsigned int size, { case 1: return BFD_RELOC_8_PCREL; case 2: return BFD_RELOC_16_PCREL; - case 4: return BFD_RELOC_32_PCREL; + case 4: return (bnd_prefix && object_64bit + ? BFD_RELOC_X86_64_PC32_BND + : BFD_RELOC_32_PCREL); case 8: return BFD_RELOC_64_PCREL; } as_bad (_("cannot do %u byte pc-relative relocation"), size); @@ -6770,7 +6776,13 @@ output_branch (void) /* 1 possible extra opcode + 4 byte displacement go in var part. Pass reloc in fr_var. */ - frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); + frag_var (rs_machine_dependent, 5, + ((!object_64bit + || i.reloc[0] != NO_RELOC + || (i.bnd_prefix == NULL && !add_bnd_prefix)) + ? i.reloc[0] + : BFD_RELOC_X86_64_PC32_BND), + subtype, sym, off, p); } static void @@ -6846,7 +6858,10 @@ output_jump (void) } fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0])); + i.op[0].disps, 1, reloc (size, 1, 1, + (i.bnd_prefix != NULL + || add_bnd_prefix), + 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 @@ -6912,7 +6927,7 @@ output_interseg_jump (void) } else fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1])); + i.op[1].imms, 0, reloc (size, 0, 0, 0, i.reloc[1])); if (i.op[0].imms->X_op != O_constant) as_bad (_("can't handle non absolute segment in `%s'"), i.tm.name); @@ -7191,7 +7206,10 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) } p = frag_more (size); - reloc_type = reloc (size, pcrel, sign, i.reloc[n]); + reloc_type = reloc (size, pcrel, sign, + (i.bnd_prefix != NULL + || add_bnd_prefix), + i.reloc[n]); if (GOT_symbol && GOT_symbol == i.op[n].disps->X_add_symbol && (((reloc_type == BFD_RELOC_32 @@ -7282,7 +7300,7 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off) sign = 0; p = frag_more (size); - reloc_type = reloc (size, 0, sign, i.reloc[n]); + reloc_type = reloc (size, 0, sign, 0, i.reloc[n]); /* This is tough to explain. We end up with this one if we * have operands that look like @@ -7375,7 +7393,7 @@ void x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len, expressionS *exp, bfd_reloc_code_real_type r) { - r = reloc (len, 0, cons_sign, r); + r = reloc (len, 0, cons_sign, 0, r); #ifdef TE_PE if (exp->X_op == O_secrel) @@ -7401,7 +7419,7 @@ x86_address_bytes (void) #if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \ || defined (LEX_AT) -# define lex_got(reloc, adjust, types) NULL +# define lex_got(reloc, adjust, types, bnd_prefix) NULL #else /* Parse operands of the form <symbol>@GOTOFF+<nnn> @@ -7415,7 +7433,8 @@ x86_address_bytes (void) static char * lex_got (enum bfd_reloc_code_real *rel, int *adjust, - i386_operand_type *types) + i386_operand_type *types, + int bnd_prefix) { /* Some of the relocations depend on the size of what field is to be relocated. But in our callers i386_immediate and i386_displacement @@ -7550,6 +7569,8 @@ lex_got (enum bfd_reloc_code_real *rel, *adjust = len; memcpy (tmpbuf + first, past_reloc, second); tmpbuf[first + second] = '\0'; + if (bnd_prefix && *rel == BFD_RELOC_X86_64_PLT32) + *rel = BFD_RELOC_X86_64_PLT32_BND; return tmpbuf; } @@ -7582,7 +7603,8 @@ lex_got (enum bfd_reloc_code_real *rel, static char * lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, int *adjust ATTRIBUTE_UNUSED, - i386_operand_type *types) + i386_operand_type *types, + int bnd_prefix ATTRIBUTE_UNUSED) { static const struct { @@ -7683,7 +7705,7 @@ x86_cons (expressionS *exp, int size) int adjust = 0; save = input_line_pointer; - gotfree_input_line = lex_got (&got_reloc, &adjust, NULL); + gotfree_input_line = lex_got (&got_reloc, &adjust, NULL, 0); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -7917,7 +7939,9 @@ i386_immediate (char *imm_start) save_input_line_pointer = input_line_pointer; input_line_pointer = imm_start; - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, + (i.bnd_prefix != NULL + || add_bnd_prefix)); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -8174,7 +8198,9 @@ i386_displacement (char *disp_start, char *disp_end) *displacement_string_end = '0'; } #endif - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, + (i.bnd_prefix != NULL + || add_bnd_prefix)); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -9134,7 +9160,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) && (fixP->fx_r_type == BFD_RELOC_32_PCREL || fixP->fx_r_type == BFD_RELOC_64_PCREL || fixP->fx_r_type == BFD_RELOC_16_PCREL - || fixP->fx_r_type == BFD_RELOC_8_PCREL) + || fixP->fx_r_type == BFD_RELOC_8_PCREL + || fixP->fx_r_type == BFD_RELOC_X86_64_PC32_BND) && !use_rela_relocations) { /* This is a hack. There should be a better way to handle this. @@ -9203,6 +9230,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { case BFD_RELOC_386_PLT32: case BFD_RELOC_X86_64_PLT32: + case BFD_RELOC_X86_64_PLT32_BND: /* Make the jump instruction point to the address of the operand. At runtime we merely add the offset to the actual PLT entry. */ value = -4; @@ -10326,6 +10354,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) #endif case BFD_RELOC_X86_64_PLT32: + case BFD_RELOC_X86_64_PLT32_BND: case BFD_RELOC_X86_64_GOT32: case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_386_PLT32: @@ -10386,7 +10415,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) break; case 1: code = BFD_RELOC_8_PCREL; break; case 2: code = BFD_RELOC_16_PCREL; break; - case 4: code = BFD_RELOC_32_PCREL; break; + case 4: + code = (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_BND + ? fixp-> fx_r_type : BFD_RELOC_32_PCREL); + break; #ifdef BFD64 case 8: code = BFD_RELOC_64_PCREL; break; #endif @@ -10479,6 +10511,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) switch (code) { case BFD_RELOC_X86_64_PLT32: + case BFD_RELOC_X86_64_PLT32_BND: case BFD_RELOC_X86_64_GOT32: case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_X86_64_TLSGD: |