Hackery to handle ix86 "jmp constant" as a pc-relative jump to the given

absolute address.
This commit is contained in:
Alan Modra
1999-09-13 06:45:15 +00:00
parent 9169713a19
commit 2f66722d55
4 changed files with 63 additions and 106 deletions

View File

@ -1,3 +1,8 @@
1999-09-13 Alan Modra <alan@spri.levels.unisa.edu.au>
* elfcode.h (write_relocs): Check for the_bfd NULL when handling
an absolute symbol in REL relocs.
Sun Sep 12 23:47:58 1999 Jeffrey A Law (law@cygnus.com) Sun Sep 12 23:47:58 1999 Jeffrey A Law (law@cygnus.com)
* elf-hppa.h (elf_hppa_final_link_relocate): Handle SECREL32. * elf-hppa.h (elf_hppa_final_link_relocate): Handle SECREL32.

View File

@ -871,7 +871,8 @@ write_relocs (abfd, sec, data)
last_sym_idx = n; last_sym_idx = n;
} }
if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
&& ! _bfd_elf_validate_reloc (abfd, ptr)) && ! _bfd_elf_validate_reloc (abfd, ptr))
{ {
*failedp = true; *failedp = true;

View File

@ -1,5 +1,10 @@
1999-09-13 Alan Modra <alan@spri.levels.unisa.edu.au> 1999-09-13 Alan Modra <alan@spri.levels.unisa.edu.au>
* config/tc-i386.c (md_assemble): Handle "jmp/call constant" as a
pc-relative jmp/call to an absolute symbol.
(md_apply_fix3): When OBJ_ELF, don't add the values in twice for
absolute section symbols.
* config/tc-i386.c (md_assemble): Correct frag_var size. Tidy * config/tc-i386.c (md_assemble): Correct frag_var size. Tidy
jump handling code and comments. jump handling code and comments.

View File

@ -2085,6 +2085,16 @@ md_assemble (line)
i.imm_operands = 0; i.imm_operands = 0;
} }
if ((i.tm.opcode_modifier & (Jump | JumpByte | JumpDword))
&& i.disps[0]->X_op == O_constant)
{
/* Convert "jmp constant" (and "call constant") to a jump (call) to
the absolute address given by the constant. Since ix86 jumps and
calls are pc relative, we need to generate a reloc. */
i.disps[0]->X_add_symbol = &abs_symbol;
i.disps[0]->X_op = O_symbol;
}
/* We are ready to output the insn. */ /* We are ready to output the insn. */
{ {
register char *p; register char *p;
@ -2115,55 +2125,7 @@ md_assemble (line)
if (i.prefixes != 0 && !intel_syntax) if (i.prefixes != 0 && !intel_syntax)
as_warn (_("skipping prefixes on this instruction")); as_warn (_("skipping prefixes on this instruction"));
if (i.disps[0]->X_op == O_constant) /* It's always a symbol; End frag & setup for relax.
{
long n = (long) i.disps[0]->X_add_number;
if (fits_in_signed_byte (n))
{
insn_size += 2;
p = frag_more (2);
p[0] = i.tm.base_opcode;
p[1] = n;
}
else
{
/* Use 16-bit jumps only for 16-bit code,
because text segments are limited to 64K anyway;
Use 32-bit jumps for 32-bit code, because they're faster,
and a 16-bit jump will clear the top 16 bits of %eip. */
if (code16 && !fits_in_signed_word (n))
{
as_bad (_("16-bit jump out of range"));
return;
}
if (i.tm.base_opcode == JUMP_PC_RELATIVE)
{ /* pace */
/* unconditional jump */
insn_size += prefix + 1 + size;
p = frag_more (prefix + 1 + size);
if (prefix)
*p++ = DATA_PREFIX_OPCODE;
*p++ = (char) 0xe9;
md_number_to_chars (p, (valueT) n, size);
}
else
{
/* conditional jump */
insn_size += prefix + 2 + size;
p = frag_more (prefix + 2 + size);
if (prefix)
*p++ = DATA_PREFIX_OPCODE;
*p++ = TWO_BYTE_OPCODE_ESCAPE;
*p++ = i.tm.base_opcode + 0x10;
md_number_to_chars (p, (valueT) n, size);
}
}
}
else
{
/* It's a symbol; End frag & setup for relax.
Make sure there is enough room in this frag for the largest Make sure there is enough room in this frag for the largest
instruction we may generate in md_convert_frag. This is 2 instruction we may generate in md_convert_frag. This is 2
bytes for the opcode and room for the prefix and largest bytes for the opcode and room for the prefix and largest
@ -2175,7 +2137,7 @@ md_assemble (line)
if (prefix) if (prefix)
*p++ = DATA_PREFIX_OPCODE; *p++ = DATA_PREFIX_OPCODE;
*p = i.tm.base_opcode; *p = i.tm.base_opcode;
/* 1 possible extra opcode + displacement go in fr_var */ /* 1 possible extra opcode + displacement go in fr_var. */
frag_var (rs_machine_dependent, frag_var (rs_machine_dependent,
1 + size, 1 + size,
1, 1,
@ -2186,7 +2148,6 @@ md_assemble (line)
i.disps[0]->X_add_number, i.disps[0]->X_add_number,
p); p);
} }
}
else if (i.tm.opcode_modifier & (JumpByte | JumpDword)) else if (i.tm.opcode_modifier & (JumpByte | JumpDword))
{ {
int size; int size;
@ -2240,28 +2201,8 @@ md_assemble (line)
} }
*p++ = i.tm.base_opcode & 0xff; *p++ = i.tm.base_opcode & 0xff;
if (i.disps[0]->X_op == O_constant)
{
long n = (long) i.disps[0]->X_add_number;
if (size == 1 && !fits_in_signed_byte (n))
{
as_bad (_("`%s' only takes byte displacement; %ld shortened to %d"),
i.tm.name, n, *p);
}
else if (size == 2 && !fits_in_signed_word (n))
{
as_bad (_("16-bit jump out of range"));
return;
}
md_number_to_chars (p, (valueT) n, size);
}
else
{
fix_new_exp (frag_now, p - frag_now->fr_literal, size, fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.disps[0], 1, reloc (size, 1, i.disp_reloc[0])); i.disps[0], 1, reloc (size, 1, i.disp_reloc[0]));
}
} }
else if (i.tm.opcode_modifier & JumpInterSegment) else if (i.tm.opcode_modifier & JumpInterSegment)
{ {
@ -3912,9 +3853,13 @@ md_apply_fix3 (fixP, valp, seg)
value += fixP->fx_where + fixP->fx_frag->fr_address; value += fixP->fx_where + fixP->fx_frag->fr_address;
#endif #endif
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
&& (S_GET_SEGMENT (fixP->fx_addsy) == seg {
|| symbol_section_p (fixP->fx_addsy)) segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
if ((fseg == seg
|| (symbol_section_p (fixP->fx_addsy)
&& fseg != absolute_section))
&& ! S_IS_EXTERNAL (fixP->fx_addsy) && ! S_IS_EXTERNAL (fixP->fx_addsy)
&& ! S_IS_WEAK (fixP->fx_addsy) && ! S_IS_WEAK (fixP->fx_addsy)
&& S_IS_DEFINED (fixP->fx_addsy) && S_IS_DEFINED (fixP->fx_addsy)
@ -3926,6 +3871,7 @@ md_apply_fix3 (fixP, valp, seg)
it. FIXME. */ it. FIXME. */
value += fixP->fx_where + fixP->fx_frag->fr_address; value += fixP->fx_where + fixP->fx_frag->fr_address;
} }
}
#endif #endif
#if defined (OBJ_COFF) && defined (TE_PE) #if defined (OBJ_COFF) && defined (TE_PE)
/* For some reason, the PE format does not store a section /* For some reason, the PE format does not store a section