aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@embecosm.com>2003-03-03 21:04:01 +0000
committerJoern Rennecke <joern.rennecke@embecosm.com>2003-03-03 21:04:01 +0000
commitbdfaef528f42e9c07279aab2f37e3b888a08fc22 (patch)
tree7d39668f5661d2f58be6c5a8aa5d7e9cb93dc85b
parenta0ed55327d141094e07c8cdb3ac6f877109d917c (diff)
downloadgdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.zip
gdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.tar.gz
gdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.tar.bz2
Fix sh-elf linker relaxation:
gcc: * config/sh/sh.h (EXTRA_SPECS): Add subtarget_asm_relax_spec and subtarget_asm_isa_spec. (SUBTARGET_ASM_RELAX_SPEC, SUBTARGET_ASM_ISA_SPEC): Define. (ASM_SPEC): Define as SH_ASM_SPEC. (SH_ASM_SPEC): New; take the role of ASM_SPEC, but safe from svr4.h. Use subtarget_asm_relax_spec and subtarget_asm_isa_spec. * config/sh/elf.h (ASM_SPEC): Use SH_ASM_SPEC. (SUBTARGET_ASM_ISA_SPEC): Undef / define. gcc/testsuite: gcc.dg/sh-relax.c: New test. include/elf: * sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E, and SH2E & SH4 merge to SH4, not SH2E. gas: * config/tc-sh.c (sh_dsp): Replace with preset_target_arch. (md_begin): Use preset_target_arch. (md_longopts): Make isa option unconditional. (md_parse_option): Make OPTION_DSP and OPTION_ISA sh4 / any set preset_target_arch. (md_apply_fix3): If BFD_ASSEMBLER, adjust SWITCH_TABLE fixups by -S_GET_VALUE (fixP->fx_subsy). (tc_gen_reloc): For SWITCH_TABLE fixups, the symbol is fixp->fx_subsy, and the addend is 0. Adjust addend of R_SH_IND12W relocations by fixp->fx_offset - 4. * config/tc-sh.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define. bfd: elf32-sh.c (sh_elf_howto_tab): Make R_SH_IND12W into an ordinary relocation (no special function), and make it non-partial_inplace. (sh_elf_relax_section): When creating a bsr, use a consistent value no matter if the symbol is extern or not; set addend to -4. Don't swap load / non-load instructions for SH4. (sh_elf_relax_delete_bytes): In R_SH_IND12W case, check the offset rather than if the symbol is external to determine if adjusting the offset makes sense. Adjust the addend too if appropriate. (sh_elf_relocate_section): In R_SH_IND12W, don't fiddle with the relocation.
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/elf32-sh.c40
-rw-r--r--gas/ChangeLog14
-rw-r--r--gas/config/tc-sh.c33
-rw-r--r--gas/config/tc-sh.h2
-rw-r--r--include/elf/ChangeLog5
-rw-r--r--include/elf/sh.h3
7 files changed, 91 insertions, 19 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 393ab0f..9387ce2 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+Mon Mar 3 20:48:23 2003 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * elf32-sh.c (sh_elf_howto_tab): Make R_SH_IND12W into an ordinary
+ relocation (no special function), and make it non-partial_inplace.
+ (sh_elf_relax_section): When creating a bsr, use a consistent value
+ no matter if the symbol is extern or not; set addend to -4.
+ Don't swap load / non-load instructions for SH4.
+ (sh_elf_relax_delete_bytes): In R_SH_IND12W case, check the offset
+ rather than if the symbol is external to determine if adjusting the
+ offset makes sense. Adjust the addend too if appropriate.
+ (sh_elf_relocate_section): In R_SH_IND12W, don't fiddle with the
+ relocation.
+
2003-03-03 Nick Clifton <nickc@redhat.com>
* po/da.po: Installed latest translation.
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index 20dc7d1..c9167bc 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -179,6 +179,8 @@ static reloc_howto_type sh_elf_howto_table[] =
TRUE), /* pcrel_offset */
/* 12 bit PC relative branch divided by 2. */
+ /* This cannot be partial_inplace because relaxation can't know the
+ eventual value of a symbol. */
HOWTO (R_SH_IND12W, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
@@ -186,10 +188,10 @@ static reloc_howto_type sh_elf_howto_table[] =
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- sh_elf_reloc, /* special_function */
+ NULL, /* special_function */
"R_SH_IND12W", /* name */
- TRUE, /* partial_inplace */
- 0xfff, /* src_mask */
+ FALSE, /* partial_inplace */
+ 0x0, /* src_mask */
0xfff, /* dst_mask */
TRUE), /* pcrel_offset */
@@ -2232,6 +2234,12 @@ sh_elf_relax_section (abfd, sec, link_info, again)
/* Change the R_SH_USES reloc into an R_SH_IND12W reloc, and
replace the jsr with a bsr. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_SH_IND12W);
+ /* We used to test (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
+ here, but that only checks if the symbol is an external symbol,
+ not if the symbol is in a different section. Besides, we need
+ a consistent meaning for the relocation, so we just assume here that
+ the value of the symbol is not available. */
+#if 0
if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
{
/* If this needs to be changed because of future relaxing,
@@ -2242,12 +2250,14 @@ sh_elf_relax_section (abfd, sec, link_info, again)
contents + irel->r_offset);
}
else
+#endif
{
/* We can't fully resolve this yet, because the external
symbol value may be changed by future relaxing. We let
the final link phase handle it. */
bfd_put_16 (abfd, (bfd_vma) 0xb000, contents + irel->r_offset);
}
+ irel->r_addend = -4;
/* See if there is another R_SH_USES reloc referring to the same
register load. */
@@ -2316,7 +2326,8 @@ sh_elf_relax_section (abfd, sec, link_info, again)
/* Look for load and store instructions that we can align on four
byte boundaries. */
- if (have_code)
+ if ((elf_elfheader (abfd)->e_flags & EF_SH_MACH_MASK) != EF_SH4
+ && have_code)
{
bfd_boolean swapped;
@@ -2542,14 +2553,28 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
break;
case R_SH_IND12W:
- if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info)
- start = stop = addr;
+ off = insn & 0xfff;
+ if (! off)
+ {
+ /* This has been made by previous relaxation. Since the
+ relocation will be against an external symbol, the
+ final relocation will just do the right thing. */
+ start = stop = addr;
+ }
else
{
- off = insn & 0xfff;
if (off & 0x800)
off -= 0x1000;
stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
+
+ /* The addend will be against the section symbol, thus
+ for adjusting the addend, the relevant start is the
+ start of the section.
+ N.B. If we want to abandom in-place changes here and
+ test directly using symbol + addend, we have to take into
+ account that the addend has already been adjusted by -4. */
+ if (stop > addr && stop < toaddr)
+ irel->r_addend -= count;
}
break;
@@ -4811,7 +4836,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
break;
case R_SH_IND12W:
- relocation -= 4;
goto final_link_relocate;
case R_SH_DIR8WPN:
diff --git a/gas/ChangeLog b/gas/ChangeLog
index dc46fb3..e2253a2 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,17 @@
+Mon Mar 3 20:36:47 2003 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config/tc-sh.c (sh_dsp): Replace with preset_target_arch.
+ (md_begin): Use preset_target_arch.
+ (md_longopts): Make isa option unconditional.
+ (md_parse_option): Make OPTION_DSP and OPTION_ISA sh4 / any
+ set preset_target_arch.
+ (md_apply_fix3): If BFD_ASSEMBLER, adjust SWITCH_TABLE fixups
+ by -S_GET_VALUE (fixP->fx_subsy).
+ (tc_gen_reloc): For SWITCH_TABLE fixups, the symbol is fixp->fx_subsy,
+ and the addend is 0.
+ Adjust addend of R_SH_IND12W relocations by fixp->fx_offset - 4.
+ * config/tc-sh.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define.
+
2003-03-02 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c (append_insn): Add handling of
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c
index d3a6ac3..c73b81f 100644
--- a/gas/config/tc-sh.c
+++ b/gas/config/tc-sh.c
@@ -163,9 +163,9 @@ int sh_relax; /* set if -relax seen */
int sh_small;
-/* Whether -dsp was seen. */
+/* preset architecture set, if given; zero otherwise. */
-static int sh_dsp;
+static int preset_target_arch;
/* The bit mask of architectures that could
accomodate the insns seen so far. */
@@ -867,7 +867,8 @@ md_begin ()
char *prev_name = "";
int target_arch;
- target_arch = arch_sh1_up & ~(sh_dsp ? arch_sh3e_up : arch_sh_dsp_up);
+ target_arch
+ = preset_target_arch ? preset_target_arch : arch_sh1_up & ~arch_sh_dsp_up;
valid_arch = target_arch;
#ifdef HAVE_SH64
@@ -2593,20 +2594,20 @@ struct option md_longopts[] =
#define OPTION_LITTLE (OPTION_BIG + 1)
#define OPTION_SMALL (OPTION_LITTLE + 1)
#define OPTION_DSP (OPTION_SMALL + 1)
+#define OPTION_ISA (OPTION_DSP + 1)
{"relax", no_argument, NULL, OPTION_RELAX},
{"big", no_argument, NULL, OPTION_BIG},
{"little", no_argument, NULL, OPTION_LITTLE},
{"small", no_argument, NULL, OPTION_SMALL},
{"dsp", no_argument, NULL, OPTION_DSP},
+ {"isa", required_argument, NULL, OPTION_ISA},
#ifdef HAVE_SH64
-#define OPTION_ISA (OPTION_DSP + 1)
#define OPTION_ABI (OPTION_ISA + 1)
#define OPTION_NO_MIX (OPTION_ABI + 1)
#define OPTION_SHCOMPACT_CONST_CRANGE (OPTION_NO_MIX + 1)
#define OPTION_NO_EXPAND (OPTION_SHCOMPACT_CONST_CRANGE + 1)
#define OPTION_PT32 (OPTION_NO_EXPAND + 1)
- {"isa", required_argument, NULL, OPTION_ISA},
{"abi", required_argument, NULL, OPTION_ABI},
{"no-mix", no_argument, NULL, OPTION_NO_MIX},
{"shcompact-const-crange", no_argument, NULL, OPTION_SHCOMPACT_CONST_CRANGE},
@@ -2642,12 +2643,16 @@ md_parse_option (c, arg)
break;
case OPTION_DSP:
- sh_dsp = 1;
+ preset_target_arch = arch_sh1_up & ~arch_sh3e_up;
break;
-#ifdef HAVE_SH64
case OPTION_ISA:
- if (strcasecmp (arg, "shmedia") == 0)
+ if (strcasecmp (arg, "sh4") == 0)
+ preset_target_arch = arch_sh4;
+ else if (strcasecmp (arg, "any") == 0)
+ preset_target_arch = arch_sh1_up;
+#ifdef HAVE_SH64
+ else if (strcasecmp (arg, "shmedia") == 0)
{
if (sh64_isa_mode == sh64_isa_shcompact)
as_bad (_("Invalid combination: --isa=SHcompact with --isa=SHmedia"));
@@ -2661,10 +2666,12 @@ md_parse_option (c, arg)
as_bad (_("Invalid combination: --abi=64 with --isa=SHcompact"));
sh64_isa_mode = sh64_isa_shcompact;
}
+#endif /* HAVE_SH64 */
else
as_bad ("Invalid argument to --isa option: %s", arg);
break;
+#ifdef HAVE_SH64
case OPTION_ABI:
if (strcmp (arg, "32") == 0)
{
@@ -3381,7 +3388,10 @@ md_apply_fix3 (fixP, valP, seg)
val -= S_GET_VALUE (fixP->fx_addsy);
#endif
-#ifndef BFD_ASSEMBLER
+#ifdef BFD_ASSEMBLER
+ if (SWITCH_TABLE (fixP))
+ val -= S_GET_VALUE (fixP->fx_subsy);
+#else
if (fixP->fx_r_type == 0)
{
if (fixP->fx_size == 2)
@@ -3902,7 +3912,8 @@ tc_gen_reloc (section, fixp)
if (SWITCH_TABLE (fixp))
{
- rel->addend = rel->address - S_GET_VALUE (fixp->fx_subsy);
+ *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
+ rel->addend = 0;
if (r_type == BFD_RELOC_16)
r_type = BFD_RELOC_SH_SWITCH16;
else if (r_type == BFD_RELOC_8)
@@ -3941,6 +3952,8 @@ tc_gen_reloc (section, fixp)
rel->addend = 0;
rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
+ if (rel->howto->type == R_SH_IND12W)
+ rel->addend += fixp->fx_offset - 4;
if (rel->howto == NULL)
{
as_bad_where (fixp->fx_file, fixp->fx_line,
diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h
index 6537a6d..b1c9bc0 100644
--- a/gas/config/tc-sh.h
+++ b/gas/config/tc-sh.h
@@ -235,6 +235,8 @@ extern bfd_boolean sh_fix_adjustable PARAMS ((struct fix *));
|| (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC \
|| TC_FORCE_RELOCATION (FIX))
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) (sh_relax && SWITCH_TABLE (FIX))
+
/* This keeps the subtracted symbol around, for use by PLT_PCREL
relocs. */
#define TC_FORCE_RELOCATION_SUB_ABS(FIX) \
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index beb85a7..e87cdd2 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,8 @@
+Mon Mar 3 20:35:58 2003 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E,
+ and SH2E & SH4 merge to SH4, not SH2E.
+
2003-02-21 Ian Wienand <ianw@gelato.unsw.edu.au>
* ia64.h (SHT_IA_64_LOPSREG, SHT_IA_64_HIPSREG,
diff --git a/include/elf/sh.h b/include/elf/sh.h
index 41bf0bf..00a5f2a 100644
--- a/include/elf/sh.h
+++ b/include/elf/sh.h
@@ -56,7 +56,8 @@
: (((mach1) == EF_SH3E && (mach2) == EF_SH_UNKNOWN) \
|| ((mach2) == EF_SH3E && (mach1) == EF_SH_UNKNOWN)) \
? EF_SH4 \
- : ((mach1) > (mach2) ? (mach1) : (mach2)))
+ : (((mach1) == EF_SH2E ? 7 : (mach1)) > ((mach2) == EF_SH2E ? 7 : (mach2)) \
+ ? (mach1) : (mach2)))
/* Flags for the st_other symbol field.
Keep away from the STV_ visibility flags (bit 0..1). */