Contribution: Intel's iWMMXt processor

Nick Clifton nickc@redhat.com
Thu Mar 27 17:49:00 GMT 2003


Hi Richard,

> Actually, it's a combination of all the areas related to this.
> 
> 1) The assembler sets the architecture to v5e if the user hasn't specified 
> any particular architecture.   It should probably be set to unknown.
>
> 2) The bit of code above should be able to combine files with different 
> architecture specifications with the result being the most specific 
> architecture requested (provided they are compatible); except that 
> unknown+anything is always unknown, unless some command-line option forces 
> it otherwise.
>
> 3) I also don't like the fact that it is directly exporting the internal 
> bfd numbers, which haven't been logically selected.  If we must do 
> something like this, it should be based on names and the tools should map 
> the names onto internal numbers as files are read and written.
>
> Finally, the use of .note.arm.ident for a GNU extension is a really BAD 
> idea.  This should have "gnu" somewhere in the note name.

I agree with these points - but we do now need a effective way of
identifying and labelling different types of ARM binaries.  The current
method - bits in the flags field of the header is no longer sufficient
and using a .note section seems the best way forward.

How about this compromise patch then ?  It:

  * Changes the name of the section to .note.gnu.arm.ident.

  * Changes the value stored in the section to be a string saying:

     "arch: <unknown|armv2|armv3|...etc"

  * Removes the bogus test for incompatible architectures and replaces
    it with one that can handle the new notes.

Cheers
        Nick

Index: include/elf/arm.h
===================================================================
RCS file: /cvs/src/src/include/elf/arm.h,v
retrieving revision 1.11
diff -c -3 -p -w -r1.11 arm.h
*** include/elf/arm.h	25 Mar 2003 20:56:01 -0000	1.11
--- include/elf/arm.h	27 Mar 2003 16:29:18 -0000
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 141,146 ****
  END_RELOC_NUMBERS (R_ARM_max)
  
  /* The name of the note section used to identify arm variants.  */
! #define ARM_NOTE_SECTION ".note.arm.ident"
       
  #endif /* _ELF_ARM_H */
--- 141,146 ----
  END_RELOC_NUMBERS (R_ARM_max)
  
  /* The name of the note section used to identify arm variants.  */
! #define ARM_NOTE_SECTION ".note.gnu.arm.ident"
       
  #endif /* _ELF_ARM_H */

Index: bfd/archures.c
===================================================================
RCS file: /cvs/src/src/bfd/archures.c,v
retrieving revision 1.67
diff -c -3 -p -w -r1.67 archures.c
*** bfd/archures.c	25 Mar 2003 20:55:57 -0000	1.67
--- bfd/archures.c	27 Mar 2003 16:29:19 -0000
*************** DESCRIPTION
*** 224,229 ****
--- 224,230 ----
  .#define bfd_mach_alpha_ev5  0x20
  .#define bfd_mach_alpha_ev6  0x30
  .  bfd_arch_arm,       {* Advanced Risc Machines ARM.  *}
+ .#define bfd_mach_arm_unknown	0
  .#define bfd_mach_arm_2		1
  .#define bfd_mach_arm_2a	2
  .#define bfd_mach_arm_3		3

Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.57
diff -c -3 -p -w -r1.57 bfd-in.h
*** bfd/bfd-in.h	28 Feb 2003 23:43:35 -0000	1.57
--- bfd/bfd-in.h	27 Mar 2003 16:29:20 -0000
*************** extern bfd_boolean bfd_elf32_arm_get_bfd
*** 835,840 ****
--- 835,850 ----
  extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd
    PARAMS ((bfd *, struct bfd_link_info *));
  
+ /* ARM Note section processing.  */
+ extern bfd_boolean arm_merge_machines
+   PARAMS ((bfd *, bfd *));
+ 
+ extern bfd_boolean arm_update_notes
+   PARAMS ((bfd *, const char *));
+ 
+ extern unsigned int arm_get_mach_from_notes
+   PARAMS ((bfd *, const char *));
+ 
  /* TI COFF load page support.  */
  extern void bfd_ticoff_set_section_load_page
    PARAMS ((struct sec *, int));

