diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 3bf6972661..f5b45d8c86 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,16 @@ +2016-07-14 Andrew Burgess + + * objcopy.c (find_section_list): Handle section patterns starting + with '!' being a non-matching pattern. + * doc/binutils.texi (objcopy): Give example of using '!' with + --remove-section and --only-section. + (strip): Give example of using '!' with --remove-section. + * testsuite/binutils-all/data-sections.s: New file. + * testsuite/binutils-all/only-section-01.d: New file. + * testsuite/binutils-all/remove-section-01.d: New file. + * testsuite/binutils-all/objcopy.exp: Run new tests. + * NEWS: Mention new feature. + 2016-07-09 Alan Modra PR binutils/20337 diff --git a/binutils/NEWS b/binutils/NEWS index 5bc6888ab5..9625cf49e2 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,15 @@ -*- text -*- +* The --remove-section option for objcopy and strip now accepts section + patterns starting with an exclamation point to indicate a non-matching + section. A non-matching section is removed from the set of sections + matched by an earlier --remove-section pattern. + +* The --only-section option for objcopy now accepts section patterns + starting with an exclamation point to indicate a non-matching section. + A non-matching section is removed from the set of sections matched by + an earlier --only-section pattern. + Changes in 2.27: * Add a configure option, --enable-64-bit-archive, to force use of a diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 5a004a34ec..d77bc86b0f 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -1221,6 +1221,18 @@ This option may be given more than once. Note that using this option inappropriately may make the output file unusable. Wildcard characters are accepted in @var{sectionpattern}. +If the first character of @var{sectionpattern} is the exclamation +point (!) then matching sections will not be copied, even if earlier +use of @option{--only-section} on the same command line would +otherwise copy it. For example: + +@smallexample + --only-section=.text.* --only-section=!.text.foo +@end smallexample + +will copy all sectinos maching '.text.*' but not the section +'.text.foo'. + @item -R @var{sectionpattern} @itemx --remove-section=@var{sectionpattern} Remove any section matching @var{sectionpattern} from the output file. @@ -1230,6 +1242,18 @@ characters are accepted in @var{sectionpattern}. Using both the @option{-j} and @option{-R} options together results in undefined behaviour. +If the first character of @var{sectionpattern} is the exclamation +point (!) then matching sections will not be removed even if an +earlier use of @option{--remove-section} on the same command line +would otherwise remove it. For example: + +@smallexample + --remove-section=.text.* --remove-section=!.text.foo +@end smallexample + +will remove all sections matching the pattern '.text.*', but will not +remove the section '.text.foo'. + @item -S @itemx --strip-all Do not copy relocation and symbol information from the source file. @@ -3021,6 +3045,18 @@ inappropriately may make the output file unusable. The wildcard character @samp{*} may be given at the end of @var{sectionname}. If so, then any section starting with @var{sectionname} will be removed. +If the first character of @var{sectionpattern} is the exclamation +point (!) then matching sections will not be removed even if an +earlier use of @option{--remove-section} on the same command line +would otherwise remove it. For example: + +@smallexample + --remove-section=.text.* --remove-section=!.text.foo +@end smallexample + +will remove all sections matching the pattern '.text.*', but will not +remove the section '.text.foo'. + @item -s @itemx --strip-all Remove all symbols. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 4bb625a039..41ccc761d5 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -854,7 +854,7 @@ parse_symflags (const char *s, char **other) static struct section_list * find_section_list (const char *name, bfd_boolean add, unsigned int context) { - struct section_list *p; + struct section_list *p, *match = NULL; /* assert ((context & ((1 << 7) - 1)) != 0); */ @@ -890,19 +890,36 @@ find_section_list (const char *name, bfd_boolean add, unsigned int context) } /* If we are not adding a new name/pattern then only check for a match if the context applies. */ - else if ((p->context & context) - /* We could check for the presence of wildchar characters - first and choose between calling strcmp and fnmatch, - but is that really worth it ? */ - && fnmatch (p->pattern, name, 0) == 0) - { - p->used = TRUE; - return p; - } + else if (p->context & context) + { + /* We could check for the presence of wildchar characters + first and choose between calling strcmp and fnmatch, + but is that really worth it ? */ + if (p->pattern [0] == '!') + { + if (fnmatch (p->pattern + 1, name, 0) == 0) + { + p->used = TRUE; + return NULL; + } + } + else + { + if (fnmatch (p->pattern, name, 0) == 0) + { + if (match == NULL) + match = p; + } + } + } } if (! add) - return NULL; + { + if (match != NULL) + match->used = TRUE; + return match; + } p = (struct section_list *) xmalloc (sizeof (struct section_list)); p->pattern = name; diff --git a/binutils/testsuite/binutils-all/data-sections.s b/binutils/testsuite/binutils-all/data-sections.s new file mode 100644 index 0000000000..0d6284c678 --- /dev/null +++ b/binutils/testsuite/binutils-all/data-sections.s @@ -0,0 +1,17 @@ + .section ".data.aa.01", "aw" + .word 0x1 + + .section ".data.aa.02", "aw" + .word 0x2 + + .section ".data.aa.03", "aw" + .word 0x3 + + .section ".data.bb.01", "aw" + .word 0x4 + + .section ".data.bb.02", "aw" + .word 0x5 + + .section ".data.bb.03", "aw" + .word 0x6 diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index ccd4422101..be8a7d2b50 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -1118,6 +1118,9 @@ if [is_elf_format] { run_dump_test "exclude-1a" run_dump_test "exclude-1b" + + run_dump_test "only-section-01" + run_dump_test "remove-section-01" } run_dump_test "localize-hidden-2" diff --git a/binutils/testsuite/binutils-all/only-section-01.d b/binutils/testsuite/binutils-all/only-section-01.d new file mode 100644 index 0000000000..0e71430a6d --- /dev/null +++ b/binutils/testsuite/binutils-all/only-section-01.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#source: data-sections.s +#objcopy: --only-section=.data.aa.* --only-section=!.data.aa.02 +#readelf: -WS + +#... + \[ [0-9]+\] .data.aa.01.* + \[ [0-9]+\] .data.aa.03.* +#... diff --git a/binutils/testsuite/binutils-all/remove-section-01.d b/binutils/testsuite/binutils-all/remove-section-01.d new file mode 100644 index 0000000000..b2837b2870 --- /dev/null +++ b/binutils/testsuite/binutils-all/remove-section-01.d @@ -0,0 +1,8 @@ +#PROG: objcopy +#source: data-sections.s +#objcopy: --remove-section=.data.aa.* --remove-section=!.data.aa.02 +#readelf: -WS + +#... + \[ [0-9]+\] \.data\.aa\.02.* +#...