Improve verbose message
[deliverable/binutils-gdb.git] / bfd / elf32-arm.h
index 2ebfa862f79acd7289cf695353eb22d632b1dabd..e655781bde6a60fcd7a20555d19d1f85e3336ac8 100644 (file)
@@ -1,5 +1,5 @@
 /* 32-bit ELF support for ARM
-   Copyright 1998, 1999 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -545,7 +545,10 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
 
   if (sec == NULL)
     {
-      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+      /* Note: we do not include the flag SEC_LINKER_CREATED, as this
+        will prevent elf_link_input_bfd() from processing the contents
+        of this section.  */
+      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
 
       sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
 
@@ -553,13 +556,17 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
          || !bfd_set_section_flags (abfd, sec, flags)
          || !bfd_set_section_alignment (abfd, sec, 2))
        return false;
+      
+      /* Set the gc mark to prevent the section from being removed by garbage
+        collection, despite the fact that no relocs refer to this section.  */
+      sec->gc_mark = 1;
     }
 
   sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
 
   if (sec == NULL)
     {
-      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
 
       sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
 
@@ -567,6 +574,8 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
          || !bfd_set_section_flags (abfd, sec, flags)
          || !bfd_set_section_alignment (abfd, sec, 2))
        return false;
+      
+      sec->gc_mark = 1;
     }
 
   /* Save the bfd for later use.  */
@@ -705,7 +714,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
            {
            case R_ARM_PC24:
              /* This one is a call from arm code.  We need to look up
-                the target of the call. If it is a thumb target, we
+                the target of the call.  If it is a thumb target, we
                 insert glue.  */
 
              if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)
@@ -714,7 +723,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
 
            case R_ARM_THM_PC22:
              /* This one is a call from thumb code.  We look
-                up the target of the call. If it is not a thumb
+                up the target of the call.  If it is not a thumb
                  target, we insert glue.  */
 
              if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)
@@ -728,6 +737,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
     }
 
   return true;
+  
 error_return:
   if (free_relocs != NULL)
     free (free_relocs);
@@ -735,8 +745,8 @@ error_return:
     free (free_contents);
   if (free_extsyms != NULL)
     free (free_extsyms);
+  
   return false;
-
 }
 
 /* The thumb form of a long branch is a bit finicky, because the offset
@@ -765,10 +775,10 @@ error_return:
    moves the computed address into the PC, so it must be the second one
    in the sequence.  The problem, however is that whilst little endian code
    stores the instructions in HI then LOW order, big endian code does the
-   reverse.  nickc@cygnus.com  */
+   reverse.  nickc@cygnus.com.  */
 
-#define LOW_HI_ORDER 0xF800F000
-#define HI_LOW_ORDER 0xF000F800
+#define LOW_HI_ORDER      0xF800F000
+#define HI_LOW_ORDER      0xF000F800
 
 static insn32
 insert_thumb_branch (br_insn, rel_off)
@@ -781,9 +791,9 @@ insert_thumb_branch (br_insn, rel_off)
 
   BFD_ASSERT ((rel_off & 1) != 1);
 
-  rel_off >>= 1;               /* half word aligned address */
-  low_bits = rel_off & 0x000007FF;     /* the bottom 11 bits */
-  high_bits = (rel_off >> 11) & 0x000007FF;    /* the top 11 bits */
+  rel_off >>= 1;                               /* Half word aligned address.  */
+  low_bits = rel_off & 0x000007FF;             /* The bottom 11 bits.  */
+  high_bits = (rel_off >> 11) & 0x000007FF;    /* The top 11 bits.  */
 
   if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
     br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
@@ -793,7 +803,7 @@ insert_thumb_branch (br_insn, rel_off)
     abort ();                  /* error - not a valid branch instruction form */
 
   /* FIXME: abort is probably not the right call. krk@cygnus.com */
-
+  
   return br_insn;
 }
 
@@ -885,7 +895,7 @@ elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,
     + my_offset
     - (input_section->output_offset
        + offset + addend)
-    - 4;
+    - 8;
 
   tmp = bfd_get_32 (input_bfd, hit_data
                    - input_section->vma);
@@ -1052,6 +1062,9 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
     case R_ARM_PC24:
     case R_ARM_ABS32:
     case R_ARM_REL32:
+#ifndef OLD_ARM_ABI
+    case R_ARM_XPC25:
+#endif
       /* When generating a shared object, these relocations are copied
         into the output file to be resolved at run time. */
 
