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] Allow symbols in MEMORY region specification


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

commit cc9ad334a71b0c032f711e86885fb73821f3be16
Author: Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
Date:   Wed Jan 28 15:01:50 2015 +1030

    Allow symbols in MEMORY region specification
    
    This patch fixes PR 4643 by allowing symbols in the LENGTH and ORIGIN
    fields of MEMORY regions.  Previously, only constants and constant
    expressions are allowed.
    
    For the AVR target, this helps define memory constraints more
    accurately (per device), without having to create a ton of device
    specific linker scripts.
    
    ld/
    	PR 4643
    	* ldexp.c (fold_name): Fold LENGTH only after
    	lang_first_phase_enum.
    	* ldgram.y (memory_spec): Don't evaluate ORIGIN and LENGTH
    	rightaway.
    	* ldlang.h (struct memory_region_struct): Add origin_exp and
    	length_exp fields.
    	* ldlang.c (lang_do_memory_regions): New.
    	(lang_memory_region_lookup): Initialize origin_exp and
    	length_exp fields.
    	(lang_process): Call lang_do_memory_regions.
    ld/testsuite/
    	* ld-scripts/memory.t: Define new symbol tred.
    	* ld-scripts/memory_sym.t: New.
    	* ld-scripts/script.exp: Perform MEMORY with symbols test, and
    	conditionally check values of linker symbols.

Diff:
---
 ld/ChangeLog                         | 14 ++++++++++++++
 ld/ldexp.c                           | 21 ++++++++++++---------
 ld/ldgram.y                          |  4 ++--
 ld/ldlang.c                          | 36 ++++++++++++++++++++++++++++++++++++
 ld/ldlang.h                          |  2 ++
 ld/testsuite/ChangeLog               |  7 +++++++
 ld/testsuite/ld-scripts/memory.t     |  3 ++-
 ld/testsuite/ld-scripts/memory_sym.t | 36 ++++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-scripts/script.exp   | 21 +++++++++++++++++++++
 9 files changed, 132 insertions(+), 12 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 5a97e32..c61baae 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,17 @@
+2015-01-28  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+
+	PR 4643
+	* ldexp.c (fold_name): Fold LENGTH only after
+	lang_first_phase_enum.
+	* ldgram.y (memory_spec): Don't evaluate ORIGIN and LENGTH
+	rightaway.
+	* ldlang.h (struct memory_region_struct): Add origin_exp and
+	length_exp fields.
+	* ldlang.c (lang_do_memory_regions): New.
+	(lang_memory_region_lookup): Initialize origin_exp and
+	length_exp fields.
+	(lang_process): Call lang_do_memory_regions.
+
 2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* ldlang.c (print_assignment): Only evaluate the expression for a
diff --git a/ld/ldexp.c b/ld/ldexp.c
index f2c8620..ac66cc0 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -828,15 +828,18 @@ fold_name (etree_type *tree)
 
     case LENGTH:
       {
-        lang_memory_region_type *mem;
-
-        mem = lang_memory_region_lookup (tree->name.name, FALSE);
-        if (mem != NULL)
-          new_number (mem->length);
-        else
-          einfo (_("%F%S: undefined MEMORY region `%s'"
-		   " referenced in expression\n"),
-		 tree, tree->name.name);
+      if (expld.phase != lang_first_phase_enum)
+        {
+          lang_memory_region_type *mem;
+
+          mem = lang_memory_region_lookup (tree->name.name, FALSE);
+          if (mem != NULL)
+            new_number (mem->length);
+          else
+            einfo (_("%F%S: undefined MEMORY region `%s'"
+             " referenced in expression\n"),
+           tree, tree->name.name);
+        }
       }
       break;
 
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 736f77d..f46aa9e 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -817,7 +817,7 @@ memory_spec: 	NAME
 origin_spec:
 	ORIGIN '=' mustbe_exp
 		{
-		  region->origin = exp_get_vma ($3, 0, "origin");
+		  region->origin_exp = $3;
 		  region->current = region->origin;
 		}
 	;
@@ -825,7 +825,7 @@ origin_spec:
 length_spec:
              LENGTH '=' mustbe_exp
 		{
-		  region->length = exp_get_vma ($3, -1, "length");
+		  region->length_exp = $3;
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3ea22c2..5344e5e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -85,6 +85,7 @@ static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
 static void lang_finalize_version_expr_head
   (struct bfd_elf_version_expr_head *);
+static void lang_do_memory_regions (void);
 
 /* Exported variables.  */
 const char *output_target;
@@ -1305,7 +1306,9 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
   new_region->name_list.name = xstrdup (name);
   new_region->name_list.next = NULL;
   new_region->next = NULL;
+  new_region->origin_exp = NULL;
   new_region->origin = 0;
+  new_region->length_exp = NULL;
   new_region->length = ~(bfd_size_type) 0;
   new_region->current = 0;
   new_region->last_os = NULL;
@@ -6707,6 +6710,8 @@ lang_process (void)
   /* PR 13683: We must rerun the assignments prior to running garbage
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
+
+  lang_do_memory_regions();
   expld.phase = lang_first_phase_enum;
 
   /* Size up the common data.  */
@@ -7970,6 +7975,37 @@ lang_do_version_exports_section (void)
 			   lang_new_vers_node (greg, lreg), NULL);
 }
 
