Add new command line switch --thumb-entry.
authorNick Clifton <nickc@redhat.com>
Mon, 21 Jun 1999 03:30:32 +0000 (03:30 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 21 Jun 1999 03:30:32 +0000 (03:30 +0000)
ld/ChangeLog
ld/emultempl/armcoff.em
ld/emultempl/armelf.em
ld/emultempl/pe.em
ld/ld.texinfo

index 16e607df3e38d4eca74683ed7ee9470faed9a7d4..b1e5071fdc6400cb91b093915bc897aba8e728d6 100644 (file)
@@ -1,3 +1,10 @@
+1999-06-18  Nick Clifton  <nickc@cygnus.com>
+
+       * emultempl/pe.em: Add new command line switch --thumb-entry.
+       * emultempl/armelf.em: Add new command line switch --thumb-entry.
+       * emultempl/armcoff.em: Add new command line switch --thumb-entry.
+       * ld.texinfo: Document new ARM command line switch: --thumb-entry.      
+
 1999-06-20  H.J. Lu  <hjl@gnu.org>
 
        * configure.in (all_libpath): Accumulate across all enabled targets.
index 351a4505060420ab101e3764a768bd6452a3a0e7..28a798fb79f2e8b8bc2eb9b053d4625fb364a660 100644 (file)
@@ -44,17 +44,21 @@ static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 static int  gld${EMULATION_NAME}_parse_args PARAMS((int, char **));
 static void gld${EMULATION_NAME}_list_options PARAMS ((FILE *));
+static void gld_${EMULATION_NAME}_finish PARAMS ((void));
 
 /* If true, then interworking stubs which support calls to old, non-interworking
    aware ARM code should be generated.  */
 
 static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
 
 #define OPTION_SUPPORT_OLD_CODE                300
+#define OPTION_THUMB_ENTRY             301
 
 static struct option longopts[] =
 {
   {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+  {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
   {NULL, no_argument, NULL, 0}
 };
 
@@ -63,6 +67,7 @@ gld${EMULATION_NAME}_list_options (file)
      FILE * file;
 {
   fprintf (file, _("  --support-old-code   Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<sym>  Set the entry point to be Thumb symbol <sym>\n"));
 }
 
 static int
@@ -97,6 +102,10 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     case OPTION_SUPPORT_OLD_CODE:
       support_old_code = 1;
       break;
+
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
     }
   
   return 1;
@@ -146,6 +155,49 @@ gld${EMULATION_NAME}_after_open ()
     }
 }
 
+static void
+gld${EMULATION_NAME}_finish PARAMS((void))
+{
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol == NULL)
+    return;
+  
+  h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true);
+
+  if (h != (struct bfd_link_hash_entry *) NULL
+      && (h->type == bfd_link_hash_defined
+         || h->type == bfd_link_hash_defweak)
+      && h->u.def.section->output_section != NULL)
+    {
+      static char buffer[32];
+      bfd_vma val;
+      
+      /* Special procesing is required for a Thumb entry symbol.  The
+        bottom bit of its address must be set.  */
+      val = (h->u.def.value
+            + bfd_get_section_vma (output_bfd,
+                                   h->u.def.section->output_section)
+            + h->u.def.section->output_offset);
+      
+      val |= 1;
+
+      /* Now convert this value into a string and store it in entry_symbol
+         where the lang_finish() function will pick it up.  */
+      buffer[0] = '0';
+      buffer[1] = 'x';
+      
+      sprintf_vma (buffer + 2, val);
+
+      if (entry_symbol != NULL && entry_from_cmdline)
+       einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+              thumb_entry_symbol, entry_symbol);
+      entry_symbol = buffer;
+    }
+  else
+    einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+}
+
 static char *
 gld${EMULATION_NAME}_get_script (isfile)
      int *isfile;
@@ -214,7 +266,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld${EMULATION_NAME}_get_script,
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  NULL, /* finish */
+  gld${EMULATION_NAME}_finish, /* finish */
   NULL, /* create output section statements */
   NULL, /* open dynamic archive */
   NULL, /* place orphan */
index ee6aa7697f78215b276d66f75c1aad90c3fbf081..6e3cfa6fe86f985463f97443dc246e61b6f7a030 100644 (file)
@@ -65,13 +65,18 @@ static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
 static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
 static int  gld${EMULATION_NAME}_parse_args PARAMS((int, char **));
 static void gld${EMULATION_NAME}_list_options PARAMS ((FILE *));
+static void gld_${EMULATION_NAME}_finish PARAMS ((void));
 
 \f
 static int no_pipeline_knowledge = 0;
+static char * thumb_entry_symbol = NULL;
+
+#define OPTION_THUMB_ENTRY             301
 
 static struct option longopts[] =
 {
   { "no-pipeline-knowledge", no_argument, NULL, 'p'},
+  { "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
   { NULL, no_argument, NULL, 0 }
 };
 
@@ -80,6 +85,7 @@ gld${EMULATION_NAME}_list_options (file)
      FILE * file;
 {
   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"));
 }
 
 static int
@@ -114,6 +120,10 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
     case 'p':
       no_pipeline_knowledge = 1;
       break;
+
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
     }
   
   return 1;
@@ -1136,6 +1146,49 @@ gld${EMULATION_NAME}_before_allocation ()
   bfd_elf32_arm_allocate_interworking_sections (& link_info);
 }
 