Index: bfd/coff-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-arm.c,v
retrieving revision 1.42
diff -c -3 -p -w -r1.42 coff-arm.c
*** bfd/coff-arm.c	25 Mar 2003 20:55:57 -0000	1.42
--- bfd/coff-arm.c	27 Mar 2003 16:29:26 -0000
*************** coff_arm_merge_private_bfd_data (ibfd, o
*** 2240,2264 ****
    if (ibfd == obfd)
      return TRUE;
  
-   if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd))
-     {
-       /* For now, allow an output file type of 'xscale' if the
- 	 input file type is 'iWMMXt'.  This means that we will
- 	 not have to build an entire iWMMXt enabled set of libraries
- 	 just to test a iWMMXt enabled binary.  Change the output
- 	 type to iWMMXt though.  Similarly allow 'xscale' binaries
-          to be linked into a 'iWMMXt' output binary.  */
-       if (   bfd_get_mach (obfd) == bfd_mach_arm_XScale
- 	  && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt)
- 	bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt);
-       else if (   bfd_get_mach (ibfd) != bfd_mach_arm_XScale
- 	       || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt)
- 	{
- 	  bfd_set_error (bfd_error_wrong_format);
- 	  return FALSE;
- 	}
-     }
- 
    /* If the two formats are different we cannot merge anything.
       This is not an error, since it is permissable to change the
       input and output formats.  */
--- 2240,2245 ----
*************** coff_arm_merge_private_bfd_data (ibfd, o
*** 2266,2272 ****
        || obfd->xvec->flavour != bfd_target_coff_flavour)
      return TRUE;
  
!   /* Verify that the APCS is the same for the two BFDs */
    if (APCS_SET (ibfd))
      {
        if (APCS_SET (obfd))
--- 2247,2258 ----
        || obfd->xvec->flavour != bfd_target_coff_flavour)
      return TRUE;
  
!   /* Determine what should happen if the input ARM architecture
!      does not match the output ARM architecture.  */
!   if (! arm_merge_machines (ibfd, obfd))
!     return FALSE;
! 
!   /* Verify that the APCS is the same for the two BFDs.  */
    if (APCS_SET (ibfd))
      {
        if (APCS_SET (obfd))
*************** coff_arm_final_link_postscript (abfd, pf
*** 2603,2647 ****
        globals->bfd_of_glue_owner->output_has_begun = TRUE;
      }
  
!   {
!     asection * arm_arch_section;
! 
!     /* Look for a .note section.  If one is present check
!        the machine number encoded in it, and set it to the current
!        machine number if it is different.  This allows XScale and
!        iWMMXt binaries to be merged and the resulting output to be set
!        to iWMMXt, even if the first input file had an XScale .note.  */
! 
!     arm_arch_section = bfd_get_section_by_name (abfd, ".note");
! 
!     if (arm_arch_section != NULL)
!       {
! 	char buffer [4];
! 
! 	if (bfd_get_section_contents (abfd, arm_arch_section, buffer,
! 					(file_ptr) 0, sizeof buffer))
! 	  {
! 	    unsigned long arm_mach;
! 
! 	    /* We have to extract the value this way to allow for a
! 	       host whose endian-ness is different from the target.  */
! 	    arm_mach = bfd_get_32 (abfd, buffer);
!   
! 	    if (arm_mach != bfd_get_mach (abfd))
! 	      {
! 		bfd_put_32 (abfd, bfd_get_mach (abfd), buffer);
! 
! 		if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
! 						(file_ptr) 0, sizeof buffer))
! 		  (*_bfd_error_handler)
! 		    (_("warning: unable to update contents of .note section in %s"),
! 		     bfd_get_filename (abfd));
! 	      }
! 	  }
!       }
!   }
! 
!   return TRUE;
  }
  
  #include "coffcode.h"
--- 2589,2595 ----
        globals->bfd_of_glue_owner->output_has_begun = TRUE;
      }
  
!   return arm_update_notes (abfd, ARM_NOTE_SECTION);
  }
  
  #include "coffcode.h"

