public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add new NOCROSSREFSTO linker script command
@ 2016-04-14 14:08 Matthew Fortune
  2016-04-14 22:30 ` Alan Modra
  0 siblings, 1 reply; 5+ messages in thread
From: Matthew Fortune @ 2016-04-14 14:08 UTC (permalink / raw)
  To: binutils

This patch introduces a new linker script command NOCROSSREFSTO.

The command performs a one-way cross referencing check instead
of the bi-directional checks done by NOCROSSREFS.

The idea of this feature is to support multi-core layouts where
each core has a private memory region that is inaccessible to the
other core as well as some shared memory. Functions and data
in shared memory can be safely referenced from core specific
memory. If a reference were allowed in the reverse direction then
one core may end up trying to access another core's memory by
calling into shared memory and then back out.

The feature does not give absolute safety as there remain ways
to circumvent the rules; it is however much better than no checks
at all.

New tests pass on x86_64-pc-linux-gnu and no new regressions.

Does anyone else think they or their users would use this
feature?  I and other MIPS users would of course :-)

Comments on implementation most welcome. I tried to keep it
lightweight.

Thanks,
Matthew

ld/
	* ldlang.h (struct lang_nocrossrefs): Add onlyfirst field.
	(lang_add_nocrossrefto): New prototype.
	* ldlex.l (NOCROSSREFSTO): New token.
	* ldgram.y (NOCROSSREFSTO): New script command.
	* ldlang.c (lang_add_nocrossref): Set onlyfirst to FALSE.
	(lang_add_nocrossrefto): New function.
	* ldcref.c (check_local_sym_xref): Use onlyfirst to only look for
	symbols defined in the first section.
	(check_nocrossref): Likewise.
	* ld.texinfo: Document NOCROSSREFSTO script command.
	* NEWS: Mention NOCROSSREFSTO.

ld/testsuite/

	* ld-scripts/cross4.t: New file.
	* ld-scripts/cross5.t: Likewise.
	* ld-scripts/cross6.t: Likewise.
	* ld-scripts/cross7.t: Likewise.
	* ld-scripts/crossref.exp: Run 4 new NOCROSSREFSTO tests.
---
 ld/NEWS                              |  2 ++
 ld/ld.texinfo                        | 19 +++++++++++
 ld/ldcref.c                          | 24 ++++++++++----
 ld/ldgram.y                          |  6 +++-
 ld/ldlang.c                          | 10 ++++++
 ld/ldlang.h                          |  3 ++
 ld/ldlex.l                           |  1 +
 ld/testsuite/ld-scripts/cross4.t     | 10 ++++++
 ld/testsuite/ld-scripts/cross5.t     | 10 ++++++
 ld/testsuite/ld-scripts/cross6.t     |  9 +++++
 ld/testsuite/ld-scripts/cross7.t     |  9 +++++
 ld/testsuite/ld-scripts/crossref.exp | 64 ++++++++++++++++++++++++++++++++++++
 12 files changed, 160 insertions(+), 7 deletions(-)
 create mode 100644 ld/testsuite/ld-scripts/cross4.t
 create mode 100644 ld/testsuite/ld-scripts/cross5.t
 create mode 100644 ld/testsuite/ld-scripts/cross6.t
 create mode 100644 ld/testsuite/ld-scripts/cross7.t

diff --git a/ld/NEWS b/ld/NEWS
index b88da5c..b4abd0b 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -9,6 +9,8 @@
 * Support for -z nodynamic-undefined-weak in the x86 ELF linker, which
   avoids dynamic relocations against undefined weak symbols in executable.
 
+* The NOCROSSREFSTO command was added to the linker script language.
+
 Changes in 2.26:
 
 * Add --fix-stm32l4xx-629360 to the ARM linker to enable a link-time
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index d3d8dc6..f6b8def 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -3674,6 +3674,25 @@ an error and returns a non-zero exit status.  Note that the
 @code{NOCROSSREFS} command uses output section names, not input section
 names.
 
+@item NOCROSSREFSTO(@var{tosection} @var{fromsection} @dots{})
+@kindex NOCROSSREFSTO(@var{tosection} @var{fromsections})
+@cindex cross references
+This command may be used to tell @command{ld} to issue an error about any
+references to one section from a list of other sections.
+
+The @code{NOCROSSREFS} command is useful when ensuring that two or more
+output sections are entirely independent but there are situations where
+a one-way dependency is needed. For example, in a multi-core application
+there may be shared code that can be called from each core but for safety
+must never call back.
+
+The @code{NOCROSSREFSTO} command takes a list of output section names.
+The first section can not be referenced from any of the other sections.
+If @command{ld} detects any references to the first section from any of
+the other sections, it reports an error and returns a non-zero exit
+status.  Note that the @code{NOCROSSREFSTO} command uses output section
+names, not input section names.
+
 @ifclear SingleFormat
 @item OUTPUT_ARCH(@var{bfdarch})
 @kindex OUTPUT_ARCH(@var{bfdarch})
diff --git a/ld/ldcref.c b/ld/ldcref.c
index b87f384..3b4f683 100644
--- a/ld/ldcref.c
+++ b/ld/ldcref.c
@@ -534,8 +534,14 @@ check_local_sym_xref (lang_input_statement_type *statement)
 	    symname = sym->name;
 	  for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
 	    for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
-	      if (strcmp (ncr->name, outsecname) == 0)
-		check_refs (symname, FALSE, sym->section, abfd, ncrs);
+	      {
+		if (strcmp (ncr->name, outsecname) == 0)
+		  check_refs (symname, FALSE, sym->section, abfd, ncrs);
+		/* The NOCROSSREFSTO command only checks symbols defined in
+		   the first section in the list.  */
+		if (ncrs->onlyfirst)
+		  break;
+	      }
 	}
     }
 }
@@ -572,10 +578,16 @@ check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
 
   for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
     for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
-      if (strcmp (ncr->name, defsecname) == 0)
-	for (ref = h->refs; ref != NULL; ref = ref->next)
-	  check_refs (hl->root.string, TRUE, hl->u.def.section,
-		      ref->abfd, ncrs);
+      {
+	if (strcmp (ncr->name, defsecname) == 0)
+	  for (ref = h->refs; ref != NULL; ref = ref->next)
+	    check_refs (hl->root.string, TRUE, hl->u.def.section,
+			ref->abfd, ncrs);
+	/* The NOCROSSREFSTO command only checks symbols defined in the first
+	   section in the list.  */
+	if (ncrs->onlyfirst)
+	  break;
+      }
 
   return TRUE;
 }
diff --git a/ld/ldgram.y b/ld/ldgram.y
index a664258..460d8e5 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -141,7 +141,7 @@ static int error_index;
 %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
 %token <integer> NEXT
 %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
-%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
+%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS NOCROSSREFSTO
 %token ORIGIN FILL
 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
 %token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
@@ -353,6 +353,10 @@ ifile_p1:
 		{
 		  lang_add_nocrossref ($3);
 		}
+	|	NOCROSSREFSTO '(' nocrossref_list ')'
+		{
+		  lang_add_nocrossrefto ($3);
+		}
 	|	EXTERN '(' extern_name_list ')'
 	|	INSERT_K AFTER NAME
 		{ lang_add_insert ($3, 0); }
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 1947efc..fa3b665 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -7486,11 +7486,21 @@ lang_add_nocrossref (lang_nocrossref_type *l)
   n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
   n->next = nocrossref_list;
   n->list = l;
+  n->onlyfirst = FALSE;
   nocrossref_list = n;
 
   /* Set notice_all so that we get informed about all symbols.  */
   link_info.notice_all = TRUE;
 }
+
+/* Record a section that cannot be referenced from a list of sections.  */
+
+void
+lang_add_nocrossrefto (lang_nocrossref_type *l)
+{
+  lang_add_nocrossref (l);
+  nocrossref_list->onlyfirst = TRUE;
+}
 

 /* Overlay handling.  We handle overlays with some static variables.  */
 
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 65d768b..44ab422 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -464,6 +464,7 @@ struct lang_nocrossrefs
 {
   struct lang_nocrossrefs *next;
   lang_nocrossref_type *list;
+  bfd_boolean onlyfirst;
 };
 
 /* This structure is used to hold a list of input section names which
@@ -654,6 +655,8 @@ extern void lang_new_phdr
    etree_type *);
 extern void lang_add_nocrossref
   (lang_nocrossref_type *);
+extern void lang_add_nocrossrefto
+  (lang_nocrossref_type *);
 extern void lang_enter_overlay
   (etree_type *, etree_type *);
 extern void lang_enter_overlay_section
diff --git a/ld/ldlex.l b/ld/ldlex.l
index d70fad1..f677e70 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -298,6 +298,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <BOTH,SCRIPT>"BYTE"			{ RTOKEN( BYTE);}
 <BOTH,SCRIPT>"NOFLOAT"			{ RTOKEN(NOFLOAT);}
 <EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS"	{ RTOKEN(NOCROSSREFS);}
+<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFSTO"	{ RTOKEN(NOCROSSREFSTO);}
 <BOTH,SCRIPT>"OVERLAY"			{ RTOKEN(OVERLAY); }
 <BOTH,SCRIPT>"SORT_BY_NAME"		{ RTOKEN(SORT_BY_NAME); }
 <BOTH,SCRIPT>"SORT_BY_ALIGNMENT"	{ RTOKEN(SORT_BY_ALIGNMENT); }
diff --git a/ld/testsuite/ld-scripts/cross4.t b/ld/testsuite/ld-scripts/cross4.t
new file mode 100644
index 0000000..7858a37
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross4.t
@@ -0,0 +1,10 @@
+NOCROSSREFSTO(.data .nocrossrefs)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .nocrossrefs : { *(.nocrossrefs) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross5.t b/ld/testsuite/ld-scripts/cross5.t
new file mode 100644
index 0000000..ae55033
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross5.t
@@ -0,0 +1,10 @@
+NOCROSSREFSTO(.nocrossrefs .data)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .nocrossrefs : { *(.nocrossrefs) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross6.t b/ld/testsuite/ld-scripts/cross6.t
new file mode 100644
index 0000000..9ba5b87
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross6.t
@@ -0,0 +1,9 @@
+NOCROSSREFSTO(.text .data)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross7.t b/ld/testsuite/ld-scripts/cross7.t
new file mode 100644
index 0000000..22fc786
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross7.t
@@ -0,0 +1,9 @@
+NOCROSSREFSTO(.data .text)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/crossref.exp b/ld/testsuite/ld-scripts/crossref.exp
index 7244b90..940ac7c 100644
--- a/ld/testsuite/ld-scripts/crossref.exp
+++ b/ld/testsuite/ld-scripts/crossref.exp
@@ -22,11 +22,19 @@
 set test1 "NOCROSSREFS 1"
 set test2 "NOCROSSREFS 2"
 set test3 "NOCROSSREFS 3"
+set test4 "NOCROSSREFSTO 1"
+set test5 "NOCROSSREFSTO 2"
+set test6 "NOCROSSREFSTO 3"
+set test7 "NOCROSSREFSTO 4"
 
 if { ![is_remote host] && [which $CC] == 0 } {
     untested $test1
     untested $test2
     untested $test3
+    untested $test4
+    untested $test5
+    untested $test6
+    untested $test7
     return
 }
 
@@ -158,5 +166,61 @@ if [string match "" $exec_output] then {
     fail $test3
 }
 
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross4 -T $srcdir/$subdir/cross4.t tmpdir/cross4.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    pass $test4
+} else {
+    verbose -log "$exec_output"
+    fail $test4
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross5 -T $srcdir/$subdir/cross5.t tmpdir/cross4.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    fail $test5
+} else {
+    verbose -log "$exec_output"
+    if [regexp "prohibited cross reference from .* to `.*' in" $exec_output] {
+	pass $test5
+    } else {
+	fail $test5
+    }
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross6 -T $srcdir/$subdir/cross6.t tmpdir/cross3.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    pass $test6
+} else {
+    verbose -log "$exec_output"
+    fail $test6
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross7 -T $srcdir/$subdir/cross7.t tmpdir/cross3.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    fail $test7
+} else {
+    verbose -log "$exec_output"
+    if [regexp "prohibited cross reference from .* to `.*' in" $exec_output] {
+	pass $test7
+    } else {
+	fail $test7
+    }
+}
+
 set CFLAGS "$old_CFLAGS"
 set CC "$old_CC"
