Add MN10300 linker relaxation support for symbol differences
authorNick Clifton <nickc@redhat.com>
Fri, 19 Oct 2007 17:31:31 +0000 (17:31 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 19 Oct 2007 17:31:31 +0000 (17:31 +0000)
32 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/config.bfd
bfd/elf-m10300.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-mn10300.c
gas/config/tc-mn10300.h
gas/doc/internals.texi
gas/expr.c
gas/testsuite/ChangeLog
gas/testsuite/gas/mn10300/basic.exp
gas/testsuite/gas/mn10300/pr997.l [new file with mode: 0644]
gas/testsuite/gas/mn10300/pr997.s [new file with mode: 0644]
include/elf/ChangeLog
include/elf/mn10300.h
ld/ChangeLog
ld/configure.tgt
ld/testsuite/ChangeLog
ld/testsuite/ld-mn10300/i112045-1.d [new file with mode: 0644]
ld/testsuite/ld-mn10300/i112045-1.s [new file with mode: 0644]
ld/testsuite/ld-mn10300/i112045-2.d [new file with mode: 0644]
ld/testsuite/ld-mn10300/i112045-2.s [new file with mode: 0644]
ld/testsuite/ld-mn10300/i126256-1.c [new file with mode: 0644]
ld/testsuite/ld-mn10300/i126256-2.c [new file with mode: 0644]
ld/testsuite/ld-mn10300/i135409.d [new file with mode: 0644]
ld/testsuite/ld-mn10300/i135409.s [new file with mode: 0644]
ld/testsuite/ld-mn10300/i36434-2.s [new file with mode: 0644]
ld/testsuite/ld-mn10300/i36434.d [new file with mode: 0644]
ld/testsuite/ld-mn10300/i36434.s [new file with mode: 0644]
ld/testsuite/ld-mn10300/mn10300.exp [new file with mode: 0644]

index 6d7fa26..55cfb10 100644 (file)
@@ -1,5 +1,24 @@
 2007-10-19  Nick Clifton  <nickc@redhat.com>
 
 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>
        * elf-m10300.c: Convert to ISO C.
 
 2007-10-18  H.J. Lu  <hongjiu.lu@intel.com>
index e425db1..35aad28 100644 (file)
@@ -2774,6 +2774,11 @@ in the instruction.  */
 /* Adjust by program base.  */
   BFD_RELOC_MN10300_RELATIVE,
 
 /* 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,
 
 /* i386/elf relocations  */
   BFD_RELOC_386_GOT32,
index 899e18e..98183fc 100644 (file)
@@ -71,6 +71,7 @@ esac
 targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
 case "${targ_cpu}" in
 alpha*)                 targ_archs=bfd_alpha_arch ;;
 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 ;;
 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 ;;
 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
 
 *)              targ_archs=bfd_${targ_cpu}_arch ;;
 esac
 
@@ -197,9 +197,10 @@ case "${targ}" in
     ;;
 #endif /* BFD64 */
 
     ;;
 #endif /* BFD64 */
 
-  am33_2.0-*-linux*)
+  am34-*-linux* | am33_2.0-*-linux*)
     targ_defvec=bfd_elf32_am33lin_vec
     ;;
     targ_defvec=bfd_elf32_am33lin_vec
     ;;
+
   arc-*-elf*)
     targ_defvec=bfd_elf32_littlearc_vec
     targ_selvecs=bfd_elf32_bigarc_vec
   arc-*-elf*)
     targ_defvec=bfd_elf32_littlearc_vec
     targ_selvecs=bfd_elf32_bigarc_vec
index 9aedc06..6c688bd 100644 (file)
@@ -446,6 +446,30 @@ static reloc_howto_type elf_mn10300_howto_table[] =
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
         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
 };
 
 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_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.  */
 };
 
 /* Create the GOT section.  */
@@ -619,6 +644,7 @@ mn10300_elf_check_relocs (bfd *abfd,
                          asection *sec,
                          const Elf_Internal_Rela *relocs)
 {
                          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;
   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;
   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++)
     {
 
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -814,53 +841,98 @@ mn10300_elf_check_relocs (bfd *abfd,
            h->non_got_ref = 1;
          break;
 
            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;
 
        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
          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)
                    {
                  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;
                        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;
        }
            }
 
          break;
        }