Index: bfd/coffcode.h
===================================================================
RCS file: /cvs/src/src/bfd/coffcode.h,v
retrieving revision 1.88
diff -c -3 -p -w -r1.88 coffcode.h
*** bfd/coffcode.h	25 Mar 2003 20:55:57 -0000	1.88
--- bfd/coffcode.h	27 Mar 2003 16:29:31 -0000
*************** coff_set_arch_mach_hook (abfd, filehdr)
*** 1883,1888 ****
--- 1883,1891 ----
      case ARMPEMAGIC:
      case THUMBPEMAGIC:
        arch = bfd_arch_arm;
+       machine = arm_get_mach_from_notes (abfd, ARM_NOTE_SECTION);
+       if (machine == bfd_mach_arm_unknown)
+ 	{
  	  switch (internal_f->f_flags & F_ARM_ARCHITECTURE_MASK)
  	    {
  	    case F_ARM_2:  machine = bfd_mach_arm_2;  break;
*************** coff_set_arch_mach_hook (abfd, filehdr)
*** 1899,1924 ****
  	     currently the XScale.  */
          case F_ARM_5:  machine = bfd_mach_arm_XScale;  break;
  	}
- 
-       {
- 	asection * arm_arch_section;
-   
- 	arm_arch_section = bfd_get_section_by_name (abfd, ".note");
- 
- 	if (arm_arch_section)
- 	  {
- 	    bfd_byte buffer [4];
- 
- 	    if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
- 					    (file_ptr) 0, sizeof buffer))
- 	      (*_bfd_error_handler)
- 		(_("%s: warning: unable to retrieve .note section from %s"),
- 		 bfd_get_filename (abfd));
- 	      
- 	    /* We have to extract the value this way to allow for a
- 	       host whose endian-ness is different from the target.  */
- 	    machine = bfd_get_32 (abfd, buffer);
- 	  }
        }
        break;
  #endif
--- 1902,1907 ----

Index: bfd/coffgen.c
===================================================================
RCS file: /cvs/src/src/bfd/coffgen.c,v
retrieving revision 1.37
diff -c -3 -p -w -r1.37 coffgen.c
*** bfd/coffgen.c	25 Mar 2003 20:55:57 -0000	1.37
--- bfd/coffgen.c	27 Mar 2003 16:29:33 -0000
*************** coff_real_object_p (abfd, nscns, interna
*** 241,249 ****
  	}
      }
  
-   bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f);
-   /*  make_abs_section (abfd); */
- 
    return abfd->xvec;
  
   fail:
--- 241,246 ----

