]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf-m10300.c
Touches most files in bfd/, so likely will be blamed for everything..
[thirdparty/binutils-gdb.git] / bfd / elf-m10300.c
index 19f03a70ba1d856a9e656009b34d35697f270975..01211ba9d3215db2a58de5e14870d94583a27dec 100644 (file)
@@ -1,5 +1,5 @@
 /* Matsushita 10300 specific support for 32-bit ELF
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -24,6 +24,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "elf-bfd.h"
 #include "elf/mn10300.h"
 
+static bfd_reloc_status_type mn10300_elf_final_link_relocate
+  PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
+          bfd_vma, bfd_vma, bfd_vma, struct bfd_link_info *,
+          asection *, int));
+static boolean mn10300_elf_relocate_section
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean mn10300_elf_relax_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
+static bfd_byte * mn10300_elf_get_relocated_section_contents
+  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+          bfd_byte *, boolean, asymbol **));
+static unsigned long elf_mn10300_mach PARAMS ((flagword));
+
+void    _bfd_mn10300_elf_final_write_processing PARAMS ((bfd *, boolean));
+boolean _bfd_mn10300_elf_object_p PARAMS ((bfd *));
+boolean _bfd_mn10300_elf_merge_private_bfd_data PARAMS ((bfd *,bfd *));
+
 struct elf32_mn10300_link_hash_entry {
   /* The basic elf link hash table entry.  */
   struct elf_link_hash_entry root;
@@ -599,8 +617,8 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       else
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
+         while (h->root.root.type == bfd_link_hash_indirect
+                || h->root.root.type == bfd_link_hash_warning)
            h = (struct elf32_mn10300_link_hash_entry *) h->root.root.u.i.link;
          if (h->root.root.type == bfd_link_hash_defined
              || h->root.root.type == bfd_link_hash_defweak)
@@ -822,15 +840,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
+             bfd_size_type amt = symtab_hdr->sh_size;
              /* Go get them off disk.  */
-             extsyms = ((Elf32_External_Sym *)
-                        bfd_malloc (symtab_hdr->sh_size));
+             extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
              if (extsyms == NULL)
                goto error_return;
              free_extsyms = extsyms;
              if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-                 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd)
-                     != symtab_hdr->sh_size))
+                 || bfd_bread (extsyms, amt, input_bfd) != amt)
                goto error_return;
            }
 
@@ -907,6 +924,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                        {
                          /* A local symbol.  */
                          Elf_Internal_Sym isym;
+                         struct elf_link_hash_table *elftab;
+                         bfd_size_type amt;
 
                          bfd_elf32_swap_symbol_in (input_bfd,
                                                    extsyms + r_index, &isym);
@@ -935,7 +954,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
                          /* Tack on an ID so we can uniquely identify this
                             local symbol in the global hash table.  */
-                         new_name = bfd_malloc (strlen (sym_name) + 10);
+                         amt = strlen (sym_name) + 10;
+                         new_name = bfd_malloc (amt);
                          if (new_name == 0)
                            goto error_return;
 
@@ -943,10 +963,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                   sym_name, (int) sym_sec);
                          sym_name = new_name;
 
-                         hash = (struct elf32_mn10300_link_hash_entry *)
-                                  elf_link_hash_lookup (&hash_table->static_hash_table->root,
-                                                        sym_name, true,
-                                                        true, false);
+                         elftab = &hash_table->static_hash_table->root;
+                         hash = ((struct elf32_mn10300_link_hash_entry *)
+                                 elf_link_hash_lookup (elftab, sym_name,
+                                                       true, true, false));
                          free (new_name);
                        }
                      else
@@ -998,6 +1018,9 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                      if (isym.st_shndx == shndx
                          && ELF_ST_TYPE (isym.st_info) == STT_FUNC)
                        {
+                         struct elf_link_hash_table *elftab;
+                         bfd_size_type amt;
+
                          if (isym.st_shndx == SHN_UNDEF)
                            sym_sec = bfd_und_section_ptr;
                          else if (isym.st_shndx > 0
@@ -1010,13 +1033,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                          else if (isym.st_shndx == SHN_COMMON)
                            sym_sec = bfd_com_section_ptr;
 
-                         sym_name = bfd_elf_string_from_elf_section (input_bfd,
-                                                       symtab_hdr->sh_link,
-                                                       isym.st_name);
+                         sym_name = (bfd_elf_string_from_elf_section
+                                     (input_bfd, symtab_hdr->sh_link,
+                                      isym.st_name));
 
                          /* Tack on an ID so we can uniquely identify this
                             local symbol in the global hash table.  */
-                         new_name = bfd_malloc (strlen (sym_name) + 10);
+                         amt = strlen (sym_name) + 10;
+                         new_name = bfd_malloc (amt);
                          if (new_name == 0)
                            goto error_return;
 
@@ -1024,10 +1048,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                   sym_name, (int) sym_sec);
                          sym_name = new_name;
 
-                         hash = (struct elf32_mn10300_link_hash_entry *)
-                                   elf_link_hash_lookup (&hash_table->static_hash_table->root,
-                                                         sym_name, true,
-                                                         true, false);
+                         elftab = &hash_table->static_hash_table->root;
+                         hash = ((struct elf32_mn10300_link_hash_entry *)
+                                 elf_link_hash_lookup (elftab, sym_name,
+                                                       true, true, false));
                          free (new_name);
                          compute_function_info (input_bfd, hash,
                                                 isym.st_value, contents);
@@ -1120,15 +1144,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
+             bfd_size_type amt = symtab_hdr->sh_size;
              /* Go get them off disk.  */
-             extsyms = ((Elf32_External_Sym *)
-                        bfd_malloc (symtab_hdr->sh_size));
+             extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
              if (extsyms == NULL)
                goto error_return;
              free_extsyms = extsyms;
              if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-                 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd)