+
+      if (ELF32_R_TYPE (rel->r_info) != R_MN10300_SYM_DIFF)
+       sym_diff_reloc_seen = FALSE;
     }
 
   return TRUE;
     }
 
   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)
 {
                                 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;
   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;
     }
 
        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)
     {
   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
     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;
          && (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
                      && 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
                      && !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)
 {
 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;
 
   (*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
 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 *b
-    = *(struct elf32_mn10300_link_hash_entry **)vb;
+    = *(struct elf32_mn10300_link_hash_entry **) vb;
 
   return a->value - b->value;
 }
 
   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
     {
       if (isym->st_shndx == sec_shndx
          && isym->st_value > addr
-         && isym->st_value < toaddr)
+         && isym->st_value <= toaddr)
        isym->st_value -= count;
        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.  */
     }
 
   /* 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.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;
        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;
     }
 
   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);
                             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);
                            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);
                             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);
                            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);
                     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;
                    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;
          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);
 
          /* 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)
            {
              && 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;
              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 += 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);
 
          /* 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;
            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;
 
               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);
          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
                  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.  */
                      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
 
                    /* 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.  */
                      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
                  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
                      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.  */
                      continue;
 
                    /* Note that we've changed the relocation contents, etc.  */
index 7f10f46..18d01ca 100644 (file)
@@ -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_GLOB_DAT",
   "BFD_RELOC_MN10300_JMP_SLOT",
   "BFD_RELOC_MN10300_RELATIVE",
+  "BFD_RELOC_MN10300_SYM_DIFF",
 
   "BFD_RELOC_386_GOT32",
   "BFD_RELOC_386_PLT32",
 
   "BFD_RELOC_386_GOT32",
   "BFD_RELOC_386_PLT32",
index 525fe35..aa21875 100644 (file)
@@ -2361,6 +2361,12 @@ ENUM
   BFD_RELOC_MN10300_RELATIVE
 ENUMDOC
   Adjust by program base.
   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
 COMMENT
 
 ENUM
index 5911282..f53d2ab 100644 (file)
@@ -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 '%'.
 2007-10-19  Alan Modra  <amodra@bigpond.net.au>
 
        * config/tc-ppc.c (ppc_parse_name): Skip leading '%'.
index 671c008..5ec58bb 100644 (file)
@@ -2141,15 +2141,21 @@ keep_going:
 
       dwarf2_emit_insn (size);
     }
 
       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.  */
 
 }
 
 /* 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)
 {
 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
 {
+  static arelent * no_relocs = NULL;
+  static arelent * relocs[MAX_RELOC_EXPANSION + 1];
   arelent *reloc;
   arelent *reloc;
+
   reloc = xmalloc (sizeof (arelent));
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   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);
       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;
   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)
 
   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;
 
     {
       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)
        {
       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))
        }
 
       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;
            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);
            }
        }
 
       if (reloc->sym_ptr_ptr)
        free (reloc->sym_ptr_ptr);
       free (reloc);
-      return NULL;
+      return & no_relocs;
     }
   else
     {
     }
   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;
     }
       *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
       reloc->addend = fixp->fx_offset;
     }
-  return reloc;
+  return relocs;
 }
 
 int
 }
 
 int
@@ -2377,11 +2376,14 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
 bfd_boolean
 mn10300_fix_adjustable (struct fix *fixp)
 {
 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,
     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.  */
      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;
     return FALSE;
+
   if (strncmp (S_GET_SEGMENT (fixp->fx_addsy)->name, ".debug", 6) == 0)
     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}
 };
   { "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;
+}
index 20de21c..af7a6e6 100644 (file)
@@ -98,13 +98,21 @@ void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
 
 #define md_number_to_chars number_to_chars_littleendian
 
 
 #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)
 #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
 
 /* 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
index ff1df98..62f16f7 100644 (file)
@@ -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.
 
 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
 @end table
 
 @node Object format backend
index 4f4d380..285b438 100644 (file)
@@ -1738,6 +1738,9 @@ expr (int rankarg,                /* Larger # is higher rank.  */
               && right.X_op == O_symbol
               && resultP->X_op == O_symbol
               && retval == rightseg
               && 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),
               && (SEG_NORMAL (rightseg)
                   || right.X_add_symbol == resultP->X_add_symbol)
               && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
index c180bea..953f096 100644 (file)
@@ -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.
 2007-10-17  Nathan Sidwell  <nathan@codesourcery.com>
 
        * gas/m68k/mcf-movsr.s: New.
index 9b1b53b..c74fcf6 100644 (file)
@@ -1801,6 +1801,7 @@ if [istarget mn10300*-*-*] then {
     do_am33_8
 
     run_list_test "movpc" ""
     do_am33_8
 
     run_list_test "movpc" ""
+    run_list_test "pr997" "-a" 
 
     run_dump_test "am33-2"
     run_dump_test "relax"
 
     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 (file)
index 0000000..b122095
--- /dev/null
@@ -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 (file)
index 0000000..4a54bbc
--- /dev/null
@@ -0,0 +1,5 @@
+        .data
+
+msg:    .asciz  "hello world.\n"
+msglen = .-msg-1
+msglen=msglen & 0xff
index e7ff097..e8e12ac 100644 (file)
@@ -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.
 2007-10-18  Roland McGrath  <roland@redhat.com>
 
        * common.h (NT_PPC_VMX): New macro.
index d241e9c..74de473 100644 (file)
@@ -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_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,
 END_RELOC_NUMBERS (R_MN10300_MAX)
 
 /* Machine variant if we know it.  This field was invented at Cygnus,
index 38b0146..1ecce86 100644 (file)
@@ -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
 2007-10-17  Zack Weinberg  <zack@codesourcery.com>
 
        * ldlang.c (lang_check_section_addresses): Also report size of
index d4f53ef..e897d1e 100644 (file)
@@ -400,6 +400,7 @@ mips*-*-sysv4*)         targ_emul=elf32btsmip
 mmix-*-*)              targ_emul=mmo
                        targ_extra_emuls=elf64mmix
                        ;;
 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
 am33_2.0-*-linux*)     targ_emul=elf32am33lin ;;
 mn10200-*-*)           targ_emul=mn10200 ;;
 mn10300-*-*)           targ_emul=mn10300
index ffc2296..db66430 100644 (file)
@@ -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>
 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 (file)
index 0000000..dcb5a41
--- /dev/null
@@ -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 (file)
index 0000000..b9e0346
--- /dev/null
@@ -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 (file)
index 0000000..9aa2d82
--- /dev/null
@@ -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 (file)
index 0000000..90e942d
--- /dev/null
@@ -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 (file)
index 0000000..5907d87
--- /dev/null
@@ -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 (file)
index 0000000..2948e5b
--- /dev/null
@@ -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 (file)
index 0000000..2d64a42
--- /dev/null
@@ -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 (file)
index 0000000..b9faaf4
--- /dev/null
@@ -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 (file)
index 0000000..cf31ce1
--- /dev/null
@@ -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 (file)
index 0000000..25cea45
--- /dev/null
@@ -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 (file)
index 0000000..84c1d83
--- /dev/null
@@ -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 (file)
index 0000000..14ba85b
--- /dev/null
@@ -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