Index: bfd/cpu-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/cpu-arm.c,v
retrieving revision 1.9
diff -c -3 -p -w -r1.9 cpu-arm.c
*** bfd/cpu-arm.c	25 Mar 2003 20:55:57 -0000	1.9
--- bfd/cpu-arm.c	27 Mar 2003 16:29:34 -0000
***************
*** 1,5 ****
  /* BFD support for the ARM processor
!    Copyright 1994, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
     Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
  
     This file is part of BFD, the Binary File Descriptor library.
--- 1,5 ----
  /* BFD support for the ARM processor
!    Copyright 1994, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
  
     This file is part of BFD, the Binary File Descriptor library.
***************
*** 21,31 ****
--- 21,34 ----
  #include "bfd.h"
  #include "sysdep.h"
  #include "libbfd.h"
+ #include "libiberty.h"
  
  static const bfd_arch_info_type * compatible
    PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
  static bfd_boolean scan
    PARAMS ((const struct bfd_arch_info *, const char *));
+ static bfd_boolean arm_check_note
+   PARAMS ((bfd *, char *, bfd_size_type, const char *, char **));
  
  /* This routine is provided two arch_infos and works out which ARM
     machine which would be compatible with both and returns a pointer
*************** static const bfd_arch_info_type arch_inf
*** 149,151 ****
--- 152,427 ----
  
  const bfd_arch_info_type bfd_arm_arch =
    N (0, "arm", TRUE, & arch_info_struct[0]);
+ 
+ /* Support functions used by both the COFF and ELF versions of the ARM port.  */
+ 
+ /* Handle the mergeing of the 'machine' settings of input file IBFD
+    and an output file OBFD.  These values actually represent the
+    different possible ARM architecture variants.
+    Returns TRUE if they were merged successfully or FALSE otherwise.  */
+ 
+ bfd_boolean
+ arm_merge_machines (ibfd, obfd)
+      bfd * ibfd;
+      bfd * obfd;
+ {
+   unsigned int in  = bfd_get_mach (ibfd);
+   unsigned int out = bfd_get_mach (obfd);
+ 
+   /* If the output architecture is unknown, we now have a value to set.  */
+   if (out == bfd_mach_arm_unknown)
+     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
+ 
+   /* If the input architecure is unknown,
+      then so must be the output architecture.  */
+   else if (in == bfd_mach_arm_unknown)
+     /* FIXME: We ought to have some way to
+        override this on the command line.  */
+     bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
+ 
+   /* If they are the same then nothing needs to be done.  */
+   else if (out == in)
+     ;
+ 
+   /* Otherwise the general principle that a earlier architecture can be
+      linked with a later architecure to produce a binary that will execute
+      on the later architecture.
+ 
+      We fail however if we attempt to link a Cirrus EP9312 binary with an
+      Intel XScale binary, since these architecture have co-processors which
+      will not both be present on the same physical hardware.  */
+   else if (in == bfd_mach_arm_ep9312
+ 	   && (out == bfd_mach_arm_XScale || out == bfd_mach_arm_iWMMXt))
+     {
+       _bfd_error_handler (_("\
+ ERROR: %s is compiled for the EP9312, whereas %s is compiled for XScale"),
+ 			  bfd_archive_filename (ibfd),
+ 			  bfd_get_filename (obfd));
+       bfd_set_error (bfd_error_wrong_format);
+       return FALSE;
+     }
+   else if (out == bfd_mach_arm_ep9312
+ 	   && (in == bfd_mach_arm_XScale || in == bfd_mach_arm_iWMMXt))
+     {
+       _bfd_error_handler (_("\
+ ERROR: %s is compiled for the EP9312, whereas %s is compiled for XScale"),
+ 			  bfd_archive_filename (obfd),
+ 			  bfd_get_filename (ibfd));
+       bfd_set_error (bfd_error_wrong_format);
+       return FALSE;
+     }
+   else if (in > out)
+     bfd_set_arch_mach (obfd, bfd_arch_arm, in);
+   /* else
+      Nothing to do.  */
+ 
+   return TRUE;
+ }
+ 
+ typedef struct
+ {
+   unsigned char	namesz[4];	/* Size of entry's owner string.  */
+   unsigned char	descsz[4];	/* Size of the note descriptor.  */
+   unsigned char	type[4];	/* Interpretation of the descriptor.  */
+   char		name[1];	/* Start of the name+desc data.  */
+ } arm_Note;
+ 
+ static bfd_boolean
+ arm_check_note (abfd, buffer, buffer_size, expected_name, description_return)
+      bfd *           abfd;
+      char *          buffer;
+      bfd_size_type   buffer_size;
+      const char *    expected_name;
+      char **         description_return;
+ {
+   unsigned long namesz;
+   unsigned long descsz;
+   unsigned long type;
+   char *        descr;
+ 
+   if (buffer_size < offsetof (arm_Note, name))
+     return FALSE;
+ 
+   /* We have to extract the values this way to allow for a
+      host whose endian-ness is different from the target.  */
+   namesz = bfd_get_32 (abfd, buffer);
+   descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
+   type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
+   descr  = buffer + offsetof (arm_Note, name);
+ 
+   /* Check for buffer overflow.  */
+   if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
+     return FALSE;
+ 
+   if (expected_name == NULL)
+     {
+       if (namesz != 0)
+ 	return FALSE;
+     }
+   else
+     { 
+       if (namesz != (strlen (expected_name) + 1 + 3) & ~3)
+ 	return FALSE;
+       
+       if (strcmp (descr, expected_name) != 0)
+ 	return FALSE;
+ 
+       descr += (namesz + 3) & ~3;
+     }
+ 
+   /* FIXME: We should probably check the type as well.  */
+ 
+   if (description_return != NULL)
+     * description_return = descr;
+ 
+   return TRUE;
+ }
+ 
+ #define NOTE_ARCH_STRING 	"arch: "
+ 
+ bfd_boolean
+ arm_update_notes (abfd, note_section)
+      bfd * abfd;
+      const char * note_section;
+ {
+   asection *     arm_arch_section;
+   bfd_size_type  buffer_size;
+   char *         buffer;
+   char *         arch_string;
+   char *         expected;
+ 
+   /* Look for a note section.  If one is present check the architecture
+      string encoded in it, and set it to the current architecture if it is
+      different.  */
+   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
+ 
+   if (arm_arch_section == NULL)
+     return TRUE;
+ 
+   buffer_size = arm_arch_section->_raw_size;
+   if (buffer_size == 0)
+     return FALSE;
+ 
+   buffer = bfd_malloc (buffer_size);
+   if (buffer == NULL)
+     return FALSE;
+   
+   if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
+ 				  (file_ptr) 0, buffer_size))
+     goto FAIL;
+ 
+   /* Parse the note.  */
+   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
+     goto FAIL;
+ 
+   /* Check the architecture in the note against the architecture of the bfd.  */
+   switch (bfd_get_mach (abfd))
+     {
+     default:
+     case bfd_mach_arm_unknown: expected = "unknown"; break;
+     case bfd_mach_arm_2:       expected = "armv2"; break;
+     case bfd_mach_arm_2a:      expected = "armv2a"; break;
+     case bfd_mach_arm_3:       expected = "armv3"; break;
+     case bfd_mach_arm_3M:      expected = "armv3M"; break;
+     case bfd_mach_arm_4:       expected = "armv4"; break;
+     case bfd_mach_arm_4T:      expected = "armv4t"; break;
+     case bfd_mach_arm_5:       expected = "armv5"; break;
+     case bfd_mach_arm_5T:      expected = "armv5t"; break;
+     case bfd_mach_arm_5TE:     expected = "armv5te"; break;
+     case bfd_mach_arm_XScale:  expected = "XScale"; break;
+     case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
+     case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
+     }
+ 
+   if (strcmp (arch_string, expected) != 0)
+     {
+       strcpy (buffer + offsetof (arm_Note, name) + ((strlen (NOTE_ARCH_STRING) + 3) & ~3), expected);
+ 
+       if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
+ 				      (file_ptr) 0, buffer_size))
+ 	{
+ 	  (*_bfd_error_handler)
+ 	    (_("warning: unable to update contents of %s section in %s"),
+ 	     note_section, bfd_get_filename (abfd));
+ 	  goto FAIL;
+ 	}
+     }
+ 
+   free (buffer);
+   return TRUE;
+ 
+  FAIL:
+   free (buffer);
+   return FALSE;
+ }
+ 
+ 
+ static struct
+ {
+   const char * string;
+   unsigned int mach;
+ }
+ architectures[] =
+ {
+   { "armv2",   bfd_mach_arm_2 },
+   { "armv2a",  bfd_mach_arm_2a },
+   { "armv3",   bfd_mach_arm_3 },
+   { "armv3M",  bfd_mach_arm_3M },
+   { "armv4",   bfd_mach_arm_4 },
+   { "armv4t",  bfd_mach_arm_4T },
+   { "armv5",   bfd_mach_arm_5 },
+   { "armv5t",  bfd_mach_arm_5T },
+   { "armv5te", bfd_mach_arm_5TE },
+   { "XScale",  bfd_mach_arm_XScale },
+   { "ep9312",  bfd_mach_arm_ep9312 },
+   { "iWMMXt",  bfd_mach_arm_iWMMXt }
+ };
+ 
+ /* Extract the machine number stored in a note section.  */
+ unsigned int
+ arm_get_mach_from_notes (abfd, note_section)
+      bfd * abfd;
+      const char * note_section;
+ {
+   asection *     arm_arch_section;
+   bfd_size_type  buffer_size;
+   char *         buffer;
+   char *         arch_string;
+   int            i;
+ 
+   /* Look for a note section.  If one is present check the architecture
+      string encoded in it, and set it to the current architecture if it is
+      different.  */
+   arm_arch_section = bfd_get_section_by_name (abfd, note_section);
+ 
+   if (arm_arch_section == NULL)
+     return bfd_mach_arm_unknown;
+ 
+   buffer_size = arm_arch_section->_raw_size;
+   if (buffer_size == 0)
+     return bfd_mach_arm_unknown;
+ 
+   buffer = bfd_malloc (buffer_size);
+   if (buffer == NULL)
+     return bfd_mach_arm_unknown;
+   
+   if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
+ 				  (file_ptr) 0, buffer_size))
+     goto FAIL;
+ 
+   /* Parse the note.  */
+   if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
+     goto FAIL;
+ 
+   /* Interpret the architecture string.  */
+   for (i = ARRAY_SIZE (architectures); i--;)
+     if (strcmp (arch_string, architectures[i].string) == 0)
+       {
+ 	free (buffer);
+ 	return architectures[i].mach;
+       }
+ 
+  FAIL:
+   free (buffer);
+   return bfd_mach_arm_unknown;
+ }

Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.104
diff -c -3 -p -w -r1.104 elf32-arm.h
*** bfd/elf32-arm.h	25 Mar 2003 20:55:57 -0000	1.104
--- bfd/elf32-arm.h	27 Mar 2003 16:29:38 -0000
*************** static bfd_boolean
*** 2119,2161 ****
  elf32_arm_object_p (abfd)
       bfd *abfd;
  {
!   asection * arm_arch_section;
  
!   arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION);
  
