Implement objcopy/strip --keep-section=<sectionpattern>

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.
This commit is contained in:
Fāng-ruì Sòng
2019-11-01 14:47:55 -07:00
committed by Alan Modra
parent 5e874de30b
commit 64f52b3ec1
7 changed files with 73 additions and 7 deletions

View File

@ -1,3 +1,18 @@
2019-11-04 Fangrui Song <maskray@google.com>
* 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 <palmer@sifive.com> 2019-10-20 Palmer Dabbelt <palmer@sifive.com>
* MAINTAINERS: Change palmer@sifive.com to palmer@dabbelt.com. * MAINTAINERS: Change palmer@sifive.com to palmer@dabbelt.com.

View File

@ -3,6 +3,9 @@
* Add --output option to the "ar" program. This option can be used to specify * Add --output option to the "ar" program. This option can be used to specify
the output directory when extracting members from an archive. 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: Changes in 2.33:
* Add --source-comment[=<txt>] option to objdump which if present, * Add --source-comment[=<txt>] option to objdump which if present,

View File

@ -1186,6 +1186,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
[@option{--interleave-width=}@var{width}] [@option{--interleave-width=}@var{width}]
[@option{-j} @var{sectionpattern}|@option{--only-section=}@var{sectionpattern}] [@option{-j} @var{sectionpattern}|@option{--only-section=}@var{sectionpattern}]
[@option{-R} @var{sectionpattern}|@option{--remove-section=}@var{sectionpattern}] [@option{-R} @var{sectionpattern}|@option{--remove-section=}@var{sectionpattern}]
[@option{--keep-section=}@var{sectionpattern}]
[@option{--remove-relocations=}@var{sectionpattern}] [@option{--remove-relocations=}@var{sectionpattern}]
[@option{-p}|@option{--preserve-dates}] [@option{-p}|@option{--preserve-dates}]
[@option{-D}|@option{--enable-deterministic-archives}] [@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 will remove all sections matching the pattern '.text.*', but will not
remove the section '.text.foo'. 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} @item --remove-relocations=@var{sectionpattern}
Remove non-dynamic relocations from the output file for any section Remove non-dynamic relocations from the output file for any section
matching @var{sectionpattern}. This option may be given more than 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{-w}|@option{--wildcard}]
[@option{-x}|@option{--discard-all}] [@option{-X} |@option{--discard-locals}] [@option{-x}|@option{--discard-all}] [@option{-X} |@option{--discard-locals}]
[@option{-R} @var{sectionname} |@option{--remove-section=}@var{sectionname}] [@option{-R} @var{sectionname} |@option{--remove-section=}@var{sectionname}]
[@option{--keep-section=}@var{sectionpattern}]
[@option{--remove-relocations=}@var{sectionpattern}] [@option{--remove-relocations=}@var{sectionpattern}]
[@option{-o} @var{file}] [@option{-p}|@option{--preserve-dates}] [@option{-o} @var{file}] [@option{-p}|@option{--preserve-dates}]
[@option{-D}|@option{--enable-deterministic-archives}] [@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 will remove all sections matching the pattern '.text.*', but will not
remove the section '.text.foo'. 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} @item --remove-relocations=@var{sectionpattern}
Remove relocations from the output file for any section matching Remove relocations from the output file for any section matching
@var{sectionpattern}. This option may be given more than once. Note @var{sectionpattern}. This option may be given more than once. Note

View File

