diff options
author | Nick Clifton <nickc@redhat.com> | 2015-05-05 13:38:00 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-05-05 13:38:00 +0100 |
commit | 837a17b36c9e297f4bf33727e25dfa9f38360c17 (patch) | |
tree | 5cf6ecb482076cf1e20e437b6ea94c00c87cb103 | |
parent | b76f99d702c3501ac320396ea06bc7f9237173c3 (diff) | |
download | gdb-837a17b36c9e297f4bf33727e25dfa9f38360c17.zip gdb-837a17b36c9e297f4bf33727e25dfa9f38360c17.tar.gz gdb-837a17b36c9e297f4bf33727e25dfa9f38360c17.tar.bz2 |
Add support to the MSP430 linker for the automatic placement of code and data into either low or high memory regions.
gas * config/tc-msp430.c (MAX_OP_LEN): Increase to 4096.
(msp430_make_init_symbols): New function.
(msp430_section): Call it.
(msp430_frob_section): Likewise.
ld * emulparams/msp430elf.sh (TEMPLATE_NAME): Change to msp430.
* scripttempl/msp430.sc (.text): Add .lower.text and .either.text.
(.data): Add .lower.data and .either.data.
(.bss): Add .lower.bss and .either.bss.
(.rodata): Add .lower.rodata and .either.rodata.
* emultempl/msp430.em: New file. Implements a new orphan
placement algorithm that divides sections between lower and upper
memory regions.
* Makefile.am (emsp430elf.c): Depend upon msp430.em.
*emsp430X.c): Likewise.
* Makefine.in: Regenerate.
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-msp430.c | 40 | ||||
-rw-r--r-- | ld/ChangeLog | 14 | ||||
-rw-r--r-- | ld/Makefile.am | 2 | ||||
-rw-r--r-- | ld/Makefile.in | 2 | ||||
-rw-r--r-- | ld/emulparams/msp430elf.sh | 2 | ||||
-rw-r--r-- | ld/emultempl/msp430.em | 298 | ||||
-rw-r--r-- | ld/scripttempl/elf32msp430.sc | 20 |
8 files changed, 369 insertions, 16 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 13b6705..30831ae 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2015-05-05 Nick Clifton <nickc@redhat.com> + + * config/tc-msp430.c (MAX_OP_LEN): Increase to 4096. + (msp430_make_init_symbols): New function. + (msp430_section): Call it. + (msp430_frob_section): Likewise. + 2015-05-02 Max Filippov <jcmvbkbc@gmail.com> * config/tc-xtensa.c (cached_fixupS, fixup_cacheS): New typedefs. diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c index 2891c13..5307746 100644 --- a/gas/config/tc-msp430.c +++ b/gas/config/tc-msp430.c @@ -255,7 +255,7 @@ relax_typeS md_relax_table[] = }; -#define MAX_OP_LEN 256 +#define MAX_OP_LEN 4096 typedef enum msp_isa { @@ -840,14 +840,11 @@ md_parse_option (int c, char * arg) The code which initializes these sections should have a global label for these symbols, and should be marked with KEEP() in the - linker script. - */ + linker script. */ + static void -msp430_section (int arg) +msp430_make_init_symbols (const char * name) { - char * saved_ilp = input_line_pointer; - char * name = obj_elf_section_name (); - if (strncmp (name, ".bss", 4) == 0 || strncmp (name, ".gnu.linkonce.b.", 16) == 0) (void) symbol_find_or_make ("__crt0_init_bss"); @@ -856,6 +853,27 @@ msp430_section (int arg) || strncmp (name, ".gnu.linkonce.d.", 16) == 0) (void) symbol_find_or_make ("__crt0_movedata"); + /* Note - data assigned to the .either.data section may end up being + placed in the .upper.data section if the .lower.data section is + full. Hence the need to define the crt0 symbol. */ + if (strncmp (name, ".either.data", 12) == 0 + || strncmp (name, ".upper.data", 11) == 0) + (void) symbol_find_or_make ("__crt0_move_highdata"); + + /* See note about .either.data above. */ + if (strncmp (name, ".upper.bss", 10) == 0 + || strncmp (name, ".either.bss", 11) == 0) + (void) symbol_find_or_make ("__crt0_init_highbss"); +} + +static void +msp430_section (int arg) +{ + char * saved_ilp = input_line_pointer; + char * name = obj_elf_section_name (); + + msp430_make_init_symbols (name); + input_line_pointer = saved_ilp; obj_elf_section (arg); } @@ -868,13 +886,7 @@ msp430_frob_section (asection *sec) if (sec->size == 0) return; - if (strncmp (name, ".bss", 4) == 0 - || strncmp (name, ".gnu.linkonce.b.", 16) == 0) - (void) symbol_find_or_make ("__crt0_init_bss"); - - if (strncmp (name, ".data", 5) == 0 - || strncmp (name, ".gnu.linkonce.d.", 16) == 0) - (void) symbol_find_or_make ("__crt0_movedata"); + msp430_make_init_symbols (name); } static void diff --git a/ld/ChangeLog b/ld/ChangeLog index 3448bba..243bf5f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,17 @@ +2015-05-05 Nick Clifton <nickc@redhat.com> + + * emulparams/msp430elf.sh (TEMPLATE_NAME): Change to msp430. + * scripttempl/msp430.sc (.text): Add .lower.text and .either.text. + (.data): Add .lower.data and .either.data. + (.bss): Add .lower.bss and .either.bss. + (.rodata): Add .lower.rodata and .either.rodata. + * emultempl/msp430.em: New file. Implements a new orphan + placement algorithm that divides sections between lower and upper + memory regions. + * Makefile.am (emsp430elf.c): Depend upon msp430.em. + *emsp430X.c): Likewise. + * Makefine.in: Regenerate. + 2015-04-28 Andreas Schwab <schwab@linux-m68k.org> PR ld/18344 diff --git a/ld/Makefile.am b/ld/Makefile.am index 15f8994..ee22e75 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -1529,9 +1529,11 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} emsp430elf.c: $(srcdir)/emulparams/msp430elf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} emsp430X.c: $(srcdir)/emulparams/msp430elf.sh $(srcdir)/emulparams/msp430X.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} ends32elf.c: $(srcdir)/emulparams/nds32elf.sh \ diff --git a/ld/Makefile.in b/ld/Makefile.in index 169fae1..2d8b09d 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -3027,9 +3027,11 @@ emn10300.c: $(srcdir)/emulparams/mn10300.sh \ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} emsp430elf.c: $(srcdir)/emulparams/msp430elf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} emsp430X.c: $(srcdir)/emulparams/msp430elf.sh $(srcdir)/emulparams/msp430X.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/msp430.em \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf32msp430.sc ${GEN_DEPENDS} ends32elf.c: $(srcdir)/emulparams/nds32elf.sh \ diff --git a/ld/emulparams/msp430elf.sh b/ld/emulparams/msp430elf.sh index b459698..a76e9ee 100644 --- a/ld/emulparams/msp430elf.sh +++ b/ld/emulparams/msp430elf.sh @@ -3,7 +3,7 @@ # This called by genscripts_extra.sh SCRIPT_NAME=elf32msp430 -TEMPLATE_NAME=generic +TEMPLATE_NAME=msp430 EXTRA_EM_FILE=genelf OUTPUT_FORMAT="elf32-msp430" MACHINE= diff --git a/ld/emultempl/msp430.em b/ld/emultempl/msp430.em new file mode 100644 index 0000000..0eff3f0 --- /dev/null +++ b/ld/emultempl/msp430.em @@ -0,0 +1,298 @@ +# This shell script emits a C file. -*- C -*- +# It does some substitutions. +fragment <<EOF +/* This file is is generated by a shell script. DO NOT EDIT! */ + +/* Emulate the original gld for the given ${EMULATION_NAME} + Copyright (C) 2014-2015 Free Software Foundation, Inc. + Written by Steve Chamberlain steve@cygnus.com + Extended for the MSP430 by Nick Clifton nickc@redhat.com + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define TARGET_IS_${EMULATION_NAME} + +#include "sysdep.h" +#include "bfd.h" +#include "bfdlink.h" + +#include "ld.h" +#include "ldmain.h" +#include "ldmisc.h" +#include "ldexp.h" +#include "ldlang.h" +#include "ldfile.h" +#include "ldemul.h" +#include "libiberty.h" + +EOF + +# Import any needed special functions and/or overrides. +# +if test -n "$EXTRA_EM_FILE" ; then + source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em +fi + +if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then +fragment <<EOF + +static void +gld${EMULATION_NAME}_before_parse (void) +{ +#ifndef TARGET_ /* I.e., if not generic. */ + ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown); +#endif /* not TARGET_ */ + + /* The MSP430 port *needs* linker relaxtion in order to cope with large + functions where conditional branches do not fit into a +/- 1024 byte range. */ + if (! link_info.relocatable) + TARGET_ENABLE_RELAXATION; +} + +EOF +fi + +if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then +fragment <<EOF + +static char * +gld${EMULATION_NAME}_get_script (int *isfile) +EOF + +if test x"$COMPILE_IN" = xyes +then +# Scripts compiled in. + +# sed commands to quote an ld script as a C string. +sc="-f stringify.sed" + +fragment <<EOF +{ + *isfile = 0; + + if (link_info.relocatable && config.build_constructors) + return +EOF +sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c +echo ' ; else if (link_info.relocatable) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c +echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c +echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c +echo ' ; else return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c +echo '; }' >> e${EMULATION_NAME}.c + +else +# Scripts read from the filesystem. + +fragment <<EOF +{ + *isfile = 1; + + if (link_info.relocatable && config.build_constructors) + return "ldscripts/${EMULATION_NAME}.xu"; + else if (link_info.relocatable) + return "ldscripts/${EMULATION_NAME}.xr"; + else if (!config.text_read_only) + return "ldscripts/${EMULATION_NAME}.xbn"; + else if (!config.magic_demand_paged) + return "ldscripts/${EMULATION_NAME}.xn"; + else + return "ldscripts/${EMULATION_NAME}.x"; +} +EOF +fi +fi + +if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then +fragment <<EOF + +/* Helper function for place_orphan that computes the size + of sections already mapped to the given statement. */ + +static bfd_size_type +scan_children (lang_statement_union_type * l) +{ + bfd_size_type amount = 0; + + while (l != NULL) + { + switch (l->header.type) + { + case lang_input_section_enum: + if (l->input_section.section->flags & SEC_ALLOC) + amount += l->input_section.section->size; + break; + + case lang_constructors_statement_enum: + case lang_assignment_statement_enum: + break; + + case lang_wild_statement_enum: + amount += scan_children (l->wild_statement.children.head); + break; + + default: + fprintf (stderr, "msp430 orphan placer: unhandled lang type %d\n", l->header.type); + break; + } + + l = l->header.next; + } + + return amount; +} + +/* Place an orphan section. We use this to put .either sections + into either their lower or their upper equivalents. */ + +static lang_output_section_statement_type * +gld${EMULATION_NAME}_place_orphan (asection * s, + const char * secname, + int constraint) +{ + char * lower_name; + char * upper_name; + char * name; + lang_output_section_statement_type * lower; + lang_output_section_statement_type * upper; + lang_output_section_statement_type * os; + + if ((s->flags & SEC_ALLOC) == 0) + return NULL; + + if (link_info.relocatable) + return NULL; + + /* If constraints are involved let the linker handle the placement normally. */ + if (constraint != 0) + return NULL; + + /* We only need special handling for .either sections. */ + if (strncmp (secname, ".either.", 8) != 0) + return NULL; + + /* Skip the .either prefix. */ + secname += 7; + + /* Compute the names of the corresponding upper and lower + sections. If the input section name contains another period, + only use the part of the name before the second dot. */ + if (strchr (secname + 1, '.') != NULL) + { + name = ACONCAT ((secname, NULL)); + + * strchr (name + 1, '.') = 0; + } + else + name = (char *) secname; + + lower_name = ACONCAT ((".lower", name, NULL)); + upper_name = ACONCAT ((".upper", name, NULL)); + + /* Find the corresponding lower and upper sections. */ + lower = lang_output_section_find (lower_name); + upper = lang_output_section_find (upper_name); + /* If the upper section does not exist, try again without the suffix. */ + if (upper == NULL) + upper = lang_output_section_find (name); + + if (lower == NULL) + { + os = upper; + if (upper == NULL) + { + einfo ("%P: error: no section named %s or %s in linker script\n", lower_name, upper_name); + return NULL; + } + } + else if (upper == NULL) + os = lower; + else if (lower->region == NULL) + os = lower; + /* If the section is too big for the region containing + the lower section then do not even try to use it. */ + else if (lower->region->length < s->size) + os = upper; + else + { + bfd_size_type amount = 0; + struct lang_output_section_statement_struct * p; + + amount += scan_children (lower->children.head); + + /* Also check forwards for other statements assigned to the same region. */ + for (p = lower->next; p != NULL; p = p->next) + if (p->region == lower->region) + amount += scan_children (p->children.head); + + /* Scan backwards as well. */ + for (p = lower->prev; p != NULL; p = p->prev) + if (p->region == lower->region) + amount += scan_children (p->children.head); + + if (amount + s->size >= lower->region->length) + os = upper; + else + os = lower; + } + + lang_add_section (& os->children, s, NULL, os); + return os; +} +EOF +fi + +fragment <<EOF + +struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = +{ + ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse}, + ${LDEMUL_SYSLIB-syslib_default}, + ${LDEMUL_HLL-hll_default}, + ${LDEMUL_AFTER_PARSE-after_parse_default}, + ${LDEMUL_AFTER_OPEN-after_open_default}, + ${LDEMUL_AFTER_ALLOCATION-after_allocation_default}, + ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, + ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, + ${LDEMUL_BEFORE_ALLOCATION-before_allocation_default}, + ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, + "${EMULATION_NAME}", + "${OUTPUT_FORMAT}", + ${LDEMUL_FINISH-finish_default}, + ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, + ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-NULL}, + ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, + ${LDEMUL_SET_SYMBOLS-NULL}, + ${LDEMUL_PARSE_ARGS-NULL}, + ${LDEMUL_ADD_OPTIONS-NULL}, + ${LDEMUL_HANDLE_OPTION-NULL}, + ${LDEMUL_UNRECOGNIZED_FILE-NULL}, + ${LDEMUL_LIST_OPTIONS-NULL}, + ${LDEMUL_RECOGNIZED_FILE-NULL}, + ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, + ${LDEMUL_NEW_VERS_PATTERN-NULL}, + ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL} +}; +EOF +# +# Local Variables: +# mode: c +# End: diff --git a/ld/scripttempl/elf32msp430.sc b/ld/scripttempl/elf32msp430.sc index 15d5630..65105e5 100644 --- a/ld/scripttempl/elf32msp430.sc +++ b/ld/scripttempl/elf32msp430.sc @@ -154,12 +154,17 @@ SECTIONS ${CONSTRUCTING+ __dtors_end = . ; } ${RELOCATING+. = ALIGN(2);} + *(.lower.text.* .lower.text) + + ${RELOCATING+. = ALIGN(2);} *(.text) ${RELOCATING+. = ALIGN(2);} *(.text.*) ${RELOCATING+. = ALIGN(2);} *(.text:*) + *(.either.text.* .either.text) + ${RELOCATING+. = ALIGN(2);} *(SORT_NONE(.fini9)) *(SORT_NONE(.fini8)) @@ -178,11 +183,15 @@ SECTIONS .rodata : { + ${RELOCATING+. = ALIGN(2);} + *(.lower.rodata.* .lower.rodata) + . = ALIGN(2); *(.plt) *(.rodata .rodata.* .gnu.linkonce.r.* .const .const:*) *(.rodata1) + *(.either.rodata.*) *(.either.rodata) *(.eh_frame_hdr) KEEP (*(.eh_frame)) @@ -242,23 +251,32 @@ SECTIONS *(.data.rel.ro.local) *(.data.rel.ro*) *(.dynamic) + ${RELOCATING+. = ALIGN(2);} + *(.lower.data.* .lower.data) + *(.data) *(.data.*) *(.gnu.linkonce.d*) KEEP (*(.gnu.linkonce.d.*personality*)) *(.data1) + + *(.either.data.* .either.data) + *(.got.plt) *(.got) ${RELOCATING+. = ALIGN(2);} *(.sdata .sdata.* .gnu.linkonce.s.*) ${RELOCATING+. = ALIGN(2);} ${RELOCATING+ _edata = . ; } } ${RELOCATING+ > data ${RELOCATING+AT> text}} - + .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} : { ${RELOCATING+. = ALIGN(2);} ${RELOCATING+ PROVIDE (__bss_start = .) ; } + *(.lower.bss.* .lower.bss) + ${RELOCATING+. = ALIGN(2);} *(.bss) + *(.either.bss.* .either.bss) *(COMMON) ${RELOCATING+ PROVIDE (__bss_end = .) ; } ${RELOCATING+ _end = . ; } |