!   if (arm_arch_section)
!     {
!       char          buffer [4];
!       unsigned long arm_mach;
! 
!       if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
! 				      (file_ptr) 0, sizeof buffer))
! 	(*_bfd_error_handler)
! 	  (_("%s: warning: unable to retrieve %s section from %s"),
! 	   ARM_NOTE_SECTION, bfd_get_filename (abfd));
!       else
! 	{
! 	  /* We have to extract the value this way to allow for a
! 	     host whose endian-ness is different from the target.  */
! 	  arm_mach = bfd_get_32 (abfd, buffer);
! 	  bfd_default_set_arch_mach (abfd, bfd_arch_arm, arm_mach);
  
! 	  if (bfd_get_arch (abfd) == bfd_arch_arm)
! 	    return TRUE;
        
- 	  /* If the set failed for some reason, do not leave the architecture
- 	     type as 0 (unknown), but issue a warning message and force it to
- 	     be set to bfd_arch_arm.  */
- 	  (*_bfd_error_handler)
- 	    (_("%s: warning: unrecognized ARM machine number: %x"),
- 	     bfd_get_filename (abfd), arm_mach);
- 	}
-     }
    else
!     {
!       if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
! 	bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
!     }
  
    return TRUE;
  }
--- 2119,2136 ----
  elf32_arm_object_p (abfd)
       bfd *abfd;
  {
!   unsigned int mach;
    
!   mach = arm_get_mach_from_notes (abfd, ARM_NOTE_SECTION);
  
!   if (mach != bfd_mach_arm_unknown)
!     bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
  
!   else if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
!     bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
  
    else
!     bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
  
    return TRUE;
  }
*************** elf32_arm_merge_private_bfd_data (ibfd, 
*** 2296,2319 ****
        return TRUE;
      }
  
!   if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd))
!     {
!       /* For now, allow an output file type of 'xscale' if the
! 	 input file type is 'iWMMXt'.  This means that we will
! 	 not have to build an entire iWMMXt enabled set of libraries
! 	 just to test a iWMMXt enabled binary.  Change the output
! 	 type to iWMMXt though.  Similarly allow 'xscale' binaries
!          to be linked into a 'iWMMXt' output binary.  */
!       if (   bfd_get_mach (obfd) == bfd_mach_arm_XScale
! 	  && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt)
! 	bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt);
!       else if (   bfd_get_mach (ibfd) != bfd_mach_arm_XScale
! 	       || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt)
! 	{
! 	  bfd_set_error (bfd_error_wrong_format);
  	  return FALSE;
- 	}
-     }
  
    /* Identical flags must be compatible.  */
    if (in_flags == out_flags)
--- 2271,2280 ----
        return TRUE;
      }
  
!   /* Determine what should happen if the input ARM architecture
!      does not match the output ARM architecture.  */
!   if (! arm_merge_machines (ibfd, obfd))
      return FALSE;
  
    /* Identical flags must be compatible.  */
    if (in_flags == out_flags)
