From 2e62b7218b7147ee409b1b0551d6ca9576b37746 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 15 Feb 2013 09:32:31 +0000 Subject: [PATCH] PR binutils/15033 * objcopy.c (enum change_action): Delete. (struct section_list): Delete remove, copy, change_vma, change_lma and set_flags fields. Add context field. (find_section_list): Add a context parameter. Add support for wildcard characters in section names. (is_strip_section): Check for sections being both copied and removed. (copy_object): Pass context to find_section_list. (setup_section): Likewise. (copy_section): Likewise. (copy_main): Likewise. * doc/binutils: Document the new behaviour. * NEWS: Mention the new feature --- binutils/ChangeLog | 17 +++ binutils/NEWS | 3 + binutils/doc/binutils.texi | 125 ++++++++-------- binutils/objcopy.c | 284 +++++++++++++++++++++++-------------- 4 files changed, 266 insertions(+), 163 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index e9d030eced6..54d4dab89ce 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,20 @@ +2013-02-15 Nick Clifton + + PR binutils/15033 + * objcopy.c (enum change_action): Delete. + (struct section_list): Delete remove, copy, change_vma, change_lma + and set_flags fields. Add context field. + (find_section_list): Add a context parameter. Add support for + wildcard characters in section names. + (is_strip_section): Check for sections being both copied and + removed. + (copy_object): Pass context to find_section_list. + (setup_section): Likewise. + (copy_section): Likewise. + (copy_main): Likewise. + * doc/binutils: Document the new behaviour. + * NEWS: Mention the new feature + 2013-02-14 Nick Clifton PR binutils/15125 diff --git a/binutils/NEWS b/binutils/NEWS index 91400435f89..3853275fba6 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,8 @@ -*- text -*- +* Objcopy now supports wildcard characters in command line options that take + section names. + * Add support for Altera Nios II. Changes in 2.23: diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index fbe1f060762..d733fdba9a1 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -1065,8 +1065,8 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}] [@option{-b} @var{byte}|@option{--byte=}@var{byte}] [@option{-i} [@var{breadth}]|@option{--interleave}[=@var{breadth}]] [@option{--interleave-width=}@var{width}] - [@option{-j} @var{sectionname}|@option{--only-section=}@var{sectionname}] - [@option{-R} @var{sectionname}|@option{--remove-section=}@var{sectionname}] + [@option{-j} @var{sectionpattern}|@option{--only-section=}@var{sectionpattern}] + [@option{-R} @var{sectionpattern}|@option{--remove-section=}@var{sectionpattern}] [@option{-p}|@option{--preserve-dates}] [@option{-D}|@option{--enable-deterministic-archives}] [@option{-U}|@option{--disable-deterministic-archives}] @@ -1076,11 +1076,11 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}] [@option{--set-start=}@var{val}] [@option{--adjust-start=}@var{incr}] [@option{--change-addresses=}@var{incr}] - [@option{--change-section-address} @var{section}@{=,+,-@}@var{val}] - [@option{--change-section-lma} @var{section}@{=,+,-@}@var{val}] - [@option{--change-section-vma} @var{section}@{=,+,-@}@var{val}] + [@option{--change-section-address} @var{sectionpattern}@{=,+,-@}@var{val}] + [@option{--change-section-lma} @var{sectionpattern}@{=,+,-@}@var{val}] + [@option{--change-section-vma} @var{sectionpattern}@{=,+,-@}@var{val}] [@option{--change-warnings}] [@option{--no-change-warnings}] - [@option{--set-section-flags} @var{section}=@var{flags}] + [@option{--set-section-flags} @var{sectionpattern}=@var{flags}] [@option{--add-section} @var{sectionname}=@var{filename}] [@option{--rename-section} @var{oldname}=@var{newname}[,@var{flags}]] [@option{--long-section-names} @{enable,disable,keep@}] @@ -1204,17 +1204,21 @@ called _binary_@var{objfile}_start, _binary_@var{objfile}_end and _binary_@var{objfile}_size. e.g. you can transform a picture file into an object file and then access it in your code using these symbols. -@item -j @var{sectionname} -@itemx --only-section=@var{sectionname} -Copy only the named section from the input file to the output file. +@item -j @var{sectionpattern} +@itemx --only-section=@var{sectionpattern} +Copy only the indicated sections from the input file to the output file. This option may be given more than once. Note that using this option -inappropriately may make the output file unusable. +inappropriately may make the output file unusable. Wildcard +characters are accepted in @var{sectionpattern}. -@item -R @var{sectionname} -@itemx --remove-section=@var{sectionname} -Remove any section named @var{sectionname} from the output file. This -option may be given more than once. Note that using this option -inappropriately may make the output file unusable. +@item -R @var{sectionpattern} +@itemx --remove-section=@var{sectionpattern} +Remove any section matching @var{sectionpattern} from the output file. +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}. Using both the +@option{-j} and @option{-R} options together results in undefined +behaviour. @item -S @itemx --strip-all @@ -1396,65 +1400,68 @@ relocate the sections; if the program expects sections to be loaded at a certain address, and this option is used to change the sections such that they are loaded at a different address, the program may fail. -@item --change-section-address @var{section}@{=,+,-@}@var{val} -@itemx --adjust-section-vma @var{section}@{=,+,-@}@var{val} +@item --change-section-address @var{sectionpattern}@{=,+,-@}@var{val} +@itemx --adjust-section-vma @var{sectionpattern}@{=,+,-@}@var{val} @cindex changing section address -Set or change both the VMA address and the LMA address of the named -@var{section}. If @samp{=} is used, the section address is set to -@var{val}. Otherwise, @var{val} is added to or subtracted from the -section address. See the comments under @option{--change-addresses}, -above. If @var{section} does not exist in the input file, a warning will -be issued, unless @option{--no-change-warnings} is used. +Set or change both the VMA address and the LMA address of any section +matching @var{sectionpattern}. If @samp{=} is used, the section +address is set to @var{val}. Otherwise, @var{val} is added to or +subtracted from the section address. See the comments under +@option{--change-addresses}, above. If @var{sectionpattern} does not +match any sections in the input file, a warning will be issued, unless +@option{--no-change-warnings} is used. -@item --change-section-lma @var{section}@{=,+,-@}@var{val} +@item --change-section-lma @var{sectionpattern}@{=,+,-@}@var{val} @cindex changing section LMA -Set or change the LMA address of the named @var{section}. The LMA -address is the address where the section will be loaded into memory at -program load time. Normally this is the same as the VMA address, which -is the address of the section at program run time, but on some systems, +Set or change the LMA address of any sections matching +@var{sectionpattern}. The LMA address is the address where the +section will be loaded into memory at program load time. Normally +this is the same as the VMA address, which is the address of the +section at program run time, but on some systems, especially those +where a program is held in ROM, the two can be different. If @samp{=} +is used, the section address is set to @var{val}. Otherwise, +@var{val} is added to or subtracted from the section address. See the +comments under @option{--change-addresses}, above. If +@var{sectionpattern} does not match any sections in the input file, a +warning will be issued, unless @option{--no-change-warnings} is used. + +@item --change-section-vma @var{sectionpattern}@{=,+,-@}@var{val} +@cindex changing section VMA +Set or change the VMA address of any section matching +@var{sectionpattern}. The VMA address is the address where the +section will be located once the program has started executing. +Normally this is the same as the LMA address, which is the address +where the section will be loaded into memory, but on some systems, especially those where a program is held in ROM, the two can be different. If @samp{=} is used, the section address is set to @var{val}. Otherwise, @var{val} is added to or subtracted from the section address. See the comments under @option{--change-addresses}, -above. If @var{section} does not exist in the input file, a warning -will be issued, unless @option{--no-change-warnings} is used. - -@item --change-section-vma @var{section}@{=,+,-@}@var{val} -@cindex changing section VMA -Set or change the VMA address of the named @var{section}. The VMA -address is the address where the section will be located once the -program has started executing. Normally this is the same as the LMA -address, which is the address where the section will be loaded into -memory, but on some systems, especially those where a program is held in -ROM, the two can be different. If @samp{=} is used, the section address -is set to @var{val}. Otherwise, @var{val} is added to or subtracted -from the section address. See the comments under -@option{--change-addresses}, above. If @var{section} does not exist in -the input file, a warning will be issued, unless +above. If @var{sectionpattern} does not match any sections in the +input file, a warning will be issued, unless @option{--no-change-warnings} is used. @item --change-warnings @itemx --adjust-warnings If @option{--change-section-address} or @option{--change-section-lma} or -@option{--change-section-vma} is used, and the named section does not -exist, issue a warning. This is the default. +@option{--change-section-vma} is used, and the section pattern does not +match any sections, issue a warning. This is the default. @item --no-change-warnings @itemx --no-adjust-warnings Do not issue a warning if @option{--change-section-address} or @option{--adjust-section-lma} or @option{--adjust-section-vma} is used, even -if the named section does not exist. - -@item --set-section-flags @var{section}=@var{flags} -Set the flags for the named section. The @var{flags} argument is a -comma separated string of flag names. The recognized names are -@samp{alloc}, @samp{contents}, @samp{load}, @samp{noload}, -@samp{readonly}, @samp{code}, @samp{data}, @samp{rom}, @samp{share}, and -@samp{debug}. You can set the @samp{contents} flag for a section which -does not have contents, but it is not meaningful to clear the -@samp{contents} flag of a section which does have contents--just remove -the section instead. Not all flags are meaningful for all object file -formats. +if the section pattern does not match any sections. + +@item --set-section-flags @var{sectionpattern}=@var{flags} +Set the flags for any sections matching @var{sectionpattern}. The +@var{flags} argument is a comma separated string of flag names. The +recognized names are @samp{alloc}, @samp{contents}, @samp{load}, +@samp{noload}, @samp{readonly}, @samp{code}, @samp{data}, @samp{rom}, +@samp{share}, and @samp{debug}. You can set the @samp{contents} flag +for a section which does not have contents, but it is not meaningful +to clear the @samp{contents} flag of a section which does have +contents--just remove the section instead. Not all flags are +meaningful for all object file formats. @item --add-section @var{sectionname}=@var{filename} Add a new section named @var{sectionname} while copying the file. The @@ -2787,7 +2794,9 @@ Replace @var{objfile} with a file in the output format @var{bfdname}. @itemx --remove-section=@var{sectionname} Remove any section named @var{sectionname} from the output file. This option may be given more than once. Note that using this option -inappropriately may make the output file unusable. +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. @item -s @itemx --strip-all diff --git a/binutils/objcopy.c b/binutils/objcopy.c index ca372889bea..288aa52f3c4 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1,7 +1,5 @@ /* objcopy.c -- copy object file from input to output, optionally massaging it. - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 - Free Software Foundation, Inc. + Copyright 1991-2013 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -114,27 +112,26 @@ enum locals_action /* Which local symbols to remove. Overrides STRIP_ALL. */ static enum locals_action discard_locals; -/* What kind of change to perform. */ -enum change_action -{ - CHANGE_IGNORE, - CHANGE_MODIFY, - CHANGE_SET -}; - /* Structure used to hold lists of sections and actions to take. */ struct section_list { struct section_list * next; /* Next section to change. */ - const char * name; /* Section name. */ + const char * pattern; /* Section name pattern. */ bfd_boolean used; /* Whether this entry was used. */ - bfd_boolean remove; /* Whether to remove this section. */ - bfd_boolean copy; /* Whether to copy this section. */ - enum change_action change_vma;/* Whether to change or set VMA. */ + + unsigned int context; /* What to do with matching sections. */ + /* Flag bits used in the context field. + 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. */ + bfd_vma vma_val; /* Amount to change by or set to. */ - enum change_action change_lma;/* Whether to change or set LMA. */ bfd_vma lma_val; /* Amount to change by or set to. */ - bfd_boolean set_flags; /* Whether to set the section flags. */ flagword flags; /* What to set the section flags to. */ }; @@ -712,32 +709,93 @@ parse_flags (const char *s) return ret; } -/* Find and optionally add an entry in the change_sections list. */ +/* Find and optionally add an entry in the change_sections list. + + We need to be careful in how we match section names because of the support + for wildcard characters. For example suppose that the user has invoked + objcopy like this: + + --set-section-flags .debug_*=debug + --set-section-flags .debug_str=readonly,debug + --change-section-address .debug_*ranges=0x1000 + + With the idea that all debug sections will receive the DEBUG flag, the + .debug_str section will also receive the READONLY flag and the + .debug_ranges and .debug_aranges sections will have their address set to + 0x1000. (This may not make much sense, but it is just an example). + + When adding the section name patterns to the section list we need to make + sure that previous entries do not match with the new entry, unless the + match is exact. (In which case we assume that the user is overriding + the previous entry with the new context). + + When matching real section names to the section list we make use of the + wildcard characters, but we must do so in context. Eg if we are setting + section addresses then we match for .debug_ranges but not for .debug_info. + + Finally, if ADD is false and we do find a match, we mark the section list + entry as used. */ static struct section_list * -find_section_list (const char *name, bfd_boolean add) +find_section_list (const char *name, bfd_boolean add, unsigned int context) { struct section_list *p; + /* assert ((context & ((1 << 7) - 1)) != 0); */ + for (p = change_sections; p != NULL; p = p->next) - if (strcmp (p->name, name) == 0) - return p; + { + if (add) + { + if (strcmp (p->pattern, name) == 0) + { + /* Check for context conflicts. */ + if (((p->context & SECTION_CONTEXT_REMOVE) + && (context & SECTION_CONTEXT_COPY)) + || ((context & SECTION_CONTEXT_REMOVE) + && (p->context & SECTION_CONTEXT_COPY))) + fatal (_("error: %s both copied and removed"), name); + + if (((p->context & SECTION_CONTEXT_SET_VMA) + && (context & SECTION_CONTEXT_ALTER_VMA)) + || ((context & SECTION_CONTEXT_SET_VMA) + && (context & SECTION_CONTEXT_ALTER_VMA))) + fatal (_("error: %s both sets and alters VMA"), name); + + if (((p->context & SECTION_CONTEXT_SET_LMA) + && (context & SECTION_CONTEXT_ALTER_LMA)) + || ((context & SECTION_CONTEXT_SET_LMA) + && (context & SECTION_CONTEXT_ALTER_LMA))) + fatal (_("error: %s both sets and alters LMA"), name); + + /* Extend the context. */ + p->context |= context; + return p; + } + } + /* 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; + } + } if (! add) return NULL; p = (struct section_list *) xmalloc (sizeof (struct section_list)); - p->name = name; + p->pattern = name; p->used = FALSE; - p->remove = FALSE; - p->copy = FALSE; - p->change_vma = CHANGE_IGNORE; - p->change_lma = CHANGE_IGNORE; + p->context = context; p->vma_val = 0; p->lma_val = 0; - p->set_flags = FALSE; p->flags = 0; - p->next = change_sections; change_sections = p; @@ -988,12 +1046,20 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) if (sections_removed || sections_copied) { struct section_list *p; + struct section_list *q; - p = find_section_list (bfd_get_section_name (abfd, sec), FALSE); + p = find_section_list (bfd_get_section_name (abfd, sec), FALSE, + SECTION_CONTEXT_REMOVE); + q = find_section_list (bfd_get_section_name (abfd, sec), FALSE, + SECTION_CONTEXT_COPY); - if (sections_removed && p != NULL && p->remove) + if (p && q) + fatal (_("error: section %s matches both remove and copy options"), + bfd_get_section_name (abfd, sec)); + + if (p != NULL) return TRUE; - if (sections_copied && (p == NULL || ! p->copy)) + if (sections_copied && q == NULL) return TRUE; } @@ -1696,13 +1762,12 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) { flagword flags; - pset = find_section_list (padd->name, FALSE); + pset = find_section_list (padd->name, FALSE, + SECTION_CONTEXT_SET_FLAGS); if (pset != NULL) - pset->used = TRUE; - - flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; - if (pset != NULL && pset->set_flags) flags = pset->flags | SEC_HAS_CONTENTS; + else + flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; /* bfd_make_section_with_flags() does not return very helpful error codes, so check for the most likely user error first. */ @@ -1735,27 +1800,27 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) return FALSE; } + pset = find_section_list (padd->name, FALSE, + SECTION_CONTEXT_SET_VMA | SECTION_CONTEXT_ALTER_VMA); + if (pset != NULL + && ! bfd_set_section_vma (obfd, padd->section, pset->vma_val)) + { + bfd_nonfatal_message (NULL, obfd, padd->section, NULL); + return FALSE; + } + + pset = find_section_list (padd->name, FALSE, + SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_ALTER_LMA); if (pset != NULL) { - if (pset->change_vma != CHANGE_IGNORE) - if (! bfd_set_section_vma (obfd, padd->section, - pset->vma_val)) - { - bfd_nonfatal_message (NULL, obfd, padd->section, NULL); - return FALSE; - } + padd->section->lma = pset->lma_val; - if (pset->change_lma != CHANGE_IGNORE) + if (! bfd_set_section_alignment + (obfd, padd->section, + bfd_section_alignment (obfd, padd->section))) { - padd->section->lma = pset->lma_val; - - if (! bfd_set_section_alignment - (obfd, padd->section, - bfd_section_alignment (obfd, padd->section))) - { - bfd_nonfatal_message (NULL, obfd, padd->section, NULL); - return FALSE; - } + bfd_nonfatal_message (NULL, obfd, padd->section, NULL); + return FALSE; } } } @@ -2531,10 +2596,6 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) if (is_strip_section (ibfd, isection)) return; - p = find_section_list (bfd_section_name (ibfd, isection), FALSE); - if (p != NULL) - p->used = TRUE; - /* Get the, possibly new, name of the output section. */ name = find_section_rename (ibfd, isection, & flags); @@ -2556,7 +2617,10 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) } make_nobits = FALSE; - if (p != NULL && p->set_flags) + + p = find_section_list (bfd_section_name (ibfd, isection), FALSE, + SECTION_CONTEXT_SET_FLAGS); + if (p != NULL) flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC)); else if (strip_symbols == STRIP_NONDEBUG && (flags & (SEC_ALLOC | SEC_GROUP)) != 0 @@ -2599,10 +2663,15 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) } vma = bfd_section_vma (ibfd, isection); - if (p != NULL && p->change_vma == CHANGE_MODIFY) - vma += p->vma_val; - else if (p != NULL && p->change_vma == CHANGE_SET) - vma = p->vma_val; + p = find_section_list (bfd_section_name (ibfd, isection), FALSE, + SECTION_CONTEXT_ALTER_VMA | SECTION_CONTEXT_SET_VMA); + if (p != NULL) + { + if (p->context & SECTION_CONTEXT_SET_VMA) + vma = p->vma_val; + else + vma += p->vma_val; + } else vma += change_section_address; @@ -2613,14 +2682,14 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) } lma = isection->lma; - if ((p != NULL) && p->change_lma != CHANGE_IGNORE) + p = find_section_list (bfd_section_name (ibfd, isection), FALSE, + SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_SET_LMA); + if (p != NULL) { - if (p->change_lma == CHANGE_MODIFY) + if (p->context & SECTION_CONTEXT_ALTER_LMA) lma += p->lma_val; - else if (p->change_lma == CHANGE_SET) - lma = p->lma_val; else - abort (); + lma = p->lma_val; } else lma += change_section_address; @@ -2812,8 +2881,6 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) osection = isection->output_section; size = bfd_get_section_size (isection); - p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE); - if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS) { @@ -2880,7 +2947,9 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) } free (memhunk); } - else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0) + else if ((p = find_section_list (bfd_get_section_name (ibfd, isection), + FALSE, SECTION_CONTEXT_SET_FLAGS)) != NULL + && (p->flags & SEC_HAS_CONTENTS) != 0) { void *memhunk = xmalloc (size); @@ -3082,7 +3151,6 @@ strip_main (int argc, char *argv[]) bfd_boolean formats_info = FALSE; int c; int i; - struct section_list *p; char *output_file = NULL; while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw", @@ -3100,8 +3168,7 @@ strip_main (int argc, char *argv[]) input_target = output_target = optarg; break; case 'R': - p = find_section_list (optarg, TRUE); - p->remove = TRUE; + find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE); sections_removed = TRUE; break; case 's': @@ -3374,7 +3441,6 @@ copy_main (int argc, char *argv[]) bfd_boolean change_warn = TRUE; bfd_boolean formats_info = FALSE; int c; - struct section_list *p; struct stat statbuf; const bfd_arch_info_type *input_arch = NULL; @@ -3427,18 +3493,12 @@ copy_main (int argc, char *argv[]) break; case 'j': - p = find_section_list (optarg, TRUE); - if (p->remove) - fatal (_("%s both copied and removed"), optarg); - p->copy = TRUE; + find_section_list (optarg, TRUE, SECTION_CONTEXT_COPY); sections_copied = TRUE; break; case 'R': - p = find_section_list (optarg, TRUE); - if (p->copy) - fatal (_("%s both copied and removed"), optarg); - p->remove = TRUE; + find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE); sections_removed = TRUE; break; @@ -3601,23 +3661,27 @@ copy_main (int argc, char *argv[]) case OPTION_CHANGE_SECTION_LMA: case OPTION_CHANGE_SECTION_VMA: { + struct section_list * p; + unsigned int context; const char *s; int len; char *name; char *option = NULL; bfd_vma val; - enum change_action what = CHANGE_IGNORE; switch (c) { case OPTION_CHANGE_SECTION_ADDRESS: option = "--change-section-address"; + context = SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_ALTER_VMA; break; case OPTION_CHANGE_SECTION_LMA: option = "--change-section-lma"; + context = SECTION_CONTEXT_ALTER_LMA; break; case OPTION_CHANGE_SECTION_VMA: option = "--change-section-vma"; + context = SECTION_CONTEXT_ALTER_VMA; break; } @@ -3632,38 +3696,46 @@ copy_main (int argc, char *argv[]) fatal (_("bad format for %s"), option); } } + else + { + /* Correct the context. */ + switch (c) + { + case OPTION_CHANGE_SECTION_ADDRESS: + context = SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_SET_VMA; + break; + case OPTION_CHANGE_SECTION_LMA: + context = SECTION_CONTEXT_SET_LMA; + break; + case OPTION_CHANGE_SECTION_VMA: + context = SECTION_CONTEXT_SET_VMA; + break; + } + } len = s - optarg; name = (char *) xmalloc (len + 1); strncpy (name, optarg, len); name[len] = '\0'; - p = find_section_list (name, TRUE); + p = find_section_list (name, TRUE, context); val = parse_vma (s + 1, option); - - switch (*s) - { - case '=': what = CHANGE_SET; break; - case '-': val = - val; /* Drop through. */ - case '+': what = CHANGE_MODIFY; break; - } + if (*s == '-') + val = - val; switch (c) { case OPTION_CHANGE_SECTION_ADDRESS: - p->change_vma = what; - p->vma_val = val; + p->vma_val = val; /* Drop through. */ case OPTION_CHANGE_SECTION_LMA: - p->change_lma = what; - p->lma_val = val; + p->lma_val = val; break; case OPTION_CHANGE_SECTION_VMA: - p->change_vma = what; - p->vma_val = val; + p->vma_val = val; break; } } @@ -3762,6 +3834,7 @@ copy_main (int argc, char *argv[]) case OPTION_SET_SECTION_FLAGS: { + struct section_list *p; const char *s; int len; char *name; @@ -3775,9 +3848,8 @@ copy_main (int argc, char *argv[]) strncpy (name, optarg, len); name[len] = '\0'; - p = find_section_list (name, TRUE); + p = find_section_list (name, TRUE, SECTION_CONTEXT_SET_FLAGS); - p->set_flags = TRUE; p->flags = parse_flags (s + 1); } break; @@ -4126,11 +4198,13 @@ copy_main (int argc, char *argv[]) if (change_warn) { + struct section_list *p; + for (p = change_sections; p != NULL; p = p->next) { if (! p->used) { - if (p->change_vma != CHANGE_IGNORE) + if (p->context & (SECTION_CONTEXT_SET_VMA | SECTION_CONTEXT_ALTER_VMA)) { char buff [20]; @@ -4139,12 +4213,12 @@ copy_main (int argc, char *argv[]) /* xgettext:c-format */ non_fatal (_("%s %s%c0x%s never used"), "--change-section-vma", - p->name, - p->change_vma == CHANGE_SET ? '=' : '+', + p->pattern, + p->context & SECTION_CONTEXT_SET_VMA ? '=' : '+', buff); } - if (p->change_lma != CHANGE_IGNORE) + if (p->context & (SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_ALTER_LMA)) { char buff [20]; @@ -4153,8 +4227,8 @@ copy_main (int argc, char *argv[]) /* xgettext:c-format */ non_fatal (_("%s %s%c0x%s never used"), "--change-section-lma", - p->name, - p->change_lma == CHANGE_SET ? '=' : '+', + p->pattern, + p->context & SECTION_CONTEXT_SET_LMA ? '=' : '+', buff); } } -- 2.30.2