aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2007-10-19 17:31:31 +0000
committerNick Clifton <nickc@redhat.com>2007-10-19 17:31:31 +0000
commitbfff1642494227904c6c9a6c285cbaa6cf615bbb (patch)
tree7bf1ece58861b5e9c520e056102994251c0a7504
parent97030eea009ba78139fe20eae4585984435ac178 (diff)
downloadgdb-bfff1642494227904c6c9a6c285cbaa6cf615bbb.zip
gdb-bfff1642494227904c6c9a6c285cbaa6cf615bbb.tar.gz
gdb-bfff1642494227904c6c9a6c285cbaa6cf615bbb.tar.bz2
Add MN10300 linker relaxation support for symbol differences
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/bfd-in2.h5
-rw-r--r--bfd/config.bfd5
-rw-r--r--bfd/elf-m10300.c234
-rw-r--r--bfd/libbfd.h1
-rw-r--r--bfd/reloc.c6
-rw-r--r--gas/ChangeLog21
-rw-r--r--gas/config/tc-mn10300.c144
-rw-r--r--gas/config/tc-mn10300.h14
-rw-r--r--gas/doc/internals.texi12
-rw-r--r--gas/expr.c3
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/mn10300/basic.exp1
-rw-r--r--gas/testsuite/gas/mn10300/pr997.l20
-rw-r--r--gas/testsuite/gas/mn10300/pr997.s5
-rw-r--r--include/elf/ChangeLog4
-rw-r--r--include/elf/mn10300.h1
-rw-r--r--ld/ChangeLog4
-rw-r--r--ld/configure.tgt1
-rw-r--r--ld/testsuite/ChangeLog16
-rw-r--r--ld/testsuite/ld-mn10300/i112045-1.d22
-rw-r--r--ld/testsuite/ld-mn10300/i112045-1.s14
-rw-r--r--ld/testsuite/ld-mn10300/i112045-2.d6
-rw-r--r--ld/testsuite/ld-mn10300/i112045-2.s12
-rw-r--r--ld/testsuite/ld-mn10300/i126256-1.c7
-rw-r--r--ld/testsuite/ld-mn10300/i126256-2.c5
-rw-r--r--ld/testsuite/ld-mn10300/i135409.d11
-rw-r--r--ld/testsuite/ld-mn10300/i135409.s29
-rw-r--r--ld/testsuite/ld-mn10300/i36434-2.s16
-rw-r--r--ld/testsuite/ld-mn10300/i36434.d16
-rw-r--r--ld/testsuite/ld-mn10300/i36434.s10
-rw-r--r--ld/testsuite/ld-mn10300/mn10300.exp94
32 files changed, 668 insertions, 96 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6d7fa26..55cfb10 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,24 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
+ * config.bfd: Recognise am34-linux-gnu target.
+ * reloc.c: Add BFD_RELOC_MN10300_SYM_DIFF relocation.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+ * elf-m10300.c (elf_mn10300_howto): Add R_MN10300_SYM_DIFF.
+ (mn10300_reloc_map): Likewise.
+ (mn10300_elf_check_relocs): Do not create dynamic relocs for
+ symbol differences or relocations against absolute symbols.
+ (mn10300_elf_final_link_relocate): Likewise.
+ Handle R_MN10300_SYM_DIFF relocs.
+ (mn10300_elf_relocate_section): Fix for creating local copys of
+ dynamic relocs.
+ (mn10300_elf_relax_delete_bytes): Adjust symbols at the end of the
+ region. Adjust the size of function symbols.
+ (mn10300_elf_relax_section): Ignore symbols that are in discarded
+ sections.
+
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
* elf-m10300.c: Convert to ISO C.
2007-10-18 H.J. Lu <hongjiu.lu@intel.com>
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index e425db1..35aad28 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2774,6 +2774,11 @@ in the instruction. */
/* Adjust by program base. */
BFD_RELOC_MN10300_RELATIVE,
+/* Together with another reloc targeted at the same location,
+allows for a value that is the difference of two symbols
+in the same section. */
+ BFD_RELOC_MN10300_SYM_DIFF,
+
/* i386/elf relocations */
BFD_RELOC_386_GOT32,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 899e18e..98183fc 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -71,6 +71,7 @@ esac
targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
case "${targ_cpu}" in
alpha*) targ_archs=bfd_alpha_arch ;;
+am34*|am33_2.0*) targ_archs=bfd_mn10300_arch ;;
arm*) targ_archs=bfd_arm_arch ;;
bfin*) targ_archs=bfd_bfin_arch ;;
c30*) targ_archs=bfd_tic30_arch ;;
@@ -107,7 +108,6 @@ xscale*) targ_archs=bfd_arm_arch ;;
xtensa*) targ_archs=bfd_xtensa_arch ;;
z80|r800) targ_archs=bfd_z80_arch ;;
z8k*) targ_archs=bfd_z8k_arch ;;
-am33_2.0) targ_archs=bfd_mn10300_arch ;;
*) targ_archs=bfd_${targ_cpu}_arch ;;
esac
@@ -197,9 +197,10 @@ case "${targ}" in
;;
#endif /* BFD64 */
- am33_2.0-*-linux*)
+ am34-*-linux* | am33_2.0-*-linux*)
targ_defvec=bfd_elf32_am33lin_vec
;;
+
arc-*-elf*)
targ_defvec=bfd_elf32_littlearc_vec
targ_selvecs=bfd_elf32_bigarc_vec
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 9aedc06..6c688bd 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -446,6 +446,30 @@ static reloc_howto_type elf_mn10300_howto_table[] =
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (24),
+ EMPTY_HOWTO (25),
+ EMPTY_HOWTO (26),
+ EMPTY_HOWTO (27),
+ EMPTY_HOWTO (28),
+ EMPTY_HOWTO (29),
+ EMPTY_HOWTO (30),
+ EMPTY_HOWTO (31),
+ EMPTY_HOWTO (32),
+
+ HOWTO (R_MN10300_SYM_DIFF, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ NULL, /* special handler. */
+ "R_MN10300_SYM_DIFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE) /* pcrel_offset */
};
struct mn10300_reloc_map
@@ -480,6 +504,7 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] =
{ BFD_RELOC_MN10300_GLOB_DAT, R_MN10300_GLOB_DAT },
{ BFD_RELOC_MN10300_JMP_SLOT, R_MN10300_JMP_SLOT },
{ BFD_RELOC_MN10300_RELATIVE, R_MN10300_RELATIVE },
+ { BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF }
};
/* Create the GOT section. */
@@ -619,6 +644,7 @@ mn10300_elf_check_relocs (bfd *abfd,
asection *sec,
const Elf_Internal_Rela *relocs)
{
+ bfd_boolean sym_diff_reloc_seen;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
@@ -642,6 +668,7 @@ mn10300_elf_check_relocs (bfd *abfd,
dynobj = elf_hash_table (info)->dynobj;
local_got_offsets = elf_local_got_offsets (abfd);
rel_end = relocs + sec->reloc_count;
+ sym_diff_reloc_seen = FALSE;
for (rel = relocs; rel < rel_end; rel++)
{
@@ -814,53 +841,98 @@ mn10300_elf_check_relocs (bfd *abfd,
h->non_got_ref = 1;
break;
+ case R_MN10300_SYM_DIFF:
+ sym_diff_reloc_seen = TRUE;
+ break;
+
case R_MN10300_32:
if (h != NULL)
h->non_got_ref = 1;
- /* If we are creating a shared library, then we need to copy
- the reloc into the shared library. */
+ /* If we are creating a shared library, then we
+ need to copy the reloc into the shared library. */
if (info->shared
- && (sec->flags & SEC_ALLOC) != 0)
+ && (sec->flags & SEC_ALLOC) != 0
+ /* Do not generate a dynamic reloc for a
+ reloc associated with a SYM_DIFF operation. */
+ && ! sym_diff_reloc_seen)
{
- /* When creating a shared object, we must copy these
- reloc types into the output file. We create a reloc
- section in dynobj and make room for this reloc. */
- if (sreloc == NULL)
- {
- const char * name;
-
- name = (bfd_elf_string_from_elf_section
- (abfd,
- elf_elfheader (abfd)->e_shstrndx,
- elf_section_data (sec)->rel_hdr.sh_name));
- if (name == NULL)
- return FALSE;
+ asection * sym_section = NULL;
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && streq (bfd_get_section_name (abfd, sec), name + 5));
+ /* Find the section containing the
+ symbol involved in the relocation. */
+ if (h == NULL)
+ {
+ Elf_Internal_Sym * isymbuf;
+ Elf_Internal_Sym * isym;
+
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf)
+ {
+ isym = isymbuf + r_symndx;
+ /* All we care about is whether this local symbol is absolute. */
+ if (isym->st_shndx == SHN_ABS)
+ sym_section = bfd_abs_section_ptr;
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ sym_section = h->root.u.def.section;
+ }
- sreloc = bfd_get_section_by_name (dynobj, name);
+ /* If the symbol is absolute then the relocation can
+ be resolved during linking and there is no need for
+ a dynamic reloc. */
+ if (sym_section != bfd_abs_section_ptr)
+ {
+ /* When creating a shared object, we must copy these
+ reloc types into the output file. We create a reloc
+ section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
- flagword flags;
+ const char * name;
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- sreloc = bfd_make_section_with_flags (dynobj, name, flags);
- if (sreloc == NULL
- || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
+ if (name == NULL)
return FALSE;
+
+ BFD_ASSERT (CONST_STRNEQ (name, ".rela")
+ && streq (bfd_get_section_name (abfd, sec), name + 5));
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ flagword flags;
+
+ flags = (SEC_HAS_CONTENTS | SEC_READONLY
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ if ((sec->flags & SEC_ALLOC) != 0)
+ flags |= SEC_ALLOC | SEC_LOAD;
+ sreloc = bfd_make_section_with_flags (dynobj, name, flags);
+ if (sreloc == NULL
+ || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+ return FALSE;
+ }
}
- }
- sreloc->size += sizeof (Elf32_External_Rela);
+ sreloc->size += sizeof (Elf32_External_Rela);
+ }
}
break;
}
+
+ if (ELF32_R_TYPE (rel->r_info) != R_MN10300_SYM_DIFF)
+ sym_diff_reloc_seen = FALSE;
}
return TRUE;
@@ -904,6 +976,9 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
asection *sym_sec ATTRIBUTE_UNUSED,
int is_local ATTRIBUTE_UNUSED)
{
+ static asection * sym_diff_section;
+ static bfd_vma sym_diff_value;
+ bfd_boolean is_sym_diff_reloc;
unsigned long r_type = howto->type;
bfd_byte * hit_data = contents + offset;
bfd * dynobj;
@@ -937,13 +1012,54 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
return bfd_reloc_dangerous;
}
+ is_sym_diff_reloc = FALSE;
+ if (sym_diff_section != NULL)
+ {
+ BFD_ASSERT (sym_diff_section == input_section);
+
+ switch (r_type)
+ {
+ case R_MN10300_32:
+ case R_MN10300_24:
+ case R_MN10300_16:
+ case R_MN10300_8:
+ value -= sym_diff_value;
+ sym_diff_section = NULL;
+ is_sym_diff_reloc = TRUE;
+ break;
+
+ default:
+ sym_diff_section = NULL;
+ break;
+ }
+ }
+
switch (r_type)
{
+ case R_MN10300_SYM_DIFF:
+ BFD_ASSERT (addend == 0);
+ /* Cache the input section and value.
+ The offset is unreliable, since relaxation may
+ have reduced the following reloc's offset. */
+ sym_diff_section = input_section;
+ sym_diff_value = value;
+ return bfd_reloc_ok;
+
case R_MN10300_NONE:
return bfd_reloc_ok;
case R_MN10300_32:
if (info->shared
+ /* Do not generate relocs when an R_MN10300_32 has been used
+ with an R_MN10300_SYM_DIFF to compute a difference of two
+ symbols. */
+ && is_sym_diff_reloc == FALSE
+ /* Also, do not generate a reloc when the symbol associated
+ with the R_MN10300_32 reloc is absolute - there is no
+ need for a run time computation in this case. */
+ && sym_sec != bfd_abs_section_ptr
+ /* If the section is not going to be allocated at load time
+ then there is no need to generate relocs for it. */
&& (input_section->flags & SEC_ALLOC) != 0)
{
Elf_Internal_Rela outrel;
@@ -1370,6 +1486,10 @@ mn10300_elf_relocate_section (bfd *output_bfd,
&& elf_hash_table (info)->dynamic_sections_created
&& !SYMBOL_REFERENCES_LOCAL (info, hh))
|| (r_type == R_MN10300_32
+ /* _32 relocs in executables force _COPY relocs,
+ such that the address of the symbol ends up
+ being local. */
+ && !info->executable
&& !SYMBOL_REFERENCES_LOCAL (info, hh)
&& ((input_section->flags & SEC_ALLOC) != 0
/* DWARF will emit R_MN10300_32 relocations
@@ -1551,7 +1671,7 @@ static bfd_boolean
elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
void * in_args)
{
- int *count = (int *)in_args;
+ int *count = (int *) in_args;
(*count) ++;
return TRUE;
@@ -1576,9 +1696,9 @@ static int
sort_by_value (const void *va, const void *vb)
{
struct elf32_mn10300_link_hash_entry *a
- = *(struct elf32_mn10300_link_hash_entry **)va;
+ = *(struct elf32_mn10300_link_hash_entry **) va;
struct elf32_mn10300_link_hash_entry *b
- = *(struct elf32_mn10300_link_hash_entry **)vb;
+ = *(struct elf32_mn10300_link_hash_entry **) vb;
return a->value - b->value;
}
@@ -1735,8 +1855,14 @@ mn10300_elf_relax_delete_bytes (bfd *abfd,
{
if (isym->st_shndx == sec_shndx
&& isym->st_value > addr
- && isym->st_value < toaddr)
+ && isym->st_value <= toaddr)
isym->st_value -= count;
+ /* Adjust the function symbol's size as well. */
+ else if (isym->st_shndx == sec_shndx
+ && ELF_ST_TYPE (isym->st_info) == STT_FUNC
+ && isym->st_value + isym->st_size > addr
+ && isym->st_value + isym->st_size <= toaddr)
+ isym->st_size -= count;
}
/* Now adjust the global symbols defined in this section. */
@@ -1752,8 +1878,15 @@ mn10300_elf_relax_delete_bytes (bfd *abfd,
|| sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec
&& sym_hash->root.u.def.value > addr
- && sym_hash->root.u.def.value < toaddr)
+ && sym_hash->root.u.def.value <= toaddr)
sym_hash->root.u.def.value -= count;
+ /* Adjust the function symbol's size as well. */
+ else if (sym_hash->root.type == bfd_link_hash_defined
+ && sym_hash->root.u.def.section == sec
+ && sym_hash->type == STT_FUNC
+ && sym_hash->root.u.def.value + sym_hash->size > addr
+ && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
+ sym_hash->size -= count;
}
return TRUE;
@@ -1981,7 +2114,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
- if (new_name == 0)
+ if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@@ -2090,7 +2223,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
- if (new_name == 0)
+ if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@@ -2302,7 +2435,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
- if (new_name == 0)
+ if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
sym_name = new_name;
@@ -2514,7 +2647,6 @@ mn10300_elf_relax_section (bfd *abfd,
asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
- bfd_vma saved_addend;
/* A local symbol. */
isym = isymbuf + ELF32_R_SYM (irel->r_info);
@@ -2535,22 +2667,22 @@ mn10300_elf_relax_section (bfd *abfd,
&& ELF_ST_TYPE (isym->st_info) == STT_SECTION
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
+ bfd_vma saved_addend;
+
saved_addend = irel->r_addend;
- symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
+ symval = _bfd_elf_rela_local_sym (abfd, isym, & sym_sec, irel);
symval += irel->r_addend;
irel->r_addend = saved_addend;
}
else
- {
- symval = (isym->st_value
- + sym_sec->output_section->vma
- + sym_sec->output_offset);
- }
+ symval = (isym->st_value
+ + sym_sec->output_section->vma
+ + sym_sec->output_offset);
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
new_name = bfd_malloc ((bfd_size_type) strlen (sym_name) + 10);
- if (new_name == 0)
+ if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
sym_name = new_name;
@@ -2576,6 +2708,10 @@ mn10300_elf_relax_section (bfd *abfd,
regular reloc processing. */
continue;
+ /* Check for a reference to a discarded symbol and ignore it. */
+ if (h->root.root.u.def.section->output_section == NULL)
+ continue;
+
symval = (h->root.root.u.def.value
+ h->root.root.u.def.section->output_section->vma
+ h->root.root.u.def.section->output_offset);
@@ -3284,7 +3420,7 @@ mn10300_elf_relax_section (bfd *abfd,
case 0x93:
/* sp-based offsets are zero-extended. */
if (code >= 0x90 && code <= 0x93
- && (long)value < 0)
+ && (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */
@@ -3341,7 +3477,7 @@ mn10300_elf_relax_section (bfd *abfd,
/* mov imm16, an zero-extends the immediate. */
if (code == 0xdc
- && (long)value < 0)
+ && (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */
@@ -3422,12 +3558,12 @@ mn10300_elf_relax_section (bfd *abfd,
case 0xe3:
/* cmp imm16, an zero-extends the immediate. */
if (code == 0xdc
- && (long)value < 0)
+ && (long) value < 0)
continue;
/* So do sp-based offsets. */
if (code >= 0xb0 && code <= 0xb3
- && (long)value < 0)
+ && (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 7f10f46..18d01ca 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1046,6 +1046,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MN10300_GLOB_DAT",
"BFD_RELOC_MN10300_JMP_SLOT",
"BFD_RELOC_MN10300_RELATIVE",
+ "BFD_RELOC_MN10300_SYM_DIFF",
"BFD_RELOC_386_GOT32",
"BFD_RELOC_386_PLT32",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 525fe35..aa21875 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2361,6 +2361,12 @@ ENUM
BFD_RELOC_MN10300_RELATIVE
ENUMDOC
Adjust by program base.
+ENUM
+ BFD_RELOC_MN10300_SYM_DIFF
+ENUMDOC
+ Together with another reloc targeted at the same location,
+ allows for a value that is the difference of two symbols
+ in the same section.
COMMENT
ENUM
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5911282..f53d2ab 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,24 @@
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
+ * expr.c (expr): Test md_allow_local_subtract (if defined) before
+ allowing the evaluation of an expression involving two symbols
+ defined in the same section.
+ * doc/internals.texi (md_allow_local_subtract): Document the new
+ macro.
+ * config/tc-mn10300.h (md_allow_local_subtract): Define.
+ (RELAX_EXPANSION_POSSIBLE): Define.
+ (MAX_RELOC_EXPANSION): Define.
+ (TC_FRAG_TYPE): Define.
+ * config/tc-mn10300.c (md_assemble): Mark fragments as containing code.
+ (tc_gen_reloc): Return an array of relocs. If necessary generate
+ two relocs to handle an expressions involving the difference of
+ two symbols.
+ (mn10300_fix_adjustable): Do not test TC_FORCE_RELOCATION_LOCAL
+ when then fixup is not pc-relative.
+ (mn10300_allow_local_subtract): New function. Determine when it
+ is safe to compute the difference between two symbols at assemble
+ time.
+
2007-10-19 Alan Modra <amodra@bigpond.net.au>
* config/tc-ppc.c (ppc_parse_name): Skip leading '%'.
diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c
index 671c008..5ec58bb 100644
--- a/gas/config/tc-mn10300.c
+++ b/gas/config/tc-mn10300.c
@@ -2141,15 +2141,21 @@ keep_going:
dwarf2_emit_insn (size);
}
+
+ /* Label this frag as one that contains instructions. */
+ frag_now->tc_frag_data = TRUE;
}
/* If while processing a fixup, a reloc really needs to be created
then it is done here. */
-arelent *
+arelent **
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
+ static arelent * no_relocs = NULL;
+ static arelent * relocs[MAX_RELOC_EXPANSION + 1];
arelent *reloc;
+
reloc = xmalloc (sizeof (arelent));
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
@@ -2158,9 +2164,13 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("reloc %d not supported by object file format"),
(int) fixp->fx_r_type);
- return NULL;
+ free (reloc);
+ return & no_relocs;
}
+
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ relocs[0] = reloc;
+ relocs[1] = NULL;
if (fixp->fx_subsy
&& S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
@@ -2173,44 +2183,33 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
reloc->sym_ptr_ptr = NULL;
- /* If we got a difference between two symbols, and the
- subtracted symbol is in the current section, use a
- PC-relative relocation. If both symbols are in the same
- section, the difference would have already been simplified
- to a constant. */
+ /* If we have a difference between two (non-absolute) symbols we must
+ generate two relocs (one for each symbol) and allow the linker to
+ resolve them - relaxation may change the distances between symbols,
+ even local symbols defined in the same segment. */
if (S_GET_SEGMENT (fixp->fx_subsy) == seg)
{
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
- *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
- reloc->addend = (reloc->address - S_GET_VALUE (fixp->fx_subsy)
- + fixp->fx_offset);
+ arelent * reloc2 = xmalloc (sizeof * reloc);
- switch (fixp->fx_r_type)
- {
- case BFD_RELOC_8:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_8_PCREL);
- return reloc;
+ relocs[0] = reloc2;
+ relocs[1] = reloc;
- case BFD_RELOC_16:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_16_PCREL);
- return reloc;
+ reloc2->address = reloc->address;
+ reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_MN10300_SYM_DIFF);
+ reloc2->addend = - S_GET_VALUE (fixp->fx_subsy);
+ reloc2->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ *reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
- case BFD_RELOC_24:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_24_PCREL);
- return reloc;
+ reloc->addend = fixp->fx_offset;
+ if (S_GET_SEGMENT (fixp->fx_addsy) == absolute_section)
+ reloc->addend += S_GET_VALUE (fixp->fx_addsy);
- case BFD_RELOC_32:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_32_PCREL);
- return reloc;
+ reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
- default:
- /* Try to compute the absolute value below. */
- break;
- }
+ fixp->fx_pcrel = 0;
+ fixp->fx_done = 1;
+ return relocs;
}
if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
@@ -2247,14 +2246,14 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
default:
reloc->sym_ptr_ptr
= (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
- return reloc;
+ return relocs;
}
}
if (reloc->sym_ptr_ptr)
free (reloc->sym_ptr_ptr);
free (reloc);
- return NULL;
+ return & no_relocs;
}
else
{
@@ -2262,7 +2261,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->addend = fixp->fx_offset;
}
- return reloc;
+ return relocs;
}
int
@@ -2377,11 +2376,14 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
bfd_boolean
mn10300_fix_adjustable (struct fix *fixp)
{
- if (TC_FORCE_RELOCATION_LOCAL (fixp))
- return FALSE;
-
- if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
- || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ if (fixp->fx_pcrel)
+ {
+ if (TC_FORCE_RELOCATION_LOCAL (fixp))
+ return FALSE;
+ }
+ /* Non-relative relocs can (and must) be adjusted if they do
+ not meet the criteria below, or the generic criteria. */
+ else if (TC_FORCE_RELOCATION (fixp))
return FALSE;
/* Do not adjust relocations involving symbols in code sections,
@@ -2395,8 +2397,9 @@ mn10300_fix_adjustable (struct fix *fixp)
symbols, because they too break relaxation. We do want to adjust
other mergable symbols, like .rodata, because code relaxations
need section-relative symbols to properly relax them. */
- if (! (S_GET_SEGMENT(fixp->fx_addsy)->flags & SEC_MERGE))
+ if (! (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
return FALSE;
+
if (strncmp (S_GET_SEGMENT (fixp->fx_addsy)->name, ".debug", 6) == 0)
return FALSE;
@@ -2502,3 +2505,60 @@ const pseudo_typeS md_pseudo_table[] =
{ "mn10300", set_arch_mach, MN103 },
{NULL, 0, 0}
};
+
+/* Returns FALSE if there is some mn10300 specific reason why the
+ subtraction of two same-section symbols cannot be computed by
+ the assembler. */
+
+bfd_boolean
+mn10300_allow_local_subtract (expressionS * left, expressionS * right, segT section)
+{
+ bfd_boolean result;
+ fragS * left_frag;
+ fragS * right_frag;
+ fragS * frag;
+
+ /* If we are not performing linker relaxation then we have nothing
+ to worry about. */
+ if (linkrelax == 0)
+ return TRUE;
+
+ /* If the symbols are not in a code section then they are OK. */
+ if ((section->flags & SEC_CODE) == 0)
+ return TRUE;
+
+ /* Otherwise we have to scan the fragments between the two symbols.
+ If any instructions are found then we have to assume that linker
+ relaxation may change their size and so we must delay resolving
+ the subtraction until the final link. */
+ left_frag = symbol_get_frag (left->X_add_symbol);
+ right_frag = symbol_get_frag (right->X_add_symbol);
+
+ if (left_frag == right_frag)
+ return ! left_frag->tc_frag_data;
+
+ result = TRUE;
+ for (frag = left_frag; frag != NULL; frag = frag->fr_next)
+ {
+ if (frag->tc_frag_data)
+ result = FALSE;
+ if (frag == right_frag)
+ break;
+ }
+
+ if (frag == NULL)
+ for (frag = right_frag; frag != NULL; frag = frag->fr_next)
+ {
+ if (frag->tc_frag_data)
+ result = FALSE;
+ if (frag == left_frag)
+ break;
+ }
+
+ if (frag == NULL)
+ /* The two symbols are on disjoint fragment chains
+ - we cannot possibly compute their difference. */
+ return FALSE;
+
+ return result;
+}
diff --git a/gas/config/tc-mn10300.h b/gas/config/tc-mn10300.h
index 20de21c..af7a6e6 100644
--- a/gas/config/tc-mn10300.h
+++ b/gas/config/tc-mn10300.h
@@ -98,13 +98,21 @@ void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
#define md_number_to_chars number_to_chars_littleendian
-/* Don't bother to adjust relocs. */
-/* #define tc_fix_adjustable(FIX) 0 */
#define tc_fix_adjustable(FIX) mn10300_fix_adjustable (FIX)
-extern bfd_boolean mn10300_fix_adjustable PARAMS ((struct fix *));
+extern bfd_boolean mn10300_fix_adjustable (struct fix *);
/* We do relaxing in the assembler as well as the linker. */
extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table
#define DWARF2_LINE_MIN_INSN_LENGTH 1
+
+/* The difference between same-section symbols may be affected by linker
+ relaxation, so do not resolve such expressions in the assembler. */
+#define md_allow_local_subtract(l,r,s) mn10300_allow_local_subtract (l, r, s)
+extern bfd_boolean mn10300_allow_local_subtract (expressionS *, expressionS *, segT);
+
+#define RELOC_EXPANSION_POSSIBLE
+#define MAX_RELOC_EXPANSION 2
+
+#define TC_FRAG_TYPE bfd_boolean
diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi
index ff1df98..62f16f7 100644
--- a/gas/doc/internals.texi
+++ b/gas/doc/internals.texi
@@ -1535,6 +1535,18 @@ The function should return the debug format that is preferred by the CPU
backend. This format will be used when generating assembler specific debug
information.
+@item md_allow_local_subtract (@var{left}, @var{right}, @var{section})
+If defined, GAS will call this macro when evaluating an expression which is the
+difference of two symbols defined in the same section. It takes three
+arguments: @code{expressioS * @var{left}} which is the symbolic expression on
+the left hand side of the subtraction operation, @code{expressionS *
+@var{right}} which is the symbolic expression on the right hand side of the
+subtraction, and @code{segT @var{section}} which is the section containing the two
+symbols. The macro should return a non-zero value if the expression should be
+evaluated. Targets which implement link time relaxation which may change the
+position of the two symbols relative to each other should ensure that this
+macro returns zero in situations where this can occur.
+
@end table
@node Object format backend
diff --git a/gas/expr.c b/gas/expr.c
index 4f4d380..285b438 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1738,6 +1738,9 @@ expr (int rankarg, /* Larger # is higher rank. */
&& right.X_op == O_symbol
&& resultP->X_op == O_symbol
&& retval == rightseg
+#ifdef md_allow_local_subtract
+ && md_allow_local_subtract (resultP, & right, rightseg)
+#endif
&& (SEG_NORMAL (rightseg)
|| right.X_add_symbol == resultP->X_add_symbol)
&& frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index c180bea..953f096 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
+ * gas/mn10300/basic.exp: Run pr997 test.
+ * gas/mn10300/pr997.s: New test.
+ * gas/mn10300/pr887.l: Expected output.
+
2007-10-17 Nathan Sidwell <nathan@codesourcery.com>
* gas/m68k/mcf-movsr.s: New.
diff --git a/gas/testsuite/gas/mn10300/basic.exp b/gas/testsuite/gas/mn10300/basic.exp
index 9b1b53b..c74fcf6 100644
--- a/gas/testsuite/gas/mn10300/basic.exp
+++ b/gas/testsuite/gas/mn10300/basic.exp
@@ -1801,6 +1801,7 @@ if [istarget mn10300*-*-*] then {
do_am33_8
run_list_test "movpc" ""
+ run_list_test "pr997" "-a"
run_dump_test "am33-2"
run_dump_test "relax"
diff --git a/gas/testsuite/gas/mn10300/pr997.l b/gas/testsuite/gas/mn10300/pr997.l
new file mode 100644
index 0000000..b122095
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/pr997.l
@@ -0,0 +1,20 @@
+GAS LISTING .*/pr997.s.*page 1
+
+
+ 1.*.data
+ 2.*
+ 3 0000 68656C6C.*msg:.*.asciz "hello world.\\n"
+ 3 6F20776F
+ 3 726C642E
+ 3 0A00
+ 4.*msglen = .-msg-1
+ 5.*msglen=msglen & 0xff
+
+.*GAS LISTING.*/pr997.s.*page 2
+
+
+DEFINED SYMBOLS
+.*/pr997.s:3.*.data:0+00 msg
+.*/pr997.s:4.*\*ABS\*:0+0d msglen
+
+NO UNDEFINED SYMBOLS
diff --git a/gas/testsuite/gas/mn10300/pr997.s b/gas/testsuite/gas/mn10300/pr997.s
new file mode 100644
index 0000000..4a54bbc
--- /dev/null
+++ b/gas/testsuite/gas/mn10300/pr997.s
@@ -0,0 +1,5 @@
+ .data
+
+msg: .asciz "hello world.\n"
+msglen = .-msg-1
+msglen=msglen & 0xff
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index e7ff097..e8e12ac 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
+ * mn10300.h: Add R_MN10300_SYM_DIFF reloc.
+
2007-10-18 Roland McGrath <roland@redhat.com>
* common.h (NT_PPC_VMX): New macro.
diff --git a/include/elf/mn10300.h b/include/elf/mn10300.h
index d241e9c..74de473 100644
--- a/include/elf/mn10300.h
+++ b/include/elf/mn10300.h
@@ -50,6 +50,7 @@ START_RELOC_NUMBERS (elf_mn10300_reloc_type)
RELOC_NUMBER (R_MN10300_GLOB_DAT, 21)
RELOC_NUMBER (R_MN10300_JMP_SLOT, 22)
RELOC_NUMBER (R_MN10300_RELATIVE, 23)
+ RELOC_NUMBER (R_MN10300_SYM_DIFF, 33)
END_RELOC_NUMBERS (R_MN10300_MAX)
/* Machine variant if we know it. This field was invented at Cygnus,
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 38b0146..1ecce86 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
+ * configure.tgt: Add support for am34-linux-gnu target.
+
2007-10-17 Zack Weinberg <zack@codesourcery.com>
* ldlang.c (lang_check_section_addresses): Also report size of
diff --git a/ld/configure.tgt b/ld/configure.tgt
index d4f53ef..e897d1e 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -400,6 +400,7 @@ mips*-*-sysv4*) targ_emul=elf32btsmip
mmix-*-*) targ_emul=mmo
targ_extra_emuls=elf64mmix
;;
+am34-*-linux*) targ_emul=elf32am33lin ;;
am33_2.0-*-linux*) targ_emul=elf32am33lin ;;
mn10200-*-*) targ_emul=mn10200 ;;
mn10300-*-*) targ_emul=mn10300
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index ffc2296..db66430 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,19 @@
+2007-10-19 Nick Clifton <nickc@redhat.com>
+
+ * ld-mn10300: New test directory.
+ * ld-mn10300/mn10300.exp: Run the new tests.
+ * ld-mn10300/i112045-1.s: Linker relaxation test.
+ * ld-mn10300/i112045-1.d: Expected disassembly.
+ * ld-mn10300/i112045-2.s: Linker relaxation test.
+ * ld-mn10300/i112045-2.d: Expected disassembly.
+ * ld-mn10300/i126256-1.c: Test source.
+ * ld-mn10300/i126256-2.c: Test source.
+ * ld-mn10300/i135409.s: Linker relaxation test.
+ * ld-mn10300/i135409.d: Expected symbol table contents.
+ * ld-mn10300/i136434.s: Linker string section merge test.
+ * ld-mn10300/i136434.d: Expected disassembly.
+ * ld-mn10300/i136434-2.s: Test source file.
+
2007-10-17 Zack Weinberg <zack@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com>
Mark Shinwell <shinwell@codesourcery.com>
diff --git a/ld/testsuite/ld-mn10300/i112045-1.d b/ld/testsuite/ld-mn10300/i112045-1.d
new file mode 100644
index 0000000..dcb5a41
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i112045-1.d
@@ -0,0 +1,22 @@
+
+tmpdir/i112045-1.x: file format elf32-.*
+
+Disassembly of section .text:
+
+0+0 <_start>:
+ 0: fc d0 f8 0f[ ]+add 4088,a0
+ 4: 00 00
+ 6: cb[ ]+nop[ ]+
+ 7: cb[ ]+nop[ ]+
+
+0+08 <L01>:
+ 8: fc d0 2b 01[ ]+add 299,a0
+ c: 00 00
+ e: cb[ ]+nop[ ]+
+ f: cb[ ]+nop[ ]+
+
+0+010 <L02>:
+ 10: fc d0 08 00[ ]+add 8,a0
+ 14: 00 00
+ 16: cb[ ]+nop[ ]+
+ 17: cb[ ]+nop[ ]+
diff --git a/ld/testsuite/ld-mn10300/i112045-1.s b/ld/testsuite/ld-mn10300/i112045-1.s
new file mode 100644
index 0000000..b9e0346
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i112045-1.s
@@ -0,0 +1,14 @@
+ .text
+ .global _start
+_start:
+ add 0x1000 - L01, A0
+ nop
+ nop
+L01:
+ add L01 + 0x123, A0
+ nop
+ nop
+L02:
+ add L02 - L01, A0
+ nop
+ nop
diff --git a/ld/testsuite/ld-mn10300/i112045-2.d b/ld/testsuite/ld-mn10300/i112045-2.d
new file mode 100644
index 0000000..9aa2d82
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i112045-2.d
@@ -0,0 +1,6 @@
+
+tmpdir/i112045-2.x: file format elf32-.*
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+[0-9a-f]+ R_MN10300_RELATIVE \*ABS\*\+0x[0-9a-f]+
diff --git a/ld/testsuite/ld-mn10300/i112045-2.s b/ld/testsuite/ld-mn10300/i112045-2.s
new file mode 100644
index 0000000..90e942d
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i112045-2.s
@@ -0,0 +1,12 @@
+ .section .data
+L01:
+ .long L04 - L01
+L02:
+ .long L04 - L02
+L03:
+ .long L04 - L03
+L04:
+ .long L04
+ .long L00
+ .equ L00, 0xff
+
diff --git a/ld/testsuite/ld-mn10300/i126256-1.c b/ld/testsuite/ld-mn10300/i126256-1.c
new file mode 100644
index 0000000..5907d87
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i126256-1.c
@@ -0,0 +1,7 @@
+void
+sub0 (int i)
+{
+ extern int sub (int);
+
+ sub (i);
+}
diff --git a/ld/testsuite/ld-mn10300/i126256-2.c b/ld/testsuite/ld-mn10300/i126256-2.c
new file mode 100644
index 0000000..2948e5b
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i126256-2.c
@@ -0,0 +1,5 @@
+int
+sub (int i)
+{
+ return i + 10;
+}
diff --git a/ld/testsuite/ld-mn10300/i135409.d b/ld/testsuite/ld-mn10300/i135409.d
new file mode 100644
index 0000000..2d64a42
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i135409.d
@@ -0,0 +1,11 @@
+
+Symbol table '.symtab' contains .. entries:
+ Num: Value Size Type Bind Vis Ndx Name
+#...
+ ..: 0[0-9a-f]+[ ]+7 FUNC LOCAL DEFAULT . _func
+#...
+ ..: 0[0-9a-f]+[ ]+0 NOTYPE LOCAL DEFAULT . A
+ ..: 0[0-9a-f]+[ ]+7 FUNC GLOBAL DEFAULT . _func2
+#...
+ ..: 0[0-9a-f]+[ ]+0 NOTYPE GLOBAL DEFAULT . BOTTOM
+#...
diff --git a/ld/testsuite/ld-mn10300/i135409.s b/ld/testsuite/ld-mn10300/i135409.s
new file mode 100644
index 0000000..b9faaf4
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i135409.s
@@ -0,0 +1,29 @@
+ .text
+
+ nop
+
+ .global _start
+_start:
+ .type _func, @function
+_func:
+ mov L001,A1
+ nop
+A:
+ mov L001,A1
+ .size _func, . - _func
+
+
+ .global _func2
+_func2:
+ .type _func2, @function
+ mov L001,A1
+ nop
+ mov L001,A1
+ .size _func2, . - _func2
+
+ .global BOTTOM
+BOTTOM:
+
+ .data
+L001:
+
diff --git a/ld/testsuite/ld-mn10300/i36434-2.s b/ld/testsuite/ld-mn10300/i36434-2.s
new file mode 100644
index 0000000..cf31ce1
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i36434-2.s
@@ -0,0 +1,16 @@
+ .section .text
+ .global _bar
+ .type _bar,@function
+_bar:
+ mov .LC1,d0
+ mov .LC2,d1
+ nop
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC1:
+ .rept 32768
+ .byte 'a'
+ .endr
+ .byte 0
+.LC2:
+ .string "abc\n"
diff --git a/ld/testsuite/ld-mn10300/i36434.d b/ld/testsuite/ld-mn10300/i36434.d
new file mode 100644
index 0000000..25cea45
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i36434.d
@@ -0,0 +1,16 @@
+
+tmpdir/i36434.x: file format elf32-.*
+
+Disassembly of section .text:
+
+08000000 <_start>:
+ 8000000: fc cd 18 80 mov 134250520,d1
+ 8000004: 00 08
+ 8000006: cb nop
+
+08000007 <_bar>:
+ 8000007: fc cc 14 00 mov 134217748,d0
+ 800000b: 00 08
+ 800000d: fc cd 15 80 mov 134250517,d1
+ 8000011: 00 08
+ 8000013: cb nop
diff --git a/ld/testsuite/ld-mn10300/i36434.s b/ld/testsuite/ld-mn10300/i36434.s
new file mode 100644
index 0000000..84c1d83
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/i36434.s
@@ -0,0 +1,10 @@
+ .section .text
+ .global _start
+ .type _start,@function
+_start:
+ mov .LC2,d1
+ nop
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC2:
+ .string "\n"
diff --git a/ld/testsuite/ld-mn10300/mn10300.exp b/ld/testsuite/ld-mn10300/mn10300.exp
new file mode 100644
index 0000000..14ba85b
--- /dev/null
+++ b/ld/testsuite/ld-mn10300/mn10300.exp
@@ -0,0 +1,94 @@
+# Expect script for ld-mn10300 tests
+# Copyright (C) 2007 Free Software Foundation
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+if {!([istarget "am3*-*-*"]) && !([istarget "mn10300*-*-*"]) } {
+ return
+}
+
+# Set up a list as described in ld-lib.exp
+
+set am33_tests {
+ {
+ "am33 string merging"
+ "--relax -Ttext 0x8000000"
+ ""
+ { "i36434.s" "i36434-2.s" }
+ { {objdump -dz i36434.d} }
+ "i36434.x"
+ }
+ {
+ "difference of two symbols"
+ "-Ttext 0"
+ ""
+ { "i112045-1.s" }
+ { {objdump -d i112045-1.d} }
+ "i112045-1.x"
+ }
+ {
+ "(shared) difference of two symbols"
+ "-shared"
+ ""
+ { "i112045-2.s" }
+ { {objdump -R i112045-2.d} }
+ "i112045-2.x"
+ }
+ {
+ "adjustment of symbols due to relaxation"
+ "-Tdata 1f -relax"
+ ""
+ { "i135409.s" }
+ { {readelf --syms i135409.d } }
+ "i135409.x"
+ }
+}
+
+run_ld_link_tests $am33_tests
+
+proc i126256-test { } {
+ global CC
+ global ld
+ global srcdir
+ global subdir
+
+ set tmpdir tmpdir
+ set testname "Issue 126256 - seg fault whilst linking one shared library into another when relaxation is enabled."
+
+ if { ![ld_compile "$CC -mrelax -fPIC" $srcdir/$subdir/i126256-1.c $tmpdir/i126256-1.o] } {
+ unresolved $testname
+ return
+ }
+
+ if { ![ld_compile "$CC -mrelax -fPIC" $srcdir/$subdir/i126256-2.c $tmpdir/i126256-2.o] } {
+ unresolved $testname
+ return
+ }
+
+ if { ![ld_simple_link $ld $tmpdir/i126256-1.so "-shared $tmpdir/i126256-1.o -e 0"]} {
+ unresolved $testname
+ return
+ }
+
+ if { ![ld_simple_link $ld $tmpdir/i126256-2.so "--relax -shared $tmpdir/i126256-2.o $tmpdir/i126256-1.so -e 0"]} {
+ fail $testname
+ return
+ }
+
+ pass $testname
+}
+
+i126256-test