-- 
2.2.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add new NOCROSSREFSTO linker script command
  2016-04-14 14:08 [PATCH] Add new NOCROSSREFSTO linker script command Matthew Fortune
@ 2016-04-14 22:30 ` Alan Modra
  2016-04-15 11:12   ` Matthew Fortune
  0 siblings, 1 reply; 5+ messages in thread
From: Alan Modra @ 2016-04-14 22:30 UTC (permalink / raw)
  To: Matthew Fortune; +Cc: binutils

On Thu, Apr 14, 2016 at 02:08:26PM +0000, Matthew Fortune wrote:
> This patch introduces a new linker script command NOCROSSREFSTO.

You have my vote for the feature.  The patch looks good.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH] Add new NOCROSSREFSTO linker script command
  2016-04-14 22:30 ` Alan Modra
@ 2016-04-15 11:12   ` Matthew Fortune
  2016-04-18 11:15     ` Nick Clifton
  0 siblings, 1 reply; 5+ messages in thread
From: Matthew Fortune @ 2016-04-15 11:12 UTC (permalink / raw)
  To: Alan Modra, Hans-Peter Nilsson; +Cc: binutils

Alan Modra <amodra@gmail.com> writes:
> On Thu, Apr 14, 2016 at 02:08:26PM +0000, Matthew Fortune wrote:
> > This patch introduces a new linker script command NOCROSSREFSTO.
> 
> You have my vote for the feature.  The patch looks good.

H-P suggested adding an underscore to make the command
NOCROSSREFS_TO:

https://sourceware.org/ml/binutils/2016-04/msg00221.html

I have no objection if this seems clearer. If there are no other
opinions I'll update to add an underscore.

Thanks,
Matthew

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add new NOCROSSREFSTO linker script command
  2016-04-15 11:12   ` Matthew Fortune
