aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog20
-rw-r--r--ld/NEWS2
-rw-r--r--ld/ld.texinfo19
-rw-r--r--ld/ldcref.c24
-rw-r--r--ld/ldgram.y6
-rw-r--r--ld/ldlang.c10
-rw-r--r--ld/ldlang.h3
-rw-r--r--ld/ldlex.l1
-rw-r--r--ld/testsuite/ld-scripts/cross4.t10
-rw-r--r--ld/testsuite/ld-scripts/cross5.t10
-rw-r--r--ld/testsuite/ld-scripts/cross6.t9
-rw-r--r--ld/testsuite/ld-scripts/cross7.t9
-rw-r--r--ld/testsuite/ld-scripts/crossref.exp64
13 files changed, 180 insertions, 7 deletions
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"