-                     != symtab_hdr->sh_size))
+                 || bfd_bread (extsyms, amt, input_bfd) != amt)
                goto error_return;
            }
 
@@ -1188,6 +1211,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  asection *sym_sec = NULL;
                  const char *sym_name;
                  char *new_name;
+                 struct elf_link_hash_table *elftab;
+                 bfd_size_type amt;
 
                  bfd_elf32_swap_symbol_in (input_bfd, esym, &isym);
 
@@ -1212,16 +1237,17 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
                  /* Tack on an ID so we can uniquely identify this
                     local symbol in the global hash table.  */
-                 new_name = bfd_malloc (strlen (sym_name) + 10);
+                 amt = strlen (sym_name) + 10;
+                 new_name = bfd_malloc (amt);
                  if (new_name == 0)
                    goto error_return;
                  sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec);
                  sym_name = new_name;
 
-                 sym_hash = (struct elf32_mn10300_link_hash_entry *)
-                           elf_link_hash_lookup (&hash_table->static_hash_table->root,
-                                                 sym_name, false,
-                                                 false, false);
+                 elftab = &hash_table->static_hash_table->root;
+                 sym_hash = ((struct elf32_mn10300_link_hash_entry *)
+                             elf_link_hash_lookup (elftab, sym_name,
+                                                   false, false, false));
 
                  free (new_name);
                  if (sym_hash == NULL)
@@ -1437,15 +1463,14 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
            extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
          else
            {
+             bfd_size_type amt = symtab_hdr->sh_size;
              /* Go get them off disk.  */
-             extsyms = ((Elf32_External_Sym *)
-                        bfd_malloc (symtab_hdr->sh_size));
+             extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
              if (extsyms == NULL)
                goto error_return;
              free_extsyms = extsyms;
              if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-                 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
-                     != symtab_hdr->sh_size))
+                 || bfd_bread (extsyms, amt, abfd) != amt)
                goto error_return;
            }
        }
@@ -1483,7 +1508,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
          /* Tack on an ID so we can uniquely identify this
             local symbol in the global hash table.  */
-         new_name = bfd_malloc (strlen (sym_name) + 10);
+         new_name = bfd_malloc ((bfd_size_type) strlen (sym_name) + 10);
          if (new_name == 0)
            goto error_return;
          sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec);
@@ -2183,6 +2208,11 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  case 0x91:
                  case 0x92:
                  case 0x93:
+                   /* sp-based offsets are zero-extended.  */
+                   if (code >= 0x90 && code <= 0x93
+                       && (long)value < 0)
+                     continue;
+
                    /* Note that we've changed the relocation contents, etc.  */
                    elf_section_data (sec)->relocs = internal_relocs;
                    free_relocs = NULL;
@@ -2231,6 +2261,11 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                        && (value & 0x8000))
                      continue;
 
+                   /* mov imm16, an zero-extends the immediate.  */
+                   if (code == 0xdc
+                       && (long)value < 0)
+                     continue;
+
                    /* Note that we've changed the relocation contents, etc.  */
                    elf_section_data (sec)->relocs = internal_relocs;
                    free_relocs = NULL;
@@ -2276,18 +2311,18 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                    break;
 
                  /* mov (abs32),an    -> mov (abs16),an
-                    mov (d32,sp),an   -> mov (d32,sp),an
-                    mov (d32,sp),dn   -> mov (d32,sp),dn
-                    movbu (d32,sp),dn -> movbu (d32,sp),dn
-                    movhu (d32,sp),dn -> movhu (d32,sp),dn
+                    mov (d32,sp),an   -> mov (d16,sp),an
+                    mov (d32,sp),dn   -> mov (d16,sp),dn
+                    movbu (d32,sp),dn -> movbu (d16,sp),dn
+                    movhu (d32,sp),dn -> movhu (d16,sp),dn
                     add imm32,dn      -> add imm16,dn
                     cmp imm32,dn      -> cmp imm16,dn
                     add imm32,an      -> add imm16,an
                     cmp imm32,an      -> cmp imm16,an
-                    and imm32,dn      -> and imm32,dn
-                    or imm32,dn       -> or imm32,dn
-                    xor imm32,dn      -> xor imm32,dn
-                    btst imm32,dn     -> btst imm32,dn */
+                    and imm32,dn      -> and imm16,dn
+                    or imm32,dn       -> or imm16,dn
+                    xor imm32,dn      -> xor imm16,dn
+                    btst imm32,dn     -> btst imm16,dn */
 
                  case 0xa0:
                  case 0xb0:
@@ -2303,6 +2338,16 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  case 0xe1:
                  case 0xe2:
                  case 0xe3:
+                   /* cmp imm16, an zero-extends the immediate.  */
+                   if (code == 0xdc
+                       && (long)value < 0)
+                     continue;
+
+                   /* So do sp-based offsets.  */
+                   if (code >= 0xb0 && code <= 0xb3
+                       && (long)value < 0)
+                     continue;
+
                    /* Note that we've changed the relocation contents, etc.  */
                    elf_section_data (sec)->relocs = internal_relocs;
                    free_relocs = NULL;
@@ -2545,7 +2590,8 @@ mn10300_elf_relax_delete_bytes (abfd, sec, addr, count)
   irelend = irel + sec->reloc_count;
 
   /* Actually delete the bytes.  */
-  memmove (contents + addr, contents + addr + count, toaddr - addr - count);
+  memmove (contents + addr, contents + addr + count,
+          (size_t) (toaddr - addr - count));
   sec->_cooked_size -= count;
 
   /* Adjust all the relocs.  */
@@ -2678,7 +2724,7 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
-         input_section->_raw_size);
+         (size_t) input_section->_raw_size);
 
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
@@ -2686,20 +2732,19 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isymp;
       asection **secpp;
       Elf32_External_Sym *esym, *esymend;
+      bfd_size_type size;
 
       if (symtab_hdr->contents != NULL)
        external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
       else
        {
-         external_syms = ((Elf32_External_Sym *)
-                          bfd_malloc (symtab_hdr->sh_info
-                                      * sizeof (Elf32_External_Sym)));
-         if (external_syms == NULL && symtab_hdr->sh_info > 0)
+         size = symtab_hdr->sh_info;
+         size *= sizeof (Elf32_External_Sym);
+         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
+         if (external_syms == NULL && size != 0)
            goto error_return;
          if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || (bfd_read (external_syms, sizeof (Elf32_External_Sym),
-                           symtab_hdr->sh_info, input_bfd)
-                 != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym))))
+             || bfd_bread (external_syms, size, input_bfd) != size)
            goto error_return;
        }
 
@@ -2709,15 +2754,16 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      internal_syms = ((Elf_Internal_Sym *)
-                      bfd_malloc (symtab_hdr->sh_info
-                                  * sizeof (Elf_Internal_Sym)));
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
+      size = symtab_hdr->sh_info;
+      size *= sizeof (Elf_Internal_Sym);
+      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
+      if (internal_syms == NULL && size != 0)
        goto error_return;
 
-      sections = (asection **) bfd_malloc (symtab_hdr->sh_info
-                                          * sizeof (asection *));
-      if (sections == NULL && symtab_hdr->sh_info > 0)
+      size = symtab_hdr->sh_info;
+      size *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (size);
+      if (sections == NULL && size != 0)
        goto error_return;
 
       isymp = internal_syms;
@@ -2828,9 +2874,9 @@ elf32_mn10300_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct elf32_mn10300_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct elf32_mn10300_link_hash_table);
 
-  ret = ((struct elf32_mn10300_link_hash_table *)
-        bfd_alloc (abfd, sizeof (struct elf32_mn10300_link_hash_table)));
+  ret = (struct elf32_mn10300_link_hash_table *) bfd_alloc (abfd, amt);
   if (ret == (struct elf32_mn10300_link_hash_table *) NULL)
     return NULL;
 
@@ -2842,9 +2888,9 @@ elf32_mn10300_link_hash_table_create (abfd)
     }
 
   ret->flags = 0;
+  amt = sizeof (struct elf_link_hash_table);
   ret->static_hash_table
-    = ((struct elf32_mn10300_link_hash_table *)
-       bfd_alloc (abfd, sizeof (struct elf_link_hash_table)));
+    = (struct elf32_mn10300_link_hash_table *) bfd_alloc (abfd, amt);
   if (ret->static_hash_table == NULL)
     {
       bfd_release (abfd, ret);
@@ -2861,7 +2907,7 @@ elf32_mn10300_link_hash_table_create (abfd)
   return &ret->root.root;
 }
 
-static int
+static unsigned long
 elf_mn10300_mach (flags)
      flagword flags;
 {
@@ -2938,7 +2984,8 @@ _bfd_mn10300_elf_merge_private_bfd_data (ibfd, obfd)
 #define TARGET_LITTLE_SYM      bfd_elf32_mn10300_vec
 #define TARGET_LITTLE_NAME     "elf32-mn10300"
 #define ELF_ARCH               bfd_arch_mn10300
-#define ELF_MACHINE_CODE       EM_CYGNUS_MN10300
+#define ELF_MACHINE_CODE       EM_MN10300
+#define ELF_MACHINE_ALT1       EM_CYGNUS_MN10300
 #define ELF_MAXPAGESIZE                0x1000
 
 #define elf_info_to_howto              mn10300_info_to_howto