From 143bdb8811b8f45a3b9ebf62c2ecb3d45473d0f9 Mon Sep 17 00:00:00 2001 From: Hans-Peter Nilsson Date: Wed, 15 Oct 2014 03:54:43 +0200 Subject: [PATCH] Backport "="-ldscript-path-prefix changes from master. --- ld/ChangeLog | 24 ++++ ld/ld.texinfo | 7 +- ld/ldgram.y | 23 ++-- ld/ldlang.c | 20 ++++ ld/ldlex.h | 1 + ld/ldlex.l | 32 +++-- ld/testsuite/ChangeLog | 7 ++ ld/testsuite/ld-scripts/sysroot-prefix-x.s | 5 + ld/testsuite/ld-scripts/sysroot-prefix-y.s | 4 + ld/testsuite/ld-scripts/sysroot-prefix.exp | 183 +++++++++++++++++++++++++++++ ld/testsuite/lib/ld-lib.exp | 18 +++ 11 files changed, 304 insertions(+), 20 deletions(-) create mode 100644 ld/testsuite/ld-scripts/sysroot-prefix-x.s create mode 100644 ld/testsuite/ld-scripts/sysroot-prefix-y.s create mode 100644 ld/testsuite/ld-scripts/sysroot-prefix.exp diff --git a/ld/ChangeLog b/ld/ChangeLog index e02b109..9f620c9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,27 @@ +2014-10-15 Hans-Peter Nilsson + + Backport "="-ldscript-path-prefix changes from master. + * ldlex.l (INPUTLIST): New start condition. + (comment pattern, ",", "(", ")", "AS_NEEDED") + ({FILENAMECHAR1}{FILENAMECHAR}*, "-l"{FILENAMECHAR}+) + (quoted string pattern, whitespace pattern): Add INPUTLIST to + valid start conditions. + ("="{FILENAMECHAR1}{FILENAMECHAR}*): New NAME rule. + (ldlex_inputlist): New start-condition-setter function. + * ldgram.y (input_list1): Rename from input_list. All recursive + use changed. + (input_list): New wrapper rule for input_list1, setting + INPUTLIST lexer state for the duration of parsing input_list1. + * ldlang.c (lang_add_input_file): If the first character in the + filename is '=', prepend the sysroot and force the context of that + input file to non-sysroot. + * ld.texinfo (Options): When mentioning "=" and sysroot, mention + that --sysroot controls it, not only through the configuration. + (input files in linker scripts): When mentioning + behavior of first character "/" on scripts within sysroot, also + mention that effect can be forced by prefixing with "=" and + refer to SEARCH_DIR. + 2014-10-14 Tristan Gingold * NEWS: Add marker for 2.25. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index e71be5e..8eb7ba3 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -706,7 +706,8 @@ how @command{ld} searches for a linker script unless @option{-T} option is specified. If @var{searchdir} begins with @code{=}, then the @code{=} will be replaced -by the @dfn{sysroot prefix}, a path specified when the linker is configured. +by the @dfn{sysroot prefix}, controlled by the @samp{--sysroot} option, or +specified when the linker is configured. @ifset UsesEnvVars The default set of paths searched (without being specified with @@ -3142,7 +3143,9 @@ with the @samp{/} character, and the script being processed was located inside the @dfn{sysroot prefix}, the filename will be looked for in the @dfn{sysroot prefix}. Otherwise, the linker will try to open the file in the current directory. If it is not found, the -linker will search through the archive library search path. See the +linker will search through the archive library search path. +The @dfn{sysroot prefix} can also be forced by specifying @code{=} +as the first character in the filename path. See also the description of @samp{-L} in @ref{Options,,Command Line Options}. If you use @samp{INPUT (-l@var{file})}, @command{ld} will transform the diff --git a/ld/ldgram.y b/ld/ldgram.y index 4875fa7..e76a0a3 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -365,38 +365,43 @@ ifile_p1: ; input_list: + { ldlex_inputlist(); } + input_list1 + { ldlex_popstate(); } + +input_list1: NAME { lang_add_input_file($1,lang_input_file_is_search_file_enum, (char *)NULL); } - | input_list ',' NAME + | input_list1 ',' NAME { lang_add_input_file($3,lang_input_file_is_search_file_enum, (char *)NULL); } - | input_list NAME + | input_list1 NAME { lang_add_input_file($2,lang_input_file_is_search_file_enum, (char *)NULL); } | LNAME { lang_add_input_file($1,lang_input_file_is_l_enum, (char *)NULL); } - | input_list ',' LNAME + | input_list1 ',' LNAME { lang_add_input_file($3,lang_input_file_is_l_enum, (char *)NULL); } - | input_list LNAME + | input_list1 LNAME { lang_add_input_file($2,lang_input_file_is_l_enum, (char *)NULL); } | AS_NEEDED '(' { $$ = input_flags.add_DT_NEEDED_for_regular; input_flags.add_DT_NEEDED_for_regular = TRUE; } - input_list ')' + input_list1 ')' { input_flags.add_DT_NEEDED_for_regular = $3; } - | input_list ',' AS_NEEDED '(' + | input_list1 ',' AS_NEEDED '(' { $$ = input_flags.add_DT_NEEDED_for_regular; input_flags.add_DT_NEEDED_for_regular = TRUE; } - input_list ')' + input_list1 ')' { input_flags.add_DT_NEEDED_for_regular = $5; } - | input_list AS_NEEDED '(' + | input_list1 AS_NEEDED '(' { $$ = input_flags.add_DT_NEEDED_for_regular; input_flags.add_DT_NEEDED_for_regular = TRUE; } - input_list ')' + input_list1 ')' { input_flags.add_DT_NEEDED_for_regular = $4; } ; diff --git a/ld/ldlang.c b/ld/ldlang.c index 5960e5c..c4da07f 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1118,6 +1118,26 @@ lang_add_input_file (const char *name, lang_input_file_enum_type file_type, const char *target) { + if (name != NULL && *name == '=') + { + lang_input_statement_type *ret; + char *sysrooted_name + = concat (ld_sysroot, name + 1, (const char *) NULL); + + /* We've now forcibly prepended the sysroot, making the input + file independent of the context. Therefore, temporarily + force a non-sysrooted context for this statement, so it won't + get the sysroot prepended again when opened. (N.B. if it's a + script, any child nodes with input files starting with "/" + will be handled as "sysrooted" as they'll be found to be + within the sysroot subdirectory.) */ + unsigned int outer_sysrooted = input_flags.sysrooted; + input_flags.sysrooted = 0; + ret = new_afile (sysrooted_name, file_type, target, TRUE); + input_flags.sysrooted = outer_sysrooted; + return ret; + } + return new_afile (name, file_type, target, TRUE); } diff --git a/ld/ldlex.h b/ld/ldlex.h index 63f4c81..56cd121 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -161,6 +161,7 @@ extern int yylex (void); extern void lex_push_file (FILE *, const char *, unsigned int); extern void lex_redirect (const char *, const char *, unsigned int); extern void ldlex_script (void); +extern void ldlex_inputlist (void); extern void ldlex_mri_script (void); extern void ldlex_version_script (void); extern void ldlex_version_file (void); diff --git a/ld/ldlex.l b/ld/ldlex.l index 234867c..d162128 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -77,6 +77,7 @@ static void lex_warn_invalid (char *where, char *what); /* STATES EXPRESSION definitely in an expression SCRIPT definitely in a script + INPUTLIST definitely in a script, a filename-list BOTH either EXPRESSION or SCRIPT DEFSYMEXP in an argument to -defsym MRI in an MRI script @@ -109,6 +110,7 @@ V_TAG [.$_a-zA-Z][._a-zA-Z0-9]* V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* %s SCRIPT +%s INPUTLIST %s EXPRESSION %s BOTH %s DEFSYMEXP @@ -134,7 +136,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* } } -"/*" { comment (); } +"/*" { comment (); } "-" { RTOKEN('-');} @@ -221,7 +223,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* "|=" { RTOKEN(OREQ);} "&&" { RTOKEN(ANDAND);} ">" { RTOKEN('>');} -"," { RTOKEN(',');} +"," { RTOKEN(',');} "&" { RTOKEN('&');} "|" { RTOKEN('|');} "~" { RTOKEN('~');} @@ -236,8 +238,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* "=" { RTOKEN('=');} "}" { RTOKEN('}') ; } "{" { RTOKEN('{'); } -")" { RTOKEN(')');} -"(" { RTOKEN('(');} +")" { RTOKEN(')');} +"(" { RTOKEN('(');} ":" { RTOKEN(':'); } ";" { RTOKEN(';');} "MEMORY" { RTOKEN(MEMORY);} @@ -272,7 +274,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* "OUTPUT" { RTOKEN(OUTPUT);} "INPUT" { RTOKEN(INPUT);} "GROUP" { RTOKEN(GROUP);} -"AS_NEEDED" { RTOKEN(AS_NEEDED);} +"AS_NEEDED" { RTOKEN(AS_NEEDED);} "DEFINED" { RTOKEN(DEFINED);} "CREATE_OBJECT_SYMBOLS" { RTOKEN(CREATE_OBJECT_SYMBOLS);} "CONSTRUCTORS" { RTOKEN( CONSTRUCTORS);} @@ -373,11 +375,16 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* } -{FILENAMECHAR1}{FILENAMECHAR}* { +{FILENAMECHAR1}{FILENAMECHAR}* { yylval.name = xstrdup (yytext); return NAME; } -"-l"{FILENAMECHAR}+ { +"="{FILENAMECHAR1}{FILENAMECHAR}* { +/* Filename to be prefixed by --sysroot or when non-sysrooted, nothing. */ + yylval.name = xstrdup (yytext); + return NAME; + } +"-l"{FILENAMECHAR}+ { yylval.name = xstrdup (yytext + 2); return LNAME; } @@ -406,7 +413,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* } } -"\""[^\"]*"\"" { +"\""[^\"]*"\"" { /* No matter the state, quotes give what's inside */ yylval.name = xstrdup (yytext + 1); @@ -447,7 +454,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* #.* { /* Eat up comments */ } -[ \t\r]+ { /* Eat up whitespace */ } +[ \t\r]+ { /* Eat up whitespace */ } <> { include_stack_ptr--; @@ -566,6 +573,13 @@ ldlex_script (void) } void +ldlex_inputlist (void) +{ + *(state_stack_p)++ = yy_start; + BEGIN (INPUTLIST); +} + +void ldlex_mri_script (void) { *(state_stack_p)++ = yy_start; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index fd0c8ba..c01990c 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-10-15 Hans-Peter Nilsson + + Backport "="-ldscript-path-prefix changes from master. + * ld-scripts/sysroot-prefix.exp, ld-scripts/sysroot-prefix-x.s, + ld-scripts/sysroot-prefix-y.s: New files. + * lib/ld-lib.exp (check_sysroot_available): New proc. + 2014-10-04 Alan Modra * ld-elf/eh1.s: Don't create FDEs with zero address ranges. diff --git a/ld/testsuite/ld-scripts/sysroot-prefix-x.s b/ld/testsuite/ld-scripts/sysroot-prefix-x.s new file mode 100644 index 0000000..9b81905 --- /dev/null +++ b/ld/testsuite/ld-scripts/sysroot-prefix-x.s @@ -0,0 +1,5 @@ + .data + .globl x +x: + .dc.a y + diff --git a/ld/testsuite/ld-scripts/sysroot-prefix-y.s b/ld/testsuite/ld-scripts/sysroot-prefix-y.s new file mode 100644 index 0000000..f05ffa0 --- /dev/null +++ b/ld/testsuite/ld-scripts/sysroot-prefix-y.s @@ -0,0 +1,4 @@ + .data + .globl y +y: + .dc.a 0 diff --git a/ld/testsuite/ld-scripts/sysroot-prefix.exp b/ld/testsuite/ld-scripts/sysroot-prefix.exp new file mode 100644 index 0000000..cf434df --- /dev/null +++ b/ld/testsuite/ld-scripts/sysroot-prefix.exp @@ -0,0 +1,183 @@ +# Copyright (C) 2014 Free Software Foundation, Inc. +# +# This file is part of the GNU Binutils. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# Check that scripts using the "=" sysroot-prefix work, for both +# toolchains with and without --sysroot support. + +# We test this by emitting archives into a subdirectory and expect +# constructs such as GROUP and AS_NEEDED (the only two constructs +# actually tested) to find them (or not); both quoted and unquoted +# paths, with different prefixes on the path and with --sysroot +# present or not, with different arguments. + +# Find out if the linker supports sysroot; if it was configured +# "--with-sysroot X". We ignore that X can actually be set to +# interfere with the tests, as that's unlikely to be useful, and +# assume that the build-directory (aka. $base_dir) does not contain X. +set with_sysroot [check_sysroot_available] +verbose -log "Has (non-empty) sysroot support: $with_sysroot" + +# Entries in the array-tables: +# 0: Testtype (1: only non-sysroot, 2: only sysroot, 3: either). +# 1: Description, forming part of the dejagnu test-name. +# 2: Replacement for @p@. +# 3: Option to pass to linker (usually something with --sysroot). +# 4: Message substring; a substring to match against the error message +# if an error is expected, or empty if no error is expected. +# +# If the replacement or option contains @cwd@, that'll be replaced by +# "$base_dir/tmpdir", the full path to the location of the script +# (with the actual files in the "sysroot" subdirectory). If the +# description contains @cwd@, that will be replaced by "". + +set sysroot_prefix_tests { + {3 "plain -Lpath" "sysroot/" {} ""} + {3 "root-anchored but -Lpath" "/sysroot/" {} "cannot find"} + {3 "full-path" "@cwd@/sysroot/" {} ""} + {3 "root-anchored =-prefixed -Lpath" "=/sysroot/" {} "cannot find"} + {3 "full-path =-prefixed with empty" "=@cwd@/sysroot/" "--sysroot=" ""} + {3 "plain =-prefixed with empty" "=sysroot/" "--sysroot=" ""} + {2 "root-anchored but script outside sysroot" "/" "--sysroot=@cwd@/sysroot" "cannot find"} + {2 "root-anchored and script inside sysroot" "/sysroot/" "--sysroot=@cwd@" ""} + {2 "root-anchored =-prefixed script outside" "=/" "--sysroot=@cwd@/sysroot" ""} + {2 "root-anchored =-prefixed script inside" "=/sysroot/" "--sysroot=@cwd@" ""} + {2 "plain =-prefixed without but -Lpath" "=sysroot/" {} "cannot find"} + {2 "full-path =-prefixed without" "=@cwd@/sysroot/" {} "cannot find"} + {1 "plain =-prefixed -Lpath" "=sysroot/" {} ""} + {1 "full-path =-prefixed without" "=@cwd@/sysroot/" {} ""} +} + +# May have to provide a target-specific assembler option for some targets. +set gasopt "" + +# Intentionally similar to the ubiquitous glibc libc.so script. +set template "GROUP ( @q@@p@tmp/ldtest-xyzzy/libx.a@q@ AS_NEEDED ( @q@@p@tmp/ldtest-xyzzy/liby.a@q@ ) )" + +# Set up everything from the variables above. +proc sysroot_prefix_test_setup { } { + global as gasopt srcdir subdir ar + + if {![ld_assemble_flags $as $gasopt $srcdir/$subdir/pr14962a.s tmpdir/main.o]} { + error "Error assembling a trivial file for sysroot-prefix tests framework" + return 0 + } + + # We need somewhere under tmpdir to point the sysroot, a subdirectory + # that is benevolent if it escapes into "/". + remote_exec host "mkdir -p tmpdir/sysroot/tmp/ldtest-xyzzy" + + # 0: a "main" object that needs a symbol (x) (most portably by + # using a pre-existing file). 1: a library with an object that + # provides that symbol and needs another one (y). 2: another + # library with a third object providing that other symbol. + set sysroot_prefix_tests_framework_objects { + {"pr14962a.s" "main" ""} + {"sysroot-prefix-x.s" "x" "x"} + {"sysroot-prefix-y.s" "y" "y"} + } + + foreach test_object $sysroot_prefix_tests_framework_objects { + set sname [lindex $test_object 0] + set onamebase [lindex $test_object 1] + set oname "tmpdir/$onamebase.o" + set libnamebase [lindex $test_object 2] + + if ![ld_assemble_flags $as $gasopt $srcdir/$subdir/$sname $oname] { + error "Error assembling trivial file $sname for sysroot-prefix tests framework" + return 0 + } + + if { [string length $libnamebase] != 0 && + ![ar_simple_create $ar "" tmpdir/sysroot/tmp/ldtest-xyzzy/lib$libnamebase.a $oname] } { + error "Error creating archive $libnamebase for sysroot-prefix tests framework" + return 0 + } + } + + return 1 +} + +# Run a single linker test. +proc single_sysroot_prefix_test { type xtestname finalscript ldopt errstr } { + global ld exec_output with_sysroot + set scriptname "tmpdir/libsysroottest.a" + set testname "sysroot-prefix $xtestname" + + if { ($type & ($with_sysroot + 1)) == 0 } { + unsupported $testname + return + } + + if [catch { set ofd [open $scriptname w] } x] { + perror "$x" + unresolved $testname + return + } + + puts $ofd "$finalscript" + close $ofd + verbose -log "script: $finalscript" + + set res [ld_simple_link $ld tmpdir/output "$ldopt tmpdir/main.o -Ltmpdir -lsysroottest"] + set ld_output "$exec_output" + set expect_success [expr [string length $errstr] == 0] + + if { $res == $expect_success && + ($expect_success || [regexp "$errstr" $ld_output]) } { + pass $testname + catch "exec rm -f $scriptname" + } { + fail $testname + } +} + +# Run all interesting variants from an option-and-path combination. +proc run_sysroot_prefix_test { type name templ p ldopt errstr } { + global base_dir + set qlist { { "quoted" "\"" } { "unquoted" {} } } + + regsub -all "@p@" $templ $p templ + regsub -all "@cwd@" $templ "$base_dir/tmpdir" templ + regsub -all "@cwd@" $ldopt "$base_dir/tmpdir" ldopt + regsub -all "@cwd@" $name "" name + + foreach qitems $qlist { + regsub -all "@q@" $templ [lindex $qitems 1] finalscript + single_sysroot_prefix_test $type "$name, [lindex $qitems 0]" \ + $finalscript $ldopt $errstr + } +} + +# Run a list of option-and-path test-combinations. +proc run_sysroot_prefix_tests { descr templ items } { + foreach item $items { + set type [lindex $item 0] + set name [lindex $item 1] + set p [lindex $item 2] + set ldopt [lindex $item 3] + set errstr [lindex $item 4] + run_sysroot_prefix_test $type "$descr $name" $templ "$p" "$ldopt" "$errstr" + } +} + +if ![sysroot_prefix_test_setup] { + return +} + +run_sysroot_prefix_tests "common" $template $sysroot_prefix_tests diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index 292a873..ffdf805 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -1669,6 +1669,24 @@ proc check_plugin_api_available { } { return $plugin_api_available_saved } +# Returns true if the target ld supports sysroot. +proc check_sysroot_available { } { + global ld_sysroot_available_saved + global ld + if {![info exists ld_sysroot_available_saved]} { + # Check if ld supports --sysroot *other* than empty + # (non-sysroot linkers don't emit errors for --sysroot=""). + # The help-text by itself is no indication as it always lists --sysroot. + set status [remote_exec host $ld "--sysroot=ldxyzzy --help >/dev/null"] + if { [lindex $status 0] != 0 } { + set ld_sysroot_available_saved 0 + } else { + set ld_sysroot_available_saved 1 + } + } + return $ld_sysroot_available_saved +} + # Returns true if the target compiler supports LTO proc check_lto_available { } { global lto_available_saved -- 2.7.4