@ 2016-04-18 11:15     ` Nick Clifton
  2016-04-18 11:49       ` Matthew Fortune
  0 siblings, 1 reply; 5+ messages in thread
From: Nick Clifton @ 2016-04-18 11:15 UTC (permalink / raw)
  To: Matthew Fortune, Alan Modra, Hans-Peter Nilsson; +Cc: binutils

Hi Matthew,

> I have no objection if this seems clearer. If there are no other
> opinions I'll update to add an underscore.

Please do.  Otherwise the patch looks fine to me too.

Cheers
  Nick

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH] Add new NOCROSSREFSTO linker script command
  2016-04-18 11:15     ` Nick Clifton
@ 2016-04-18 11:49       ` Matthew Fortune
  0 siblings, 0 replies; 5+ messages in thread
From: Matthew Fortune @ 2016-04-18 11:49 UTC (permalink / raw)
  To: Nick Clifton, Alan Modra, Hans-Peter Nilsson; +Cc: binutils

Nick Clifton <nickc@redhat.com> writes:
> > I have no objection if this seems clearer. If there are no other
> > opinions I'll update to add an underscore.
> 
> Please do.  Otherwise the patch looks fine to me too.

Thanks. Committed as below.

Matthew

NOCROSSREFS_TO is similar to the existing NOCROSSREFS command but only
checks one direction of cross referencing.

