/* 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
+ 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Binutils.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
\f
#include "bfd.h"
#include "progress.h"
/* List of symbols to strip, keep, localize, keep-global, weaken,
or redefine. */
static struct symlist *strip_specific_list = NULL;
+static struct symlist *strip_unneeded_list = NULL;
static struct symlist *keep_specific_list = NULL;
static struct symlist *localize_specific_list = NULL;
+static struct symlist *globalize_specific_list = NULL;
static struct symlist *keepglobal_specific_list = NULL;
static struct symlist *weaken_specific_list = NULL;
static struct redefine_node *redefine_sym_list = NULL;
OPTION_SREC_LEN,
OPTION_SREC_FORCES3,
OPTION_STRIP_SYMBOLS,
+ OPTION_STRIP_UNNEEDED_SYMBOL,
+ OPTION_STRIP_UNNEEDED_SYMBOLS,
OPTION_KEEP_SYMBOLS,
OPTION_LOCALIZE_SYMBOLS,
+ OPTION_GLOBALIZE_SYMBOL,
+ OPTION_GLOBALIZE_SYMBOLS,
OPTION_KEEPGLOBAL_SYMBOLS,
OPTION_WEAKEN_SYMBOLS,
OPTION_RENAME_SECTION,
{"discard-locals", no_argument, 0, 'X'},
{"format", required_argument, 0, 'F'}, /* Obsolete */
{"gap-fill", required_argument, 0, OPTION_GAP_FILL},
+ {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
+ {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
{"help", no_argument, 0, 'h'},
{"impure", no_argument, 0, OPTION_IMPURE},
{"info", no_argument, 0, OPTION_FORMATS_INFO},
{"strip-all", no_argument, 0, 'S'},
{"strip-debug", no_argument, 0, 'g'},
{"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
+ {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
+ {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
{"strip-symbol", required_argument, 0, 'N'},
{"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
{"target", required_argument, 0, 'F'},
/* Forward declarations. */
static void setup_section (bfd *, asection *, void *);
+static void setup_bfd_headers (bfd *, bfd *);
static void copy_section (bfd *, asection *, void *);
static void get_sections (bfd *, asection *, void *);
static int compare_section_lma (const void *, const void *);
-g --strip-debug Remove all debugging symbols & sections\n\
--strip-unneeded Remove all symbols not needed by relocations\n\
-N --strip-symbol <name> Do not copy symbol <name>\n\
+ --strip-unneeded-symbol <name>\n\
+ Do not copy symbol <name> unless needed by\n\
+ relocations\n\
--only-keep-debug Strip everything but the debug information\n\
- -K --keep-symbol <name> Only copy symbol <name>\n\
+ -K --keep-symbol <name> Do not strip symbol <name>\n\
-L --localize-symbol <name> Force symbol <name> to be marked as a local\n\
+ --globalize-symbol <name> Force symbol <name> to be marked as a global\n\
-G --keep-global-symbol <name> Localize all symbols except <name>\n\
-W --weaken-symbol <name> Force symbol <name> to be marked as a weak\n\
--weaken Force all global symbols to be marked as weak\n\
- -w --wildcard Permit wildcard in symbol comparasion\n\
+ -w --wildcard Permit wildcard in symbol comparison\n\
-x --discard-all Remove all non-global symbols\n\
-X --discard-locals Remove any compiler-generated symbols\n\
-i --interleave <number> Only copy one out of every <number> bytes\n\
--srec-len <number> Restrict the length of generated Srecords\n\
--srec-forceS3 Restrict the type of generated Srecords to S3\n\
--strip-symbols <file> -N for all symbols listed in <file>\n\
+ --strip-unneeded-symbols <file>\n\
+ --strip-unneeded-symbol for all symbols listed\n\
+ in <file>\n\
--keep-symbols <file> -K for all symbols listed in <file>\n\
--localize-symbols <file> -L for all symbols listed in <file>\n\
+ --globalize-symbols <file> --globalize-symbol for all in <file>\n\
--keep-global-symbols <file> -G for all symbols listed in <file>\n\
--weaken-symbols <file> -W for all symbols listed in <file>\n\
--alt-machine-code <index> Use alternate machine code for output\n\
--strip-unneeded Remove all symbols not needed by relocations\n\
--only-keep-debug Strip everything but the debug information\n\
-N --strip-symbol=<name> Do not copy symbol <name>\n\
- -K --keep-symbol=<name> Only copy symbol <name>\n\
- -w --wildcard Permit wildcard in symbol comparasion\n\
+ -K --keep-symbol=<name> Do not strip symbol <name>\n\
+ -w --wildcard Permit wildcard in symbol comparison\n\
-x --discard-all Remove all non-global symbols\n\
-X --discard-locals Remove any compiler-generated symbols\n\
-v --verbose List all object files modified\n\
PARSE_FLAG ("code", SEC_CODE);
PARSE_FLAG ("data", SEC_DATA);
PARSE_FLAG ("rom", SEC_ROM);
- PARSE_FLAG ("share", SEC_SHARED);
+ PARSE_FLAG ("share", SEC_COFF_SHARED);
PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
#undef PARSE_FLAG
else
;
if (! IS_LINE_TERMINATOR (* extra))
- non_fatal (_("Ignoring rubbish found on line %d of %s"),
- line_count, filename);
+ non_fatal (_("%s:%d: Ignoring rubbish found on this line"),
+ filename, line_count);
}
* name_end = '\0';
keep = (strip_symbols != STRIP_DEBUG
&& strip_symbols != STRIP_UNNEEDED
&& ! convert_debugging);
- else if (bfd_get_section (sym)->comdat)
+ else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
/* COMDAT sections store special information in local
symbols, so we cannot risk stripping any of them. */
keep = 1;
if (keep && is_specified_symbol (name, strip_specific_list))
keep = 0;
+ if (keep
+ && !(flags & BSF_KEEP)
+ && is_specified_symbol (name, strip_unneeded_list))
+ keep = 0;
if (!keep && is_specified_symbol (name, keep_specific_list))
keep = 1;
if (keep && is_strip_section (abfd, bfd_get_section (sym)))
keep = 0;
- if (keep && (flags & BSF_GLOBAL) != 0
- && (weaken || is_specified_symbol (name, weaken_specific_list)))
- {
- sym->flags &=~ BSF_GLOBAL;
- sym->flags |= BSF_WEAK;
- }
- if (keep && !undefined && (flags & (BSF_GLOBAL | BSF_WEAK))
- && (is_specified_symbol (name, localize_specific_list)
- || (keepglobal_specific_list != NULL
- && ! is_specified_symbol (name, keepglobal_specific_list))))
+ if (keep)
{
- sym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
- sym->flags |= BSF_LOCAL;
- }
+ if ((flags & BSF_GLOBAL) != 0
+ && (weaken || is_specified_symbol (name, weaken_specific_list)))
+ {
+ sym->flags &= ~ BSF_GLOBAL;
+ sym->flags |= BSF_WEAK;
+ }
- if (keep)
- to[dst_count++] = sym;
+ if (!undefined
+ && (flags & (BSF_GLOBAL | BSF_WEAK))
+ && (is_specified_symbol (name, localize_specific_list)
+ || (keepglobal_specific_list != NULL
+ && ! is_specified_symbol (name, keepglobal_specific_list))))
+ {
+ sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
+ sym->flags |= BSF_LOCAL;
+ }
+
+ if (!undefined
+ && (flags & BSF_LOCAL)
+ && is_specified_symbol (name, globalize_specific_list))
+ {
+ sym->flags &= ~ BSF_LOCAL;
+ sym->flags |= BSF_GLOBAL;
+ }
+
+ to[dst_count++] = sym;
+ }
}
to[dst_count] = NULL;
continue;
}
else
- fatal (_("%s: garbage at end of line %d"), filename, lineno);
+ fatal (_("%s:%d: garbage found at end of line"), filename, lineno);
comment:
if (len != 0 && (outsym_off == 0 || outsym_off == len))
- fatal (_("%s: missing new symbol name at line %d"), filename, lineno);
+ fatal (_("%s:%d: missing new symbol name"), filename, lineno);
buf[len++] = '\0';
/* Eat the rest of the line and finish it. */
}
if (len != 0)
- fatal (_("%s: premature end of file at line %d"), filename, lineno);
+ fatal (_("%s:%d: premature end of file"), filename, lineno);
free (buf);
}
any output is done. Thus, we traverse all sections multiple times. */
bfd_map_over_sections (ibfd, setup_section, obfd);
+ setup_bfd_headers (ibfd, obfd);
+
if (add_sections != NULL)
{
struct section_add *padd;
|| strip_specific_list != NULL
|| keep_specific_list != NULL
|| localize_specific_list != NULL
+ || globalize_specific_list != NULL
|| keepglobal_specific_list != NULL
|| weaken_specific_list != NULL
|| prefix_symbols_string
l = xmalloc (sizeof (struct name_list));
l->name = output_name;
l->next = list;
+ l->obfd = NULL;
list = l;
if (output_bfd == NULL)
if (get_file_size (input_filename) < 1)
{
+ non_fatal (_("error: the input file '%s' is empty"), input_filename);
status = 1;
return;
}
else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
{
bfd *obfd;
- bfd_boolean delete;
do_copy:
/* bfd_get_target does not return the correct value until
if (obfd == NULL)
RETURN_NONFATAL (output_filename);
- delete = ! copy_object (ibfd, obfd);
+ if (! copy_object (ibfd, obfd))
+ status = 1;
if (!bfd_close (obfd))
RETURN_NONFATAL (output_filename);
if (!bfd_close (ibfd))
RETURN_NONFATAL (input_filename);
- if (delete)
- {
- unlink (output_filename);
- status = 1;
- }
}
else
{
return old_name;
}
+/* Once each of the sections is copied, we may still need to do some
+ finalization work for private section headers. Do that here. */
+
+static void
+setup_bfd_headers (bfd *ibfd, bfd *obfd)
+{
+ const char *err;
+
+ /* Allow the BFD backend to copy any private data it understands
+ from the input section to the output section. */
+ if (! bfd_copy_private_header_data (ibfd, obfd))
+ {
+ err = _("private header data");
+ goto loser;
+ }
+
+ /* All went well. */
+ return;
+
+loser:
+ non_fatal (_("%s: error in %s: %s"),
+ bfd_get_filename (ibfd),
+ err, bfd_errmsg (bfd_get_error ()));
+ status = 1;
+}
+
/* Create a section in OBFD with the same
name and attributes as ISECTION in IBFD. */
return;
osection = isection->output_section;
- size = bfd_get_section_size_before_reloc (isection);
+ size = bfd_get_section_size (isection);
if (size == 0 || osection == 0)
return;
free (relpp);
}
- isection->_cooked_size = isection->_raw_size;
- isection->reloc_done = TRUE;
-
if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
{
return -1;
/* Sort sections with the same LMA by size. */
- if ((*sec1)->_raw_size > (*sec2)->_raw_size)
+ if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2))
return 1;
- else if ((*sec1)->_raw_size < (*sec2)->_raw_size)
+ else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2))
return -1;
return 0;
status = hold_status;
}
else
- unlink (tmpname);
+ unlink_if_ordinary (tmpname);
if (output_file == NULL)
free (tmpname);
}
add_specific_symbol (optarg, &strip_specific_list);
break;
+ case OPTION_STRIP_UNNEEDED_SYMBOL:
+ add_specific_symbol (optarg, &strip_unneeded_list);
+ break;
+
case 'L':
add_specific_symbol (optarg, &localize_specific_list);
break;
+ case OPTION_GLOBALIZE_SYMBOL:
+ add_specific_symbol (optarg, &globalize_specific_list);
+ break;
+
case 'G':
add_specific_symbol (optarg, &keepglobal_specific_list);
break;
add_specific_symbols (optarg, &strip_specific_list);
break;
+ case OPTION_STRIP_UNNEEDED_SYMBOLS:
+ add_specific_symbols (optarg, &strip_unneeded_list);
+ break;
+
case OPTION_KEEP_SYMBOLS:
add_specific_symbols (optarg, &keep_specific_list);
break;
add_specific_symbols (optarg, &localize_specific_list);
break;
+ case OPTION_GLOBALIZE_SYMBOLS:
+ add_specific_symbols (optarg, &globalize_specific_list);
+ break;
+
case OPTION_KEEPGLOBAL_SYMBOLS:
add_specific_symbols (optarg, &keepglobal_specific_list);
break;
if (status == 0 && preserve_dates)
set_times (output_filename, &statbuf);
+ else if (status != 0)
+ unlink_if_ordinary (output_filename);
}
if (change_warn)