@@ -1161,16 +1174,33 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
        }
       else switch (r_type)
        {
-       case R_ARM_PC24:
-         /* Arm B/BL instruction */
-
-         /* Check for arm calling thumb function.  */
-         if (sym_flags == STT_ARM_TFUNC)
+#ifndef OLD_ARM_ABI
+       case R_ARM_XPC25:         /* Arm BLX instruction.  */
+#endif
+       case R_ARM_PC24:          /* Arm B/BL instruction */
+#ifndef OLD_ARM_ABI
+         if (r_type == R_ARM_XPC25)
+           {
+             /* Check for Arm calling Arm function.  */
+             /* FIXME: Should we translate the instruction into a BL
+                instruction instead ?  */
+             if (sym_flags != STT_ARM_TFUNC)
+               _bfd_error_handler (_("\
+%s: Warning: Arm BLX instruction targets Arm function '%s'."),
+                                   bfd_get_filename (input_bfd),
+                                   h->root.root.string);
+           }
+         else
+#endif
            {
-             elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
-                                      input_section, hit_data, sym_sec, rel->r_offset,
-                                      signed_addend, value);
-             return bfd_reloc_ok;
+             /* Check for Arm calling Thumb function.  */
+             if (sym_flags == STT_ARM_TFUNC)
+               {
+                 elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
+                                          input_section, hit_data, sym_sec, rel->r_offset,
+                                          signed_addend, value);
+                 return bfd_reloc_ok;
+               }
            }
 
          if (   strcmp (bfd_get_target (input_bfd), "elf32-littlearm-oabi") == 0
@@ -1311,8 +1341,11 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
       bfd_put_16 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
+#ifndef OLD_ARM_ABI
+    case R_ARM_THM_XPC22:
+#endif
     case R_ARM_THM_PC22:
-      /* Thumb BL (branch long instruction). */
+      /* Thumb BL (branch long instruction).  */
       {
        bfd_vma        relocation;
        boolean        overflow = false;
@@ -1334,18 +1367,33 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
          signed_addend = addend;
        }
 #endif
-
-        /* If it is not a call to thumb, assume call to arm.
-          If it is a call relative to a section name, then it is not a
-          function call at all, but rather a long jump.  */
-       if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
+#ifndef OLD_ARM_ABI
+       if (r_type == R_ARM_THM_XPC22)
          {
-           if (elf32_thumb_to_arm_stub
-               (info, sym_name, input_bfd, output_bfd, input_section,
-                hit_data, sym_sec, rel->r_offset, signed_addend, value))
-             return bfd_reloc_ok;
-           else
-             return bfd_reloc_dangerous;
+           /* Check for Thumb to Thumb call.  */
+           /* FIXME: Should we translate the instruction into a BL
+              instruction instead ?  */
+           if (sym_flags == STT_ARM_TFUNC)
+             _bfd_error_handler (_("\
+%s: Warning: Thumb BLX instruction targets thumb function '%s'."),
+                                 bfd_get_filename (input_bfd),
+                                 h->root.root.string);
+         }
+       else
+#endif
+         {
+           /* If it is not a call to Thumb, assume call to Arm.
+              If it is a call relative to a section name, then it is not a
+              function call at all, but rather a long jump.  */
+           if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION)
+             {
+               if (elf32_thumb_to_arm_stub
+                   (info, sym_name, input_bfd, output_bfd, input_section,
+                    hit_data, sym_sec, rel->r_offset, signed_addend, value))
+                 return bfd_reloc_ok;
+               else
+                 return bfd_reloc_dangerous;
+             }
          }
 
        relocation = value + signed_addend;
@@ -1790,13 +1838,17 @@ elf32_arm_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)))
+                    input_section, rel->r_offset,
+                    (!info->shared || info->no_undefined
+                     || ELF_ST_VISIBILITY (h->other)))))
                return false;
              relocation = 0;
            }
@@ -1834,7 +1886,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
            case bfd_reloc_undefined:
              if (!((*info->callbacks->undefined_symbol)
                    (info, name, input_bfd, input_section,
-                    rel->r_offset)))
+                    rel->r_offset, true)))
                return false;
              break;
 
@@ -1867,7 +1919,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section,
   return true;
 }
 
-/* Function to keep ARM specific flags in the ELF header. */
+/* Function to keep ARM specific flags in the ELF header.  */
 static boolean
 elf32_arm_set_private_flags (abfd, flags)
      bfd *abfd;
