mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-29 08:24:05 +08:00
* coff-sh.c (sh_relax_delete_bytes): Correct address comparisons
when handling 32 bit immediate relocs. * elf32-sh.c (sh_elf_relax_delete_bytes): Likewise.
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
Wed Jul 1 16:58:50 1998 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
|
* coff-sh.c (sh_relax_delete_bytes): Correct address comparisons
|
||||||
|
when handling 32 bit immediate relocs.
|
||||||
|
* elf32-sh.c (sh_elf_relax_delete_bytes): Likewise.
|
||||||
|
|
||||||
Tue Jun 30 09:55:03 1998 Jeffrey A Law (law@cygnus.com)
|
Tue Jun 30 09:55:03 1998 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
* section.c (STD_SECTION): Account for recently added gc_mark
|
* section.c (STD_SECTION): Account for recently added gc_mark
|
||||||
|
442
bfd/coff-sh.c
442
bfd/coff-sh.c
@ -1,5 +1,5 @@
|
|||||||
/* BFD back-end for Hitachi Super-H COFF binaries.
|
/* BFD back-end for Hitachi Super-H COFF binaries.
|
||||||
Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
|
||||||
Contributed by Cygnus Support.
|
Contributed by Cygnus Support.
|
||||||
Written by Steve Chamberlain, <sac@cygnus.com>.
|
Written by Steve Chamberlain, <sac@cygnus.com>.
|
||||||
Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
|
Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
|
||||||
@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||||||
|
|
||||||
#include "bfd.h"
|
#include "bfd.h"
|
||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
#include "obstack.h"
|
|
||||||
#include "libbfd.h"
|
#include "libbfd.h"
|
||||||
#include "bfdlink.h"
|
#include "bfdlink.h"
|
||||||
#include "coff/sh.h"
|
#include "coff/sh.h"
|
||||||
@ -33,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||||||
static bfd_reloc_status_type sh_reloc
|
static bfd_reloc_status_type sh_reloc
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
||||||
static long get_symbol_value PARAMS ((asymbol *));
|
static long get_symbol_value PARAMS ((asymbol *));
|
||||||
|
static boolean sh_merge_private_data PARAMS ((bfd *, bfd *));
|
||||||
static boolean sh_relax_section
|
static boolean sh_relax_section
|
||||||
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
|
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
|
||||||
static boolean sh_relax_delete_bytes
|
static boolean sh_relax_delete_bytes
|
||||||
@ -41,7 +41,7 @@ static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
|
|||||||
static boolean sh_align_loads
|
static boolean sh_align_loads
|
||||||
PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *, boolean *));
|
PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *, boolean *));
|
||||||
static boolean sh_swap_insns
|
static boolean sh_swap_insns
|
||||||
PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *, bfd_vma));
|
PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
|
||||||
static boolean sh_relocate_section
|
static boolean sh_relocate_section
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
||||||
struct internal_reloc *, struct internal_syment *, asection **));
|
struct internal_reloc *, struct internal_syment *, asection **));
|
||||||
@ -49,8 +49,8 @@ static bfd_byte *sh_coff_get_relocated_section_contents
|
|||||||
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
|
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
|
||||||
bfd_byte *, boolean, asymbol **));
|
bfd_byte *, boolean, asymbol **));
|
||||||
|
|
||||||
/* Default section alignment to 2**2. */
|
/* Default section alignment to 2**4. */
|
||||||
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
|
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (4)
|
||||||
|
|
||||||
/* Generate long file names. */
|
/* Generate long file names. */
|
||||||
#define COFF_LONG_FILENAMES
|
#define COFF_LONG_FILENAMES
|
||||||
@ -276,6 +276,20 @@ static reloc_howto_type sh_coff_howtos[] =
|
|||||||
true, /* partial_inplace */
|
true, /* partial_inplace */
|
||||||
0xffffffff, /* src_mask */
|
0xffffffff, /* src_mask */
|
||||||
0xffffffff, /* dst_mask */
|
0xffffffff, /* dst_mask */
|
||||||
|
false), /* pcrel_offset */
|
||||||
|
|
||||||
|
HOWTO (R_SH_SWITCH8, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
0, /* size (0 = byte, 1 = short, 2 = long) */
|
||||||
|
8, /* bitsize */
|
||||||
|
false, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_bitfield, /* complain_on_overflow */
|
||||||
|
sh_reloc, /* special_function */
|
||||||
|
"r_switch8", /* name */
|
||||||
|
true, /* partial_inplace */
|
||||||
|
0xff, /* src_mask */
|
||||||
|
0xff, /* dst_mask */
|
||||||
false) /* pcrel_offset */
|
false) /* pcrel_offset */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -348,7 +362,8 @@ get_symbol_value (symbol)
|
|||||||
cache_ptr->addend = - (ptr->section->vma + ptr->value); \
|
cache_ptr->addend = - (ptr->section->vma + ptr->value); \
|
||||||
else \
|
else \
|
||||||
cache_ptr->addend = 0; \
|
cache_ptr->addend = 0; \
|
||||||
if ((reloc).r_type == R_SH_SWITCH16 \
|
if ((reloc).r_type == R_SH_SWITCH8 \
|
||||||
|
|| (reloc).r_type == R_SH_SWITCH16 \
|
||||||
|| (reloc).r_type == R_SH_SWITCH32 \
|
|| (reloc).r_type == R_SH_SWITCH32 \
|
||||||
|| (reloc).r_type == R_SH_USES \
|
|| (reloc).r_type == R_SH_USES \
|
||||||
|| (reloc).r_type == R_SH_COUNT \
|
|| (reloc).r_type == R_SH_COUNT \
|
||||||
@ -427,6 +442,32 @@ sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
|
|||||||
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This routine checks for linking big and little endian objects
|
||||||
|
together. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
sh_merge_private_data (ibfd, obfd)
|
||||||
|
bfd *ibfd;
|
||||||
|
bfd *obfd;
|
||||||
|
{
|
||||||
|
if (ibfd->xvec->byteorder != obfd->xvec->byteorder
|
||||||
|
&& obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
("%s: compiled for a %s endian system and target is %s endian",
|
||||||
|
bfd_get_filename (ibfd),
|
||||||
|
bfd_big_endian (ibfd) ? "big" : "little",
|
||||||
|
bfd_big_endian (obfd) ? "big" : "little");
|
||||||
|
|
||||||
|
bfd_set_error (bfd_error_wrong_format);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define coff_bfd_merge_private_bfd_data sh_merge_private_data
|
||||||
|
|
||||||
/* We can do relaxing. */
|
/* We can do relaxing. */
|
||||||
#define coff_bfd_relax_section sh_relax_section
|
#define coff_bfd_relax_section sh_relax_section
|
||||||
|
|
||||||
@ -558,7 +599,9 @@ sh_relax_section (abfd, sec, link_info, again)
|
|||||||
the register load. The 4 is because the r_offset field is
|
the register load. The 4 is because the r_offset field is
|
||||||
computed as though it were a jump offset, which are based
|
computed as though it were a jump offset, which are based
|
||||||
from 4 bytes after the jump instruction. */
|
from 4 bytes after the jump instruction. */
|
||||||
laddr = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
|
laddr = irel->r_vaddr - sec->vma + 4;
|
||||||
|
/* Careful to sign extend the 32-bit offset. */
|
||||||
|
laddr += ((irel->r_offset & 0xffffffff) ^ 0x80000000) - 0x80000000;
|
||||||
if (laddr >= sec->_raw_size)
|
if (laddr >= sec->_raw_size)
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler) ("%s: 0x%lx: warning: bad R_SH_USES offset",
|
(*_bfd_error_handler) ("%s: 0x%lx: warning: bad R_SH_USES offset",
|
||||||
@ -568,8 +611,7 @@ sh_relax_section (abfd, sec, link_info, again)
|
|||||||
}
|
}
|
||||||
insn = bfd_get_16 (abfd, contents + laddr);
|
insn = bfd_get_16 (abfd, contents + laddr);
|
||||||
|
|
||||||
/* If the instruction is not mov.l NN,rN, we don't know what to
|
/* If the instruction is not mov.l NN,rN, we don't know what to do. */
|
||||||
do. */
|
|
||||||
if ((insn & 0xf000) != 0xd000)
|
if ((insn & 0xf000) != 0xd000)
|
||||||
{
|
{
|
||||||
((*_bfd_error_handler)
|
((*_bfd_error_handler)
|
||||||
@ -929,11 +971,12 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
/* Adjust all the relocs. */
|
/* Adjust all the relocs. */
|
||||||
for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
|
for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
|
||||||
{
|
{
|
||||||
bfd_vma nraddr, start, stop;
|
bfd_vma nraddr, stop;
|
||||||
|
bfd_vma start = 0;
|
||||||
int insn = 0;
|
int insn = 0;
|
||||||
struct internal_syment sym;
|
struct internal_syment sym;
|
||||||
int off, adjust, oinsn;
|
int off, adjust, oinsn;
|
||||||
bfd_signed_vma voff;
|
bfd_signed_vma voff = 0;
|
||||||
boolean overflow;
|
boolean overflow;
|
||||||
|
|
||||||
/* Get the new reloc address. */
|
/* Get the new reloc address. */
|
||||||
@ -951,7 +994,8 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
&& irel->r_vaddr - sec->vma < addr + count
|
&& irel->r_vaddr - sec->vma < addr + count
|
||||||
&& irel->r_type != R_SH_ALIGN
|
&& irel->r_type != R_SH_ALIGN
|
||||||
&& irel->r_type != R_SH_CODE
|
&& irel->r_type != R_SH_CODE
|
||||||
&& irel->r_type != R_SH_DATA)
|
&& irel->r_type != R_SH_DATA
|
||||||
|
&& irel->r_type != R_SH_LABEL)
|
||||||
irel->r_type = R_SH_UNUSED;
|
irel->r_type = R_SH_UNUSED;
|
||||||
|
|
||||||
/* If this is a PC relative reloc, see if the range it covers
|
/* If this is a PC relative reloc, see if the range it covers
|
||||||
@ -995,7 +1039,7 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
|
|
||||||
val = bfd_get_32 (abfd, contents + nraddr);
|
val = bfd_get_32 (abfd, contents + nraddr);
|
||||||
val += sym.n_value;
|
val += sym.n_value;
|
||||||
if (val >= addr && val < toaddr)
|
if (val > addr && val < toaddr)
|
||||||
bfd_put_32 (abfd, val - count, contents + nraddr);
|
bfd_put_32 (abfd, val - count, contents + nraddr);
|
||||||
}
|
}
|
||||||
start = stop = addr;
|
start = stop = addr;
|
||||||
@ -1035,6 +1079,7 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
|
stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_SH_SWITCH8:
|
||||||
case R_SH_SWITCH16:
|
case R_SH_SWITCH16:
|
||||||
case R_SH_SWITCH32:
|
case R_SH_SWITCH32:
|
||||||
/* These relocs types represent
|
/* These relocs types represent
|
||||||
@ -1060,6 +1105,8 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
|
|
||||||
if (irel->r_type == R_SH_SWITCH16)
|
if (irel->r_type == R_SH_SWITCH16)
|
||||||
voff = bfd_get_signed_16 (abfd, contents + nraddr);
|
voff = bfd_get_signed_16 (abfd, contents + nraddr);
|
||||||
|
else if (irel->r_type == R_SH_SWITCH8)
|
||||||
|
voff = bfd_get_8 (abfd, contents + nraddr);
|
||||||
else
|
else
|
||||||
voff = bfd_get_signed_32 (abfd, contents + nraddr);
|
voff = bfd_get_signed_32 (abfd, contents + nraddr);
|
||||||
stop = (bfd_vma) ((bfd_signed_vma) start + voff);
|
stop = (bfd_vma) ((bfd_signed_vma) start + voff);
|
||||||
@ -1124,6 +1171,13 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
bfd_put_16 (abfd, insn, contents + nraddr);
|
bfd_put_16 (abfd, insn, contents + nraddr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_SH_SWITCH8:
|
||||||
|
voff += adjust;
|
||||||
|
if (voff < 0 || voff >= 0xff)
|
||||||
|
overflow = true;
|
||||||
|
bfd_put_8 (abfd, voff, contents + nraddr);
|
||||||
|
break;
|
||||||
|
|
||||||
case R_SH_SWITCH16:
|
case R_SH_SWITCH16:
|
||||||
voff += adjust;
|
voff += adjust;
|
||||||
if (voff < - 0x8000 || voff >= 0x8000)
|
if (voff < - 0x8000 || voff >= 0x8000)
|
||||||
@ -1221,7 +1275,7 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
|
|
||||||
val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
|
val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
|
||||||
val += sym.n_value;
|
val += sym.n_value;
|
||||||
if (val >= addr && val < toaddr)
|
if (val > addr && val < toaddr)
|
||||||
bfd_put_32 (abfd, val - count,
|
bfd_put_32 (abfd, val - count,
|
||||||
ocontents + irelscan->r_vaddr - o->vma);
|
ocontents + irelscan->r_vaddr - o->vma);
|
||||||
|
|
||||||
@ -1281,16 +1335,16 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
|
|||||||
r_vaddr for it already. */
|
r_vaddr for it already. */
|
||||||
if (irelalign != NULL)
|
if (irelalign != NULL)
|
||||||
{
|
{
|
||||||
bfd_vma alignaddr;
|
bfd_vma alignto, alignaddr;
|
||||||
|
|
||||||
|
alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_offset);
|
||||||
alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
|
alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
|
||||||
1 << irelalign->r_offset);
|
1 << irelalign->r_offset);
|
||||||
if (alignaddr != toaddr)
|
if (alignto != alignaddr)
|
||||||
{
|
{
|
||||||
/* Tail recursion. */
|
/* Tail recursion. */
|
||||||
return sh_relax_delete_bytes (abfd, sec,
|
return sh_relax_delete_bytes (abfd, sec, alignaddr,
|
||||||
irelalign->r_vaddr - sec->vma,
|
alignto - alignaddr);
|
||||||
1 << irelalign->r_offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1883,7 +1937,8 @@ sh_insn_uses_freg (insn, op, freg)
|
|||||||
|
|
||||||
/* See whether instructions I1 and I2 conflict, assuming I1 comes
|
/* See whether instructions I1 and I2 conflict, assuming I1 comes
|
||||||
before I2. OP1 and OP2 are the corresponding sh_opcode structures.
|
before I2. OP1 and OP2 are the corresponding sh_opcode structures.
|
||||||
This should return true if the instructions can be swapped safely. */
|
This should return true if there is a conflict, or false if the
|
||||||
|
instructions can be swapped safely. */
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
sh_insns_conflict (i1, op1, i2, op2)
|
sh_insns_conflict (i1, op1, i2, op2)
|
||||||
@ -1902,7 +1957,7 @@ sh_insns_conflict (i1, op1, i2, op2)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ((f1 & SETSSP) != 0 && (f2 & USESSP) != 0)
|
if ((f1 & SETSSP) != 0 && (f2 & USESSP) != 0)
|
||||||
return false;
|
return true;
|
||||||
if ((f2 & SETSSP) != 0 && (f1 & USESSP) != 0)
|
if ((f2 & SETSSP) != 0 && (f1 & USESSP) != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1972,63 +2027,31 @@ sh_load_use (i1, op1, i2, op2)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for loads and stores which we can align to four byte
|
/* Try to align loads and stores within a span of memory. This is
|
||||||
boundaries. See the longer comment above sh_relax_section for why
|
called by both the ELF and the COFF sh targets. ABFD and SEC are
|
||||||
this is desirable. This sets *PSWAPPED if some instruction was
|
the BFD and section we are examining. CONTENTS is the contents of
|
||||||
swapped. */
|
the section. SWAP is the routine to call to swap two instructions.
|
||||||
|
RELOCS is a pointer to the internal relocation information, to be
|
||||||
|
passed to SWAP. PLABEL is a pointer to the current label in a
|
||||||
|
sorted list of labels; LABEL_END is the end of the list. START and
|
||||||
|
STOP are the range of memory to examine. If a swap is made,
|
||||||
|
*PSWAPPED is set to true. */
|
||||||
|
|
||||||
static boolean
|
boolean
|
||||||
sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
_bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
|
||||||
|
plabel, label_end, start, stop, pswapped)
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
asection *sec;
|
asection *sec;
|
||||||
struct internal_reloc *internal_relocs;
|
|
||||||
bfd_byte *contents;
|
bfd_byte *contents;
|
||||||
|
boolean (*swap) PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
|
||||||
|
PTR relocs;
|
||||||
|
bfd_vma **plabel;
|
||||||
|
bfd_vma *label_end;
|
||||||
|
bfd_vma start;
|
||||||
|
bfd_vma stop;
|
||||||
boolean *pswapped;
|
boolean *pswapped;
|
||||||
{
|
{
|
||||||
struct internal_reloc *irel, *irelend;
|
bfd_vma i;
|
||||||
bfd_vma *labels = NULL;
|
|
||||||
bfd_vma *label, *label_end;
|
|
||||||
|
|
||||||
*pswapped = false;
|
|
||||||
|
|
||||||
irelend = internal_relocs + sec->reloc_count;
|
|
||||||
|
|
||||||
/* Get all the addresses with labels on them. */
|
|
||||||
labels = (bfd_vma *) bfd_malloc (sec->reloc_count * sizeof (bfd_vma));
|
|
||||||
if (labels == NULL)
|
|
||||||
goto error_return;
|
|
||||||
label_end = labels;
|
|
||||||
for (irel = internal_relocs; irel < irelend; irel++)
|
|
||||||
{
|
|
||||||
if (irel->r_type == R_SH_LABEL)
|
|
||||||
{
|
|
||||||
*label_end = irel->r_vaddr - sec->vma;
|
|
||||||
++label_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that the assembler currently always outputs relocs in
|
|
||||||
address order. If that ever changes, this code will need to sort
|
|
||||||
the label values and the relocs. */
|
|
||||||
|
|
||||||
label = labels;
|
|
||||||
|
|
||||||
for (irel = internal_relocs; irel < irelend; irel++)
|
|
||||||
{
|
|
||||||
bfd_vma start, stop, i;
|
|
||||||
|
|
||||||
if (irel->r_type != R_SH_CODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
start = irel->r_vaddr - sec->vma;
|
|
||||||
|
|
||||||
for (irel++; irel < irelend; irel++)
|
|
||||||
if (irel->r_type == R_SH_DATA)
|
|
||||||
break;
|
|
||||||
if (irel < irelend)
|
|
||||||
stop = irel->r_vaddr - sec->vma;
|
|
||||||
else
|
|
||||||
stop = sec->_cooked_size;
|
|
||||||
|
|
||||||
/* Instructions should be aligned on 2 byte boundaries. */
|
/* Instructions should be aligned on 2 byte boundaries. */
|
||||||
if ((start & 1) == 1)
|
if ((start & 1) == 1)
|
||||||
@ -2051,11 +2074,10 @@ sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
|||||||
|| (op->flags & (LOAD | STORE)) == 0)
|
|| (op->flags & (LOAD | STORE)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* This is a load or store which is not on a four byte
|
/* This is a load or store which is not on a four byte boundary. */
|
||||||
boundary. */
|
|
||||||
|
|
||||||
while (label < label_end && *label < i)
|
while (*plabel < label_end && **plabel < i)
|
||||||
++label;
|
++*plabel;
|
||||||
|
|
||||||
if (i > start)
|
if (i > start)
|
||||||
{
|
{
|
||||||
@ -2069,7 +2091,7 @@ sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i > start
|
if (i > start
|
||||||
&& (label >= label_end || *label != i)
|
&& (*plabel >= label_end || **plabel != i)
|
||||||
&& prev_op != NULL
|
&& prev_op != NULL
|
||||||
&& (prev_op->flags & (LOAD | STORE)) == 0
|
&& (prev_op->flags & (LOAD | STORE)) == 0
|
||||||
&& ! sh_insns_conflict (prev_insn, prev_op, insn, op))
|
&& ! sh_insns_conflict (prev_insn, prev_op, insn, op))
|
||||||
@ -2111,19 +2133,18 @@ sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
|||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
if (! sh_swap_insns (abfd, sec, internal_relocs,
|
if (! (*swap) (abfd, sec, relocs, contents, i - 2))
|
||||||
contents, i - 2))
|
return false;
|
||||||
goto error_return;
|
|
||||||
*pswapped = true;
|
*pswapped = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (label < label_end && *label < i + 2)
|
while (*plabel < label_end && **plabel < i + 2)
|
||||||
++label;
|
++*plabel;
|
||||||
|
|
||||||
if (i + 2 < stop
|
if (i + 2 < stop
|
||||||
&& (label >= label_end || *label != i + 2))
|
&& (*plabel >= label_end || **plabel != i + 2))
|
||||||
{
|
{
|
||||||
unsigned int next_insn;
|
unsigned int next_insn;
|
||||||
const struct sh_opcode *next_op;
|
const struct sh_opcode *next_op;
|
||||||
@ -2177,15 +2198,80 @@ sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
|||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
if (! sh_swap_insns (abfd, sec, internal_relocs,
|
if (! (*swap) (abfd, sec, relocs, contents, i))
|
||||||
contents, i))
|
return false;
|
||||||
goto error_return;
|
|
||||||
*pswapped = true;
|
*pswapped = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for loads and stores which we can align to four byte
|
||||||
|
boundaries. See the longer comment above sh_relax_section for why
|
||||||
|
this is desirable. This sets *PSWAPPED if some instruction was
|
||||||
|
swapped. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
||||||
|
bfd *abfd;
|
||||||
|
asection *sec;
|
||||||
|
struct internal_reloc *internal_relocs;
|
||||||
|
bfd_byte *contents;
|
||||||
|
boolean *pswapped;
|
||||||
|
{
|
||||||
|
struct internal_reloc *irel, *irelend;
|
||||||
|
bfd_vma *labels = NULL;
|
||||||
|
bfd_vma *label, *label_end;
|
||||||
|
|
||||||
|
*pswapped = false;
|
||||||
|
|
||||||
|
irelend = internal_relocs + sec->reloc_count;
|
||||||
|
|
||||||
|
/* Get all the addresses with labels on them. */
|
||||||
|
labels = (bfd_vma *) bfd_malloc (sec->reloc_count * sizeof (bfd_vma));
|
||||||
|
if (labels == NULL)
|
||||||
|
goto error_return;
|
||||||
|
label_end = labels;
|
||||||
|
for (irel = internal_relocs; irel < irelend; irel++)
|
||||||
|
{
|
||||||
|
if (irel->r_type == R_SH_LABEL)
|
||||||
|
{
|
||||||
|
*label_end = irel->r_vaddr - sec->vma;
|
||||||
|
++label_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that the assembler currently always outputs relocs in
|
||||||
|
address order. If that ever changes, this code will need to sort
|
||||||
|
the label values and the relocs. */
|
||||||
|
|
||||||
|
label = labels;
|
||||||
|
|
||||||
|
for (irel = internal_relocs; irel < irelend; irel++)
|
||||||
|
{
|
||||||
|
bfd_vma start, stop;
|
||||||
|
|
||||||
|
if (irel->r_type != R_SH_CODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
start = irel->r_vaddr - sec->vma;
|
||||||
|
|
||||||
|
for (irel++; irel < irelend; irel++)
|
||||||
|
if (irel->r_type == R_SH_DATA)
|
||||||
|
break;
|
||||||
|
if (irel < irelend)
|
||||||
|
stop = irel->r_vaddr - sec->vma;
|
||||||
|
else
|
||||||
|
stop = sec->_cooked_size;
|
||||||
|
|
||||||
|
if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_swap_insns,
|
||||||
|
(PTR) internal_relocs, &label,
|
||||||
|
label_end, start, stop, pswapped))
|
||||||
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (labels);
|
free (labels);
|
||||||
@ -2201,13 +2287,14 @@ sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
|
|||||||
/* Swap two SH instructions. */
|
/* Swap two SH instructions. */
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
sh_swap_insns (abfd, sec, internal_relocs, contents, addr)
|
sh_swap_insns (abfd, sec, relocs, contents, addr)
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
asection *sec;
|
asection *sec;
|
||||||
struct internal_reloc *internal_relocs;
|
PTR relocs;
|
||||||
bfd_byte *contents;
|
bfd_byte *contents;
|
||||||
bfd_vma addr;
|
bfd_vma addr;
|
||||||
{
|
{
|
||||||
|
struct internal_reloc *internal_relocs = (struct internal_reloc *) relocs;
|
||||||
unsigned short i1, i2;
|
unsigned short i1, i2;
|
||||||
struct internal_reloc *irel, *irelend;
|
struct internal_reloc *irel, *irelend;
|
||||||
|
|
||||||
@ -2374,6 +2461,15 @@ sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (symndx < 0
|
||||||
|
|| (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
("%s: illegal symbol index %ld in relocs",
|
||||||
|
bfd_get_filename (input_bfd), symndx);
|
||||||
|
bfd_set_error (bfd_error_bad_value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
h = obj_coff_sym_hashes (input_bfd)[symndx];
|
h = obj_coff_sym_hashes (input_bfd)[symndx];
|
||||||
sym = syms + symndx;
|
sym = syms + symndx;
|
||||||
}
|
}
|
||||||
@ -2676,3 +2772,173 @@ const bfd_target shlcoff_vec =
|
|||||||
|
|
||||||
COFF_SWAP_TABLE,
|
COFF_SWAP_TABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Some people want versions of the SH COFF target which do not align
|
||||||
|
to 16 byte boundaries. We implement that by adding a couple of new
|
||||||
|
target vectors. These are just like the ones above, but they
|
||||||
|
change the default section alignment. To generate them in the
|
||||||
|
assembler, use -small. To use them in the linker, use -b
|
||||||
|
coff-sh{l}-small and -oformat coff-sh{l}-small.
|
||||||
|
|
||||||
|
Yes, this is a horrible hack. A general solution for setting
|
||||||
|
section alignment in COFF is rather complex. ELF handles this
|
||||||
|
correctly. */
|
||||||
|
|
||||||
|
/* Only recognize the small versions if the target was not defaulted.
|
||||||
|
Otherwise we won't recognize the non default endianness. */
|
||||||
|
|
||||||
|
static const bfd_target *
|
||||||
|
coff_small_object_p (abfd)
|
||||||
|
bfd *abfd;
|
||||||
|
{
|
||||||
|
if (abfd->target_defaulted)
|
||||||
|
{
|
||||||
|
bfd_set_error (bfd_error_wrong_format);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return coff_object_p (abfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the section alignment for the small versions. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
coff_small_new_section_hook (abfd, section)
|
||||||
|
bfd *abfd;
|
||||||
|
asection *section;
|
||||||
|
{
|
||||||
|
if (! coff_new_section_hook (abfd, section))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* We must align to at least a four byte boundary, because longword
|
||||||
|
accesses must be on a four byte boundary. */
|
||||||
|
if (section->alignment_power == COFF_DEFAULT_SECTION_ALIGNMENT_POWER)
|
||||||
|
section->alignment_power = 2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is copied from bfd_coff_std_swap_table so that we can change
|
||||||
|
the default section alignment power. */
|
||||||
|
|
||||||
|
static const bfd_coff_backend_data bfd_coff_small_swap_table =
|
||||||
|
{
|
||||||
|
coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
|
||||||
|
coff_swap_aux_out, coff_swap_sym_out,
|
||||||
|
coff_swap_lineno_out, coff_swap_reloc_out,
|
||||||
|
coff_swap_filehdr_out, coff_swap_aouthdr_out,
|
||||||
|
coff_swap_scnhdr_out,
|
||||||
|
FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ,
|
||||||
|
#ifdef COFF_LONG_FILENAMES
|
||||||
|
true,
|
||||||
|
#else
|
||||||
|
false,
|
||||||
|
#endif
|
||||||
|
#ifdef COFF_LONG_SECTION_NAMES
|
||||||
|
true,
|
||||||
|
#else
|
||||||
|
false,
|
||||||
|
#endif
|
||||||
|
2,
|
||||||
|
coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
|
||||||
|
coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
|
||||||
|
coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
|
||||||
|
coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
|
||||||
|
coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
|
||||||
|
coff_sym_is_global, coff_compute_section_file_positions,
|
||||||
|
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
|
||||||
|
coff_adjust_symndx, coff_link_add_one_symbol,
|
||||||
|
coff_link_output_has_begun, coff_final_link_postscript
|
||||||
|
};
|
||||||
|
|
||||||
|
#define coff_small_close_and_cleanup \
|
||||||
|
coff_close_and_cleanup
|
||||||
|
#define coff_small_bfd_free_cached_info \
|
||||||
|
coff_bfd_free_cached_info
|
||||||
|
#define coff_small_get_section_contents \
|
||||||
|
coff_get_section_contents
|
||||||
|
#define coff_small_get_section_contents_in_window \
|
||||||
|
coff_get_section_contents_in_window
|
||||||
|
|
||||||
|
const bfd_target shcoff_small_vec =
|
||||||
|
{
|
||||||
|
"coff-sh-small", /* name */
|
||||||
|
bfd_target_coff_flavour,
|
||||||
|
BFD_ENDIAN_BIG, /* data byte order is big */
|
||||||
|
BFD_ENDIAN_BIG, /* header byte order is big */
|
||||||
|
|
||||||
|
(HAS_RELOC | EXEC_P | /* object flags */
|
||||||
|
HAS_LINENO | HAS_DEBUG |
|
||||||
|
HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
|
||||||
|
|
||||||
|
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
|
||||||
|
'_', /* leading symbol underscore */
|
||||||
|
'/', /* ar_pad_char */
|
||||||
|
15, /* ar_max_namelen */
|
||||||
|
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
|
||||||
|
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
|
||||||
|
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
|
||||||
|
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
|
||||||
|
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
|
||||||
|
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
|
||||||
|
|
||||||
|
{_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
|
||||||
|
bfd_generic_archive_p, _bfd_dummy_target},
|
||||||
|
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
|
||||||
|
bfd_false},
|
||||||
|
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
|
||||||
|
_bfd_write_archive_contents, bfd_false},
|
||||||
|
|
||||||
|
BFD_JUMP_TABLE_GENERIC (coff_small),
|
||||||
|
BFD_JUMP_TABLE_COPY (coff),
|
||||||
|
BFD_JUMP_TABLE_CORE (_bfd_nocore),
|
||||||
|
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
|
||||||
|
BFD_JUMP_TABLE_SYMBOLS (coff),
|
||||||
|
BFD_JUMP_TABLE_RELOCS (coff),
|
||||||
|
BFD_JUMP_TABLE_WRITE (coff),
|
||||||
|
BFD_JUMP_TABLE_LINK (coff),
|
||||||
|
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||||
|
|
||||||
|
(PTR) &bfd_coff_small_swap_table
|
||||||
|
};
|
||||||
|
|
||||||
|
const bfd_target shlcoff_small_vec =
|
||||||
|
{
|
||||||
|
"coff-shl-small", /* name */
|
||||||
|
bfd_target_coff_flavour,
|
||||||
|
BFD_ENDIAN_LITTLE, /* data byte order is little */
|
||||||
|
BFD_ENDIAN_LITTLE, /* header byte order is little endian too*/
|
||||||
|
|
||||||
|
(HAS_RELOC | EXEC_P | /* object flags */
|
||||||
|
HAS_LINENO | HAS_DEBUG |
|
||||||
|
HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
|
||||||
|
|
||||||
|
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
|
||||||
|
'_', /* leading symbol underscore */
|
||||||
|
'/', /* ar_pad_char */
|
||||||
|
15, /* ar_max_namelen */
|
||||||
|
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||||
|
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||||
|
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
|
||||||
|
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||||
|
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||||
|
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
|
||||||
|
|
||||||
|
{_bfd_dummy_target, coff_small_object_p, /* bfd_check_format */
|
||||||
|
bfd_generic_archive_p, _bfd_dummy_target},
|
||||||
|
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
|
||||||
|
bfd_false},
|
||||||
|
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
|
||||||
|
_bfd_write_archive_contents, bfd_false},
|
||||||
|
|
||||||
|
BFD_JUMP_TABLE_GENERIC (coff_small),
|
||||||
|
BFD_JUMP_TABLE_COPY (coff),
|
||||||
|
BFD_JUMP_TABLE_CORE (_bfd_nocore),
|
||||||
|
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
|
||||||
|
BFD_JUMP_TABLE_SYMBOLS (coff),
|
||||||
|
BFD_JUMP_TABLE_RELOCS (coff),
|
||||||
|
BFD_JUMP_TABLE_WRITE (coff),
|
||||||
|
BFD_JUMP_TABLE_LINK (coff),
|
||||||
|
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||||
|
|
||||||
|
(PTR) &bfd_coff_small_swap_table
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user