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