aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl/armelf.em
diff options
context:
space:
mode:
Diffstat (limited to 'ld/emultempl/armelf.em')
-rw-r--r--ld/emultempl/armelf.em55
1 files changed, 54 insertions, 1 deletions
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,