+static void
+gld${EMULATION_NAME}_finish PARAMS((void))
+{
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol == NULL)
+    return;
+  
+  h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true);
+
+  if (h != (struct bfd_link_hash_entry *) NULL
+      && (h->type == bfd_link_hash_defined
+         || h->type == bfd_link_hash_defweak)
+      && h->u.def.section->output_section != NULL)
+    {
+      static char buffer[32];
+      bfd_vma val;
+      
+      /* Special procesing is required for a Thumb entry symbol.  The
+        bottom bit of its address must be set.  */
+      val = (h->u.def.value
+            + bfd_get_section_vma (output_bfd,
+                                   h->u.def.section->output_section)
+            + h->u.def.section->output_offset);
+      
+      val |= 1;
+
+      /* Now convert this value into a string and store it in entry_symbol
+         where the lang_finish() function will pick it up.  */
+      buffer[0] = '0';
+      buffer[1] = 'x';
+      
+      sprintf_vma (buffer + 2, val);
+
+      if (entry_symbol != NULL && entry_from_cmdline)
+       einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+              thumb_entry_symbol, entry_symbol);
+      entry_symbol = buffer;
+    }
+  else
+    einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+}
+
 static char *
 gld${EMULATION_NAME}_get_script (isfile)
      int *isfile;
@@ -1204,7 +1257,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
   gld${EMULATION_NAME}_get_script,
   "${EMULATION_NAME}",
   "${OUTPUT_FORMAT}",
-  NULL, /* finish */
+  gld${EMULATION_NAME}_finish, /* finish */
   NULL, /* create output section statements */
   gld${EMULATION_NAME}_open_dynamic_archive,
   gld${EMULATION_NAME}_place_orphan,
index 671f49090e6e07933e84f5b724dccf636b66def1..c3a289fa72c66184b926ed2afe0df07e1695f681 100644 (file)
@@ -74,10 +74,12 @@ static void gld${EMULATION_NAME}_place_section
   PARAMS ((lang_statement_union_type *));
 static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *));
 static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **));
+static void gld_${EMULATION_NAME}_finish PARAMS ((void));
 
 static struct internal_extra_pe_aouthdr pe;
 static int dll;
 static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
 extern def_file *pe_def_file;
 static lang_assignment_statement_type *image_base_statement = 0;
 
@@ -126,6 +128,7 @@ gld_${EMULATION_NAME}_before_parse()
 #define OPTION_ENABLE_STDCALL_FIXUP    (OPTION_STDCALL_ALIASES + 1)
 #define OPTION_DISABLE_STDCALL_FIXUP   (OPTION_ENABLE_STDCALL_FIXUP + 1)
 #define OPTION_IMPLIB_FILENAME         (OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY             (OPTION_IMPLIB_FILENAME + 1)
 
 static struct option longopts[] =
 {
@@ -145,6 +148,7 @@ static struct option longopts[] =
   {"stack", required_argument, NULL, OPTION_STACK},
   {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
   {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+  {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
 #ifdef DLL_SUPPORT
   /* getopt allows abbreviations, so we do this to stop it from treating -o
      as an abbreviation for this option */
@@ -219,6 +223,7 @@ gld_${EMULATION_NAME}_list_options (file)
   fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
   fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
   fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
 #ifdef DLL_SUPPORT
   fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
   fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
@@ -427,6 +432,9 @@ gld_${EMULATION_NAME}_parse_args(argc, argv)
     case OPTION_SUPPORT_OLD_CODE:
       support_old_code = 1;
       break;
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
 #ifdef DLL_SUPPORT
     case OPTION_OUT_DEF:
       pe_out_def_filename = xstrdup (optarg);
@@ -884,6 +892,47 @@ gld_${EMULATION_NAME}_recognized_file(entry)
 static void
 gld_${EMULATION_NAME}_finish ()
 {
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol != NULL)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true);
+      
+      if (h != (struct bfd_link_hash_entry *) NULL
+         && (h->type == bfd_link_hash_defined
+             || h->type == bfd_link_hash_defweak)
+         && h->u.def.section->output_section != NULL)
+       {
+         static char buffer[32];
+         bfd_vma val;
+         
+         /* Special procesing is required for a Thumb entry symbol.  The
+            bottom bit of its address must be set.  */
+         val = (h->u.def.value
+                + bfd_get_section_vma (output_bfd,
+                                       h->u.def.section->output_section)
+                + h->u.def.section->output_offset);
+         
+         val |= 1;
+         
+         /* Now convert this value into a string and store it in entry_symbol
+            where the lang_finish() function will pick it up.  */
+         buffer[0] = '0';
+         buffer[1] = 'x';
+         
+         sprintf_vma (buffer + 2, val);
+         
+         if (entry_symbol != NULL && entry_from_cmdline)
+           einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+                  thumb_entry_symbol, entry_symbol);
+         entry_symbol = buffer;
+       }
+      else
+       einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+    }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
 #ifdef DLL_SUPPORT
   if (link_info.shared)
     {
index 43e7e82bf1cef0c5302b30264d4ff945af9ecf9b..9e720de914b2c372416efcdb638ffe106df94e55 100644 (file)
@@ -3879,7 +3879,7 @@ not itself call any subroutines).
 @section @code{ld}'s support for interworking between ARM and Thumb code
 
 @cindex ARM interworking support
-@cindex --support-old-code
+@kindex --support-old-code
 For the ARM, @code{ld} will generate code stubs to allow functions calls
 betweem ARM and Thumb code.  These stubs only work with code that has
 been compiled and assembled with the @samp{-mthumb-interwork} command
@@ -3891,6 +3891,15 @@ which will work with non-interworking aware ARM code.  Note, however,
 the linker does not support generating stubs for function calls to
 non-interworking aware Thumb code.
 
+@cindex thumb entry point
+@cindex entry point, thumb
+@kindex --thumb-entry=@var{entry}
+The @samp{--thumb-entry} switch is a duplicate of the generic
+@samp{--entry} switch, in that it sets the program's starting address.  
+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.
+
 @ifclear GENERIC
 @lowersections
 @end ifclear