From 6f798e5c174ed44a384c889a73a02e4f454b0f4c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 21 Jun 1999 03:30:32 +0000 Subject: [PATCH] Add new command line switch --thumb-entry. --- ld/ChangeLog | 7 ++++++ ld/emultempl/armcoff.em | 54 +++++++++++++++++++++++++++++++++++++++- ld/emultempl/armelf.em | 55 ++++++++++++++++++++++++++++++++++++++++- ld/emultempl/pe.em | 49 ++++++++++++++++++++++++++++++++++++ ld/ld.texinfo | 11 ++++++++- 5 files changed, 173 insertions(+), 3 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 16e607df3e3..b1e5071fdc6 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +1999-06-18 Nick Clifton + + * 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 * configure.in (all_libpath): Accumulate across all enabled targets. diff --git a/ld/emultempl/armcoff.em b/ld/emultempl/armcoff.em index 351a4505060..28a798fb79f 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= Set the entry point to be Thumb symbol \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 ee6aa7697f7..6e3cfa6fe86 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= Set the entry point to be Thumb symbol \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 671f49090e6..c3a289fa72c 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 Set size of the initial stack\n")); fprintf (file, _(" --subsystem [:] Set required OS subsystem [& version]\n")); fprintf (file, _(" --support-old-code Support interworking with old code\n")); + fprintf (file, _(" --thumb-entry= Set the entry point to be Thumb \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 43e7e82bf1c..9e720de914b 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 -- 2.30.2