diff --git a/ld/ChangeLog b/ld/ChangeLog index 3098b4cf75..577af33056 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,32 @@ +2016-11-04 Andrew Burgess + + * ldlang.h (struct lang_wild_statement_struct): Add + exclude_name_list field. + * ldlang.c (walk_wild_file_in_exclude_list): New function. + (walk_wild_consider_section): Use new + walk_wild_file_in_exclude_list function. + (walk_wild_file): Add call to walk_wild_file_in_exclude_list. + (print_wild_statement): Print new exclude_name_list field. + (lang_add_wild): Initialise new exclude_name_list field. + * testsuite/ld-scripts/exclude-file-1.d: New file. + * testsuite/ld-scripts/exclude-file-1.map: New file. + * testsuite/ld-scripts/exclude-file-1.t: New file. + * testsuite/ld-scripts/exclude-file-2.d: New file. + * testsuite/ld-scripts/exclude-file-2.map: New file. + * testsuite/ld-scripts/exclude-file-2.t: New file. + * testsuite/ld-scripts/exclude-file-3.d: New file. + * testsuite/ld-scripts/exclude-file-3.map: New file. + * testsuite/ld-scripts/exclude-file-3.t: New file. + * testsuite/ld-scripts/exclude-file-4.d: New file. + * testsuite/ld-scripts/exclude-file-4.map: New file. + * testsuite/ld-scripts/exclude-file-4.t: New file. + * testsuite/ld-scripts/exclude-file-a.s: New file. + * testsuite/ld-scripts/exclude-file-b.s: New file. + * testsuite/ld-scripts/exclude-file.exp: New file. + * ld.texinfo (Input Section Basics): Update description of + EXCLUDE_FILE to cover the new features. + * NEWS: Mention new EXCLUDE_FILE usage. + 2016-11-04 Andrew Burgess * testsuite/lib/ld-lib.exp (run_dump_test): Use object file names diff --git a/ld/NEWS b/ld/NEWS index 0efa411243..f8bf58da7c 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,9 @@ -*- text -*- +* The EXCLUDE_FILE linker script construct can now be applied outside of the + section list in order for the exclusions to apply over all input sections in + the list. + * Add support for the RISC-V architecture. * The command line option --no-eh-frame-hdr can now be used in ELF based diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 6528b6a8f5..500fda6d76 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -4192,14 +4192,24 @@ include all input @samp{.text} sections, you would write: @end smallexample @noindent Here the @samp{*} is a wildcard which matches any file name. To exclude a list +@cindex EXCLUDE_FILE of files from matching the file name wildcard, EXCLUDE_FILE may be used to match all files except the ones specified in the EXCLUDE_FILE list. For example: @smallexample +EXCLUDE_FILE (*crtend.o *otherfile.o) *(.ctors) +@end smallexample +@noindent +will cause all .ctors sections from all files except @file{crtend.o} +and @file{otherfile.o} to be included. The EXCLUDE_FILE can also be +placed inside the section list, for example: +@smallexample *(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors) @end smallexample -will cause all .ctors sections from all files except @file{crtend.o} and -@file{otherfile.o} to be included. +@noindent +The result of this is identically to the previous example. Supporting +two syntaxes for EXCLUDE_FILE is useful if the section list contains +more than one section, as described below. There are two ways to include more than one section: @smallexample @@ -4214,8 +4224,9 @@ they are found in the linker input. In the second example, all @samp{.text} input sections will appear first, followed by all @samp{.rdata} input sections. -When using EXCLUDE_FILE with more than one section, the exclusion only -applies to the section immediately following, for example: +When using EXCLUDE_FILE with more than one section, if the exclusion +is within the section list then the exclusion only applies to the +immediately following section, for example: @smallexample *(EXCLUDE_FILE (*somefile.o) .text .rdata) @end smallexample @@ -4224,10 +4235,17 @@ will cause all @samp{.text} sections from all files except @file{somefile.o} to be included, while all @samp{.rdata} sections from all files, including @file{somefile.o}, will be included. To exclude the @samp{.rdata} sections from @file{somefile.o} the example -should be modified to: +could be modified to: @smallexample *(EXCLUDE_FILE (*somefile.o) .text EXCLUDE_FILE (*somefile.o) .rdata) @end smallexample +@noindent +Alternatively, placing the EXCLUDE_FILE outside of the section list, +before the input file selection, will cause the exclusion to apply for +all sections. Thus the previous example can be rewritten as: +@smallexample +EXCLUDE_FILE (*somefile.o) *(.text .rdata) +@end smallexample You can specify a file name to include sections from a particular file. You would do this if one or more of your files contain special data that diff --git a/ld/ldlang.c b/ld/ldlang.c index af2ca99638..7d495c0900 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -223,6 +223,43 @@ unique_section_p (const asection *sec, /* Generic traversal routines for finding matching sections. */ +/* Return true if FILE matches a pattern in EXCLUDE_LIST, otherwise return + false. */ + +static bfd_boolean +walk_wild_file_in_exclude_list (struct name_list *exclude_list, + lang_input_statement_type *file) +{ + struct name_list *list_tmp; + + for (list_tmp = exclude_list; + list_tmp; + list_tmp = list_tmp->next) + { + char *p = archive_path (list_tmp->name); + + if (p != NULL) + { + if (input_statement_is_archive_path (list_tmp->name, p, file)) + return TRUE; + } + + else if (name_match (list_tmp->name, file->filename) == 0) + return TRUE; + + /* FIXME: Perhaps remove the following at some stage? Matching + unadorned archives like this was never documented and has + been superceded by the archive:path syntax. */ + else if (file->the_bfd != NULL + && file->the_bfd->my_archive != NULL + && name_match (list_tmp->name, + file->the_bfd->my_archive->filename) == 0) + return TRUE; + } + + return FALSE; +} + /* Try processing a section against a wildcard. This just calls the callback unless the filename exclusion list is present and excludes the file. It's hardly ever present so this @@ -236,33 +273,9 @@ walk_wild_consider_section (lang_wild_statement_type *ptr, callback_t callback, void *data) { - struct name_list *list_tmp; - /* Don't process sections from files which were excluded. */ - for (list_tmp = sec->spec.exclude_name_list; - list_tmp; - list_tmp = list_tmp->next) - { - char *p = archive_path (list_tmp->name); - - if (p != NULL) - { - if (input_statement_is_archive_path (list_tmp->name, p, file)) - return; - } - - else if (name_match (list_tmp->name, file->filename) == 0) - return; - - /* FIXME: Perhaps remove the following at some stage? Matching - unadorned archives like this was never documented and has - been superceded by the archive:path syntax. */ - else if (file->the_bfd != NULL - && file->the_bfd->my_archive != NULL - && name_match (list_tmp->name, - file->the_bfd->my_archive->filename) == 0) - return; - } + if (walk_wild_file_in_exclude_list (sec->spec.exclude_name_list, file)) + return; (*callback) (ptr, sec, s, ptr->section_flag_list, file, data); } @@ -860,6 +873,9 @@ walk_wild_file (lang_wild_statement_type *s, callback_t callback, void *data) { + if (walk_wild_file_in_exclude_list (s->exclude_name_list, f)) + return; + if (f->the_bfd == NULL || !bfd_check_format (f->the_bfd, bfd_archive)) walk_wild_section (s, f, callback, data); @@ -4419,6 +4435,15 @@ print_wild_statement (lang_wild_statement_type *w, print_space (); + if (w->exclude_name_list) + { + name_list *tmp; + minfo ("EXCLUDE_FILE(%s", w->exclude_name_list->name); + for (tmp = w->exclude_name_list->next; tmp; tmp = tmp->next) + minfo (" %s", tmp->name); + minfo (") "); + } + if (w->filenames_sorted) minfo ("SORT("); if (w->filename != NULL) @@ -7073,11 +7098,13 @@ lang_add_wild (struct wildcard_spec *filespec, new_stmt->filename = NULL; new_stmt->filenames_sorted = FALSE; new_stmt->section_flag_list = NULL; + new_stmt->exclude_name_list = NULL; if (filespec != NULL) { new_stmt->filename = filespec->name; new_stmt->filenames_sorted = filespec->sorted == by_name; new_stmt->section_flag_list = filespec->section_flag_list; + new_stmt->exclude_name_list = filespec->exclude_name_list; } new_stmt->section_list = section_list; new_stmt->keep_sections = keep_sections; diff --git a/ld/ldlang.h b/ld/ldlang.h index 0cb147c562..b70eb99642 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -372,6 +372,7 @@ struct lang_wild_statement_struct struct wildcard_list *section_list; bfd_boolean keep_sections; lang_statement_list_type children; + struct name_list *exclude_name_list; walk_wild_section_handler_t walk_wild_section_handler; struct wildcard_list *handler_data[4]; diff --git a/ld/testsuite/ld-scripts/exclude-file-1.d b/ld/testsuite/ld-scripts/exclude-file-1.d new file mode 100644 index 0000000000..068ecac4af --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-1.d @@ -0,0 +1,5 @@ +#source: exclude-file-a.s +#source: exclude-file-b.s +#ld: -T exclude-file-1.t +#map: exclude-file-1.map + diff --git a/ld/testsuite/ld-scripts/exclude-file-1.map b/ld/testsuite/ld-scripts/exclude-file-1.map new file mode 100644 index 0000000000..0fbf601166 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-1.map @@ -0,0 +1,8 @@ +#... +\.data +0x[0-9a-f]+ +0x[0-9a-f]+ + \*\(EXCLUDE_FILE\(\*-b\.o\) \.data \.data\.\*\) + \.data +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + \.data\.1 +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + \.data\.1 +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-b\.o + +#... \ No newline at end of file diff --git a/ld/testsuite/ld-scripts/exclude-file-1.t b/ld/testsuite/ld-scripts/exclude-file-1.t new file mode 100644 index 0000000000..f75e6c386f --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-1.t @@ -0,0 +1,10 @@ +SECTIONS +{ + .data : { + * (EXCLUDE_FILE (*-b.o) .data .data.*) + } + + /DISCARD/ : { + * (*) + } +} diff --git a/ld/testsuite/ld-scripts/exclude-file-2.d b/ld/testsuite/ld-scripts/exclude-file-2.d new file mode 100644 index 0000000000..7c62c2f1e0 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-2.d @@ -0,0 +1,5 @@ +#source: exclude-file-a.s +#source: exclude-file-b.s +#ld: -T exclude-file-2.t +#map: exclude-file-2.map + diff --git a/ld/testsuite/ld-scripts/exclude-file-2.map b/ld/testsuite/ld-scripts/exclude-file-2.map new file mode 100644 index 0000000000..67acfe7535 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-2.map @@ -0,0 +1,7 @@ +#... +\.data +0x[0-9a-f]+ +0x[0-9a-f]+ + \*\(EXCLUDE_FILE\(\*-b\.o\) \.data EXCLUDE_FILE\(\*-b\.o\) \.data\.\*\) + \.data +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + \.data\.1 +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + +#... \ No newline at end of file diff --git a/ld/testsuite/ld-scripts/exclude-file-2.t b/ld/testsuite/ld-scripts/exclude-file-2.t new file mode 100644 index 0000000000..efdb5c0cc0 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-2.t @@ -0,0 +1,10 @@ +SECTIONS +{ + .data : { + * (EXCLUDE_FILE (*-b.o) .data EXCLUDE_FILE (*-b.o) .data.*) + } + + /DISCARD/ : { + * (*) + } +} diff --git a/ld/testsuite/ld-scripts/exclude-file-3.d b/ld/testsuite/ld-scripts/exclude-file-3.d new file mode 100644 index 0000000000..19bfc4f1e9 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-3.d @@ -0,0 +1,5 @@ +#source: exclude-file-a.s +#source: exclude-file-b.s +#ld: -T exclude-file-3.t +#map: exclude-file-3.map + diff --git a/ld/testsuite/ld-scripts/exclude-file-3.map b/ld/testsuite/ld-scripts/exclude-file-3.map new file mode 100644 index 0000000000..389d1708c9 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-3.map @@ -0,0 +1,7 @@ +#... +\.data +0x[0-9a-f]+ +0x[0-9a-f]+ + EXCLUDE_FILE\(\*-b\.o\) \*\(\.data \.data\.\*\) + \.data +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + \.data\.1 +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + +#... \ No newline at end of file diff --git a/ld/testsuite/ld-scripts/exclude-file-3.t b/ld/testsuite/ld-scripts/exclude-file-3.t new file mode 100644 index 0000000000..4d4be5852b --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-3.t @@ -0,0 +1,10 @@ +SECTIONS +{ + .data : { + EXCLUDE_FILE (*-b.o) * (.data .data.*) + } + + /DISCARD/ : { + * (*) + } +} diff --git a/ld/testsuite/ld-scripts/exclude-file-4.d b/ld/testsuite/ld-scripts/exclude-file-4.d new file mode 100644 index 0000000000..b087feea1c --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-4.d @@ -0,0 +1,5 @@ +#source: exclude-file-a.s +#source: exclude-file-b.s +#ld: -T exclude-file-4.t +#map: exclude-file-4.map + diff --git a/ld/testsuite/ld-scripts/exclude-file-4.map b/ld/testsuite/ld-scripts/exclude-file-4.map new file mode 100644 index 0000000000..8549283e0c --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-4.map @@ -0,0 +1,7 @@ +#... +\.data +0x[0-9a-f]+ +0x[0-9a-f]+ + \*\(EXCLUDE_FILE\(\*-b\.o\) \.data EXCLUDE_FILE\(\*-a\.o\) \.data\.\*\) + \.data +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-a\.o + \.data\.1 +0x[0-9a-f]+ +0x[0-9a-f]+ tmpdir/exclude-file-b\.o + +#... \ No newline at end of file diff --git a/ld/testsuite/ld-scripts/exclude-file-4.t b/ld/testsuite/ld-scripts/exclude-file-4.t new file mode 100644 index 0000000000..a9b03c4d73 --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-4.t @@ -0,0 +1,10 @@ +SECTIONS +{ + .data : { + * (EXCLUDE_FILE (*-b.o) .data EXCLUDE_FILE (*-a.o) .data.*) + } + + /DISCARD/ : { + * (*) + } +} diff --git a/ld/testsuite/ld-scripts/exclude-file-a.s b/ld/testsuite/ld-scripts/exclude-file-a.s new file mode 100644 index 0000000000..19f5def47a --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-a.s @@ -0,0 +1,5 @@ + .section ".data", "aw" + .word 0x0 + + .section ".data.1", "aw" + .word 0x0 diff --git a/ld/testsuite/ld-scripts/exclude-file-b.s b/ld/testsuite/ld-scripts/exclude-file-b.s new file mode 100644 index 0000000000..19f5def47a --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file-b.s @@ -0,0 +1,5 @@ + .section ".data", "aw" + .word 0x0 + + .section ".data.1", "aw" + .word 0x0 diff --git a/ld/testsuite/ld-scripts/exclude-file.exp b/ld/testsuite/ld-scripts/exclude-file.exp new file mode 100644 index 0000000000..79fba1718a --- /dev/null +++ b/ld/testsuite/ld-scripts/exclude-file.exp @@ -0,0 +1,32 @@ +# Test EXCLUDE_FILE in a linker script. +# By Nathan Sidwell, CodeSourcery LLC +# Copyright (C) 2004-2016 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. + +if { ![is_elf_format] } then { + unsupported exclude-file.exp + return +} + +set test_list [lsort [glob -nocomplain $srcdir/$subdir/exclude-file-*.d]] +foreach t $test_list { + # We need to strip the ".d", but can leave the dirname. + verbose [file rootname $t] + run_dump_test [file rootname $t] +}