@@ -1876,14 +1928,17 @@ elf32_arm_set_private_flags (abfd, flags)
   if (elf_flags_init (abfd)
       && elf_elfheader (abfd)->e_flags != flags)
     {
-      if (flags & EF_INTERWORK)
-       _bfd_error_handler (_ ("\
+      if (EF_ARM_EABI_VERSION (flags) == EF_ARM_EABI_UNKNOWN)
+       {
+         if (flags & EF_INTERWORK)
+           _bfd_error_handler (_ ("\
 Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
-                           bfd_get_filename (abfd));
-      else
-       _bfd_error_handler (_ ("\
+                               bfd_get_filename (abfd));
+         else
+           _bfd_error_handler (_ ("\
 Warning: Clearing the interwork flag of %s due to outside request"),
-                           bfd_get_filename (abfd));
+                               bfd_get_filename (abfd));
+       }
     }
   else
     {
@@ -1894,7 +1949,7 @@ Warning: Clearing the interwork flag of %s due to outside request"),
   return true;
 }
 
-/* Copy backend specific data from one object module to another */
+/* Copy backend specific data from one object module to another */
 static boolean
 elf32_arm_copy_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
@@ -1903,14 +1958,16 @@ elf32_arm_copy_private_bfd_data (ibfd, obfd)
   flagword in_flags;
   flagword out_flags;
 
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+  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;
+  in_flags  = elf_elfheader (ibfd)->e_flags;
   out_flags = elf_elfheader (obfd)->e_flags;
 
-  if (elf_flags_init (obfd) && in_flags != out_flags)
+  if (elf_flags_init (obfd)
+      && EF_ARM_EABI_VERSION (out_flags) == EF_ARM_EABI_UNKNOWN
+      && in_flags != out_flags)
     {
       /* Cannot mix PIC and non-PIC code.  */
       if ((in_flags & EF_PIC) != (out_flags & EF_PIC))
@@ -1947,31 +2004,20 @@ Warning: Clearing the interwork flag in %s because non-interworking code in %s h
    object file when linking.  */
 static boolean
 elf32_arm_merge_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+     bfd * ibfd;
+     bfd * obfd;
 {
   flagword out_flags;
   flagword in_flags;
 
+  /* Check if we have the same endianess */
+  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+    return false;
+
   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return true;
 
-  /* Check if we have the same endianess */
-  if (   ibfd->xvec->byteorder != obfd->xvec->byteorder
-      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
-      && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
-    {
-      (*_bfd_error_handler)
-       (_("%s: compiled for a %s endian system and target is %s endian"),
-        bfd_get_filename (ibfd),
-        bfd_big_endian (ibfd) ? "big" : "little",
-        bfd_big_endian (obfd) ? "big" : "little");
-
-      bfd_set_error (bfd_error_wrong_format);
-      return false;
-    }
-
   /* The input BFD must have had its flags initialised.  */
   /* The following seems bogus to me -- The flags are initialized in
      the assembler but I don't think an elf_flags_init field is
@@ -2007,6 +2053,18 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
     return true;
 
   /* Complain about various flag mismatches.  */
+  if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
+    {
+      _bfd_error_handler (_("\
+Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"),
+                        bfd_get_filename (ibfd),
+                        (in_flags & EF_ARM_EABIMASK) >> 24,
+                        bfd_get_filename (obfd),
+                        (out_flags & EF_ARM_EABIMASK) >> 24);
+    }
+  else if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_UNKNOWN)
+    /* Not sure what needs to be checked for EABI versions >= 1.  */
+    return true;
 
   if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26))
     _bfd_error_handler (_ ("\
@@ -2052,38 +2110,82 @@ elf32_arm_print_private_bfd_data (abfd, ptr)
      bfd *abfd;
      PTR ptr;
 {
-  FILE *file = (FILE *) ptr;
+  FILE * file = (FILE *) ptr;
+  unsigned long flags;
 
   BFD_ASSERT (abfd != NULL && ptr != NULL);
 
   /* Print normal ELF private data.  */
   _bfd_elf_print_private_bfd_data (abfd, ptr);
 
+  flags = elf_elfheader (abfd)->e_flags;
   /* Ignore init flag - it may not be set, despite the flags field containing valid data.  */
 
   /* xgettext:c-format */
   fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
 
-  if (elf_elfheader (abfd)->e_flags & EF_INTERWORK)
-    fprintf (file, _ (" [interworking enabled]"));
-  else
-    fprintf (file, _ (" [interworking not enabled]"));
+  switch (EF_ARM_EABI_VERSION (flags))
+    {
+    case EF_ARM_EABI_UNKNOWN:
+      /* The following flag bits are GNU extenstions and not part of the
+        official ARM ELF extended ABI.  Hence they are only decoded if
+        the EABI version is not set.  */
+      if (flags & EF_INTERWORK)
+       fprintf (file, _ (" [interworking enabled]"));
+      
+      if (flags & EF_APCS_26)
+       fprintf (file, _ (" [APCS-26]"));
+      else
+       fprintf (file, _ (" [APCS-32]"));
+      
+      if (flags & EF_APCS_FLOAT)
+       fprintf (file, _ (" [floats passed in float registers]"));
+      
+      if (flags & EF_PIC)
+       fprintf (file, _ (" [position independent]"));
+
+      if (flags & EF_NEW_ABI)
+       fprintf (file, _ (" [new ABI]"));
+                
+      if (flags & EF_OLD_ABI)
+       fprintf (file, _ (" [old ABI]"));
+                
+      if (flags & EF_SOFT_FLOAT)
+       fprintf (file, _ (" [software FP]"));
+                
+      flags &= ~(EF_INTERWORK | EF_APCS_26 | EF_APCS_FLOAT | EF_PIC
+                | EF_NEW_ABI | EF_OLD_ABI | EF_SOFT_FLOAT);
+      break;
+      
+    case EF_ARM_EABI_VER1:
+      fprintf (file, _ (" [Version1 EABI]"));
+      
+      if (flags & EF_ARM_SYMSARESORTED)
+       fprintf (file, _ (" [sorted symbol table]"));
+      else
+       fprintf (file, _ (" [unsorted symbol table]"));
+      
+      flags &= ~ EF_ARM_SYMSARESORTED;
+      break;
+      
+    default:
+      fprintf (file, _ (" <EABI version unrecognised>"));
+      break;
+    }
 
-  if (elf_elfheader (abfd)->e_flags & EF_APCS_26)
-    fprintf (file, _ (" [APCS-26]"));
-  else
-    fprintf (file, _ (" [APCS-32]"));
+  flags &= ~ EF_ARM_EABIMASK;
 
-  if (elf_elfheader (abfd)->e_flags & EF_APCS_FLOAT)
-    fprintf (file, _ (" [floats passed in float registers]"));
-  else
-    fprintf (file, _ (" [floats passed in integer registers]"));
+  if (flags & EF_ARM_RELEXEC)
+    fprintf (file, _ (" [relocatable executable]"));
 
-  if (elf_elfheader (abfd)->e_flags & EF_PIC)
-    fprintf (file, _ (" [position independent]"));
-  else
-    fprintf (file, _ (" [absolute position]"));
+  if (flags & EF_ARM_HASENTRY)
+    fprintf (file, _ (" [has entry point]"));
+
+  flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY);
 
+  if (flags)
+    fprintf (file, _ ("<Unrecognised flag bits set>"));
+  
   fputc ('\n', file);
 
   return true;
@@ -2094,10 +2196,25 @@ elf32_arm_get_symbol_type (elf_sym, type)
      Elf_Internal_Sym * elf_sym;
      int type;
 {
-  if (ELF_ST_TYPE (elf_sym->st_info) == STT_ARM_TFUNC)
-    return ELF_ST_TYPE (elf_sym->st_info);
-  else
-    return type;
+  switch (ELF_ST_TYPE (elf_sym->st_info))
+    {
+    case STT_ARM_TFUNC:
+      return ELF_ST_TYPE (elf_sym->st_info);
+
+    case STT_ARM_16BIT:
+      /* If the symbol is not an object, return the STT_ARM_16BIT flag.
+        This allows us to distinguish between data used by Thumb instructions
+        and non-data (which is probably code) inside Thumb regions of an
+        executable.  */
+      if (type != STT_OBJECT)
+       return ELF_ST_TYPE (elf_sym->st_info);
+      break;
+      
+    default:
+      break;
+    }
+
+  return type;
 }
 
 static asection *
@@ -2801,6 +2918,7 @@ elf32_arm_size_dynamic_sections (output_bfd, info)
                  outname = bfd_get_section_name (output_bfd,
                                                  s->output_section);
                  target = bfd_get_section_by_name (output_bfd, outname + 4);
+                 
                  if (target != NULL
                      && (target->flags & SEC_READONLY) != 0
                      && (target->flags & SEC_ALLOC) != 0)
This page took 0.029046 seconds and 4 git commands to generate.