aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/emultempl/armcoff.em54
-rw-r--r--ld/emultempl/armelf.em55
-rw-r--r--ld/emultempl/pe.em49
-rw-r--r--ld/ld.texinfo11
5 files changed, 173 insertions, 3 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 16e607d..b1e5071 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em
index 351a450..28a798f 100644
--- a/ld/emultempl/armcoff.em
+++ b/ld/emultempl/armcoff.em
@@ -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 */
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index ee6aa76..6e3cfa6 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -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));
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,
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 671f490..c3a289f 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -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)
{
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 43e7e82..9e720de 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -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