ld/ChangeLog

	* ld.texinfo: Document NOCROSSREFS_TO script command.
	* ldlang.h (struct lang_nocrossrefs): Add onlyfirst field.
	(lang_add_nocrossref_to): New prototype.
	* ldcref.c (check_local_sym_xref): Use onlyfirst to only look for
	symbols defined in the first section.
	(check_nocrossref): Likewise.
	* ldgram.y (NOCROSSREFS_TO): New script command.
	* ldlang.c (lang_add_nocrossref): Set onlyfirst to FALSE.
	(lang_add_nocrossref_to): New function.
	* ldlex.l (NOCROSSREFS_TO): New token.
	* NEWS: Mention NOCROSSREFS_TO.
	* testsuite/ld-scripts/cross4.t: New file.
	* testsuite/ld-scripts/cross5.t: Likewise.
	* testsuite/ld-scripts/cross6.t: Likewise.
	* testsuite/ld-scripts/cross7.t: Likewise.
	* testsuite/ld-scripts/crossref.exp: Run 4 new NOCROSSREFS_TO
	tests.
---
 ld/ChangeLog                         | 20 +++++++++++
 ld/NEWS                              |  2 ++
 ld/ld.texinfo                        | 19 +++++++++++
 ld/ldcref.c                          | 24 ++++++++++----
 ld/ldgram.y                          |  6 +++-
 ld/ldlang.c                          | 10 ++++++
 ld/ldlang.h                          |  3 ++
 ld/ldlex.l                           |  1 +
 ld/testsuite/ld-scripts/cross4.t     | 10 ++++++
 ld/testsuite/ld-scripts/cross5.t     | 10 ++++++
 ld/testsuite/ld-scripts/cross6.t     |  9 +++++
 ld/testsuite/ld-scripts/cross7.t     |  9 +++++
 ld/testsuite/ld-scripts/crossref.exp | 64 ++++++++++++++++++++++++++++++++++++
 13 files changed, 180 insertions(+), 7 deletions(-)
 create mode 100644 ld/testsuite/ld-scripts/cross4.t
 create mode 100644 ld/testsuite/ld-scripts/cross5.t
 create mode 100644 ld/testsuite/ld-scripts/cross6.t
 create mode 100644 ld/testsuite/ld-scripts/cross7.t