*************** elf32_arm_final_write_processing (abfd, 
*** 3733,3774 ****
       bfd *abfd;
       bfd_boolean linker ATTRIBUTE_UNUSED;
  {
!   asection *    arm_arch_section;
!   char          buffer [4];
!   unsigned long arm_mach;
! 
!   /* Look for a .note.arm.ident section.  If one is present check
!      the machine number encoded in it, and set it to the current
!      machine number if it is different.  This allows XScale and
!      iWMMXt binaries to be merged and the resulting output to be set
!      to iWMMXt, even if the first input file had an XScale .note.  */
! 
!   arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION);
! 
!   if (arm_arch_section == NULL)
!     return;
! 
!   if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
! 				(file_ptr) 0, sizeof buffer))
!     /* If the ident section does not exist then just skip this check.  */
!     return;
! 
!   /* We have to extract the value this way to allow for a
!      host whose endian-ness is different from the target.  */
!   arm_mach = bfd_get_32 (abfd, buffer);
! 
!   if (arm_mach == bfd_get_mach (abfd))
!     return;
! 
!   bfd_put_32 (abfd, bfd_get_mach (abfd), buffer);
! 
!   if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
! 				  (file_ptr) 0, sizeof buffer))
!     (*_bfd_error_handler)
!       (_("warning: unable to update contents of %s section in %s"),
!        ARM_NOTE_SECTION, bfd_get_filename (abfd));
! 
!   return;
  }
  
  #define ELF_ARCH			bfd_arch_arm
--- 3694,3700 ----
       bfd *abfd;
       bfd_boolean linker ATTRIBUTE_UNUSED;
  {
!   arm_update_notes (abfd, ARM_NOTE_SECTION);
  }
  
  #define ELF_ARCH			bfd_arch_arm

Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.138
diff -c -3 -p -w -r1.138 tc-arm.c
*** gas/config/tc-arm.c	25 Mar 2003 20:55:58 -0000	1.138
--- gas/config/tc-arm.c	27 Mar 2003 16:29:47 -0000
*************** static int arm_parse_extension PARAMS ((
*** 2361,2366 ****
--- 2361,2369 ----
  static int arm_parse_cpu PARAMS ((char *));
  static int arm_parse_arch PARAMS ((char *));
  static int arm_parse_fpu PARAMS ((char *));
+ #if defined OBJ_COFF || defined OBJ_ELF
+ static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
+ #endif
  
  /* Stuff needed to resolve the label ambiguity
     As:
*************** build_arm_ops_hsh ()
*** 10083,10088 ****
--- 10086,10139 ----
      }
  }
  
+ #if defined OBJ_ELF || defined OBJ_COFF
+ 
+ #ifdef OBJ_ELF
+ #define arm_Note Elf_External_Note
+ #else
+ typedef struct
+ {
+   unsigned char	namesz[4];	/* Size of entry's owner string.  */
+   unsigned char	descsz[4];	/* Size of the note descriptor.  */
+   unsigned char	type[4];	/* Interpretation of the descriptor.  */
+   char		name[1];	/* Start of the name+desc data.  */
+ } arm_Note;
+ #endif
+ 
+ /* The description is kept to a fix sized in order to make updating
+    it and merging it easier.  */
+ #define ARM_NOTE_DESCRIPTION_LENGTH	8
+ 
+ static void
+ arm_add_note (name, description, type)
+      const char * name;
+      const char * description;
+      unsigned int type;
+ {
+   arm_Note     note ATTRIBUTE_UNUSED;
+   char *       p;
+   unsigned int name_len;
+ 
+   name_len = (strlen (name) + 1 + 3) & ~3;
+   
+   p = frag_more (sizeof (note.namesz));
+   md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
+ 
+   p = frag_more (sizeof (note.descsz));
+   md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
+ 
+   p = frag_more (sizeof (note.type));
+   md_number_to_chars (p, (valueT) type, sizeof (note.type));
+ 
+   p = frag_more (name_len);
+   strcpy (p, name);
+ 
+   p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
+   strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
+   frag_align (2, 0, 0);
+ }
+ #endif
+ 
  void
  md_begin ()
  {
*************** md_begin ()
*** 10216,10222 ****
        break;
  
      default:
!       mach = bfd_mach_arm_4;
        break;
      }
  
--- 10267,10273 ----
        break;
  
      default:
!       mach = bfd_mach_arm_unknown;
        break;
      }
  
