From 64f52b3ec1853d14293d5a461d7abc8bde5e3f62 Mon Sep 17 00:00:00 2001 From: =?utf8?q?F=C4=81ng-ru=C3=AC=20S=C3=B2ng?= Date: Fri, 1 Nov 2019 14:47:55 -0700 Subject: [PATCH] Implement objcopy/strip --keep-section= llvm-objcopy and llvm-strip support an option --keep-section that keeps some sections from being removed. * objcopy.c (enum option_values): Add OPTION_KEEP_SECTION. (SECTION_CONTEXT_KEEP): Define. Adjust other SECTION_CONTEXT macros. (copy_usage): Describe --keep-section. (strip_usage): Likewise. (copy_main): Handle SECTION_CONTEXT_KEEP. (strip_main): Likewise. (is_strip_section_1): Likewise. * testsuite/binutils-all/objcopy.exp: Add tests. * testsuite/binutils-all/keep-section-1.d: New test driver file. * testsuite/binutils-all/keep-section-2.d: Likewise. * doc/binutils.texi: Document the new feature. * NEWS: Mention the new feature. --- binutils/ChangeLog | 15 +++++++++ binutils/NEWS | 3 ++ binutils/doc/binutils.texi | 10 ++++++ binutils/objcopy.c | 31 ++++++++++++++----- .../testsuite/binutils-all/keep-section-1.d | 8 +++++ .../testsuite/binutils-all/keep-section-2.d | 10 ++++++ binutils/testsuite/binutils-all/objcopy.exp | 3 ++ 7 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 binutils/testsuite/binutils-all/keep-section-1.d create mode 100644 binutils/testsuite/binutils-all/keep-section-2.d diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 36b75c1f3ce..0f5d06b5a69 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,18 @@ +2019-11-04 Fangrui Song + + * objcopy.c (enum option_values): Add OPTION_KEEP_SECTION. + (SECTION_CONTEXT_KEEP): Define. Adjust other SECTION_CONTEXT macros. + (copy_usage): Describe --keep-section. + (strip_usage): Likewise. + (copy_main): Handle SECTION_CONTEXT_KEEP. + (strip_main): Likewise. + (is_strip_section_1): Likewise. + * testsuite/binutils-all/objcopy.exp: Add tests. + * testsuite/binutils-all/keep-section-1.d: New test driver file. + * testsuite/binutils-all/keep-section-2.d: Likewise. + * doc/binutils.texi: Document the new feature. + * NEWS: Mention the new feature. + 2019-10-20 Palmer Dabbelt * MAINTAINERS: Change palmer@sifive.com to palmer@dabbelt.com. diff --git a/binutils/NEWS b/binutils/NEWS index fd14d71ce92..88b048995a8 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -3,6 +3,9 @@ * Add --output option to the "ar" program. This option can be used to specify the output directory when extracting members from an archive. +* Add --keep-section option to objcopy and strip. This option keeps the + specified section from being removed. + Changes in 2.33: * Add --source-comment[=] option to objdump which if present, diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 97abf980ba8..2a86b92033a 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -1186,6 +1186,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}] [@option{--interleave-width=}@var{width}] [@option{-j} @var{sectionpattern}|@option{--only-section=}@var{sectionpattern}] [@option{-R} @var{sectionpattern}|@option{--remove-section=}@var{sectionpattern}] + [@option{--keep-section=}@var{sectionpattern}] [@option{--remove-relocations=}@var{sectionpattern}] [@option{-p}|@option{--preserve-dates}] [@option{-D}|@option{--enable-deterministic-archives}] @@ -1369,6 +1370,10 @@ would otherwise remove it. For example: will remove all sections matching the pattern '.text.*', but will not remove the section '.text.foo'. +@item --keep-section=@var{sectionpattern} +When removing sections from the output file, keep sections that match +@var{sectionpattern}. + @item --remove-relocations=@var{sectionpattern} Remove non-dynamic relocations from the output file for any section matching @var{sectionpattern}. This option may be given more than @@ -3242,6 +3247,7 @@ strip [@option{-F} @var{bfdname} |@option{--target=}@var{bfdname}] [@option{-w}|@option{--wildcard}] [@option{-x}|@option{--discard-all}] [@option{-X} |@option{--discard-locals}] [@option{-R} @var{sectionname} |@option{--remove-section=}@var{sectionname}] + [@option{--keep-section=}@var{sectionpattern}] [@option{--remove-relocations=}@var{sectionpattern}] [@option{-o} @var{file}] [@option{-p}|@option{--preserve-dates}] [@option{-D}|@option{--enable-deterministic-archives}] @@ -3312,6 +3318,10 @@ would otherwise remove it. For example: will remove all sections matching the pattern '.text.*', but will not remove the section '.text.foo'. +@item --keep-section=@var{sectionpattern} +When removing sections from the output file, keep sections that match +@var{sectionpattern}. + @item --remove-relocations=@var{sectionpattern} Remove relocations from the output file for any section matching @var{sectionpattern}. This option may be given more than once. Note diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 7bdd4478931..56439700c22 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -143,13 +143,14 @@ struct section_list COPY and REMOVE are mutually exlusive. SET and ALTER are mutually exclusive. */ #define SECTION_CONTEXT_REMOVE (1 << 0) /* Remove this section. */ #define SECTION_CONTEXT_COPY (1 << 1) /* Copy this section, delete all non-copied section. */ -#define SECTION_CONTEXT_SET_VMA (1 << 2) /* Set the sections' VMA address. */ -#define SECTION_CONTEXT_ALTER_VMA (1 << 3) /* Increment or decrement the section's VMA address. */ -#define SECTION_CONTEXT_SET_LMA (1 << 4) /* Set the sections' LMA address. */ -#define SECTION_CONTEXT_ALTER_LMA (1 << 5) /* Increment or decrement the section's LMA address. */ -#define SECTION_CONTEXT_SET_FLAGS (1 << 6) /* Set the section's flags. */ -#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 7) /* Remove relocations for this section. */ -#define SECTION_CONTEXT_SET_ALIGNMENT (1 << 8) /* Set alignment for section. */ +#define SECTION_CONTEXT_KEEP (1 << 2) /* Keep this section. */ +#define SECTION_CONTEXT_SET_VMA (1 << 3) /* Set the sections' VMA address. */ +#define SECTION_CONTEXT_ALTER_VMA (1 << 4) /* Increment or decrement the section's VMA address. */ +#define SECTION_CONTEXT_SET_LMA (1 << 5) /* Set the sections' LMA address. */ +#define SECTION_CONTEXT_ALTER_LMA (1 << 6) /* Increment or decrement the section's LMA address. */ +#define SECTION_CONTEXT_SET_FLAGS (1 << 7) /* Set the section's flags. */ +#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 8) /* Remove relocations for this section. */ +#define SECTION_CONTEXT_SET_ALIGNMENT (1 << 9) /* Set alignment for section. */ bfd_vma vma_val; /* Amount to change by or set to. */ bfd_vma lma_val; /* Amount to change by or set to. */ @@ -332,6 +333,7 @@ enum command_line_switch OPTION_INTERLEAVE_WIDTH, OPTION_KEEPGLOBAL_SYMBOLS, OPTION_KEEP_FILE_SYMBOLS, + OPTION_KEEP_SECTION, OPTION_KEEP_SYMBOLS, OPTION_LOCALIZE_HIDDEN, OPTION_LOCALIZE_SYMBOLS, @@ -386,6 +388,7 @@ static struct option strip_options[] = {"input-format", required_argument, 0, 'I'}, /* Obsolete */ {"input-target", required_argument, 0, 'I'}, {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, + {"keep-section", required_argument, 0, OPTION_KEEP_SECTION}, {"keep-symbol", required_argument, 0, 'K'}, {"merge-notes", no_argument, 0, 'M'}, {"no-merge-notes", no_argument, 0, OPTION_NO_MERGE_NOTES}, @@ -457,6 +460,7 @@ static struct option copy_options[] = {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, {"keep-global-symbol", required_argument, 0, 'G'}, {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS}, + {"keep-section", required_argument, 0, OPTION_KEEP_SECTION}, {"keep-symbol", required_argument, 0, 'K'}, {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS}, {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN}, @@ -589,6 +593,7 @@ copy_usage (FILE *stream, int exit_status) --only-keep-debug Strip everything but the debug information\n\ --extract-dwo Copy only DWO sections\n\ --extract-symbol Remove section contents but keep symbols\n\ + --keep-section Do not strip section \n\ -K --keep-symbol Do not strip symbol \n\ --keep-file-symbols Do not strip file symbol(s)\n\ --localize-hidden Turn all ELF hidden symbols into locals\n\ @@ -722,6 +727,7 @@ strip_usage (FILE *stream, int exit_status) -M --merge-notes Remove redundant entries in note sections (default)\n\ --no-merge-notes Do not attempt to remove redundant notes\n\ -N --strip-symbol= Do not copy symbol \n\ + --keep-section= Do not strip section \n\ -K --keep-symbol= Do not strip symbol \n\ --keep-file-symbols Do not strip file symbol(s)\n\ -w --wildcard Permit wildcard in symbol comparison\n\ @@ -1311,6 +1317,10 @@ is_mergeable_note_section (bfd * abfd, asection * sec) static bfd_boolean is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { + if (find_section_list (bfd_section_name (sec), FALSE, SECTION_CONTEXT_KEEP) + != NULL) + return FALSE; + if (sections_removed || sections_copied) { struct section_list *p; @@ -4584,6 +4594,9 @@ strip_main (int argc, char *argv[]) case 'R': handle_remove_section_option (optarg); break; + case OPTION_KEEP_SECTION: + find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP); + break; case OPTION_REMOVE_RELOCS: handle_remove_relocations_option (optarg); break; @@ -5010,6 +5023,10 @@ copy_main (int argc, char *argv[]) handle_remove_section_option (optarg); break; + case OPTION_KEEP_SECTION: + find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP); + break; + case OPTION_REMOVE_RELOCS: handle_remove_relocations_option (optarg); break; diff --git a/binutils/testsuite/binutils-all/keep-section-1.d b/binutils/testsuite/binutils-all/keep-section-1.d new file mode 100644 index 00000000000..b28e29c1703 --- /dev/null +++ b/binutils/testsuite/binutils-all/keep-section-1.d @@ -0,0 +1,8 @@ +#PROG: objcopy +#source: data-sections.s +#objcopy: --remove-section=.data.aa.* --keep-section=.data.aa.02 +#readelf: -WS + +#... + \[ [0-9]+\] \.data\.aa\.02.* +#... diff --git a/binutils/testsuite/binutils-all/keep-section-2.d b/binutils/testsuite/binutils-all/keep-section-2.d new file mode 100644 index 00000000000..7fea62f149a --- /dev/null +++ b/binutils/testsuite/binutils-all/keep-section-2.d @@ -0,0 +1,10 @@ +#PROG: objcopy +#source: data-sections.s +#objcopy: --remove-section=.data.aa.* --keep-section=.data.aa.* +#readelf: -WS + +#... + \[ [0-9]+\] \.data\.aa\.01.* + \[ [0-9]+\] \.data\.aa\.02.* + \[ [0-9]+\] \.data\.aa\.03.* +#... diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index 6c4b0196ab7..6739ab7de84 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -1222,6 +1222,9 @@ if [is_elf_format] { run_dump_test "only-section-01" run_dump_test "remove-section-01" + run_dump_test "keep-section-1" + run_dump_test "keep-section-2" + # Test the remove relocation functionality set test_list [lsort [glob -nocomplain $srcdir/$subdir/remove-relocs-*.d]] foreach t $test_list { -- 2.30.2