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 /ld/emultempl | |
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.
Diffstat (limited to 'ld/emultempl')
-rw-r--r-- | ld/emultempl/msp430.em | 298 |
1 files changed, 298 insertions, 0 deletions
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: |