aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozef.l@mittosystems.com>2020-08-28 13:56:53 +0100
committerJozef Lawrynowicz <jozef.l@mittosystems.com>2020-08-28 14:01:10 +0100
commit64b63c2993db8606334f6f0852b4e7bb70b5682a (patch)
treeac258fac488e748215125eb78ed3e556e8b627c5 /ld/emultempl
parent87870682f3a7fc29208026dfa4aac75b195cc990 (diff)
downloadgdb-64b63c2993db8606334f6f0852b4e7bb70b5682a.zip
gdb-64b63c2993db8606334f6f0852b4e7bb70b5682a.tar.gz
gdb-64b63c2993db8606334f6f0852b4e7bb70b5682a.tar.bz2
MSP430: Fix alignment of __*_array_start symbols in default linker script
__{preinit,init,fini}_array_start symbols must be word aligned in linker scripts. If the section preceding the __*_array_start symbol has an odd size, then a NULL byte will be present between the start symbol and the .*_array section itself, when the section gets automatically word-aligned. This results in a branch to an invalid address when the CRT startup code tries to run through the functions listed in the array sections. Some MSP430 linker scripts do not align the __*_array start symbols, so this added warning will catch that problem and help the user avoid the potential incorrect execution of the program. ld/ChangeLog: * emultempl/msp430.em (input_section_exists): New. (check_array_section_alignment): New. (gld${EMULATION_NAME}_finish): New. * scripttempl/elf32msp430.sc: Add ALIGN directives before the definition of __*_array_start symbols. * testsuite/ld-msp430-elf/finiarray-warn.ld: New test. * testsuite/ld-msp430-elf/finiarray-warn.r: New test. * testsuite/ld-msp430-elf/initarray-nowarn.ld: New test. * testsuite/ld-msp430-elf/initarray-warn.ld: New test. * testsuite/ld-msp430-elf/initarray-warn.r: New test. * testsuite/ld-msp430-elf/initarray.s: New test. * testsuite/ld-msp430-elf/msp430-elf.exp: Run new tests. * testsuite/ld-msp430-elf/preinitarray-warn.ld: New test. * testsuite/ld-msp430-elf/preinitarray-warn.r: New test.
Diffstat (limited to 'ld/emultempl')
-rw-r--r--ld/emultempl/msp430.em81
1 files changed, 80 insertions, 1 deletions
diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em
index a47998a..7b78a53 100644
--- a/ld/emultempl/msp430.em
+++ b/ld/emultempl/msp430.em
@@ -826,6 +826,85 @@ msp430_elf_after_allocation (void)
gld${EMULATION_NAME}_after_allocation ();
}
+/* Return TRUE if a non-debug input section in L has positive size and matches
+ the given name. */
+static int
+input_section_exists (lang_statement_union_type * l, const char * name)
+{
+ while (l != NULL)
+ {
+ switch (l->header.type)
+ {
+ case lang_input_section_enum:
+ if ((l->input_section.section->flags & SEC_ALLOC)
+ && l->input_section.section->size > 0
+ && !strcmp (l->input_section.section->name, name))
+ return TRUE;
+ break;
+
+ case lang_wild_statement_enum:
+ if (input_section_exists (l->wild_statement.children.head, name))
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ l = l->header.next;
+ }
+ return FALSE;
+}
+
+/* Some MSP430 linker scripts do not include ALIGN directives to ensure
+ __preinit_array_start, __init_array_start or __fini_array_start are word
+ aligned.
+ If __*_array_start symbols are not word aligned, the code in crt0 to run
+ through the array and call the functions will crash.
+ To avoid warning unnecessarily when the .*_array sections are not being
+ used for running constructors/destructors, only emit the warning if
+ the associated section exists and has size. */
+static void
+check_array_section_alignment (void)
+{
+ int i;
+ lang_output_section_statement_type * rodata_sec;
+ lang_output_section_statement_type * rodata2_sec;
+ const char * array_names[3][2] = { { ".init_array", "__init_array_start" },
+ { ".preinit_array", "__preinit_array_start" },
+ { ".fini_array", "__fini_array_start" } };
+
+ /* .{preinit,init,fini}_array could be in either .rodata or .rodata2. */
+ rodata_sec = lang_output_section_find (".rodata");
+ rodata2_sec = lang_output_section_find (".rodata2");
+ if (rodata_sec == NULL && rodata2_sec == NULL)
+ return;
+
+ /* There are 3 .*_array sections which must be checked for alignment. */
+ for (i = 0; i < 3; i++)
+ {
+ struct bfd_link_hash_entry * sym;
+ if (((rodata_sec && input_section_exists (rodata_sec->children.head,
+ array_names[i][0]))
+ || (rodata2_sec && input_section_exists (rodata2_sec->children.head,
+ array_names[i][0])))
+ && (sym = bfd_link_hash_lookup (link_info.hash, array_names[i][1],
+ FALSE, FALSE, TRUE))
+ && sym->type == bfd_link_hash_defined
+ && sym->u.def.value % 2)
+ {
+ einfo ("%P: warning: \"%s\" symbol (%pU) is not word aligned\n",
+ array_names[i][1], NULL);
+ }
+ }
+}
+
+static void
+gld${EMULATION_NAME}_finish (void)
+{
+ finish_default ();
+ check_array_section_alignment ();
+}
+
struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
{
${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
@@ -842,7 +921,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
"${EMULATION_NAME}",
"${OUTPUT_FORMAT}",
- ${LDEMUL_FINISH-finish_default},
+ gld${EMULATION_NAME}_finish,
${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
${LDEMUL_OPEN_DYNAMIC_ARCHIVE-NULL},
${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},