diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 22 | ||||
-rw-r--r-- | ld/NEWS | 3 | ||||
-rw-r--r-- | ld/ld.h | 1 | ||||
-rw-r--r-- | ld/ld.texinfo | 20 | ||||
-rw-r--r-- | ld/ldgram.y | 91 | ||||
-rw-r--r-- | ld/ldlang.c | 30 | ||||
-rw-r--r-- | ld/ldlang.h | 3 | ||||
-rw-r--r-- | ld/ldlex.l | 1 | ||||
-rw-r--r-- | ld/mri.c | 2 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/section-flags-1.s | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/section-flags-1.t | 21 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/section-flags-2.s | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/section-flags-2.t | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/section-flags.exp | 52 |
15 files changed, 269 insertions, 1 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 7ce5d7a..fbbb5bd 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,25 @@ +2011-07-11 Catherine Moore <clm@codesourcery.com> + + * ld.h (section_flag_list): Add field to struct wildcard_spec. + * ld.texinfo (INPUT_SECTION_FLAGS): Document. + * ldgram.y (flag_info_list, flag_info): Add to union. + (INPUT_SECTION_FLAGS): New token. + (wildcard_spec): Initialize section_flag_list to NULL for + each alternative. + (sect_flag_list, sect_flags): New rules. + (input_section_spec_no_keep): Add alternatives to recognize + sect_flags. + * ldlang.c (walk_wild_consider_section): Initialize + section_flag_info field of the section struct. + (lang_add_section): Check input section flags. + (lang_add_wild): Initialize section_flag_list field of + the statement struct. + * ldlang.h (lang_input_statement_struct): Add section_flag_list field. + (lang_wild_statement_struct): Likewise. + * ldlex.l (INPUT_SECTION_FLAGS): New token. + * mri.c (mri_draw_tree): Initialize section_flag_list to NULL. + * NEWS: Announce INPUT_SECTION_FLAGS enhancement. + 2011-07-09 H.J. Lu <hongjiu.lu@intel.com> PR ld/12942 @@ -1,5 +1,8 @@ -*- text -*- +* INPUT_SECTION_FLAGS has been added to the linker script language +to allow selection of input sections by section header section flags. + * Add support for the Tilera TILEPRO and TILE-Gx architectures. * Added SORT_BY_INIT_PRIORITY to the linker script language to permit @@ -96,6 +96,7 @@ struct wildcard_spec { const char *name; struct name_list *exclude_name_list; sort_type sorted; + struct flag_info *section_flag_list; }; struct wildcard_list { diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 5a8e190..4fb649a 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -3859,6 +3859,26 @@ needs to be at a particular location in memory. For example: data.o(.data) @end smallexample +To refine the sections that are included based on the section flags +of an input section, INPUT_SECTION_FLAGS may be used. + +Here is a simple example for using Section header flags for ELF sections: + +@smallexample +@group +SECTIONS @{ + .text : @{ INPUT_SECTION_FLAGS (SHF_MERGE & SHF_STRINGS) *(.text) @} + .text2 : @{ INPUT_SECTION_FLAGS (!SHF_WRITE) *(.text) @} +@} +@end group +@end smallexample + +In this example, the output section @samp{.text} will be comprised of any +input section matching the name *(.text) whose section header flags +@code{SHF_MERGE} and @code{SHF_STRINGS} are set. The output section +@samp{.text2} will be comprised of any input section matching the name *(.text) +whose section header flag @code{SHF_WRITE} is clear. + You can also specify files within archives by writing a pattern matching the archive, a colon, then the pattern matching the file, with no whitespace around the colon. diff --git a/ld/ldgram.y b/ld/ldgram.y index 3795ffe..36ccb5b 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -72,6 +72,8 @@ static int error_index; struct wildcard_spec wildcard; struct wildcard_list *wildcard_list; struct name_list *name_list; + struct flag_info_list *flag_info_list; + struct flag_info *flag_info; int token; union etree_union *etree; struct phdr_info @@ -93,6 +95,8 @@ static int error_index; %type <fill> fill_opt fill_exp %type <name_list> exclude_name_list %type <wildcard_list> file_NAME_list +%type <flag_info_list> sect_flag_list +%type <flag_info> sect_flags %type <name> memspec_opt casesymlist %type <name> memspec_at_opt %type <cname> wildcard_name @@ -150,7 +154,7 @@ static int error_index; %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START %token <name> VERS_TAG VERS_IDENTIFIER %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT -%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL +%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS %token EXCLUDE_FILE %token CONSTANT %type <versyms> vers_defns @@ -437,60 +441,121 @@ wildcard_spec: $$.name = $1; $$.sorted = none; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name { $$.name = $5; $$.sorted = none; $$.exclude_name_list = $3; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' wildcard_name ')' { $$.name = $3; $$.sorted = by_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' wildcard_name ')' { $$.name = $3; $$.sorted = by_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_name_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_alignment_name; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')' { $$.name = $5; $$.sorted = by_alignment; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; } | SORT_BY_NAME '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')' { $$.name = $7; $$.sorted = by_name; $$.exclude_name_list = $5; + $$.section_flag_list = NULL; } | SORT_BY_INIT_PRIORITY '(' wildcard_name ')' { $$.name = $3; $$.sorted = by_init_priority; $$.exclude_name_list = NULL; + $$.section_flag_list = NULL; + } + ; + +sect_flag_list: NAME + { + struct flag_info_list *n; + n = ((struct flag_info_list *) xmalloc (sizeof *n)); + if ($1[0] == '!') + { + n->with = without_flags; + n->name = &$1[1]; + } + else + { + n->with = with_flags; + n->name = $1; + } + n->valid = FALSE; + n->next = NULL; + $$ = n; + } + | sect_flag_list '&' NAME + { + struct flag_info_list *n; + n = ((struct flag_info_list *) xmalloc (sizeof *n)); + if ($3[0] == '!') + { + n->with = without_flags; + n->name = &$3[1]; + } + else + { + n->with = with_flags; + n->name = $3; + } + n->valid = FALSE; + n->next = $1; + $$ = n; + } + ; + +sect_flags: + INPUT_SECTION_FLAGS '(' sect_flag_list ')' + { + struct flag_info *n; + n = ((struct flag_info *) xmalloc (sizeof *n)); + n->flag_list = $3; + n->flags_initialized = FALSE; + n->not_with_flags = 0; + n->only_with_flags = 0; + $$ = n; } ; @@ -541,16 +606,40 @@ input_section_spec_no_keep: tmp.name = $1; tmp.exclude_name_list = NULL; tmp.sorted = none; + tmp.section_flag_list = NULL; + lang_add_wild (&tmp, NULL, ldgram_had_keep); + } + | sect_flags NAME + { + struct wildcard_spec tmp; + tmp.name = $2; + tmp.exclude_name_list = NULL; + tmp.sorted = none; + tmp.section_flag_list = $1; lang_add_wild (&tmp, NULL, ldgram_had_keep); } | '[' file_NAME_list ']' { lang_add_wild (NULL, $2, ldgram_had_keep); } + | sect_flags '[' file_NAME_list ']' + { + struct wildcard_spec tmp; + tmp.name = NULL; + tmp.exclude_name_list = NULL; + tmp.sorted = none; + tmp.section_flag_list = $1; + lang_add_wild (NULL, $3, ldgram_had_keep); + } | wildcard_spec '(' file_NAME_list ')' { lang_add_wild (&$1, $3, ldgram_had_keep); } + | sect_flags wildcard_spec '(' file_NAME_list ')' + { + $2.section_flag_list = $1; + lang_add_wild (&$2, $4, ldgram_had_keep); + } ; input_section_spec: diff --git a/ld/ldlang.c b/ld/ldlang.c index 860ce27..3e63eed 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -237,6 +237,9 @@ walk_wild_consider_section (lang_wild_statement_type *ptr, { struct name_list *list_tmp; + /* Propagate the section_flag_info from the wild statement to the section. */ + s->section_flag_info = ptr->section_flag_list; + /* Don't process sections from files which were excluded. */ for (list_tmp = sec->spec.exclude_name_list; list_tmp; @@ -2261,8 +2264,11 @@ lang_add_section (lang_statement_list_type *ptr, lang_output_section_statement_type *output) { flagword flags = section->flags; + struct flag_info *sflag_info = section->section_flag_info; + bfd_boolean discard; lang_input_section_type *new_section; + bfd *abfd = link_info.output_bfd; /* Discard sections marked with SEC_EXCLUDE. */ discard = (flags & SEC_EXCLUDE) != 0; @@ -2288,6 +2294,28 @@ lang_add_section (lang_statement_list_type *ptr, return; } + if (sflag_info) + { + if (sflag_info->flags_initialized == FALSE) + bfd_lookup_section_flags (&link_info, sflag_info); + + if (sflag_info->only_with_flags != 0 + && sflag_info->not_with_flags != 0 + && ((sflag_info->not_with_flags & flags) != 0 + || (sflag_info->only_with_flags & flags) + != sflag_info->only_with_flags)) + return; + + if (sflag_info->only_with_flags != 0 + && (sflag_info->only_with_flags & flags) + != sflag_info->only_with_flags) + return; + + if (sflag_info->not_with_flags != 0 + && (sflag_info->not_with_flags & flags) != 0) + return; + } + if (section->output_section != NULL) return; @@ -6719,10 +6747,12 @@ lang_add_wild (struct wildcard_spec *filespec, new_stmt = new_stat (lang_wild_statement, stat_ptr); new_stmt->filename = NULL; new_stmt->filenames_sorted = FALSE; + new_stmt->section_flag_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->section_list = section_list; new_stmt->keep_sections = keep_sections; diff --git a/ld/ldlang.h b/ld/ldlang.h index d172c34..a6d22ce 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -240,6 +240,8 @@ typedef struct lang_input_statement_struct bfd *the_bfd; + struct flag_info *section_flag_list; + /* Point to the next file - whatever it is, wanders up and down archives */ union lang_statement_union *next; @@ -337,6 +339,7 @@ struct lang_wild_statement_struct walk_wild_section_handler_t walk_wild_section_handler; struct wildcard_list *handler_data[4]; lang_section_bst_type *tree; + struct flag_info *section_flag_list; }; typedef struct lang_address_statement_struct @@ -313,6 +313,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* <BOTH,SCRIPT>"org" { RTOKEN(ORIGIN);} <BOTH,SCRIPT>"l" { RTOKEN( LENGTH);} <BOTH,SCRIPT>"len" { RTOKEN( LENGTH);} +<EXPRESSION,BOTH,SCRIPT>"INPUT_SECTION_FLAGS" { RTOKEN(INPUT_SECTION_FLAGS); } <EXPRESSION,BOTH,SCRIPT>"INCLUDE" { RTOKEN(INCLUDE);} <BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); } <EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);} @@ -215,6 +215,7 @@ mri_draw_tree (void) tmp->spec.name = p->name; tmp->spec.exclude_name_list = NULL; tmp->spec.sorted = none; + tmp->spec.section_flag_list = NULL; lang_add_wild (NULL, tmp, FALSE); /* If there is an alias for this section, add it too. */ @@ -226,6 +227,7 @@ mri_draw_tree (void) tmp->spec.name = aptr->name; tmp->spec.exclude_name_list = NULL; tmp->spec.sorted = none; + tmp->spec.section_flag_list = NULL; lang_add_wild (NULL, tmp, FALSE); } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 4fe8d0c..64c2d10 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-07-11 Catherine Moore <clm@cm00re.com> + + * ld-scripts/section-flags-1.s: New. + * ld-scripts/section-flags-1.t: New. + * ld-scripts/section-flags-2.s: New. + * ld-scripts/section-flags-2.t: New. + * ld-scripts/section-flags.exp: New. + 2011-07-11 Alan Modra <amodra@gmail.com> * ld-powerpc/tocopt2.s, * ld-powerpc/tocopt2.out, diff --git a/ld/testsuite/ld-scripts/section-flags-1.s b/ld/testsuite/ld-scripts/section-flags-1.s new file mode 100644 index 0000000..566e3c6 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-flags-1.s @@ -0,0 +1,2 @@ + .text + .space 16 diff --git a/ld/testsuite/ld-scripts/section-flags-1.t b/ld/testsuite/ld-scripts/section-flags-1.t new file mode 100644 index 0000000..3380489 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-flags-1.t @@ -0,0 +1,21 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x100000, LENGTH = 144M +} + +SECTIONS +{ + .text : + { + INPUT_SECTION_FLAGS (!SHF_TLS) *(.text .text.* .text_* .gnu.linkonce.t.*) + } >ram + + .text_vle : + { + INPUT_SECTION_FLAGS (SHF_MERGE & SHF_STRINGS & SHF_LINK_ORDER) *(.text .text.* .text_* .gnu.linkonce.t.*) + } >ram + .text_other : + { + INPUT_SECTION_FLAGS (SHF_MERGE & !SHF_STRINGS) *(.text .text.* .text_* .gnu.linkonce.t.*) + } +} diff --git a/ld/testsuite/ld-scripts/section-flags-2.s b/ld/testsuite/ld-scripts/section-flags-2.s new file mode 100644 index 0000000..566e3c6 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-flags-2.s @@ -0,0 +1,2 @@ + .text + .space 16 diff --git a/ld/testsuite/ld-scripts/section-flags-2.t b/ld/testsuite/ld-scripts/section-flags-2.t new file mode 100644 index 0000000..ca5ae63 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-flags-2.t @@ -0,0 +1,12 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x100000, LENGTH = 144M +} + +SECTIONS +{ + .text : + { + INPUT_SECTION_FLAGS (!SHF_TLS) *(EXCLUDE_FILE (section-flags-1.o) .text .text.* .text_* .gnu.linkonce.t.*) + } >ram +} diff --git a/ld/testsuite/ld-scripts/section-flags.exp b/ld/testsuite/ld-scripts/section-flags.exp new file mode 100644 index 0000000..700c3d3 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-flags.exp @@ -0,0 +1,52 @@ +# Test SECTION_FLAGS in a linker script. +# +# 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. + +set testname "SECTION_FLAGS-1" + + +# This test only works for ELF targets +if {! [is_elf_format]} { + unsupported $testname + return +} + +if ![ld_assemble $as $srcdir/$subdir/section-flags-1.s tmpdir/section-flags-1.o] { + unresolved $testname + return +} + +if ![ld_simple_link $ld tmpdir/section-flags-1 "-T $srcdir/$subdir/section-flags-1.t tmpdir/section-flags-1.o"] { + fail $testname + return +} + +pass $testname + +set testname "SECTION_FLAGS-2" +if ![ld_assemble $as $srcdir/$subdir/section-flags-2.s tmpdir/section-flags-2.o] { + unresolved $testname + return +} + +if ![ld_simple_link $ld tmpdir/section-flags-2 "-T $srcdir/$subdir/section-flags-2.t tmpdir/section-flags-1.o tmpdir/section-flags-2.o"] { + fail $testname + return +} + +pass $testname |