Fix autoconf breakage + commit target.c, omitted in previous delta
[deliverable/binutils-gdb.git] / bfd / elf32-m68k.c
index 38e6e9cb395411d4c6db5a09407ecc3d8f483332..a3df85d5b5944e7b9e9e7b4490e9e902c1161a76 100644 (file)
@@ -1,5 +1,6 @@
 /* Motorola 68k series support for 32-bit ELF
-   Copyright 1993, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+   Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -181,7 +182,6 @@ reloc_type_lookup (abfd, code)
 /* end code generated by elf.el */
 
 #define USE_RELA
-
 \f
 /* Functions for the m68k ELF linker.  */
 
@@ -224,11 +224,11 @@ static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] =
 /* Procedure linkage table entries for the cpu32 */
 static const bfd_byte elf_cpu32_plt0_entry[PLT_CPU32_ENTRY_SIZE] =
 {
-  0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
+  0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
   0, 0, 0, 0,             /* replaced with offset to .got + 4.  */
+  0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
+  0, 0, 0, 0,             /* replace with offset to .got +8.  */
   0x4e, 0xd1,             /* jmp %a1@ */
-  0, 0, 0, 0,             /* replace with offset to .got +8. */
-  0, 0, 0, 0,             /* pad out to 24 bytes.  */
   0, 0, 0, 0,             /* pad out to 24 bytes.  */
   0, 0
 };
@@ -376,12 +376,12 @@ elf32_m68k_copy_private_bfd_data (ibfd, obfd)
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return true;
+
   in_flags = elf_elfheader (ibfd)->e_flags;
+
   elf_elfheader (obfd)->e_flags = in_flags;
   elf_flags_init (obfd) = true;
+
   return true;
 }
 
@@ -932,7 +932,6 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
   return true;
 }
 
-
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -1267,7 +1266,12 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
        }
 
       /* Allocate memory for the section contents.  */
-      s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+      /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
+        Unused entries should be reclaimed before the section's contents
+        are written out, but at the moment this does not happen.  Thus in
+        order to prevent writing out garbage, we initialise the section's
+        contents to zero.  */
+      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
       if (s->contents == NULL && s->_raw_size != 0)
        return false;
     }
@@ -1307,6 +1311,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
        {
          if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
            return false;
+         info->flags |= DF_TEXTREL;
        }
     }
 
@@ -1319,7 +1324,6 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
    in regular objects.  We allocated space for them in the check_relocs
    routine, but we won't fill them in in the relocate_section routine.  */
 
-/*ARGSUSED*/
 static boolean
 elf_m68k_discard_copies (h, ignore)
      struct elf_m68k_link_hash_entry *h;
@@ -1459,7 +1463,14 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
                      && ((! info->symbolic && h->dynindx != -1)
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0)
-                     && (input_section->flags & SEC_ALLOC) != 0
+                     && ((input_section->flags & SEC_ALLOC) != 0
+                         /* DWARF will emit R_68K_32 relocations in its
+                            sections against symbols defined externally
+                            in shared libraries.  We can't do anything
+                            with them here.  */
+                         || ((input_section->flags & SEC_DEBUGGING) != 0
+                             && (h->elf_link_hash_flags
+                                 & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
                      && (r_type == R_68K_8
                          || r_type == R_68K_16
                          || r_type == R_68K_32
@@ -1479,14 +1490,17 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared && !info->symbolic && !info->no_undefined)
+         else if (info->shared && !info->symbolic
+                  && !info->no_undefined
+                  && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
            relocation = 0;
          else
            {
              if (!(info->callbacks->undefined_symbol
                    (info, h->root.root.string, input_bfd,
                     input_section, rel->r_offset,
-                    (!info->shared || info->no_undefined))))
+                    (!info->shared || info->no_undefined
+                     || ELF_ST_VISIBILITY (h->other)))))
                return false;
              relocation = 0;
            }
@@ -2130,7 +2144,7 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
                           + sgot->output_offset + 8
                           - (splt->output_section->vma + 10)),
                          splt->contents + 12);
-              elf_section_data (splt->output_section)->this_hdr.sh_entsize 
+              elf_section_data (splt->output_section)->this_hdr.sh_entsize
                = PLT_ENTRY_SIZE;
             }
           else /* cpu32 */
@@ -2145,8 +2159,8 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
                          (sgot->output_section->vma
                           + sgot->output_offset + 8
                           - (splt->output_section->vma + 10)),
