This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ARM BE8 linker support


The attached patch adds linker support for creating arm BE8 format 
executables. These consist of big-endian data and little-endian code.

Ok?

Paul

2004-03-31  Paul Brook  <paul@codesourcery.com>

	* bfd/bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.
	* bfd/elf32-arm.h (struct elf32_elf_section_map): New.
	(struct _arm_elf_section_data): New.
	(elf32_arm_section_data): Define.
	(struct elf32_arm_link_hash_table): Add byteswap_code.
	(elf32_arm_link_hash_table_create): Initialize byteswap_code.
	(bfd_elf32_arm_process_before_allocation): Add byteswap_code.
	(elf32_arm_post_process_headers): Set EF_ARM_BE8.
	(elf32_arm_output_symbol_hook, elf32_arm_new_section_hook,
	elf32_arm_compare_mapping, elf32_arm_write_section): New functions.
	(bfd_elf32_new_section_hook, elf_backend_write_section,
	elf_backend_link_output_symbol_hook): Define.
	* ld/emultempl/armelf.em (byteswap_code): Add.
	(arm_elf_before_allocation): Pass extra parameter.
	(PARSE_AND_LIST_PROLOGUE): Add OPTION_BE8.
	(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add be8.
	(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_BE8.
	* ld/emultempl/armelf_oabi.em: Pass extra parameter.
	* ld/ld.texinfo: Document --be8.
? bfd/doc/bfdint.html
? gas/doc/as.info
? ld/ldint.html
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.77
diff -u -p -r1.77 bfd-in.h
--- bfd/bfd-in.h	27 Mar 2004 10:58:05 -0000	1.77
+++ bfd/bfd-in.h	1 Apr 2004 00:48:34 -0000
@@ -786,7 +786,7 @@ extern bfd_boolean bfd_elf32_arm_allocat
   (struct bfd_link_info *);
 
 extern bfd_boolean bfd_elf32_arm_process_before_allocation
-  (bfd *, struct bfd_link_info *, int);
+  (bfd *, struct bfd_link_info *, int, int);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.265
diff -u -p -r1.265 bfd-in2.h
--- bfd/bfd-in2.h	30 Mar 2004 14:04:26 -0000	1.265
+++ bfd/bfd-in2.h	1 Apr 2004 00:48:36 -0000
@@ -793,7 +793,7 @@ extern bfd_boolean bfd_elf32_arm_allocat
   (struct bfd_link_info *);
 
 extern bfd_boolean bfd_elf32_arm_process_before_allocation
-  (bfd *, struct bfd_link_info *, int);
+  (bfd *, struct bfd_link_info *, int, int);
 
 extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   (bfd *, struct bfd_link_info *);
Index: bfd/elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.126
diff -u -p -r1.126 elf32-arm.h
--- bfd/elf32-arm.h	31 Mar 2004 10:20:12 -0000	1.126
+++ bfd/elf32-arm.h	1 Apr 2004 00:48:39 -0000
@@ -106,7 +106,7 @@ bfd_boolean bfd_elf32_arm_allocate_inter
 bfd_boolean bfd_elf32_arm_get_bfd_for_interworking
   PARAMS ((bfd *, struct bfd_link_info *));
 bfd_boolean bfd_elf32_arm_process_before_allocation
-  PARAMS ((bfd *, struct bfd_link_info *, int));
+  PARAMS ((bfd *, struct bfd_link_info *, int, int));
 #endif
 
 
@@ -190,6 +190,26 @@ static const bfd_vma elf32_arm_plt_entry
 
 #endif
 
+/* Used to build a map of a section.  This is required for mixed-endian
+   code/data.  */
+
+typedef struct elf32_elf_section_map
+{
+  bfd_vma vma;
+  char type;
+}
+elf32_arm_section_map;
+
+struct _arm_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  int mapcount;
+  elf32_arm_section_map *map;
+};
+
+#define elf32_arm_section_data(sec) \
+  ((struct _arm_elf_section_data *) elf_section_data (sec))
+
 /* The ARM linker needs to keep track of the number of relocs that it
    decides to copy in check_relocs for each symbol.  This is so that
    it can discard PC relative relocs if it doesn't need them when
@@ -247,6 +267,9 @@ struct elf32_arm_link_hash_table
        length should be applied by the linker.  */
     int no_pipeline_knowledge;
 
+    /* Nonzero to output a BE8 image.  */
+    int byteswap_code;
+
     /* Short-cuts to get to dynamic linker sections.  */
     asection *sgot;
     asection *sgotplt;
@@ -430,6 +453,7 @@ elf32_arm_link_hash_table_create (abfd)
   ret->arm_glue_size = 0;
   ret->bfd_of_glue_owner = NULL;
   ret->no_pipeline_knowledge = 0;
+  ret->byteswap_code = 0;
   ret->sym_sec.abfd = NULL;
 
   return &ret->root.root;
@@ -808,10 +832,13 @@ bfd_elf32_arm_get_bfd_for_interworking (
 }
 
 bfd_boolean
-bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)
+bfd_elf32_arm_process_before_allocation (abfd, link_info,
+					 no_pipeline_knowledge,
+					 byteswap_code)
      bfd *abfd;
      struct bfd_link_info *link_info;
      int no_pipeline_knowledge;
