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
This commit is contained in:
Nick Clifton
2013-02-15 09:32:31 +00:00
parent 796cb314e7
commit 2e62b7218b
4 changed files with 265 additions and 162 deletions

View File

@@ -1,3 +1,20 @@
2013-02-15 Nick Clifton <nickc@redhat.com>
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 <nickc@redhat.com>
PR binutils/15125

View File

@@ -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:

View File

@@ -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.
if the section pattern does not match any sections.
@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.
@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

View File

@@ -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);
}
}