diff --git a/ld/ChangeLog b/ld/ChangeLog
index b340125..0701b12 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,23 @@
+2016-04-18  Matthew Fortune  <matthew.fortune@imgtec.com>
+
+	* ld.texinfo: Document NOCROSSREFS_TO script command.
+	* ldlang.h (struct lang_nocrossrefs): Add onlyfirst field.
+	(lang_add_nocrossref_to): New prototype.
+	* ldcref.c (check_local_sym_xref): Use onlyfirst to only look for
+	symbols defined in the first section.
+	(check_nocrossref): Likewise.
+	* ldgram.y (NOCROSSREFS_TO): New script command.
+	* ldlang.c (lang_add_nocrossref): Set onlyfirst to FALSE.
+	(lang_add_nocrossref_to): New function.
+	* ldlex.l (NOCROSSREFS_TO): New token.
+	* NEWS: Mention NOCROSSREFS_TO.
+	* testsuite/ld-scripts/cross4.t: New file.
+	* testsuite/ld-scripts/cross5.t: Likewise.
+	* testsuite/ld-scripts/cross6.t: Likewise.
+	* testsuite/ld-scripts/cross7.t: Likewise.
+	* testsuite/ld-scripts/crossref.exp: Run 4 new NOCROSSREFS_TO
+	tests.
+
 2016-04-15  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* Makefile.in: Regenerated with automake 1.11.6.
diff --git a/ld/NEWS b/ld/NEWS
index b88da5c..b4abd0b 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -9,6 +9,8 @@
 * Support for -z nodynamic-undefined-weak in the x86 ELF linker, which
   avoids dynamic relocations against undefined weak symbols in executable.
 
+* The NOCROSSREFSTO command was added to the linker script language.
+
 Changes in 2.26:
 
 * Add --fix-stm32l4xx-629360 to the ARM linker to enable a link-time
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index d3d8dc6..7a2ed3a 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -3674,6 +3674,25 @@ an error and returns a non-zero exit status.  Note that the
 @code{NOCROSSREFS} command uses output section names, not input section
 names.
 
+@item NOCROSSREFS_TO(@var{tosection} @var{fromsection} @dots{})
+@kindex NOCROSSREFS_TO(@var{tosection} @var{fromsections})
+@cindex cross references
+This command may be used to tell @command{ld} to issue an error about any
+references to one section from a list of other sections.
+
+The @code{NOCROSSREFS} command is useful when ensuring that two or more
+output sections are entirely independent but there are situations where
+a one-way dependency is needed. For example, in a multi-core application
+there may be shared code that can be called from each core but for safety
+must never call back.
+
+The @code{NOCROSSREFS_TO} command takes a list of output section names.
+The first section can not be referenced from any of the other sections.
+If @command{ld} detects any references to the first section from any of
+the other sections, it reports an error and returns a non-zero exit
+status.  Note that the @code{NOCROSSREFS_TO} command uses output section
+names, not input section names.
+
 @ifclear SingleFormat
 @item OUTPUT_ARCH(@var{bfdarch})
 @kindex OUTPUT_ARCH(@var{bfdarch})