+     int byteswap_code;
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -834,6 +861,14 @@ bfd_elf32_arm_process_before_allocation 
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
   globals->no_pipeline_knowledge = no_pipeline_knowledge;
+  if (byteswap_code && !bfd_big_endian (abfd))
+    {
+      _bfd_error_handler (
+	  _("%s: BE8 images only valid in big-endian mode."),
+	  bfd_archive_filename (abfd));
+      return FALSE;
+    }
+  globals->byteswap_code = byteswap_code;
 
   /* Rummage around all the relocs and map the glue vectors.  */
   sec = abfd->sections;
@@ -4049,11 +4084,16 @@ elf32_arm_post_process_headers (abfd, li
      struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
 {
   Elf_Internal_Ehdr * i_ehdrp;	/* ELF file header, internal form.  */
+  struct elf32_arm_link_hash_table *globals;
 
   i_ehdrp = elf_elfheader (abfd);
 
   i_ehdrp->e_ident[EI_OSABI]      = ARM_ELF_OS_ABI_VERSION;
   i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
+
+  globals = elf32_arm_hash_table (link_info);
+  if (globals->byteswap_code)
+    i_ehdrp->e_flags |= EF_ARM_BE8;
 }
 
 static enum elf_reloc_type_class
@@ -4089,7 +4129,7 @@ elf32_arm_section_flags (flags, hdr)
   return TRUE;
 }
 
-void
+static void
 elf32_arm_final_write_processing (abfd, linker)
      bfd *abfd;
      bfd_boolean linker ATTRIBUTE_UNUSED;
@@ -4097,6 +4137,148 @@ elf32_arm_final_write_processing (abfd, 
   bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
 }
 
+
+/* Called for each symbol.  Builds a section map based on mapping symbols.
+   Does not alter any of the symbols.  */
+
+static bfd_boolean
+elf32_arm_output_symbol_hook (struct bfd_link_info *info,
+			      const char *name,
+			      Elf_Internal_Sym *elfsym,
+			      asection *input_sec,
+			      struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
+{
+  int mapcount;
+  elf32_arm_section_map *map;
+  struct elf32_arm_link_hash_table *globals;
+
+  /* Only do this on final link.  */
+  if (info->relocatable)
+    return TRUE;
+
+  /* Only build a map if we need to byteswap code.  */
+  globals = elf32_arm_hash_table (info);
+  if (!globals->byteswap_code)
+    return TRUE;
+
+  /* We only want mapping symbols.  */
+  if (name == NULL
+      || name[0] != '$'
+      || (name[1] != 'a'
+	  && name[1] != 't'
+	  && name[1] != 'd'))
+    return TRUE;
+
+  mapcount = ++(elf32_arm_section_data (input_sec)->mapcount);
+  map = elf32_arm_section_data (input_sec)->map;
+  /* TODO: This may be inefficient, but we probably don't usually have many
+     mapping symbols per section.  */
+  map = bfd_realloc (map, mapcount * sizeof (elf32_arm_section_map));
+  elf32_arm_section_data (input_sec)->map = map;
+  
+  map[mapcount - 1].vma = elfsym->st_value;
+  map[mapcount - 1].type = name[1];
+  return TRUE;
+}
+
+
+/* Allocate target specific section data.  */
+
+static bfd_boolean
+elf32_arm_new_section_hook (bfd *abfd, asection *sec)
+{
+  struct _arm_elf_section_data *sdata;
+  bfd_size_type amt = sizeof (*sdata);
+
+  sdata = bfd_zalloc (abfd, amt);
+  if (sdata == NULL)
+    return FALSE;
+  sec->used_by_bfd = sdata;
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+/* Used to order a list of mapping symbols by address.  */
+
+static int
+elf32_arm_compare_mapping (const void * a, const void * b)
+{
+  return ((const elf32_arm_section_map *) a)->vma
+	 > ((const elf32_arm_section_map *) b)->vma;
+}
+
+
+/* Do code byteswapping.  Return FALSE afterwards so that the section is
+   written out as normal.  */
+
+static bfd_boolean
+elf32_arm_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, asection *sec,
+			 bfd_byte *contents)
+{
+  int mapcount;
+  elf32_arm_section_map *map;
+  bfd_vma ptr;
+  bfd_vma end;
+  bfd_vma offset;
+  bfd_byte tmp;
+  int i;
+  
+  mapcount = elf32_arm_section_data (sec)->mapcount;
+  map = elf32_arm_section_data (sec)->map;
+
+  if (mapcount == 0)
+    return FALSE;
+
+  qsort (map, mapcount, sizeof (elf32_arm_section_map),
+	 elf32_arm_compare_mapping);
+
+  offset = sec->output_section->vma + sec->output_offset;
+  ptr = map[0].vma - offset;
+  for (i = 0; i < mapcount; i++)
+    {
+      if (i == mapcount - 1)
+	end = bfd_section_size (output_bfd, sec);
+      else
+	end = map[i + 1].vma - offset;
+      
+      switch (map[i].type)
+	{
+	case 'a':
+	  /* Byte swap code words.  */
+	  while (ptr + 3 < end)
+	    {
+	      tmp = contents[ptr];
+	      contents[ptr] = contents[ptr + 3];
+	      contents[ptr + 3] = tmp;
+	      tmp = contents[ptr + 1];
+	      contents[ptr + 1] = contents[ptr + 2];
+	      contents[ptr + 2] = tmp;
+	      ptr += 4;
+	    }
+	  break;
+
+	case 't':
+	  /* Byte swap code halfwords.  */
+	  while (ptr + 1 < end)
+	    {
+	      tmp = contents[ptr];
+	      contents[ptr] = contents[ptr + 1];
+	      contents[ptr + 1] = tmp;
+	      ptr += 2;
+	    }
+	  break;
+
+	case 'd':
+	  /* Leave data alone.  */
+	  break;
+	}
+      ptr = end;
+    }
+  bfd_free (map);
+  return FALSE;
+}
+
 #define ELF_ARCH			bfd_arch_arm
 #define ELF_MACHINE_CODE		EM_ARM
 #ifdef __QNXTARGET__
@@ -4112,16 +4294,19 @@ elf32_arm_final_write_processing (abfd, 
 #define bfd_elf32_bfd_link_hash_table_create    elf32_arm_link_hash_table_create
 #define bfd_elf32_bfd_reloc_type_lookup		elf32_arm_reloc_type_lookup
 #define bfd_elf32_find_nearest_line	        elf32_arm_find_nearest_line
+#define bfd_elf32_new_section_hook		elf32_arm_new_section_hook
 
 #define elf_backend_get_symbol_type             elf32_arm_get_symbol_type
 #define elf_backend_gc_mark_hook                elf32_arm_gc_mark_hook
 #define elf_backend_gc_sweep_hook               elf32_arm_gc_sweep_hook
 #define elf_backend_check_relocs                elf32_arm_check_relocs
 #define elf_backend_relocate_section		elf32_arm_relocate_section
+#define elf_backend_write_section		elf32_arm_write_section
 #define elf_backend_adjust_dynamic_symbol	elf32_arm_adjust_dynamic_symbol
 #define elf_backend_create_dynamic_sections     elf32_arm_create_dynamic_sections
 #define elf_backend_finish_dynamic_symbol	elf32_arm_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections	elf32_arm_finish_dynamic_sections
+#define elf_backend_link_output_symbol_hook	elf32_arm_output_symbol_hook
 #define elf_backend_size_dynamic_sections	elf32_arm_size_dynamic_sections
 #define elf_backend_post_process_headers	elf32_arm_post_process_headers
 #define elf_backend_reloc_type_class		elf32_arm_reloc_type_class
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.107
diff -u -p -r1.107 ld.texinfo
--- ld/ld.texinfo	18 Mar 2004 12:50:20 -0000	1.107
+++ ld/ld.texinfo	1 Apr 2004 00:48:46 -0000
@@ -4762,6 +4762,12 @@ But it also sets the bottom bit of the a
 branched to using a BX instruction, and the program will start
 executing in Thumb mode straight away.
 
+@cindex BE8
+@kindex --be8
+The @samp{--be8} switch instructs @command{ld} to generate BE8 format
+executables.  This option is only valid when linking big-endian objects.
+The resulting image will contain big-endian data and little-endian code.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear
Index: ld/emultempl/armelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf.em,v
retrieving revision 1.36
diff -u -p -r1.36 armelf.em
--- ld/emultempl/armelf.em	3 Jan 2004 11:09:07 -0000	1.36
+++ ld/emultempl/armelf.em	1 Apr 2004 00:48:46 -0000
@@ -27,6 +27,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
 static int no_pipeline_knowledge = 0;
 static char *thumb_entry_symbol = NULL;
 static bfd *bfd_for_interwork;
+static int byteswap_code = 0;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -117,7 +118,8 @@ arm_elf_before_allocation (void)
     LANG_FOR_EACH_INPUT_STATEMENT (is)
       {
 	if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, & link_info,
-						      no_pipeline_knowledge))
+						      no_pipeline_knowledge,
+						      byteswap_code))
 	  {
 	    /* xgettext:c-format */
 	    einfo (_("Errors encountered processing file %s"), is->filename);
@@ -184,6 +186,7 @@ EOF
 #
 PARSE_AND_LIST_PROLOGUE='
 #define OPTION_THUMB_ENTRY		301
+#define OPTION_BE8			302
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -191,11 +194,13 @@ PARSE_AND_LIST_SHORTOPTS=p
 PARSE_AND_LIST_LONGOPTS='
   { "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
   { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+  { "be8", no_argument, NULL, OPTION_BE8},
 '
 
 PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  -p --no-pipeline-knowledge  Stop the linker knowing about the pipeline length\n"));
   fprintf (file, _("     --thumb-entry=<sym>      Set the entry point to be Thumb symbol <sym>\n"));
+  fprintf (file, _("     --be8                    Oputput BE8 format image\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -205,6 +210,10 @@ PARSE_AND_LIST_ARGS_CASES='
 
     case OPTION_THUMB_ENTRY:
       thumb_entry_symbol = optarg;
+      break;
+
+    case OPTION_BE8:
+      byteswap_code = 1;
       break;
 '
 
Index: ld/emultempl/armelf_oabi.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/armelf_oabi.em,v
retrieving revision 1.14
diff -u -p -r1.14 armelf_oabi.em
--- ld/emultempl/armelf_oabi.em	3 Jan 2004 11:09:07 -0000	1.14
+++ ld/emultempl/armelf_oabi.em	1 Apr 2004 00:48:46 -0000
@@ -68,7 +68,7 @@ gld${EMULATION_NAME}_before_allocation (
   {
     LANG_FOR_EACH_INPUT_STATEMENT (is)
       {
-	if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info, 0))
+	if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, &link_info, 0, 0))
 	  {
 	    /* xgettext:c-format */
 	    einfo (_("Errors encountered processing file %s"), is->filename);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]