@ -143,13 +143,14 @@ struct section_list
COPY and REMOVE are mutually exlusive. SET and ALTER are mutually exclusive. */ COPY and REMOVE are mutually exlusive. SET and ALTER are mutually exclusive. */
#define SECTION_CONTEXT_REMOVE (1 << 0) /* Remove this section. */ #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_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_KEEP (1 << 2) /* Keep this section. */
#define SECTION_CONTEXT_ALTER_VMA (1 << 3) /* Increment or decrement the section's VMA address. */ #define SECTION_CONTEXT_SET_VMA (1 << 3) /* Set the sections' VMA address. */
#define SECTION_CONTEXT_SET_LMA (1 << 4) /* Set the sections' LMA address. */ #define SECTION_CONTEXT_ALTER_VMA (1 << 4) /* Increment or decrement the section's VMA address. */
#define SECTION_CONTEXT_ALTER_LMA (1 << 5) /* Increment or decrement the section's LMA address. */ #define SECTION_CONTEXT_SET_LMA (1 << 5) /* Set the sections' LMA address. */
#define SECTION_CONTEXT_SET_FLAGS (1 << 6) /* Set the section's flags. */ #define SECTION_CONTEXT_ALTER_LMA (1 << 6) /* Increment or decrement the section's LMA address. */
#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 7) /* Remove relocations for this section. */ #define SECTION_CONTEXT_SET_FLAGS (1 << 7) /* Set the section's flags. */
#define SECTION_CONTEXT_SET_ALIGNMENT (1 << 8) /* Set alignment for section. */ #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 vma_val; /* Amount to change by or set to. */
bfd_vma lma_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_INTERLEAVE_WIDTH,
OPTION_KEEPGLOBAL_SYMBOLS, OPTION_KEEPGLOBAL_SYMBOLS,
OPTION_KEEP_FILE_SYMBOLS, OPTION_KEEP_FILE_SYMBOLS,
OPTION_KEEP_SECTION,
OPTION_KEEP_SYMBOLS, OPTION_KEEP_SYMBOLS,
OPTION_LOCALIZE_HIDDEN, OPTION_LOCALIZE_HIDDEN,
OPTION_LOCALIZE_SYMBOLS, OPTION_LOCALIZE_SYMBOLS,
@ -386,6 +388,7 @@ static struct option strip_options[] =
{"input-format", required_argument, 0, 'I'}, /* Obsolete */ {"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"input-target", required_argument, 0, 'I'}, {"input-target", required_argument, 0, 'I'},
{"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
{"keep-section", required_argument, 0, OPTION_KEEP_SECTION},
{"keep-symbol", required_argument, 0, 'K'}, {"keep-symbol", required_argument, 0, 'K'},
{"merge-notes", no_argument, 0, 'M'}, {"merge-notes", no_argument, 0, 'M'},
{"no-merge-notes", no_argument, 0, OPTION_NO_MERGE_NOTES}, {"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-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
{"keep-global-symbol", required_argument, 0, 'G'}, {"keep-global-symbol", required_argument, 0, 'G'},
{"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS}, {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
{"keep-section", required_argument, 0, OPTION_KEEP_SECTION},
{"keep-symbol", required_argument, 0, 'K'}, {"keep-symbol", required_argument, 0, 'K'},
{"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS}, {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
{"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN}, {"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\ --only-keep-debug Strip everything but the debug information\n\
--extract-dwo Copy only DWO sections\n\ --extract-dwo Copy only DWO sections\n\
--extract-symbol Remove section contents but keep symbols\n\ --extract-symbol Remove section contents but keep symbols\n\
--keep-section <name> Do not strip section <name>\n\
-K --keep-symbol <name> Do not strip symbol <name>\n\ -K --keep-symbol <name> Do not strip symbol <name>\n\
--keep-file-symbols Do not strip file symbol(s)\n\ --keep-file-symbols Do not strip file symbol(s)\n\
--localize-hidden Turn all ELF hidden symbols into locals\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\ -M --merge-notes Remove redundant entries in note sections (default)\n\
--no-merge-notes Do not attempt to remove redundant notes\n\ --no-merge-notes Do not attempt to remove redundant notes\n\
-N --strip-symbol=<name> Do not copy symbol <name>\n\ -N --strip-symbol=<name> Do not copy symbol <name>\n\
--keep-section=<name> Do not strip section <name>\n\
-K --keep-symbol=<name> Do not strip symbol <name>\n\ -K --keep-symbol=<name> Do not strip symbol <name>\n\
--keep-file-symbols Do not strip file symbol(s)\n\ --keep-file-symbols Do not strip file symbol(s)\n\
-w --wildcard Permit wildcard in symbol comparison\n\ -w --wildcard Permit wildcard in symbol comparison\n\
@ -1311,6 +1317,10 @@ is_mergeable_note_section (bfd * abfd, asection * sec)
static bfd_boolean static bfd_boolean
is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) 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) if (sections_removed || sections_copied)
{ {
struct section_list *p; struct section_list *p;
@ -4584,6 +4594,9 @@ strip_main (int argc, char *argv[])
case 'R': case 'R':
handle_remove_section_option (optarg); handle_remove_section_option (optarg);
break; break;
case OPTION_KEEP_SECTION:
find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP);
break;
case OPTION_REMOVE_RELOCS: case OPTION_REMOVE_RELOCS:
handle_remove_relocations_option (optarg); handle_remove_relocations_option (optarg);
break; break;
@ -5010,6 +5023,10 @@ copy_main (int argc, char *argv[])
handle_remove_section_option (optarg); handle_remove_section_option (optarg);
break; break;
case OPTION_KEEP_SECTION:
find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP);
break;
case OPTION_REMOVE_RELOCS: case OPTION_REMOVE_RELOCS:
handle_remove_relocations_option (optarg); handle_remove_relocations_option (optarg);
break; break;

View File

@ -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.*
#...

View File

@ -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.*
#...

View File

@ -1222,6 +1222,9 @@ if [is_elf_format] {
run_dump_test "only-section-01" run_dump_test "only-section-01"
run_dump_test "remove-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 # Test the remove relocation functionality
set test_list [lsort [glob -nocomplain $srcdir/$subdir/remove-relocs-*.d]] set test_list [lsort [glob -nocomplain $srcdir/$subdir/remove-relocs-*.d]]
foreach t $test_list { foreach t $test_list {