+/* Evaluate LENGTH and ORIGIN parts of MEMORY spec */
+
+static void
+lang_do_memory_regions (void)
+{
+  lang_memory_region_type *r = lang_memory_region_list;
+
+  for (; r != NULL; r = r->next)
+    {
+      if (r->origin_exp)
+      {
+        exp_fold_tree_no_dot (r->origin_exp);
+        if (expld.result.valid_p)
+          {
+            r->origin = expld.result.value;
+            r->current = r->origin;
+          }
+        else
+          einfo (_("%F%P: invalid origin for memory region %s\n"), r->name_list.name);
+      }
+      if (r->length_exp)
+      {
+        exp_fold_tree_no_dot (r->length_exp);
+        if (expld.result.valid_p)
+          r->length = expld.result.value;
+        else
+          einfo (_("%F%P: invalid length for memory region %s\n"), r->name_list.name);
+      }
+    }
+}
+
 void
 lang_add_unique (const char *name)
 {
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 48d7e4e..69d21a7 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -55,8 +55,10 @@ typedef struct memory_region_struct
 {
   lang_memory_region_name name_list;
   struct memory_region_struct *next;
+  union etree_union *origin_exp;
   bfd_vma origin;
   bfd_size_type length;
+  union etree_union *length_exp;
   bfd_vma current;
   union lang_statement_union *last_os;
   flagword flags;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 21cf40e..4746f14 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-01-28  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+
+	* ld-scripts/memory.t: Define new symbol tred.
+	* ld-scripts/memory_sym.t: New.
+	* ld-scripts/script.exp: Perform MEMORY with symbols test, and
+	conditionally check values of linker symbols.
+
 2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* ld-scripts/provide-4-map.d: Update expected output.
diff --git a/ld/testsuite/ld-scripts/memory.t b/ld/testsuite/ld-scripts/memory.t
index 129bd7c..937394f 100644
--- a/ld/testsuite/ld-scripts/memory.t
+++ b/ld/testsuite/ld-scripts/memory.t
@@ -29,5 +29,6 @@ SECTIONS
     data_end = .;
   } >DATAMEM
 
-  fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM);  
+  fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM);
+  tred = ORIGIN(TEXTMEM) + LENGTH(TEXTMEM);
 }
diff --git a/ld/testsuite/ld-scripts/memory_sym.t b/ld/testsuite/ld-scripts/memory_sym.t
new file mode 100644
index 0000000..4ccec55
--- /dev/null
+++ b/ld/testsuite/ld-scripts/memory_sym.t
@@ -0,0 +1,36 @@
+TXT_ORIGIN = 0x100;
+TXT_LENGTH = 32K;
+MEMORY
+{
+  R_TEXTMEM (ARX) : ORIGIN = TXT_ORIGIN, LENGTH = TXT_LENGTH
+  R_DATAMEM (AW)  : org = DATA_ORIGIN, l = DATA_LENGTH
+}
+
+REGION_ALIAS ("A_TEXTMEM", R_TEXTMEM);
+REGION_ALIAS ("A_DATAMEM", R_DATAMEM);
+
+REGION_ALIAS ("TEXTMEM", A_TEXTMEM);
+REGION_ALIAS ("DATAMEM", A_DATAMEM);
+
+SECTIONS
+{
+  . = 0;
+  .text :
+  {
+    text_start = ORIGIN (TEXTMEM);
+    *(.text)
+    *(.pr)
+    text_end = .;
+  } > TEXTMEM
+  
+  data_start = ORIGIN (DATAMEM);
+  .data :
+  {
+    *(.data)
+    *(.rw)
+    data_end = .;
+  } >DATAMEM
+
+  fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM);  
+  tred = ORIGIN(TEXTMEM) + LENGTH(TEXTMEM);  
+}
diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp
index cee706f..6ab04ec 100644
--- a/ld/testsuite/ld-scripts/script.exp
+++ b/ld/testsuite/ld-scripts/script.exp
@@ -66,6 +66,13 @@ proc check_script { } {
 	set passes 0
     } 
 
+    if {[info exists nm_output(tred)] \
+        && $nm_output(tred) != (0x100 + 0x8000)} {
+	send_log "tred == $nm_output(tred)\n"
+	verbose "tred == $nm_output(tred)"
+	set passes 0
+    }
+
     if {$nm_output(text_end) < $text_end \
 	    || $nm_output(text_end) > 0x110} {
 	send_log "text_end == $nm_output(text_end)\n"
@@ -79,6 +86,13 @@ proc check_script { } {
 	set passes 0
     } 
 
+    if {[info exists nm_output(fred)] \
+        && $nm_output(fred) != (0x1000 + 0x10000)} {
+	send_log "fred == $nm_output(fred)\n"
+	verbose "fred == $nm_output(fred)"
+	set passes 0
+    }
+
     if {$nm_output(data_end) < $data_end \
 	    || $nm_output(data_end) > 0x1010} {
 	send_log "data_end == $nm_output(data_end)\n"
@@ -126,6 +140,13 @@ if ![ld_simple_link $ld tmpdir/script "$flags -T $srcdir/$subdir/memory.t tmpdir
     check_script
 }
 
+set testname "MEMORY with symbols"
+if ![ld_simple_link $ld tmpdir/script "$flags -defsym DATA_ORIGIN=0x1000 -defsym DATA_LENGTH=0x10000 -T $srcdir/$subdir/memory_sym.t tmpdir/script.o"] {
+    fail $testname
+} else {
+    check_script
+}
+
 set test_script_list [lsort [glob $srcdir/$subdir/region-alias-*.t]]
 
 foreach test_script $test_script_list {


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