-                         splt->contents + 10);
-              elf_section_data (splt->output_section)->this_hdr.sh_entsize 
+                         splt->contents + 12);
+              elf_section_data (splt->output_section)->this_hdr.sh_entsize
                = PLT_CPU32_ENTRY_SIZE;
             }
        }
@@ -2170,6 +2184,144 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 
+/* Given a .data section and a .emreloc in-memory section, store
+   relocation information into the .emreloc section which can be
+   used at runtime to relocate the section.  This is called by the
+   linker when the --embedded-relocs switch is used.  This is called
+   after the add_symbols entry point has been called for all the
+   objects, and before the final_link entry point is called.  */
+
+boolean
+bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *datasec;
+     asection *relsec;
+     char **errmsg;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf32_External_Sym *extsyms;
+  Elf32_External_Sym *free_extsyms = NULL;
+  Elf_Internal_Rela *internal_relocs;
+  Elf_Internal_Rela *free_relocs = NULL;
+  Elf_Internal_Rela *irel, *irelend;
+  bfd_byte *p;
+
+  BFD_ASSERT (! info->relocateable);
+
+  *errmsg = NULL;
+
+  if (datasec->reloc_count == 0)
+    return true;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  /* Read this BFD's symbols if we haven't done so already, or get the cached
+     copy if it exists.  */
+  if (symtab_hdr->contents != NULL)
+    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+  else
+    {
+      /* Go get them off disk.  */
+      if (info->keep_memory)
+       extsyms = ((Elf32_External_Sym *)
+                  bfd_alloc (abfd, symtab_hdr->sh_size));
+      else
+       extsyms = ((Elf32_External_Sym *)
+                  bfd_malloc (symtab_hdr->sh_size));
+      if (extsyms == NULL)
+       goto error_return;
+      if (! info->keep_memory)
+       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))
+       goto error_return;
+      if (info->keep_memory)
+       symtab_hdr->contents = extsyms;
+    }
+
+  /* Get a copy of the native relocations.  */
+  internal_relocs = (_bfd_elf32_link_read_relocs
+                    (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                     info->keep_memory));
+  if (internal_relocs == NULL)
+    goto error_return;
+  if (! info->keep_memory)
+    free_relocs = internal_relocs;
+
+  relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
+  if (relsec->contents == NULL)
+    goto error_return;
+
+  p = relsec->contents;
+
+  irelend = internal_relocs + datasec->reloc_count;
+  for (irel = internal_relocs; irel < irelend; irel++, p += 12)
+    {
+      asection *targetsec;
+
+      /* We are going to write a four byte longword into the runtime
+       reloc section.  The longword will be the address in the data
+       section which must be relocated.  It is followed by the name
+       of the target section NUL-padded or truncated to 8
+       characters.  */
+
+      /* We can only relocate absolute longword relocs at run time.  */
+      if (ELF32_R_TYPE (irel->r_info) != (int) R_68K_32)
+       {
+         *errmsg = _("unsupported reloc type");
+         bfd_set_error (bfd_error_bad_value);
+         goto error_return;
+       }
+
+      /* Get the target section referred to by the reloc.  */
+      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+       {
+         Elf_Internal_Sym isym;
+
+         /* A local symbol.  */
+         bfd_elf32_swap_symbol_in (abfd,
+                                   extsyms + ELF32_R_SYM (irel->r_info),
+                                   &isym);
+
+         targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+       }
+      else
+       {
+         unsigned long indx;
+         struct elf_link_hash_entry *h;
+
+         /* An external symbol.  */
+         indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+         h = elf_sym_hashes (abfd)[indx];
+         BFD_ASSERT (h != NULL);
+         if (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
+           targetsec = h->root.u.def.section;
+         else
+           targetsec = NULL;
+       }
+
+      bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p);
+      memset (p + 4, 0, 8);
+      if (targetsec != NULL)
+       strncpy (p + 4, targetsec->output_section->name, 8);
+    }
+
+  if (free_extsyms != NULL)
+    free (free_extsyms);
+  if (free_relocs != NULL)
+    free (free_relocs);
+  return true;
+
+error_return:
+  if (free_extsyms != NULL)
+    free (free_extsyms);
+  if (free_relocs != NULL)
+    free (free_relocs);
+  return false;
+}
+
 #define TARGET_BIG_SYM                 bfd_elf32_m68k_vec
 #define TARGET_BIG_NAME                        "elf32-m68k"
 #define ELF_MACHINE_CODE               EM_68K
This page took 0.026645 seconds and 4 git commands to generate.