This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add support to the MSP430 linker for the automatic placement of code and data into either low or hig


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=837a17b36c9e297f4bf33727e25dfa9f38360c17

commit 837a17b36c9e297f4bf33727e25dfa9f38360c17
Author: Nick Clifton <nickc@redhat.com>
Date:   Tue May 5 13:38:00 2015 +0100

    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.

Diff:
---
 gas/ChangeLog                 |   7 +
 gas/config/tc-msp430.c        |  40 ++++--
 ld/ChangeLog                  |  14 ++
 ld/Makefile.am                |   2 +
 ld/Makefile.in                |   2 +
 ld/emulparams/msp430elf.sh    |   2 +-
 ld/emultempl/msp430.em        | 298 ++++++++++++++++++++++++++++++++++++++++++
 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 = . ;  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]