mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 12:23:31 +08:00
* coff-mips.c (mips_howto_table): Add entry for MIPS_R_SWITCH.
(mips_ecoff_swap_reloc_in): For MIPS_R_SWTICH, copy r_symndx into r_offset and set r_symndx to RELOC_SECTION_TEXT. (mips_ecoff_swap_reloc_out): For MIPS_R_SWITCH, get the r_symndx value from the r_offset field. (mips_adjust_reloc_in): Maximum r_type value is now MIPS_R_SWITCH. For MIPS_R_SWITCH, copy the r_offset field into the addend field. (mips_adjust_reloc_out): For MIPS_R_SWITCH, copy the addend field into the r_offset field. (mips_switch_reloc): New function. (mips_bfd_reloc_type_lookup): Translate BFD_RELOC_GPREL32 into MIPS_R_SWITCH. (mips_relocate_section): Handle MIPS_R_SWITCH. (mips_relax_section): Adjust MIPS_R_SWITCH offset if necessary.
This commit is contained in:
@ -1,3 +1,20 @@
|
|||||||
|
Thu Apr 7 14:23:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
||||||
|
|
||||||
|
* coff-mips.c (mips_howto_table): Add entry for MIPS_R_SWITCH.
|
||||||
|
(mips_ecoff_swap_reloc_in): For MIPS_R_SWTICH, copy r_symndx into
|
||||||
|
r_offset and set r_symndx to RELOC_SECTION_TEXT.
|
||||||
|
(mips_ecoff_swap_reloc_out): For MIPS_R_SWITCH, get the r_symndx
|
||||||
|
value from the r_offset field.
|
||||||
|
(mips_adjust_reloc_in): Maximum r_type value is now MIPS_R_SWITCH.
|
||||||
|
For MIPS_R_SWITCH, copy the r_offset field into the addend field.
|
||||||
|
(mips_adjust_reloc_out): For MIPS_R_SWITCH, copy the addend field
|
||||||
|
into the r_offset field.
|
||||||
|
(mips_switch_reloc): New function.
|
||||||
|
(mips_bfd_reloc_type_lookup): Translate BFD_RELOC_GPREL32 into
|
||||||
|
MIPS_R_SWITCH.
|
||||||
|
(mips_relocate_section): Handle MIPS_R_SWITCH.
|
||||||
|
(mips_relax_section): Adjust MIPS_R_SWITCH offset if necessary.
|
||||||
|
|
||||||
Thu Apr 7 11:10:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
|
Thu Apr 7 11:10:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
|
||||||
|
|
||||||
* elfcode.h (elf_set_section_contents): Support calling the backend
|
* elfcode.h (elf_set_section_contents): Support calling the backend
|
||||||
|
249
bfd/coff-mips.c
249
bfd/coff-mips.c
@ -72,6 +72,13 @@ static bfd_reloc_status_type mips_gprel_reloc PARAMS ((bfd *abfd,
|
|||||||
asection *section,
|
asection *section,
|
||||||
bfd *output_bfd,
|
bfd *output_bfd,
|
||||||
char **error));
|
char **error));
|
||||||
|
static bfd_reloc_status_type mips_switch_reloc PARAMS ((bfd *abfd,
|
||||||
|
arelent *reloc,
|
||||||
|
asymbol *symbol,
|
||||||
|
PTR data,
|
||||||
|
asection *section,
|
||||||
|
bfd *output_bfd,
|
||||||
|
char **error));
|
||||||
static void mips_relocate_refhi PARAMS ((struct internal_reloc *refhi,
|
static void mips_relocate_refhi PARAMS ((struct internal_reloc *refhi,
|
||||||
struct internal_reloc *reflo,
|
struct internal_reloc *reflo,
|
||||||
bfd *input_bfd,
|
bfd *input_bfd,
|
||||||
@ -262,6 +269,26 @@ static reloc_howto_type mips_howto_table[] =
|
|||||||
true, /* partial_inplace */
|
true, /* partial_inplace */
|
||||||
0xffff, /* src_mask */
|
0xffff, /* src_mask */
|
||||||
0xffff, /* dst_mask */
|
0xffff, /* dst_mask */
|
||||||
|
true), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* This reloc is a Cygnus extension used when generating position
|
||||||
|
independent code for embedded systems. It represents an entry in
|
||||||
|
a switch table, which is the difference between two symbols in
|
||||||
|
the .text section. The symndx is actually the offset from the
|
||||||
|
reloc address to the subtrahend. See include/coff/mips.h for
|
||||||
|
more details. */
|
||||||
|
HOWTO (MIPS_R_SWITCH, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||||
|
32, /* bitsize */
|
||||||
|
true, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
mips_switch_reloc, /* special_function */
|
||||||
|
"SWITCH", /* name */
|
||||||
|
true, /* partial_inplace */
|
||||||
|
0xffffffff, /* src_mask */
|
||||||
|
0xffffffff, /* dst_mask */
|
||||||
true) /* pcrel_offset */
|
true) /* pcrel_offset */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -353,6 +380,19 @@ mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
|
|||||||
>> RELOC_BITS3_TYPE_SH_LITTLE);
|
>> RELOC_BITS3_TYPE_SH_LITTLE);
|
||||||
intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
|
intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If this is a MIPS_R_SWITCH reloc, r_symndx is actually the offset
|
||||||
|
from the reloc address to the base of the difference (see
|
||||||
|
include/coff/mips.h for more details). We copy symndx into the
|
||||||
|
r_offset field so as not to confuse ecoff_slurp_reloc_table in
|
||||||
|
ecoff.c. In adjust_reloc_in we then copy r_offset into the reloc
|
||||||
|
addend. */
|
||||||
|
if (intern->r_type == MIPS_R_SWITCH)
|
||||||
|
{
|
||||||
|
BFD_ASSERT (! intern->r_extern);
|
||||||
|
intern->r_offset = intern->r_symndx;
|
||||||
|
intern->r_symndx = RELOC_SECTION_TEXT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap a reloc out. */
|
/* Swap a reloc out. */
|
||||||
@ -364,25 +404,37 @@ mips_ecoff_swap_reloc_out (abfd, intern, dst)
|
|||||||
PTR dst;
|
PTR dst;
|
||||||
{
|
{
|
||||||
RELOC *ext = (RELOC *) dst;
|
RELOC *ext = (RELOC *) dst;
|
||||||
|
long r_symndx;
|
||||||
|
|
||||||
BFD_ASSERT (intern->r_extern
|
BFD_ASSERT (intern->r_extern
|
||||||
|| (intern->r_symndx >= 0 && intern->r_symndx <= 12));
|
|| (intern->r_symndx >= 0 && intern->r_symndx <= 12));
|
||||||
|
|
||||||
|
/* If this is a MIPS_R_SWITCH reloc, we actually want to write the
|
||||||
|
contents of r_offset out as the symbol index. This undoes the
|
||||||
|
change made by mips_ecoff_swap_reloc_in. */
|
||||||
|
if (intern->r_type != MIPS_R_SWITCH)
|
||||||
|
r_symndx = intern->r_symndx;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);
|
||||||
|
r_symndx = intern->r_offset;
|
||||||
|
}
|
||||||
|
|
||||||
bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
|
bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
|
||||||
if (abfd->xvec->header_byteorder_big_p != false)
|
if (abfd->xvec->header_byteorder_big_p != false)
|
||||||
{
|
{
|
||||||
ext->r_bits[0] = intern->r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
|
ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
|
||||||
ext->r_bits[1] = intern->r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
|
ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
|
||||||
ext->r_bits[2] = intern->r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
|
ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
|
||||||
ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
|
ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
|
||||||
& RELOC_BITS3_TYPE_BIG)
|
& RELOC_BITS3_TYPE_BIG)
|
||||||
| (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
|
| (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ext->r_bits[0] = intern->r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
|
ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
|
||||||
ext->r_bits[1] = intern->r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
|
ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
|
||||||
ext->r_bits[2] = intern->r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
|
ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
|
||||||
ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
|
ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
|
||||||
& RELOC_BITS3_TYPE_LITTLE)
|
& RELOC_BITS3_TYPE_LITTLE)
|
||||||
| (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
|
| (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
|
||||||
@ -399,7 +451,7 @@ mips_adjust_reloc_in (abfd, intern, rptr)
|
|||||||
const struct internal_reloc *intern;
|
const struct internal_reloc *intern;
|
||||||
arelent *rptr;
|
arelent *rptr;
|
||||||
{
|
{
|
||||||
if (intern->r_type > MIPS_R_PCREL16)
|
if (intern->r_type > MIPS_R_SWITCH)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
if (! intern->r_extern
|
if (! intern->r_extern
|
||||||
@ -412,6 +464,14 @@ mips_adjust_reloc_in (abfd, intern, rptr)
|
|||||||
if (intern->r_type == MIPS_R_IGNORE)
|
if (intern->r_type == MIPS_R_IGNORE)
|
||||||
rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
|
rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
|
||||||
|
|
||||||
|
/* If this is a MIPS_R_SWITCH reloc, we want the addend field of the
|
||||||
|
BFD relocto hold the value which was originally in the symndx
|
||||||
|
field of the internal MIPS ECOFF reloc. This value was copied
|
||||||
|
into intern->r_offset by mips_swap_reloc_in, and here we copy it
|
||||||
|
into the addend field. */
|
||||||
|
if (intern->r_type == MIPS_R_SWITCH)
|
||||||
|
rptr->addend = intern->r_offset;
|
||||||
|
|
||||||
rptr->howto = &mips_howto_table[intern->r_type];
|
rptr->howto = &mips_howto_table[intern->r_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,6 +484,12 @@ mips_adjust_reloc_out (abfd, rel, intern)
|
|||||||
const arelent *rel;
|
const arelent *rel;
|
||||||
struct internal_reloc *intern;
|
struct internal_reloc *intern;
|
||||||
{
|
{
|
||||||
|
/* For a MIPS_R_SWITCH reloc we must copy rel->addend into
|
||||||
|
intern->r_offset. This will then be written out as the symbol
|
||||||
|
index by mips_ecoff_swap_reloc_out. This operation parallels the
|
||||||
|
action of mips_adjust_reloc_in. */
|
||||||
|
if (intern->r_type == MIPS_R_SWITCH)
|
||||||
|
intern->r_offset = rel->addend;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ECOFF relocs are either against external symbols, or against
|
/* ECOFF relocs are either against external symbols, or against
|
||||||
@ -724,6 +790,31 @@ mips_gprel_reloc (abfd,
|
|||||||
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the special function for the MIPS_R_SWITCH reloc. This
|
||||||
|
special reloc is normally correct in the object file, and only
|
||||||
|
requires special handling when relaxing. We don't want
|
||||||
|
bfd_perform_relocation to tamper with it at all. */
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
static bfd_reloc_status_type
|
||||||
|
mips_switch_reloc (abfd,
|
||||||
|
reloc_entry,
|
||||||
|
symbol,
|
||||||
|
data,
|
||||||
|
input_section,
|
||||||
|
output_bfd,
|
||||||
|
error_message)
|
||||||
|
bfd *abfd;
|
||||||
|
arelent *reloc_entry;
|
||||||
|
asymbol *symbol;
|
||||||
|
PTR data;
|
||||||
|
asection *input_section;
|
||||||
|
bfd *output_bfd;
|
||||||
|
char **error_message;
|
||||||
|
{
|
||||||
|
return bfd_reloc_ok;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the howto structure for a generic reloc type. */
|
/* Get the howto structure for a generic reloc type. */
|
||||||
|
|
||||||
static CONST struct reloc_howto_struct *
|
static CONST struct reloc_howto_struct *
|
||||||
@ -760,6 +851,9 @@ mips_bfd_reloc_type_lookup (abfd, code)
|
|||||||
case BFD_RELOC_16_PCREL_S2:
|
case BFD_RELOC_16_PCREL_S2:
|
||||||
mips_type = MIPS_R_PCREL16;
|
mips_type = MIPS_R_PCREL16;
|
||||||
break;
|
break;
|
||||||
|
case BFD_RELOC_GPREL32:
|
||||||
|
mips_type = MIPS_R_SWITCH;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return (CONST struct reloc_howto_struct *) NULL;
|
return (CONST struct reloc_howto_struct *) NULL;
|
||||||
}
|
}
|
||||||
@ -938,6 +1032,32 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
|
|
||||||
howto = &mips_howto_table[int_rel.r_type];
|
howto = &mips_howto_table[int_rel.r_type];
|
||||||
|
|
||||||
|
/* The SWITCH reloc must be handled specially. This reloc is
|
||||||
|
marks the location of a difference between two portions of an
|
||||||
|
object file. The symbol index does not reference a symbol,
|
||||||
|
but is actually the offset from the reloc to the subtrahend
|
||||||
|
of the difference. This reloc is correct in the object file,
|
||||||
|
and needs no further adjustment, unless we are relaxing. If
|
||||||
|
we are relaxing, we may have to add in an offset. Since no
|
||||||
|
symbols are involved in this reloc, we handle it completely
|
||||||
|
here. */
|
||||||
|
if (int_rel.r_type == MIPS_R_SWITCH)
|
||||||
|
{
|
||||||
|
if (offsets != NULL
|
||||||
|
&& offsets[i] != 0)
|
||||||
|
{
|
||||||
|
r = _bfd_relocate_contents (howto, input_bfd,
|
||||||
|
(bfd_vma) offsets[i],
|
||||||
|
(contents
|
||||||
|
+ adjust
|
||||||
|
+ int_rel.r_vaddr
|
||||||
|
- input_section->vma));
|
||||||
|
BFD_ASSERT (r == bfd_reloc_ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (int_rel.r_extern)
|
if (int_rel.r_extern)
|
||||||
{
|
{
|
||||||
h = sym_hashes[int_rel.r_symndx];
|
h = sym_hashes[int_rel.r_symndx];
|
||||||
@ -1532,60 +1652,105 @@ mips_relax_section (abfd, sec, info, again)
|
|||||||
|
|
||||||
offsets[i] = 1;
|
offsets[i] = 1;
|
||||||
|
|
||||||
/* Now look for all PC relative branches that cross this reloc
|
/* Now look for all PC relative branches or switch table entries
|
||||||
and adjust their offsets. We will turn the single branch
|
that cross this reloc and adjust their offsets. We will turn
|
||||||
instruction into a four instruction sequence. In this loop
|
the single branch instruction into a four instruction
|
||||||
we are only interested in local PC relative branches. */
|
sequence. In this loop we are only interested in local PC
|
||||||
|
relative branches. */
|
||||||
adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
|
adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
|
||||||
for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
|
for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
|
||||||
{
|
{
|
||||||
|
int r_type;
|
||||||
struct internal_reloc adj_int_rel;
|
struct internal_reloc adj_int_rel;
|
||||||
unsigned long insn;
|
|
||||||
bfd_vma dst;
|
|
||||||
|
|
||||||
/* Quickly check that this reloc is internal PCREL16. */
|
/* Quickly check that this reloc is internal PCREL16 or
|
||||||
|
SWITCH. */
|
||||||
if (abfd->xvec->header_byteorder_big_p)
|
if (abfd->xvec->header_byteorder_big_p)
|
||||||
{
|
{
|
||||||
if ((adj_ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0
|
if ((adj_ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0)
|
||||||
|| (((adj_ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
|
continue;
|
||||||
>> RELOC_BITS3_TYPE_SH_BIG)
|
r_type = ((adj_ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
|
||||||
!= MIPS_R_PCREL16))
|
>> RELOC_BITS3_TYPE_SH_BIG);
|
||||||
|
if (r_type != MIPS_R_PCREL16
|
||||||
|
&& r_type != MIPS_R_SWITCH)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((adj_ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0
|
if ((adj_ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0)
|
||||||
|| (((adj_ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
|
continue;
|
||||||
>> RELOC_BITS3_TYPE_SH_LITTLE)
|
r_type = ((adj_ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
|
||||||
!= MIPS_R_PCREL16))
|
>> RELOC_BITS3_TYPE_SH_LITTLE);
|
||||||
|
if (r_type != MIPS_R_PCREL16
|
||||||
|
&& r_type != MIPS_R_SWITCH)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
|
mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
|
||||||
|
|
||||||
/* We are only interested in a PC relative reloc within this
|
if (r_type == MIPS_R_PCREL16)
|
||||||
section. FIXME: Cross section PC relative relocs may not
|
{
|
||||||
be handled correctly; does anybody care? */
|
unsigned long insn;
|
||||||
if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
|
bfd_vma dst;
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Fetch the branch instruction. */
|
/* We are only interested in a PC relative reloc within
|
||||||
insn = bfd_get_32 (abfd, contents + adj_int_rel.r_vaddr - sec->vma);
|
this section. FIXME: Cross section PC relative
|
||||||
|
relocs may not be handled correctly; does anybody
|
||||||
|
care? */
|
||||||
|
if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Work out the destination address. */
|
/* Fetch the branch instruction. */
|
||||||
dst = (insn & 0xffff) << 2;
|
insn = bfd_get_32 (abfd,
|
||||||
if ((dst & 0x20000) != 0)
|
contents + adj_int_rel.r_vaddr - sec->vma);
|
||||||
dst -= 0x40000;
|
|
||||||
dst += adj_int_rel.r_vaddr + 4;
|
|
||||||
|
|
||||||
/* If this branch crosses the branch we just decided to
|
/* Work out the destination address. */
|
||||||
expand, adjust the offset appropriately. */
|
dst = (insn & 0xffff) << 2;
|
||||||
if (adj_int_rel.r_vaddr < int_rel.r_vaddr
|
if ((dst & 0x20000) != 0)
|
||||||
&& dst > int_rel.r_vaddr)
|
dst -= 0x40000;
|
||||||
offsets[adj_i] += PCREL16_EXPANSION_ADJUSTMENT;
|
dst += adj_int_rel.r_vaddr + 4;
|
||||||
else if (adj_int_rel.r_vaddr > int_rel.r_vaddr
|
|
||||||
&& dst <= int_rel.r_vaddr)
|
/* If this branch crosses the branch we just decided to
|
||||||
offsets[adj_i] -= PCREL16_EXPANSION_ADJUSTMENT;
|
expand, adjust the offset appropriately. */
|
||||||
|
if (adj_int_rel.r_vaddr <= int_rel.r_vaddr
|
||||||
|
&& dst > int_rel.r_vaddr)
|
||||||
|
offsets[adj_i] += PCREL16_EXPANSION_ADJUSTMENT;
|
||||||
|
else if (adj_int_rel.r_vaddr > int_rel.r_vaddr
|
||||||
|
&& dst <= int_rel.r_vaddr)
|
||||||
|
offsets[adj_i] -= PCREL16_EXPANSION_ADJUSTMENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_vma start, stop;
|
||||||
|
|
||||||
|
/* A MIPS_R_SWITCH reloc represents a word of the form
|
||||||
|
.word $L3-$LS12
|
||||||
|
The value in the object file is correct, assuming the
|
||||||
|
original value of $L3. The symndx value is actually
|
||||||
|
the difference between the reloc address and $LS12.
|
||||||
|
This lets us compute the original value of $LS12 as
|
||||||
|
vaddr - symndx
|
||||||
|
and the original value of $L3 as
|
||||||
|
vaddr - symndx + addend
|
||||||
|
where addend is the value from the object file. At
|
||||||
|
this point, the symndx value is actually found in the
|
||||||
|
r_offset field, since it was moved by
|
||||||
|
mips_ecoff_swap_reloc_in. */
|
||||||
|
|
||||||
|
start = adj_int_rel.r_vaddr - adj_int_rel.r_offset;
|
||||||
|
stop = start + bfd_get_32 (abfd,
|
||||||
|
(contents
|
||||||
|
+ adj_int_rel.r_vaddr
|
||||||
|
- sec->vma));
|
||||||
|
|
||||||
|
/* The value we want in the object file is stop - start.
|
||||||
|
If the expanded branch lies between start and stop,
|
||||||
|
we must adjust the offset. */
|
||||||
|
if (start <= int_rel.r_vaddr && stop > int_rel.r_vaddr)
|
||||||
|
offsets[adj_i] += PCREL16_EXPANSION_ADJUSTMENT;
|
||||||
|
else if (start > int_rel.r_vaddr && stop <= int_rel.r_vaddr)
|
||||||
|
offsets[adj_i] -= PCREL16_EXPANSION_ADJUSTMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find all symbols in this section defined by this object file
|
/* Find all symbols in this section defined by this object file
|
||||||
|
Reference in New Issue
Block a user