*************** md_begin ()
*** 10247,10257 ****
      mach = bfd_mach_arm_3M;
  
  #if defined (OBJ_ELF) || defined (OBJ_COFF)
    {
-     expressionS exp;
      segT current_seg = now_seg;
      subsegT current_subseg = now_subseg;
      asection * arm_arch;
      
      arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
  
--- 10298,10318 ----
      mach = bfd_mach_arm_3M;
  
  #if defined (OBJ_ELF) || defined (OBJ_COFF)
+ 
+   /* Create a .note section to fully identify this arm binary.  */
+ 
+ #define NOTE_ARCH_STRING 	"arch: "
+ 
+ #if defined OBJ_COFF && ! defined NT_VERSION
+ #define NT_VERSION  1
+ #define NT_ARCH     2
+ #endif
+   
    {
      segT current_seg = now_seg;
      subsegT current_subseg = now_subseg;
      asection * arm_arch;
+     const char * arch_string;
  
      arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
  
*************** md_begin ()
*** 10262,10273 ****
  #endif
      arm_arch->output_section = arm_arch;
      subseg_set (arm_arch, 0);
-     exp.X_op = O_constant;
-     exp.X_add_number = mach;
-     exp.X_add_symbol = NULL;
-     exp.X_op_symbol = NULL;
  
!     emit_expr (&exp, 4);
  
      subseg_set (current_seg, current_subseg);
    }
--- 10323,10348 ----
  #endif
      arm_arch->output_section = arm_arch;
      subseg_set (arm_arch, 0);
  
!     switch (mach)
!       {
!       default:
!       case bfd_mach_arm_unknown: arch_string = "unknown"; break;
!       case bfd_mach_arm_2:       arch_string = "armv2"; break;
!       case bfd_mach_arm_2a:      arch_string = "armv2a"; break;
!       case bfd_mach_arm_3:       arch_string = "armv3"; break;
!       case bfd_mach_arm_3M:      arch_string = "armv3M"; break;
!       case bfd_mach_arm_4:       arch_string = "armv4"; break;
!       case bfd_mach_arm_4T:      arch_string = "armv4t"; break;
!       case bfd_mach_arm_5:       arch_string = "armv5"; break;
!       case bfd_mach_arm_5T:      arch_string = "armv5t"; break;
!       case bfd_mach_arm_5TE:     arch_string = "armv5te"; break;
!       case bfd_mach_arm_XScale:  arch_string = "XScale"; break;
!       case bfd_mach_arm_ep9312:  arch_string = "ep9312"; break;
!       case bfd_mach_arm_iWMMXt:  arch_string = "iWMMXt"; break;	
!       }
! 
!     arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
  
      subseg_set (current_seg, current_subseg);
    }
*************** static struct arm_cpu_option_table arm_c
*** 11759,11766 ****
    {"arm1020t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
    {"arm1020e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
    /* ??? XSCALE is really an architecture.  */
!   {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
!   {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
    {"i80200",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
    /* Maverick */
    {"ep9312",		ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
--- 11834,11841 ----
    {"arm1020t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
    {"arm1020e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
    /* ??? XSCALE is really an architecture.  */
!   {"xscale",		ARM_ARCH_XSCALE, FPU_NONE},
!   {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_NONE},
    {"i80200",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
    /* Maverick */
    {"ep9312",		ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},



More information about the Binutils mailing list