diff --git a/ld/ldcref.c b/ld/ldcref.c
index b87f384..d96db20 100644
--- a/ld/ldcref.c
+++ b/ld/ldcref.c
@@ -534,8 +534,14 @@ check_local_sym_xref (lang_input_statement_type *statement)
 	    symname = sym->name;
 	  for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
 	    for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
-	      if (strcmp (ncr->name, outsecname) == 0)
-		check_refs (symname, FALSE, sym->section, abfd, ncrs);
+	      {
+		if (strcmp (ncr->name, outsecname) == 0)
+		  check_refs (symname, FALSE, sym->section, abfd, ncrs);
+		/* The NOCROSSREFS_TO command only checks symbols defined in
+		   the first section in the list.  */
+		if (ncrs->onlyfirst)
+		  break;
+	      }
 	}
     }
 }
@@ -572,10 +578,16 @@ check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
 
   for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
     for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
-      if (strcmp (ncr->name, defsecname) == 0)
-	for (ref = h->refs; ref != NULL; ref = ref->next)
-	  check_refs (hl->root.string, TRUE, hl->u.def.section,
-		      ref->abfd, ncrs);
+      {
+	if (strcmp (ncr->name, defsecname) == 0)
+	  for (ref = h->refs; ref != NULL; ref = ref->next)
+	    check_refs (hl->root.string, TRUE, hl->u.def.section,
+			ref->abfd, ncrs);
+	/* The NOCROSSREFS_TO command only checks symbols defined in the first
+	   section in the list.  */
+	if (ncrs->onlyfirst)
+	  break;
+      }
 
   return TRUE;
 }
diff --git a/ld/ldgram.y b/ld/ldgram.y
index a664258..9973b07 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -141,7 +141,7 @@ static int error_index;
 %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
 %token <integer> NEXT
 %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
-%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS
+%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS NOCROSSREFS_TO
 %token ORIGIN FILL
 %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
 %token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
@@ -353,6 +353,10 @@ ifile_p1:
 		{
 		  lang_add_nocrossref ($3);
 		}
+	|	NOCROSSREFS_TO '(' nocrossref_list ')'
+		{
+		  lang_add_nocrossref_to ($3);
+		}
 	|	EXTERN '(' extern_name_list ')'
 	|	INSERT_K AFTER NAME
 		{ lang_add_insert ($3, 0); }
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 1947efc..856e3e2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -7486,11 +7486,21 @@ lang_add_nocrossref (lang_nocrossref_type *l)
   n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
   n->next = nocrossref_list;
   n->list = l;
+  n->onlyfirst = FALSE;
   nocrossref_list = n;
 
   /* Set notice_all so that we get informed about all symbols.  */
   link_info.notice_all = TRUE;
 }
