From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 119759 invoked by alias); 14 Apr 2016 14:08:38 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 119746 invoked by uid 89); 14 Apr 2016 14:08:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL,BAYES_20,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=ld, AFTER, 2219, 4646 X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 14 Apr 2016 14:08:31 +0000 Received: from HHMAIL01.hh.imgtec.org (unknown [10.100.10.19]) by Websense Email with ESMTPS id ACFF154946C01 for ; Thu, 14 Apr 2016 15:08:23 +0100 (IST) Received: from hhmail02.hh.imgtec.org ([fe80::5400:d33e:81a4:f775]) by HHMAIL01.hh.imgtec.org ([fe80::710b:f219:72bc:e0b3%26]) with mapi id 14.03.0266.001; Thu, 14 Apr 2016 15:08:27 +0100 From: Matthew Fortune To: "binutils@sourceware.org" Subject: [PATCH] Add new NOCROSSREFSTO linker script command Date: Thu, 14 Apr 2016 14:08:00 -0000 Message-ID: <6D39441BF12EF246A7ABCE6654B023537E3D4B60@hhmail02.hh.imgtec.org> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-IsSubscribed: yes X-SW-Source: 2016-04/txt/msg00213.txt.bz2 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. =20 +* The NOCROSSREFSTO command was added to the linker script language. + Changes in 2.26: =20 * 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 t= hat the @code{NOCROSSREFS} command uses output section names, not input section names. =20 +@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 *state= ment) symname =3D sym->name; for (ncrs =3D nocrossref_list; ncrs !=3D NULL; ncrs =3D ncrs->next) for (ncr =3D ncrs->list; ncr !=3D NULL; ncr =3D ncr->next) - if (strcmp (ncr->name, outsecname) =3D=3D 0) - check_refs (symname, FALSE, sym->section, abfd, ncrs); + { + if (strcmp (ncr->name, outsecname) =3D=3D 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 *ig= nore ATTRIBUTE_UNUSED) =20 for (ncrs =3D nocrossref_list; ncrs !=3D NULL; ncrs =3D ncrs->next) for (ncr =3D ncrs->list; ncr !=3D NULL; ncr =3D ncr->next) - if (strcmp (ncr->name, defsecname) =3D=3D 0) - for (ref =3D h->refs; ref !=3D NULL; ref =3D ref->next) - check_refs (hl->root.string, TRUE, hl->u.def.section, - ref->abfd, ncrs); + { + if (strcmp (ncr->name, defsecname) =3D=3D 0) + for (ref =3D h->refs; ref !=3D NULL; ref =3D 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; + } =20 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 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 =3D (struct lang_nocrossrefs *) xmalloc (sizeof *n); n->next =3D nocrossref_list; n->list =3D l; + n->onlyfirst =3D FALSE; nocrossref_list =3D n; =20 /* Set notice_all so that we get informed about all symbols. */ link_info.notice_all =3D 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 =3D TRUE; +} =20 /* Overlay handling. We handle overlays with some static variables. */ =20 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; }; =20 /* 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\= [\]\-\!\^\\]|::)* "BYTE" { RTOKEN( BYTE);} "NOFLOAT" { RTOKEN(NOFLOAT);} "NOCROSSREFS" { RTOKEN(NOCROSSREFS);} +"NOCROSSREFSTO" { RTOKEN(NOCROSSREFSTO);} "OVERLAY" { RTOKEN(OVERLAY); } "SORT_BY_NAME" { RTOKEN(SORT_BY_NAME); } "SORT_BY_ALIGNMENT" { RTOKEN(SORT_BY_ALIGNMENT); } diff --git a/ld/testsuite/ld-scripts/cross4.t b/ld/testsuite/ld-scripts/cro= ss4.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/cro= ss5.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/cro= ss6.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/cro= ss7.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" =20 if { ![is_remote host] && [which $CC] =3D=3D 0 } { untested $test1 untested $test2 untested $test3 + untested $test4 + untested $test5 + untested $test6 + untested $test7 return } =20 @@ -158,5 +166,61 @@ if [string match "" $exec_output] then { fail $test3 } =20 +set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross4 -T $srcdir/$s= ubdir/cross4.t tmpdir/cross4.o"] +set exec_output [prune_warnings $exec_output] + +regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $e= xec_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/$s= ubdir/cross5.t tmpdir/cross4.o"] +set exec_output [prune_warnings $exec_output] + +regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $e= xec_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_outpu= t] { + pass $test5 + } else { + fail $test5 + } +} + +set exec_output [run_host_cmd "$ld" "$flags -o tmpdir/cross6 -T $srcdir/$s= ubdir/cross6.t tmpdir/cross3.o"] +set exec_output [prune_warnings $exec_output] + +regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $e= xec_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/$s= ubdir/cross7.t tmpdir/cross3.o"] +set exec_output [prune_warnings $exec_output] + +regsub -all "(^|\n)($ld: warning: cannot find entry symbol\[^\n\]*\n?)" $e= xec_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_outpu= t] { + pass $test7 + } else { + fail $test7 + } +} + set CFLAGS "$old_CFLAGS" set CC "$old_CC" --=20 2.2.1