* bfd/bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.
authorPaul Brook <paul@codesourcery.com>
Thu, 1 Apr 2004 11:20:04 +0000 (11:20 +0000)
committerPaul Brook <paul@codesourcery.com>
Thu, 1 Apr 2004 11:20:04 +0000 (11:20 +0000)
* 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/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf32-arm.h
ld/ChangeLog
ld/emultempl/armelf.em
ld/emultempl/armelf_oabi.em
ld/ld.texinfo

index f1ab28c28f8290960acf7034ffe527a0e3a5363e..6f6b14c27df2dbf6e7089236b0340160accea86d 100644 (file)
@@ -1,3 +1,18 @@
+2004-04-01  Paul Brook  <paul@codesourcery.com>
+
+       * bfd-in.h (bfd_elf32_arm_process_before_allocation): Update.
+       * 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.
+
 2004-04-01  Andy Chittenden  <achittenden@bluearc.com>
 
        * stabs.c (struct stab_link_includes_totals): Add field 'symb'
index 1a5d1ea0dd6b8d4c73c7d9fa662031aa3770de08..9ad727eda5693ae9a738458c9eeaa5f0163737da 100644 (file)
@@ -786,7 +786,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
   (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 e6048c33a94097989a92631aaf161b792429e591..c2e18194be80ad116b49e90df9f59888d6e3bfdc 100644 (file)
@@ -793,7 +793,7 @@ extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections
   (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 bc6904a26edca65633c11dc64b6043b306f74350..b9e3debd6062fb519a63ae542c09d5adf2fb4502 100644 (file)
@@ -106,7 +106,7 @@ bfd_boolean bfd_elf32_arm_allocate_interworking_sections
 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 [PLT_ENTRY_SIZE / 4] =
 
 #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 (abfd, info)
 }
 
 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 (abfd, link_info, no_pipeline_knowledge)
   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, link_info)
      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, linker)
   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, linker)
 #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 6ff74988236b96fc90e896e099a76a89ef73c6ba..0afd3f64ce46ee9e4b31d0c812a5ef8b39f2ae5e 100644 (file)
@@ -1,3 +1,13 @@
+2004-04-01  Paul Brook  <paul@codesourcery.com>
+
+       * 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.
+       * emultempl/armelf_oabi.em: Pass extra parameter.
+       * ld.texinfo: Document --be8.
+
 2004-03-30  Stan Shebs  <shebs@apple.com>
 
        Remove long-obsolete MPW support.
index 0c051ad62b89e2d0a8639d058a07ad601ba55d52..beeb40c72076cb93096c867451990f7349eaebd7 100644 (file)
@@ -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='
@@ -206,6 +211,10 @@ PARSE_AND_LIST_ARGS_CASES='
     case OPTION_THUMB_ENTRY:
       thumb_entry_symbol = optarg;
       break;
+
+    case OPTION_BE8:
+      byteswap_code = 1;
+      break;
 '
 
 # We have our own after_open and before_allocation functions, but they call
index d75c65863308dbcbe60ea8e4f21bf15b733b1832..8ff2ad135352bf6735bd5cdf8fab25a98cf4e955 100644 (file)
@@ -68,7 +68,7 @@ gld${EMULATION_NAME}_before_allocation (void)
   {
     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 4310c12d8b3f2e89ec1855fb0cae7227221eebe0..f6bd9ff8688d12f56f5c81f77a9dcfa7470f59e2 100644 (file)
@@ -4762,6 +4762,12 @@ But it also sets the bottom bit of the address, so that it can be
 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