+
+/* Record a section that cannot be referenced from a list of sections.  */
+
+void
+lang_add_nocrossref_to (lang_nocrossref_type *l)
+{
+  lang_add_nocrossref (l);
+  nocrossref_list->onlyfirst = TRUE;
+}
 

 /* Overlay handling.  We handle overlays with some static variables.  */
 
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 65d768b..0cb147c 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -464,6 +464,7 @@ struct lang_nocrossrefs
 {
   struct lang_nocrossrefs *next;
   lang_nocrossref_type *list;
+  bfd_boolean onlyfirst;
 };
 
 /* This structure is used to hold a list of input section names which
@@ -654,6 +655,8 @@ extern void lang_new_phdr
    etree_type *);
 extern void lang_add_nocrossref
   (lang_nocrossref_type *);
+extern void lang_add_nocrossref_to
+  (lang_nocrossref_type *);
 extern void lang_enter_overlay
   (etree_type *, etree_type *);
 extern void lang_enter_overlay_section
diff --git a/ld/ldlex.l b/ld/ldlex.l
index d70fad1..2eb8fc1 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -298,6 +298,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <BOTH,SCRIPT>"BYTE"			{ RTOKEN( BYTE);}
 <BOTH,SCRIPT>"NOFLOAT"			{ RTOKEN(NOFLOAT);}
 <EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS"	{ RTOKEN(NOCROSSREFS);}
+<EXPRESSION,BOTH,SCRIPT>"NOCROSSREFS_TO" { RTOKEN(NOCROSSREFS_TO);}
 <BOTH,SCRIPT>"OVERLAY"			{ RTOKEN(OVERLAY); }
 <BOTH,SCRIPT>"SORT_BY_NAME"		{ RTOKEN(SORT_BY_NAME); }
 <BOTH,SCRIPT>"SORT_BY_ALIGNMENT"	{ RTOKEN(SORT_BY_ALIGNMENT); }
diff --git a/ld/testsuite/ld-scripts/cross4.t b/ld/testsuite/ld-scripts/cross4.t
new file mode 100644
index 0000000..7f91b81
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross4.t
@@ -0,0 +1,10 @@
+NOCROSSREFS_TO(.data .nocrossrefs)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .nocrossrefs : { *(.nocrossrefs) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross5.t b/ld/testsuite/ld-scripts/cross5.t
new file mode 100644
index 0000000..43657f1
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross5.t
@@ -0,0 +1,10 @@
+NOCROSSREFS_TO(.nocrossrefs .data)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .nocrossrefs : { *(.nocrossrefs) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross6.t b/ld/testsuite/ld-scripts/cross6.t
new file mode 100644
index 0000000..4664221
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross6.t
@@ -0,0 +1,9 @@
+NOCROSSREFS_TO(.text .data)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/cross7.t b/ld/testsuite/ld-scripts/cross7.t
new file mode 100644
index 0000000..dad2103
--- /dev/null
+++ b/ld/testsuite/ld-scripts/cross7.t
@@ -0,0 +1,9 @@
+NOCROSSREFS_TO(.data .text)
+
+SECTIONS
+{
+  .text : { *(.text) }
+  .data : { *(.data) *(.opd) }
+  .bss : { *(.bss) *(COMMON) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/crossref.exp b/ld/testsuite/ld-scripts/crossref.exp
index 7244b90..4371320 100644
--- a/ld/testsuite/ld-scripts/crossref.exp
+++ b/ld/testsuite/ld-scripts/crossref.exp
@@ -22,11 +22,19 @@
 set test1 "NOCROSSREFS 1"
 set test2 "NOCROSSREFS 2"
 set test3 "NOCROSSREFS 3"
+set test4 "NOCROSSREFS_TO 1"
+set test5 "NOCROSSREFS_TO 2"
+set test6 "NOCROSSREFS_TO 3"
+set test7 "NOCROSSREFS_TO 4"
 
 if { ![is_remote host] && [which $CC] == 0 } {
     untested $test1
     untested $test2
     untested $test3
+    untested $test4
+    untested $test5
+    untested $test6
+    untested $test7
     return
 }
 
@@ -158,5 +166,61 @@ if [string match "" $exec_output] then {
     fail $test3
 }
 
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross4 -T $srcdir/$subdir/cross4.t tmpdir/cross4.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    pass $test4
+} else {
+    verbose -log "$exec_output"
+    fail $test4
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross5 -T $srcdir/$subdir/cross5.t tmpdir/cross4.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    fail $test5
+} else {
+    verbose -log "$exec_output"
+    if [regexp "prohibited cross reference from .* to `.*' in" $exec_output] {
+	pass $test5
+    } else {
+	fail $test5
+    }
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross6 -T $srcdir/$subdir/cross6.t tmpdir/cross3.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    pass $test6
+} else {
+    verbose -log "$exec_output"
+    fail $test6
+}
+
+set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross7 -T $srcdir/$subdir/cross7.t tmpdir/cross3.o"]
+set exec_output [prune_warnings $exec_output]
+
+regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
+
+if [string match "" $exec_output] then {
+    fail $test7
+} else {
+    verbose -log "$exec_output"
+    if [regexp "prohibited cross reference from .* to `.*' in" $exec_output] {
+	pass $test7
+    } else {
+	fail $test7
+    }
+}
+
 set CFLAGS "$old_CFLAGS"
 set CC "$old_CC"
-- 
2.2.1

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-04-18 11:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-14 14:08 [PATCH] Add new NOCROSSREFSTO linker script command Matthew Fortune
2016-04-14 22:30 ` Alan Modra
2016-04-15 11:12   ` Matthew Fortune
2016-04-18 11:15     ` Nick Clifton
2016-04-18 11:49       ` Matthew Fortune

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).