Add new NOCROSSREFS_TO linker script command
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.
This commit is contained in:
parent
5947319ef3
commit
cdf969539c
13 changed files with 180 additions and 7 deletions
20
ld/ChangeLog
20
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.
|
||||
|
|
2
ld/NEWS
2
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
|
||||
|
|
|
@ -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})
|
||||
|
|
24
ld/ldcref.c
24
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;
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
|
10
ld/ldlang.c
10
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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
|
10
ld/testsuite/ld-scripts/cross4.t
Normal file
10
ld/testsuite/ld-scripts/cross4.t
Normal file
|
@ -0,0 +1,10 @@
|
|||
NOCROSSREFS_TO(.data .nocrossrefs)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) }
|
||||
.nocrossrefs : { *(.nocrossrefs) }
|
||||
.data : { *(.data) *(.opd) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
/DISCARD/ : { *(*) }
|
||||
}
|
10
ld/testsuite/ld-scripts/cross5.t
Normal file
10
ld/testsuite/ld-scripts/cross5.t
Normal file
|
@ -0,0 +1,10 @@
|
|||
NOCROSSREFS_TO(.nocrossrefs .data)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) }
|
||||
.nocrossrefs : { *(.nocrossrefs) }
|
||||
.data : { *(.data) *(.opd) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
/DISCARD/ : { *(*) }
|
||||
}
|
9
ld/testsuite/ld-scripts/cross6.t
Normal file
9
ld/testsuite/ld-scripts/cross6.t
Normal file
|
@ -0,0 +1,9 @@
|
|||
NOCROSSREFS_TO(.text .data)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) *(.opd) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
/DISCARD/ : { *(*) }
|
||||
}
|
9
ld/testsuite/ld-scripts/cross7.t
Normal file
9
ld/testsuite/ld-scripts/cross7.t
Normal file
|
@ -0,0 +1,9 @@
|
|||
NOCROSSREFS_TO(.data .text)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) *(.opd) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
/DISCARD/ : { *(*) }
|
||||
}
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue