/* 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
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
\f
+#include "sysdep.h"
#include "bfd.h"
#include "progress.h"
-#include "bucomm.h"
#include "getopt.h"
#include "libiberty.h"
+#include "bucomm.h"
#include "budbg.h"
#include "filenames.h"
#include "fnmatch.h"
#include "elf-bfd.h"
#include <sys/stat.h>
#include "libbfd.h"
-
-/* A list of symbols to explicitly strip out, or to keep. A linked
- list is good enough for a small number from the command line, but
- this will slow things down a lot if many symbols are being
- deleted. */
-
-struct symlist
+#include "coff/internal.h"
+#include "libcoff.h"
+
+/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
+ header in generic PE code. */
+#include "coff/i386.h"
+#include "coff/pe.h"
+
+static bfd_vma pe_file_alignment = (bfd_vma) -1;
+static bfd_vma pe_heap_commit = (bfd_vma) -1;
+static bfd_vma pe_heap_reserve = (bfd_vma) -1;
+static bfd_vma pe_image_base = (bfd_vma) -1;
+static bfd_vma pe_section_alignment = (bfd_vma) -1;
+static bfd_vma pe_stack_commit = (bfd_vma) -1;
+static bfd_vma pe_stack_reserve = (bfd_vma) -1;
+static short pe_subsystem = -1;
+static short pe_major_subsystem_version = -1;
+static short pe_minor_subsystem_version = -1;
+
+struct is_specified_symbol_predicate_data
{
- const char *name;
- struct symlist *next;
+ const char *name;
+ bfd_boolean found;
};
/* A list to support redefine_sym. */
/* List of sections to be renamed. */
static section_rename *section_rename_list;
-#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
-
static asymbol **isympp = NULL; /* Input symbols. */
static asymbol **osympp = NULL; /* Output symbols that survive stripping. */
/* Whether to permit wildcard in symbol comparison. */
static bfd_boolean wildcard = FALSE;
+/* True if --localize-hidden is in effect. */
+static bfd_boolean localize_hidden = FALSE;
+
/* 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 htab_t strip_specific_htab = NULL;
+static htab_t strip_unneeded_htab = NULL;
+static htab_t keep_specific_htab = NULL;
+static htab_t localize_specific_htab = NULL;
+static htab_t globalize_specific_htab = NULL;
+static htab_t keepglobal_specific_htab = NULL;
+static htab_t weaken_specific_htab = NULL;
static struct redefine_node *redefine_sym_list = NULL;
/* If this is TRUE, we weaken global symbols (set BSF_WEAK). */
static char *prefix_sections_string = 0;
static char *prefix_alloc_sections_string = 0;
+/* True if --extract-symbol was passed on the command line. */
+static bfd_boolean extract_symbol = FALSE;
+
+/* If `reverse_bytes' is nonzero, then reverse the order of every chunk
+ of <reverse_bytes> bytes within each output section. */
+static int reverse_bytes = 0;
+
+/* For Coff objects, we may want to allow or disallow long section names,
+ or preserve them where found in the inputs. Debug info relies on them. */
+enum long_section_name_handling
+ {
+ DISABLE,
+ ENABLE,
+ KEEP
+ };
+
+/* The default long section handling mode is to preserve them.
+ This is also the only behaviour for 'strip'. */
+static enum long_section_name_handling long_section_names = KEEP;
+
/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
enum command_line_switch
{
OPTION_STRIP_UNNEEDED_SYMBOL,
OPTION_STRIP_UNNEEDED_SYMBOLS,
OPTION_KEEP_SYMBOLS,
+ OPTION_LOCALIZE_HIDDEN,
OPTION_LOCALIZE_SYMBOLS,
+ OPTION_LONG_SECTION_NAMES,
OPTION_GLOBALIZE_SYMBOL,
OPTION_GLOBALIZE_SYMBOLS,
OPTION_KEEPGLOBAL_SYMBOLS,
OPTION_READONLY_TEXT,
OPTION_WRITABLE_TEXT,
OPTION_PURE,
- OPTION_IMPURE
+ OPTION_IMPURE,
+ OPTION_EXTRACT_SYMBOL,
+ OPTION_REVERSE_BYTES,
+ OPTION_FILE_ALIGNMENT,
+ OPTION_HEAP,
+ OPTION_IMAGE_BASE,
+ OPTION_SECTION_ALIGNMENT,
+ OPTION_STACK,
+ OPTION_SUBSYSTEM
};
/* Options to handle if running as "strip". */
{"debugging", no_argument, 0, OPTION_DEBUGGING},
{"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'},
+ {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
{"format", required_argument, 0, 'F'}, /* Obsolete */
{"gap-fill", required_argument, 0, OPTION_GAP_FILL},
{"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
{"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
{"keep-symbol", required_argument, 0, 'K'},
{"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
+ {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
{"localize-symbol", required_argument, 0, 'L'},
{"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
+ {"long-section-names", required_argument, 0, OPTION_LONG_SECTION_NAMES},
{"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
{"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
{"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
{"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
{"remove-section", required_argument, 0, 'R'},
{"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
+ {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
{"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
{"set-start", required_argument, 0, OPTION_SET_START},
{"srec-len", required_argument, 0, OPTION_SREC_LEN},
{"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
{"wildcard", no_argument, 0, 'w'},
{"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
+ {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
+ {"heap", required_argument, 0, OPTION_HEAP},
+ {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
+ {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
+ {"stack", required_argument, 0, OPTION_STACK},
+ {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
{0, no_argument, 0, 0}
};
on by the --srec-forceS3 command line switch. */
extern bfd_boolean S3Forced;
-/* Defined in bfd/binary.c. Used to set architecture and machine of input
- binary files. */
-extern enum bfd_architecture bfd_external_binary_architecture;
-extern unsigned long bfd_external_machine;
-
/* Forward declarations. */
static void setup_section (bfd *, asection *, void *);
static void setup_bfd_headers (bfd *, bfd *);
fprintf (stream, _("\
-I --input-target <bfdname> Assume input file is in format <bfdname>\n\
-O --output-target <bfdname> Create an output file in format <bfdname>\n\
- -B --binary-architecture <arch> Set arch of output file, when input is binary\n\
+ -B --binary-architecture <arch> Set output arch, when input is arch-less\n\
-F --target <bfdname> Set both input and output format to <bfdname>\n\
--debugging Convert debugging information, if possible\n\
-p --preserve-dates Copy modified/access timestamps to the output\n\
Do not copy symbol <name> unless needed by\n\
relocations\n\
--only-keep-debug Strip everything but the debug information\n\
+ --extract-symbol Remove section contents but keep symbols\n\
-K --keep-symbol <name> Do not strip symbol <name>\n\
--keep-file-symbols Do not strip file symbol(s)\n\
+ --localize-hidden Turn all ELF hidden symbols into locals\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\
Set section <name>'s properties to <flags>\n\
--add-section <name>=<file> Add section <name> found in <file> to output\n\
--rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
+ --long-section-names {enable|disable|keep}\n\
+ Handle long section names in Coff objects.\n\
--change-leading-char Force output format's leading character style\n\
--remove-leading-char Remove leading character from global symbols\n\
+ --reverse-bytes=<num> Reverse <num> bytes at a time, in output sections with content\n\
--redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\
--redefine-syms <file> --redefine-sym for all symbol pairs \n\
listed in <file>\n\
--prefix-alloc-sections <prefix>\n\
Add <prefix> to start of every allocatable\n\
section name\n\
+ --file-alignment <num> Set PE file alignment to <num>\n\
+ --heap <reserve>[,<commit>] Set PE reserve/commit heap to <reserve>/\n\
+ <commit>\n\
+ --image-base <address> Set PE image base to <address>\n\
+ --section-alignment <num> Set PE section alignment to <num>\n\
+ --stack <reserve>[,<commit>] Set PE reserve/commit stack to <reserve>/\n\
+ <commit>\n\
+ --subsystem <name>[:<version>]\n\
+ Set PE subsystem to <name> [& <version>]\n]\
-v --verbose List all object files modified\n\
@<file> Read options from <file>\n\
-V --version Display this program's version number\n\
--info List object formats & architectures supported\n\
"));
list_supported_targets (program_name, stream);
- if (exit_status == 0)
+ if (REPORT_BUGS_TO[0] && exit_status == 0)
fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
exit (exit_status);
}
"));
list_supported_targets (program_name, stream);
- if (exit_status == 0)
+ if (REPORT_BUGS_TO[0] && exit_status == 0)
fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
exit (exit_status);
}
{
char *copy;
- copy = xmalloc (len + 1);
+ copy = (char *) xmalloc (len + 1);
strncpy (copy, s, len);
copy[len] = '\0';
non_fatal (_("unrecognized section flag `%s'"), copy);
if (! add)
return NULL;
- p = xmalloc (sizeof (struct section_list));
+ p = (struct section_list *) xmalloc (sizeof (struct section_list));
p->name = name;
p->used = FALSE;
p->remove = FALSE;
return p;
}
-/* Add a symbol to strip_specific_list. */
+/* There is htab_hash_string but no htab_eq_string. Makes sense. */
+
+static int
+eq_string (const void *s1, const void *s2)
+{
+ return strcmp ((const char *) s1, (const char *) s2) == 0;
+}
+
+static htab_t
+create_symbol_htab (void)
+{
+ return htab_create_alloc (16, htab_hash_string, eq_string, NULL, xcalloc, free);
+}
static void
-add_specific_symbol (const char *name, struct symlist **list)
+create_symbol_htabs (void)
{
- struct symlist *tmp_list;
+ strip_specific_htab = create_symbol_htab ();
+ strip_unneeded_htab = create_symbol_htab ();
+ keep_specific_htab = create_symbol_htab ();
+ localize_specific_htab = create_symbol_htab ();
+ globalize_specific_htab = create_symbol_htab ();
+ keepglobal_specific_htab = create_symbol_htab ();
+ weaken_specific_htab = create_symbol_htab ();
+}
+
+/* Add a symbol to strip_specific_list. */
- tmp_list = xmalloc (sizeof (struct symlist));
- tmp_list->name = name;
- tmp_list->next = *list;
- *list = tmp_list;
+static void
+add_specific_symbol (const char *name, htab_t htab)
+{
+ *htab_find_slot (htab, name, INSERT) = (char *) name;
}
/* Add symbols listed in `filename' to strip_specific_list. */
#define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
static void
-add_specific_symbols (const char *filename, struct symlist **list)
+add_specific_symbols (const char *filename, htab_t htab)
{
off_t size;
FILE * f;
size = get_file_size (filename);
if (size == 0)
- return;
+ {
+ status = 1;
+ return;
+ }
- buffer = xmalloc (size + 2);
+ buffer = (char *) xmalloc (size + 2);
f = fopen (filename, FOPEN_RT);
if (f == NULL)
fatal (_("cannot open '%s': %s"), filename, strerror (errno));
* name_end = '\0';
if (name_end > name)
- add_specific_symbol (name, list);
+ add_specific_symbol (name, htab);
/* Advance line pointer to end of line. The 'eol ++' in the for
loop above will then advance us to the start of the next line. */
}
}
-/* See whether a symbol should be stripped or kept based on
- strip_specific_list and keep_symbols. */
+/* See whether a symbol should be stripped or kept
+ based on strip_specific_list and keep_symbols. */
-static bfd_boolean
-is_specified_symbol (const char *name, struct symlist *list)
+static int
+is_specified_symbol_predicate (void **slot, void *data)
{
- struct symlist *tmp_list;
+ struct is_specified_symbol_predicate_data *d =
+ (struct is_specified_symbol_predicate_data *) data;
+ const char *slot_name = (char *) *slot;
- if (wildcard)
+ if (*slot_name != '!')
{
- for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
- if (*(tmp_list->name) != '!')
- {
- if (!fnmatch (tmp_list->name, name, 0))
- return TRUE;
- }
- else
- {
- if (fnmatch (tmp_list->name + 1, name, 0))
- return TRUE;
- }
+ if (! fnmatch (slot_name, d->name, 0))
+ {
+ d->found = TRUE;
+ /* Stop traversal. */
+ return 0;
+ }
}
else
{
- for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
- if (strcmp (name, tmp_list->name) == 0)
- return TRUE;
+ if (fnmatch (slot_name + 1, d->name, 0))
+ {
+ d->found = TRUE;
+ /* Stop traversal. */
+ return 0;
+ }
}
- return FALSE;
+ /* Continue traversal. */
+ return 1;
+}
+
+static bfd_boolean
+is_specified_symbol (const char *name, htab_t htab)
+{
+ if (wildcard)
+ {
+ struct is_specified_symbol_predicate_data data;
+
+ data.name = name;
+ data.found = FALSE;
+
+ htab_traverse (htab, is_specified_symbol_predicate, &data);
+
+ return data.found;
+ }
+
+ return htab_find (htab, name) != NULL;
+}
+
+/* Return a pointer to the symbol used as a signature for GROUP. */
+
+static asymbol *
+group_signature (asection *group)
+{
+ bfd *abfd = group->owner;
+ Elf_Internal_Shdr *ghdr;
+
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ return NULL;
+
+ ghdr = &elf_section_data (group)->this_hdr;
+ if (ghdr->sh_link < elf_numsections (abfd))
+ {
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
+
+ if (symhdr->sh_type == SHT_SYMTAB
+ && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
+ return isympp[ghdr->sh_info - 1];
+ }
+ return NULL;
}
/* See if a section is being removed. */
return FALSE;
}
+ if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
+ {
+ asymbol *gsym;
+ const char *gname;
+
+ /* PR binutils/3166
+ Group sections look like debugging sections but they are not.
+ (They have a non-zero size but they are not ALLOCated). */
+ if (strip_symbols == STRIP_NONDEBUG)
+ return TRUE;
+
+ /* PR binutils/3181
+ If we are going to strip the group signature symbol, then
+ strip the group section too. */
+ gsym = group_signature (sec);
+ if (gsym != NULL)
+ gname = gsym->name;
+ else
+ gname = sec->name;
+ if ((strip_symbols == STRIP_ALL
+ && !is_specified_symbol (gname, keep_specific_htab))
+ || is_specified_symbol (gname, strip_specific_htab))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Return true if SYM is a hidden symbol. */
+
+static bfd_boolean
+is_hidden_symbol (asymbol *sym)
+{
+ elf_symbol_type *elf_sym;
+
+ elf_sym = elf_symbol_from (sym->the_bfd, sym);
+ if (elf_sym != NULL)
+ switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
+ {
+ case STV_HIDDEN:
+ case STV_INTERNAL:
+ return TRUE;
+ }
return FALSE;
}
{
asymbol **from = isyms, **to = osyms;
long src_count = 0, dst_count = 0;
- int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC))
- == HAS_RELOC;
+ int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
for (; src_count < symcount; src_count++)
{
asymbol *sym = from[src_count];
flagword flags = sym->flags;
char *name = (char *) bfd_asymbol_name (sym);
- int keep;
+ bfd_boolean keep;
+ bfd_boolean used_in_reloc = FALSE;
bfd_boolean undefined;
bfd_boolean rem_leading_char;
bfd_boolean add_leading_char;
{
char *n, *ptr;
- ptr = n = xmalloc (1 + strlen (prefix_symbols_string)
- + strlen (name) + 1);
+ ptr = n = (char *) xmalloc (1 + strlen (prefix_symbols_string)
+ + strlen (name) + 1);
if (add_leading_char)
*ptr++ = bfd_get_symbol_leading_char (obfd);
}
if (strip_symbols == STRIP_ALL)
- keep = 0;
+ keep = FALSE;
else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */
|| ((flags & BSF_SECTION_SYM) != 0
&& ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
& BSF_KEEP) != 0))
- keep = 1;
+ {
+ keep = TRUE;
+ used_in_reloc = TRUE;
+ }
else if (relocatable /* Relocatable file. */
- && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
- keep = 1;
+ && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_com_section (bfd_get_section (sym))))
+ keep = TRUE;
else if (bfd_decode_symclass (sym) == 'I')
/* Global symbols in $idata sections need to be retained
even if relocatable is FALSE. External users of the
library containing the $idata section may reference these
symbols. */
- keep = 1;
+ keep = TRUE;
else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */
|| (flags & BSF_WEAK) != 0
|| undefined
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;
+ keep = TRUE;
else /* Local symbol. */
keep = (strip_symbols != STRIP_UNNEEDED
&& (discard_locals != LOCALS_ALL
&& (discard_locals != LOCALS_START_L
|| ! bfd_is_local_label (abfd, sym))));
- if (keep && is_specified_symbol (name, strip_specific_list))
- keep = 0;
+ if (keep && is_specified_symbol (name, strip_specific_htab))
+ {
+ /* There are multiple ways to set 'keep' above, but if it
+ was the relocatable symbol case, then that's an error. */
+ if (used_in_reloc)
+ {
+ non_fatal (_("not stripping symbol `%s' because it is named in a relocation"), name);
+ status = 1;
+ }
+ else
+ keep = FALSE;
+ }
+
if (keep
&& !(flags & BSF_KEEP)
- && is_specified_symbol (name, strip_unneeded_list))
- keep = 0;
+ && is_specified_symbol (name, strip_unneeded_htab))
+ keep = FALSE;
+
if (!keep
&& ((keep_file_symbols && (flags & BSF_FILE))
- || is_specified_symbol (name, keep_specific_list)))
- keep = 1;
+ || is_specified_symbol (name, keep_specific_htab)))
+ keep = TRUE;
+
if (keep && is_strip_section (abfd, bfd_get_section (sym)))
- keep = 0;
+ keep = FALSE;
if (keep)
{
if ((flags & BSF_GLOBAL) != 0
- && (weaken || is_specified_symbol (name, weaken_specific_list)))
+ && (weaken || is_specified_symbol (name, weaken_specific_htab)))
{
sym->flags &= ~ BSF_GLOBAL;
sym->flags |= BSF_WEAK;
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))))
+ && (is_specified_symbol (name, localize_specific_htab)
+ || (htab_elements (keepglobal_specific_htab) != 0
+ && ! is_specified_symbol (name, keepglobal_specific_htab))
+ || (localize_hidden && is_hidden_symbol (sym))))
{
sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
sym->flags |= BSF_LOCAL;
}
if (!undefined
- && (flags & BSF_LOCAL)
- && is_specified_symbol (name, globalize_specific_list))
+ && (flags & BSF_LOCAL)
+ && is_specified_symbol (name, globalize_specific_htab))
{
sym->flags &= ~ BSF_LOCAL;
sym->flags |= BSF_GLOBAL;
cause, target);
}
- new_node = xmalloc (sizeof (struct redefine_node));
+ new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
new_node->source = strdup (source);
new_node->target = strdup (target);
filename, strerror (errno));
bufsize = 100;
- buf = xmalloc (bufsize);
+ buf = (char *) xmalloc (bufsize + 1 /* For the terminating NUL. */);
lineno = 1;
c = getc (file);
if (len >= bufsize)
{
bufsize *= 2;
- buf = xrealloc (buf, bufsize);
+ buf = (char *) xrealloc (buf, bufsize + 1);
}
c = getc (file);
}
if (len >= bufsize)
{
bufsize *= 2;
- buf = xrealloc (buf, bufsize);
+ buf = (char *) xrealloc (buf, bufsize + 1);
}
c = getc (file);
}
if (buf[0] != '\0')
redefine_list_append (filename, &buf[0], &buf[outsym_off]);
- lineno++;
+ lineno++;
len = 0;
outsym_off = 0;
if (c == EOF)
if (bfd_stat_arch_elt (ibfd, &buf) != 0)
{
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
return FALSE;
}
printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
- cbuf = xmalloc (BUFSIZE);
+ cbuf = (char *) xmalloc (BUFSIZE);
ncopied = 0;
while (ncopied < size)
{
if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
!= (bfd_size_type) tocopy)
{
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
free (cbuf);
return FALSE;
}
if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
!= (bfd_size_type) tocopy)
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, NULL, NULL);
free (cbuf);
return FALSE;
}
Returns TRUE upon success, FALSE otherwise. */
static bfd_boolean
-copy_object (bfd *ibfd, bfd *obfd)
+copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
{
bfd_vma start;
long symcount;
if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, NULL, NULL);
return FALSE;
}
bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
bfd_get_filename (obfd), bfd_get_target (obfd));
- if (set_start_set)
- start = set_start;
+ if (extract_symbol)
+ start = 0;
else
- start = bfd_get_start_address (ibfd);
- start += change_start;
+ {
+ if (set_start_set)
+ start = set_start;
+ else
+ start = bfd_get_start_address (ibfd);
+ start += change_start;
+ }
/* Neither the start address nor the flags
need to be set for a core file. */
flags &= ~bfd_flags_to_clear;
flags &= bfd_applicable_file_flags (obfd);
+ if (strip_symbols == STRIP_ALL)
+ flags &= ~HAS_RELOC;
+
if (!bfd_set_start_address (obfd, start)
|| !bfd_set_file_flags (obfd, flags))
{
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
return FALSE;
}
}
/* Copy architecture of input file to output file. */
iarch = bfd_get_arch (ibfd);
imach = bfd_get_mach (ibfd);
+ if (input_arch)
+ {
+ if (bfd_get_arch_info (ibfd) == NULL
+ || bfd_get_arch_info (ibfd)->arch == bfd_arch_unknown)
+ {
+ iarch = input_arch->arch;
+ imach = input_arch->mach;
+ }
+ else
+ non_fatal (_("Input file `%s' ignores binary architecture parameter."),
+ bfd_get_archive_filename (ibfd));
+ }
if (!bfd_set_arch_mach (obfd, iarch, imach)
&& (ibfd->target_defaulted
|| bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
non_fatal (_("Unable to recognise the format of the input file `%s'"),
bfd_get_archive_filename (ibfd));
else
- non_fatal (_("Warning: Output file cannot represent architecture `%s'"),
+ non_fatal (_("Output file cannot represent architecture `%s'"),
bfd_printable_arch_mach (bfd_get_arch (ibfd),
bfd_get_mach (ibfd)));
return FALSE;
if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
{
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
return FALSE;
}
+ if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
+ && bfd_pei_p (obfd))
+ {
+ /* Set up PE parameters. */
+ pe_data_type *pe = pe_data (obfd);
+
+ /* Copy PE parameters before changing them. */
+ if (ibfd->xvec->flavour == bfd_target_coff_flavour
+ && bfd_pei_p (ibfd))
+ pe->pe_opthdr = pe_data (ibfd)->pe_opthdr;
+
+ if (pe_file_alignment != (bfd_vma) -1)
+ pe->pe_opthdr.FileAlignment = pe_file_alignment;
+ else
+ pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
+
+ if (pe_heap_commit != (bfd_vma) -1)
+ pe->pe_opthdr.SizeOfHeapCommit = pe_heap_commit;
+
+ if (pe_heap_reserve != (bfd_vma) -1)
+ pe->pe_opthdr.SizeOfHeapCommit = pe_heap_reserve;
+
+ if (pe_image_base != (bfd_vma) -1)
+ pe->pe_opthdr.ImageBase = pe_image_base;
+
+ if (pe_section_alignment != (bfd_vma) -1)
+ pe->pe_opthdr.SectionAlignment = pe_section_alignment;
+ else
+ pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
+
+ if (pe_stack_commit != (bfd_vma) -1)
+ pe->pe_opthdr.SizeOfStackCommit = pe_stack_commit;
+
+ if (pe_stack_reserve != (bfd_vma) -1)
+ pe->pe_opthdr.SizeOfStackCommit = pe_stack_reserve;
+
+ if (pe_subsystem != -1)
+ pe->pe_opthdr.Subsystem = pe_subsystem;
+
+ if (pe_major_subsystem_version != -1)
+ pe->pe_opthdr.MajorSubsystemVersion = pe_major_subsystem_version;
+
+ if (pe_minor_subsystem_version != -1)
+ pe->pe_opthdr.MinorSubsystemVersion = pe_minor_subsystem_version;
+
+ if (pe_file_alignment > pe_section_alignment)
+ {
+ char file_alignment[20], section_alignment[20];
+
+ sprintf_vma (file_alignment, pe_file_alignment);
+ sprintf_vma (section_alignment, pe_section_alignment);
+ non_fatal (_("warning: file alignment (0x%s) > section alignment (0x%s)"),
+
+ file_alignment, section_alignment);
+ }
+ }
+
if (isympp)
free (isympp);
isympp = NULL;
osympp = NULL;
+ symsize = bfd_get_symtab_upper_bound (ibfd);
+ if (symsize < 0)
+ {
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
+ return FALSE;
+ }
+
+ osympp = isympp = (asymbol **) xmalloc (symsize);
+ symcount = bfd_canonicalize_symtab (ibfd, isympp);
+ if (symcount < 0)
+ {
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
+ return FALSE;
+ }
+
/* BFD mandates that all output sections be created and sizes set before
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 (!extract_symbol)
+ setup_bfd_headers (ibfd, obfd);
if (add_sections != NULL)
{
error codes, so check for the most likely user error first. */
if (bfd_get_section_by_name (obfd, padd->name))
{
- non_fatal (_("can't add section '%s' - it already exists!"), padd->name);
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("can't add section '%s'"), padd->name);
return FALSE;
}
else
{
- padd->section = bfd_make_section_with_flags (obfd, padd->name, flags);
+ /* We use LINKER_CREATED here so that the backend hooks
+ will create any special section type information,
+ instead of presuming we know what we're doing merely
+ because we set the flags. */
+ padd->section = bfd_make_section_with_flags
+ (obfd, padd->name, flags | SEC_LINKER_CREATED);
if (padd->section == NULL)
{
- non_fatal (_("can't create section `%s': %s"),
- padd->name, bfd_errmsg (bfd_get_error ()));
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("can't create section `%s'"),
+ padd->name);
return FALSE;
}
}
if (! bfd_set_section_size (obfd, padd->section, padd->size))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
return FALSE;
}
if (! bfd_set_section_vma (obfd, padd->section,
pset->vma_val))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
return FALSE;
}
(obfd, padd->section,
bfd_section_alignment (obfd, padd->section)))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
return FALSE;
}
}
if (gnu_debuglink_section == NULL)
{
- bfd_nonfatal (gnu_debuglink_filename);
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("cannot create debug link section `%s'"),
+ gnu_debuglink_filename);
return FALSE;
}
}
}
- if (bfd_count_sections (obfd) == 0)
- {
- non_fatal (_("there are no sections to be copied!"));
- return FALSE;
- }
-
- if (gap_fill_set || pad_to_set)
+ if (bfd_count_sections (obfd) != 0
+ && (gap_fill_set || pad_to_set))
{
asection **set;
unsigned int c, i;
We write out the gap contents below. */
c = bfd_count_sections (obfd);
- osections = xmalloc (c * sizeof (asection *));
+ osections = (asection **) xmalloc (c * sizeof (asection *));
set = osections;
bfd_map_over_sections (obfd, get_sections, &set);
qsort (osections, c, sizeof (asection *), compare_section_lma);
- gaps = xmalloc (c * sizeof (bfd_size_type));
+ gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
memset (gaps, 0, c * sizeof (bfd_size_type));
if (gap_fill_set)
if (! bfd_set_section_size (obfd, osections[i],
size + (gap_stop - gap_start)))
{
- non_fatal (_("Can't fill gap after %s: %s"),
- bfd_get_section_name (obfd, osections[i]),
- bfd_errmsg (bfd_get_error ()));
+ bfd_nonfatal_message (NULL, obfd, osections[i],
+ _("Can't fill gap after section"));
status = 1;
break;
}
if (! bfd_set_section_size (obfd, osections[c - 1],
pad_to - lma))
{
- non_fatal (_("Can't add padding to %s: %s"),
- bfd_get_section_name (obfd, osections[c - 1]),
- bfd_errmsg (bfd_get_error ()));
+ bfd_nonfatal_message (NULL, obfd, osections[c - 1],
+ _("can't add padding"));
status = 1;
}
else
/* Symbol filtering must happen after the output sections
have been created, but before their contents are set. */
dhandle = NULL;
- symsize = bfd_get_symtab_upper_bound (ibfd);
- if (symsize < 0)
- {
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
- return FALSE;
- }
-
- osympp = isympp = xmalloc (symsize);
- symcount = bfd_canonicalize_symtab (ibfd, isympp);
- if (symcount < 0)
- {
- bfd_nonfatal (bfd_get_filename (ibfd));
- return FALSE;
- }
-
if (convert_debugging)
- dhandle = read_debugging_info (ibfd, isympp, symcount);
+ dhandle = read_debugging_info (ibfd, isympp, symcount, FALSE);
if (strip_symbols == STRIP_DEBUG
|| strip_symbols == STRIP_ALL
|| strip_symbols == STRIP_UNNEEDED
|| strip_symbols == STRIP_NONDEBUG
|| discard_locals != LOCALS_UNDEF
- || strip_specific_list != NULL
- || keep_specific_list != NULL
- || localize_specific_list != NULL
- || globalize_specific_list != NULL
- || keepglobal_specific_list != NULL
- || weaken_specific_list != NULL
+ || localize_hidden
+ || htab_elements (strip_specific_htab) != 0
+ || htab_elements (keep_specific_htab) != 0
+ || htab_elements (localize_specific_htab) != 0
+ || htab_elements (globalize_specific_htab) != 0
+ || htab_elements (keepglobal_specific_htab) != 0
+ || htab_elements (weaken_specific_htab) != 0
|| prefix_symbols_string
|| sections_removed
|| sections_copied
bfd_map_over_sections (ibfd,
mark_symbols_used_in_relocations,
isympp);
- osympp = xmalloc ((symcount + 1) * sizeof (asymbol *));
+ osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
}
if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
0, padd->size))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
return FALSE;
}
}
if (! bfd_fill_in_gnu_debuglink_section
(obfd, gnu_debuglink_section, gnu_debuglink_filename))
{
- bfd_nonfatal (gnu_debuglink_filename);
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("cannot fill debug link section `%s'"),
+ gnu_debuglink_filename);
return FALSE;
}
}
/* Fill in the gaps. */
if (max_gap > 8192)
max_gap = 8192;
- buf = xmalloc (max_gap);
+ buf = (bfd_byte *) xmalloc (max_gap);
memset (buf, gap_fill, max_gap);
c = bfd_count_sections (obfd);
if (! bfd_set_section_contents (obfd, osections[i], buf,
off, now))
{
- bfd_nonfatal (bfd_get_filename (obfd));
+ bfd_nonfatal_message (NULL, obfd, osections[i], NULL);
return FALSE;
}
}
}
+ /* Do not copy backend data if --extract-symbol is passed; anything
+ that needs to look at the section contents will fail. */
+ if (extract_symbol)
+ return TRUE;
+
/* Allow the BFD backend to copy any private data it understands
from the input BFD to the output BFD. This is done last to
permit the routine to look at the filtered symbol table, which is
important for the ECOFF code at least. */
- if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
- && strip_symbols == STRIP_NONDEBUG)
- /* Do not copy the private data when creating an ELF format
- debug info file. We do not want the program headers. */
- ;
- else if (! bfd_copy_private_bfd_data (ibfd, obfd))
- {
- non_fatal (_("%s: error copying private BFD data: %s"),
- bfd_get_filename (obfd),
- bfd_errmsg (bfd_get_error ()));
+ if (! bfd_copy_private_bfd_data (ibfd, obfd))
+ {
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("error copying private BFD data"));
return FALSE;
}
return TRUE;
}
-#undef MKDIR
-#if defined (_WIN32) && !defined (__CYGWIN32__)
-#define MKDIR(DIR, MODE) mkdir (DIR)
-#else
-#define MKDIR(DIR, MODE) mkdir (DIR, MODE)
-#endif
-
/* Read each archive element in turn from IBFD, copy the
- contents to temp file, and keep the temp file handle. */
+ contents to temp file, and keep the temp file handle.
+ If 'force_output_target' is TRUE then make sure that
+ all elements in the new archive are of the type
+ 'output_target'. */
static void
-copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
+copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
+ bfd_boolean force_output_target,
+ const bfd_arch_info_type *input_arch)
{
struct name_list
{
} *list, *l;
bfd **ptr = &obfd->archive_head;
bfd *this_element;
- char *dir = make_tempname (bfd_get_filename (obfd));
+ char *dir;
+ const char *filename;
/* Make a temp directory to hold the contents. */
- if (MKDIR (dir, 0700) != 0)
- fatal (_("cannot mkdir %s for archive copying (error: %s)"),
- dir, strerror (errno));
+ dir = make_tempdir (bfd_get_filename (obfd));
+ if (dir == NULL)
+ fatal (_("cannot create tempdir for archive copying (error: %s)"),
+ strerror (errno));
obfd->has_armap = ibfd->has_armap;
+ obfd->is_thin_archive = ibfd->is_thin_archive;
list = NULL;
this_element = bfd_openr_next_archived_file (ibfd, NULL);
if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
- RETURN_NONFATAL (bfd_get_filename (obfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, obfd, NULL, NULL);
+ return;
+ }
while (!status && this_element != NULL)
{
bfd *last_element;
struct stat buf;
int stat_status = 0;
- bfd_boolean delete = TRUE;
+ bfd_boolean del = TRUE;
/* Create an output file for this member. */
output_name = concat (dir, "/",
/* If the file already exists, make another temp dir. */
if (stat (output_name, &buf) >= 0)
{
- output_name = make_tempname (output_name);
- if (MKDIR (output_name, 0700) != 0)
- fatal (_("cannot mkdir %s for archive copying (error: %s)"),
- output_name, strerror (errno));
+ output_name = make_tempdir (output_name);
+ if (output_name == NULL)
+ fatal (_("cannot create tempdir for archive copying (error: %s)"),
+ strerror (errno));
- l = xmalloc (sizeof (struct name_list));
+ l = (struct name_list *) xmalloc (sizeof (struct name_list));
l->name = output_name;
l->next = list;
l->obfd = NULL;
bfd_get_filename (this_element), (char *) 0);
}
- output_bfd = bfd_openw (output_name, output_target);
if (preserve_dates)
{
stat_status = bfd_stat_arch_elt (this_element, &buf);
bfd_get_filename (this_element));
}
- l = xmalloc (sizeof (struct name_list));
+ l = (struct name_list *) xmalloc (sizeof (struct name_list));
l->name = output_name;
l->next = list;
l->obfd = NULL;
list = l;
- if (output_bfd == NULL)
- RETURN_NONFATAL (output_name);
-
if (bfd_check_format (this_element, bfd_object))
{
- delete = ! copy_object (this_element, output_bfd);
+ /* PR binutils/3110: Cope with archives
+ containing multiple target types. */
+ if (force_output_target)
+ output_bfd = bfd_openw (output_name, output_target);
+ else
+ output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
- if (! delete
+ if (output_bfd == NULL)
+ {
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
+
+ del = ! copy_object (this_element, output_bfd, input_arch);
+
+ if (! del
|| bfd_get_arch (this_element) != bfd_arch_unknown)
{
if (!bfd_close (output_bfd))
{
- bfd_nonfatal (bfd_get_filename (output_bfd));
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
/* Error in new object file. Don't change archive. */
status = 1;
}
}
else
{
- non_fatal (_("Unable to recognise the format of the input file `%s'"),
- bfd_get_archive_filename (this_element));
+ bfd_nonfatal_message (NULL, this_element, NULL,
+ _("Unable to recognise the format of file"));
+ output_bfd = bfd_openw (output_name, output_target);
copy_unknown_element:
- delete = !copy_unknown_object (this_element, output_bfd);
+ del = !copy_unknown_object (this_element, output_bfd);
if (!bfd_close_all_done (output_bfd))
{
- bfd_nonfatal (bfd_get_filename (output_bfd));
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
/* Error in new object file. Don't change archive. */
status = 1;
}
}
- if (delete)
+ if (del)
{
unlink (output_name);
status = 1;
l->obfd = output_bfd;
*ptr = output_bfd;
- ptr = &output_bfd->next;
+ ptr = &output_bfd->archive_next;
last_element = this_element;
}
*ptr = NULL;
+ filename = bfd_get_filename (obfd);
if (!bfd_close (obfd))
- RETURN_NONFATAL (bfd_get_filename (obfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (filename, NULL, NULL, NULL);
+ return;
+ }
+ filename = bfd_get_filename (ibfd);
if (!bfd_close (ibfd))
- RETURN_NONFATAL (bfd_get_filename (ibfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (filename, NULL, NULL, NULL);
+ return;
+ }
/* Delete all the files that we opened. */
for (l = list; l != NULL; l = l->next)
rmdir (dir);
}
+static void
+set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_handling style)
+{
+ /* This is only relevant to Coff targets. */
+ if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
+ {
+ if (style == KEEP
+ && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
+ style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
+ bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
+ }
+}
+
/* The top-level control. */
static void
copy_file (const char *input_filename, const char *output_filename,
- const char *input_target, const char *output_target)
+ const char *input_target, const char *output_target,
+ const bfd_arch_info_type *input_arch)
{
bfd *ibfd;
char **obj_matching;
char **core_matching;
+ off_t size = get_file_size (input_filename);
- if (get_file_size (input_filename) < 1)
+ if (size < 1)
{
- non_fatal (_("error: the input file '%s' is empty"), input_filename);
+ if (size == 0)
+ non_fatal (_("error: the input file '%s' is empty"),
+ input_filename);
status = 1;
return;
}
non-object file, failures are nonfatal. */
ibfd = bfd_openr (input_filename, input_target);
if (ibfd == NULL)
- RETURN_NONFATAL (input_filename);
+ {
+ bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
if (bfd_check_format (ibfd, bfd_archive))
{
+ bfd_boolean force_output_target;
bfd *obfd;
/* bfd_get_target does not return the correct value until
bfd_check_format succeeds. */
if (output_target == NULL)
- output_target = bfd_get_target (ibfd);
+ {
+ output_target = bfd_get_target (ibfd);
+ force_output_target = FALSE;
+ }
+ else
+ force_output_target = TRUE;
obfd = bfd_openw (output_filename, output_target);
if (obfd == NULL)
- RETURN_NONFATAL (output_filename);
+ {
+ bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
+ /* This is a no-op on non-Coff targets. */
+ set_long_section_mode (obfd, ibfd, long_section_names);
- copy_archive (ibfd, obfd, output_target);
+ copy_archive (ibfd, obfd, output_target, force_output_target, input_arch);
}
else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
{
obfd = bfd_openw (output_filename, output_target);
if (obfd == NULL)
- RETURN_NONFATAL (output_filename);
-
- if (! copy_object (ibfd, obfd))
+ {
+ bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
+ /* This is a no-op on non-Coff targets. */
+ set_long_section_mode (obfd, ibfd, long_section_names);
+
+ if (! copy_object (ibfd, obfd, input_arch))
status = 1;
if (!bfd_close (obfd))
- RETURN_NONFATAL (output_filename);
+ {
+ status = 1;
+ bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
+ return;
+ }
if (!bfd_close (ibfd))
- RETURN_NONFATAL (input_filename);
-
+ {
+ status = 1;
+ bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
+ return;
+ }
}
else
{
if (obj_error != core_error)
bfd_set_error (obj_error);
- bfd_nonfatal (input_filename);
+ bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
if (obj_error == bfd_error_file_ambiguously_recognized)
{
add_section_rename (const char * old_name, const char * new_name,
flagword flags)
{
- section_rename * rename;
+ section_rename * srename;
/* Check for conflicts first. */
- for (rename = section_rename_list; rename != NULL; rename = rename->next)
- if (strcmp (rename->old_name, old_name) == 0)
+ for (srename = section_rename_list; srename != NULL; srename = srename->next)
+ if (strcmp (srename->old_name, old_name) == 0)
{
/* Silently ignore duplicate definitions. */
- if (strcmp (rename->new_name, new_name) == 0
- && rename->flags == flags)
+ if (strcmp (srename->new_name, new_name) == 0
+ && srename->flags == flags)
return;
fatal (_("Multiple renames of section %s"), old_name);
}
- rename = xmalloc (sizeof (* rename));
+ srename = (section_rename *) xmalloc (sizeof (* srename));
- rename->old_name = old_name;
- rename->new_name = new_name;
- rename->flags = flags;
- rename->next = section_rename_list;
+ srename->old_name = old_name;
+ srename->new_name = new_name;
+ srename->flags = flags;
+ srename->next = section_rename_list;
- section_rename_list = rename;
+ section_rename_list = srename;
}
/* Check the section rename list for a new name of the input section
flagword * returned_flags)
{
const char * old_name = bfd_section_name (ibfd, isection);
- section_rename * rename;
+ section_rename * srename;
/* Default to using the flags of the input section. */
* returned_flags = bfd_get_section_flags (ibfd, isection);
- for (rename = section_rename_list; rename != NULL; rename = rename->next)
- if (strcmp (rename->old_name, old_name) == 0)
+ for (srename = section_rename_list; srename != NULL; srename = srename->next)
+ if (strcmp (srename->old_name, old_name) == 0)
{
- if (rename->flags != (flagword) -1)
- * returned_flags = rename->flags;
+ if (srename->flags != (flagword) -1)
+ * returned_flags = srename->flags;
- return rename->new_name;
+ return srename->new_name;
}
return old_name;
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;
+ status = 1;
+ bfd_nonfatal_message (NULL, ibfd, NULL,
+ _("error in private header data"));
+ return;
}
/* 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
static void
setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
{
- bfd *obfd = obfdarg;
+ bfd *obfd = (bfd *) obfdarg;
struct section_list *p;
sec_ptr osection;
bfd_size_type size;
const char *err;
const char * name;
char *prefix = NULL;
+ bfd_boolean make_nobits;
if (is_strip_section (ibfd, isection))
return;
{
char *n;
- n = xmalloc (strlen (prefix) + strlen (name) + 1);
+ n = (char *) xmalloc (strlen (prefix) + strlen (name) + 1);
strcpy (n, prefix);
strcat (n, name);
name = n;
}
+ make_nobits = FALSE;
if (p != NULL && p->set_flags)
flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
- else if (strip_symbols == STRIP_NONDEBUG && (flags & SEC_ALLOC) != 0)
- flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
+ else if (strip_symbols == STRIP_NONDEBUG
+ && (flags & SEC_ALLOC) != 0
+ && (ibfd->xvec->flavour != bfd_target_elf_flavour
+ || elf_section_type (isection) != SHT_NOTE))
+ {
+ flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
+ if (obfd->xvec->flavour == bfd_target_elf_flavour)
+ {
+ make_nobits = TRUE;
+
+ /* Twiddle the input section flags so that it seems to
+ elf.c:copy_private_bfd_data that section flags have not
+ changed between input and output sections. This hack
+ prevents wholesale rewriting of the program headers. */
+ isection->flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
+ }
+ }
osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
if (osection == NULL)
{
- err = _("making");
+ err = _("failed to create output section");
goto loser;
}
- if (strip_symbols == STRIP_NONDEBUG
- && obfd->xvec->flavour == bfd_target_elf_flavour
- && (flags & SEC_ALLOC) != 0
- && (p == NULL || !p->set_flags))
+ if (make_nobits)
elf_section_type (osection) = SHT_NOBITS;
size = bfd_section_size (ibfd, isection);
if (copy_byte >= 0)
size = (size + interleave - 1) / interleave;
+ else if (extract_symbol)
+ size = 0;
if (! bfd_set_section_size (obfd, osection, size))
{
- err = _("size");
+ err = _("failed to set size");
goto loser;
}
if (! bfd_set_section_vma (obfd, osection, vma))
{
- err = _("vma");
+ err = _("failed to set vma");
goto loser;
}
osection,
bfd_section_alignment (ibfd, isection)))
{
- err = _("alignment");
+ err = _("failed to set alignment");
goto loser;
}
isection->output_section = osection;
isection->output_offset = 0;
+ /* Do not copy backend data if --extract-symbol is passed; anything
+ that needs to look at the section contents will fail. */
+ if (extract_symbol)
+ return;
+
+ if ((isection->flags & SEC_GROUP) != 0)
+ {
+ asymbol *gsym = group_signature (isection);
+
+ if (gsym != NULL)
+ {
+ gsym->flags |= BSF_KEEP;
+ if (ibfd->xvec->flavour == bfd_target_elf_flavour)
+ elf_group_id (isection) = gsym;
+ }
+ }
+
/* Allow the BFD backend to copy any private data it understands
from the input section to the output section. */
- if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
- && strip_symbols == STRIP_NONDEBUG)
- /* Do not copy the private data when creating an ELF format
- debug info file. We do not want the program headers. */
- ;
- else if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
- {
- err = _("private data");
+ if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
+ {
+ err = _("failed to copy private data");
goto loser;
}
return;
loser:
- non_fatal (_("%s: section `%s': error in %s: %s"),
- bfd_get_filename (ibfd),
- bfd_section_name (ibfd, isection),
- err, bfd_errmsg (bfd_get_error ()));
status = 1;
+ bfd_nonfatal_message (NULL, obfd, osection, err);
}
/* Copy the data of input section ISECTION of IBFD
static void
copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
{
- bfd *obfd = obfdarg;
+ bfd *obfd = (bfd *) obfdarg;
struct section_list *p;
arelent **relpp;
long relcount;
if (size == 0 || osection == 0)
return;
+ if (extract_symbol)
+ return;
+
p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
/* Core files do not need to be relocated. */
if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
relsize = 0;
else
- RETURN_NONFATAL (bfd_get_filename (ibfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, ibfd, isection, NULL);
+ return;
+ }
}
}
bfd_set_reloc (obfd, osection, NULL, 0);
else
{
- relpp = xmalloc (relsize);
+ relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
if (relcount < 0)
- RETURN_NONFATAL (bfd_get_filename (ibfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, ibfd, isection,
+ _("relocation count is negative"));
+ return;
+ }
if (strip_symbols == STRIP_ALL)
{
long temp_relcount = 0;
long i;
- temp_relpp = xmalloc (relsize);
+ temp_relpp = (arelent **) xmalloc (relsize);
for (i = 0; i < relcount; i++)
if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
- keep_specific_list))
+ keep_specific_htab))
temp_relpp [temp_relcount++] = relpp [i];
relcount = temp_relcount;
free (relpp);
void *memhunk = xmalloc (size);
if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
- RETURN_NONFATAL (bfd_get_filename (ibfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, ibfd, isection, NULL);
+ return;
+ }
+
+ if (reverse_bytes)
+ {
+ /* We don't handle leftover bytes (too many possible behaviors,
+ and we don't know what the user wants). The section length
+ must be a multiple of the number of bytes to swap. */
+ if ((size % reverse_bytes) == 0)
+ {
+ unsigned long i, j;
+ bfd_byte b;
+
+ for (i = 0; i < size; i += reverse_bytes)
+ for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++)
+ {
+ bfd_byte *m = (bfd_byte *) memhunk;
+
+ b = m[i + j];
+ m[i + j] = m[(i + reverse_bytes) - (j + 1)];
+ m[(i + reverse_bytes) - (j + 1)] = b;
+ }
+ }
+ else
+ /* User must pad the section up in order to do this. */
+ fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"),
+ bfd_section_name (ibfd, isection), reverse_bytes);
+ }
if (copy_byte >= 0)
{
/* Keep only every `copy_byte'th byte in MEMHUNK. */
char *from = (char *) memhunk + copy_byte;
- char *to = memhunk;
+ char *to = (char *) memhunk;
char *end = (char *) memhunk + size;
for (; from < end; from += interleave)
}
if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
- RETURN_NONFATAL (bfd_get_filename (obfd));
-
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, obfd, osection, NULL);
+ return;
+ }
free (memhunk);
}
else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
memset (memhunk, 0, size);
if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
- RETURN_NONFATAL (bfd_get_filename (obfd));
+ {
+ status = 1;
+ bfd_nonfatal_message (NULL, obfd, osection, NULL);
+ return;
+ }
free (memhunk);
}
}
static void
get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
{
- asection ***secppp = secppparg;
+ asection ***secppp = (asection ***) secppparg;
**secppp = osection;
++(*secppp);
static int
compare_section_lma (const void *arg1, const void *arg2)
{
- const asection *const *sec1 = arg1;
- const asection *const *sec2 = arg2;
+ const asection *const *sec1 = (const asection * const *) arg1;
+ const asection *const *sec2 = (const asection * const *) arg2;
flagword flags1, flags2;
/* Sort non loadable sections to the front. */
static void
mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
{
- asymbol **symbols = symbolsarg;
+ asymbol **symbols = (asymbol **) symbolsarg;
long relsize;
arelent **relpp;
long relcount, i;
if (relsize == 0)
return;
- relpp = xmalloc (relsize);
+ relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
if (relcount < 0)
bfd_fatal (bfd_get_filename (ibfd));
|| ! bfd_set_section_alignment (obfd, stabsec, 2)
|| ! bfd_set_section_alignment (obfd, stabstrsec, 0))
{
- non_fatal (_("%s: can't create debugging section: %s"),
- bfd_get_filename (obfd),
- bfd_errmsg (bfd_get_error ()));
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("can't create debugging section"));
return FALSE;
}
|| ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
stringsize))
{
- non_fatal (_("%s: can't set debugging section contents: %s"),
- bfd_get_filename (obfd),
- bfd_errmsg (bfd_get_error ()));
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("can't set debugging section contents"));
return FALSE;
}
return TRUE;
}
- non_fatal (_("%s: don't know how to write debugging information for %s"),
- bfd_get_filename (obfd), bfd_get_target (obfd));
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("don't know how to write debugging information for %s"),
+ bfd_get_target (obfd));
return FALSE;
}
strip_symbols = STRIP_UNNEEDED;
break;
case 'K':
- add_specific_symbol (optarg, &keep_specific_list);
+ add_specific_symbol (optarg, keep_specific_htab);
break;
case 'N':
- add_specific_symbol (optarg, &strip_specific_list);
+ add_specific_symbol (optarg, strip_specific_htab);
break;
case 'o':
output_file = optarg;
display_info ();
return 0;
}
-
+
if (show_version)
print_version ("strip");
/* Default is to strip all symbols. */
if (strip_symbols == STRIP_UNDEF
&& discard_locals == LOCALS_UNDEF
- && strip_specific_list == NULL)
+ && htab_elements (strip_specific_htab) == 0)
strip_symbols = STRIP_ALL;
if (output_target == NULL)
char *tmpname;
if (get_file_size (argv[i]) < 1)
- continue;
+ {
+ status = 1;
+ continue;
+ }
if (preserve_dates)
/* No need to check the return value of stat().
It has already been checked in get_file_size(). */
stat (argv[i], &statbuf);
- if (output_file != NULL)
- tmpname = output_file;
- else
+ if (output_file == NULL || strcmp (argv[i], output_file) == 0)
tmpname = make_tempname (argv[i]);
- status = 0;
+ else
+ tmpname = output_file;
+
+ if (tmpname == NULL)
+ {
+ bfd_nonfatal_message (argv[i], NULL, NULL,
+ _("could not create temporary file to hold stripped copy"));
+ status = 1;
+ continue;
+ }
- copy_file (argv[i], tmpname, input_target, output_target);
+ status = 0;
+ copy_file (argv[i], tmpname, input_target, output_target, NULL);
if (status == 0)
{
if (preserve_dates)
set_times (tmpname, &statbuf);
- if (output_file == NULL)
- smart_rename (tmpname, argv[i], preserve_dates);
- status = hold_status;
+ if (output_file != tmpname)
+ status = (smart_rename (tmpname,
+ output_file ? output_file : argv[i],
+ preserve_dates) != 0);
+ if (status == 0)
+ status = hold_status;
}
else
unlink_if_ordinary (tmpname);
- if (output_file == NULL)
+ if (output_file != tmpname)
free (tmpname);
}
- return 0;
+ return status;
+}
+
+/* Set up PE subsystem. */
+
+static void
+set_pe_subsystem (const char *s)
+{
+ const char *version, *subsystem;
+ size_t i;
+ static const struct
+ {
+ const char *name;
+ const char set_def;
+ const short value;
+ }
+ v[] =
+ {
+ { "native", 0, IMAGE_SUBSYSTEM_NATIVE },
+ { "windows", 0, IMAGE_SUBSYSTEM_WINDOWS_GUI },
+ { "console", 0, IMAGE_SUBSYSTEM_WINDOWS_CUI },
+ { "posix", 0, IMAGE_SUBSYSTEM_POSIX_CUI },
+ { "wince", 0, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI },
+ { "efi-app", 1, IMAGE_SUBSYSTEM_EFI_APPLICATION },
+ { "efi-bsd", 1, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER },
+ { "efi-rtd", 1, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
+ { "sal-rtd", 1, IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER },
+ { "xbox", 0, IMAGE_SUBSYSTEM_XBOX }
+ };
+ short value;
+ char *copy;
+ int set_def = -1;
+
+ /* Check for the presence of a version number. */
+ version = strchr (s, ':');
+ if (version == NULL)
+ subsystem = s;
+ else
+ {
+ int len = version - s;
+ copy = xstrdup (s);
+ subsystem = copy;
+ copy[len] = '\0';
+ version = copy + 1 + len;
+ pe_major_subsystem_version = strtoul (version, ©, 0);
+ if (*copy == '.')
+ pe_minor_subsystem_version = strtoul (copy + 1, ©, 0);
+ if (*copy != '\0')
+ non_fatal (_("%s: bad version in PE subsystem"), s);
+ }
+
+ /* Check for numeric subsystem. */
+ value = (short) strtol (subsystem, ©, 0);
+ if (*copy == '\0')
+ {
+ for (i = 0; i < ARRAY_SIZE (v); i++)
+ if (v[i].value == value)
+ {
+ pe_subsystem = value;
+ set_def = v[i].set_def;
+ break;
+ }
+ }
+ else
+ {
+ /* Search for subsystem by name. */
+ for (i = 0; i < ARRAY_SIZE (v); i++)
+ if (strcmp (subsystem, v[i].name) == 0)
+ {
+ pe_subsystem = v[i].value;
+ set_def = v[i].set_def;
+ break;
+ }
+ }
+
+ switch (set_def)
+ {
+ case -1:
+ fatal (_("unknown PE subsystem: %s"), s);
+ break;
+ case 0:
+ break;
+ default:
+ if (pe_file_alignment == (bfd_vma) -1)
+ pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
+ if (pe_section_alignment == (bfd_vma) -1)
+ pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
+ break;
+ }
+}
+
+/* Convert EFI target to PEI target. */
+
+static void
+convert_efi_target (char *efi)
+{
+ efi[0] = 'p';
+ efi[1] = 'e';
+ efi[2] = 'i';
+
+ if (strcmp (efi + 4, "ia32") == 0)
+ {
+ /* Change ia32 to i386. */
+ efi[5]= '3';
+ efi[6]= '8';
+ efi[7]= '6';
+ }
+ else if (strcmp (efi + 4, "x86_64") == 0)
+ {
+ /* Change x86_64 to x86-64. */
+ efi[7] = '-';
+ }
}
static int
copy_main (int argc, char *argv[])
{
- char * binary_architecture = NULL;
char *input_filename = NULL;
char *output_filename = NULL;
+ char *tmpname;
char *input_target = NULL;
char *output_target = NULL;
bfd_boolean show_version = FALSE;
int c;
struct section_list *p;
struct stat statbuf;
+ const bfd_arch_info_type *input_arch = NULL;
while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w",
copy_options, (int *) 0)) != EOF)
break;
case 'B':
- binary_architecture = optarg;
+ input_arch = bfd_scan_arch (optarg);
+ if (input_arch == NULL)
+ fatal (_("architecture %s unknown"), optarg);
break;
case 'i':
break;
case 'K':
- add_specific_symbol (optarg, &keep_specific_list);
+ add_specific_symbol (optarg, keep_specific_htab);
break;
case 'N':
- add_specific_symbol (optarg, &strip_specific_list);
+ add_specific_symbol (optarg, strip_specific_htab);
break;
case OPTION_STRIP_UNNEEDED_SYMBOL:
- add_specific_symbol (optarg, &strip_unneeded_list);
+ add_specific_symbol (optarg, strip_unneeded_htab);
break;
case 'L':
- add_specific_symbol (optarg, &localize_specific_list);
+ add_specific_symbol (optarg, localize_specific_htab);
break;
case OPTION_GLOBALIZE_SYMBOL:
- add_specific_symbol (optarg, &globalize_specific_list);
+ add_specific_symbol (optarg, globalize_specific_htab);
break;
case 'G':
- add_specific_symbol (optarg, &keepglobal_specific_list);
+ add_specific_symbol (optarg, keepglobal_specific_htab);
break;
case 'W':
- add_specific_symbol (optarg, &weaken_specific_list);
+ add_specific_symbol (optarg, weaken_specific_htab);
break;
case 'p':
case OPTION_ADD_SECTION:
{
const char *s;
- off_t size;
+ size_t off, alloc;
struct section_add *pa;
- int len;
- char *name;
FILE *f;
s = strchr (optarg, '=');
if (s == NULL)
fatal (_("bad format for %s"), "--add-section");
- size = get_file_size (s + 1);
- if (size < 1)
- break;
-
- pa = xmalloc (sizeof (struct section_add));
-
- len = s - optarg;
- name = xmalloc (len + 1);
- strncpy (name, optarg, len);
- name[len] = '\0';
- pa->name = name;
-
+ pa = (struct section_add *) xmalloc (sizeof (struct section_add));
+ pa->name = xstrndup (optarg, s - optarg);
pa->filename = s + 1;
- pa->size = size;
- pa->contents = xmalloc (size);
- f = fopen (pa->filename, FOPEN_RB);
+ /* We don't use get_file_size so that we can do
+ --add-section .note.GNU_stack=/dev/null
+ get_file_size doesn't work on /dev/null. */
+ f = fopen (pa->filename, FOPEN_RB);
if (f == NULL)
fatal (_("cannot open: %s: %s"),
pa->filename, strerror (errno));
- if (fread (pa->contents, 1, pa->size, f) == 0
- || ferror (f))
- fatal (_("%s: fread failed"), pa->filename);
+ off = 0;
+ alloc = 4096;
+ pa->contents = (bfd_byte *) xmalloc (alloc);
+ while (!feof (f))
+ {
+ off_t got;
+
+ if (off == alloc)
+ {
+ alloc <<= 1;
+ pa->contents = (bfd_byte *) xrealloc (pa->contents, alloc);
+ }
+
+ got = fread (pa->contents + off, 1, alloc - off, f);
+ if (ferror (f))
+ fatal (_("%s: fread failed"), pa->filename);
+
+ off += got;
+ }
+
+ pa->size = off;
fclose (f);
}
len = s - optarg;
- name = xmalloc (len + 1);
+ name = (char *) xmalloc (len + 1);
strncpy (name, optarg, len);
name[len] = '\0';
fatal (_("bad format for %s"), "--redefine-sym");
len = s - optarg;
- source = xmalloc (len + 1);
+ source = (char *) xmalloc (len + 1);
strncpy (source, optarg, len);
source[len] = '\0';
nextarg = s + 1;
len = strlen (nextarg);
- target = xmalloc (len + 1);
+ target = (char *) xmalloc (len + 1);
strcpy (target, nextarg);
redefine_list_append ("--redefine-sym", source, target);
fatal (_("bad format for %s"), "--set-section-flags");
len = s - optarg;
- name = xmalloc (len + 1);
+ name = (char *) xmalloc (len + 1);
strncpy (name, optarg, len);
name[len] = '\0';
if (len == 0)
fatal (_("bad format for %s"), "--rename-section");
- old_name = xmalloc (len + 1);
+ old_name = (char *) xmalloc (len + 1);
strncpy (old_name, optarg, len);
old_name[len] = 0;
if (len == 0)
fatal (_("bad format for %s"), "--rename-section");
- new_name = xmalloc (len + 1);
+ new_name = (char *) xmalloc (len + 1);
strncpy (new_name, eq, len);
new_name[len] = 0;
break;
case OPTION_STRIP_SYMBOLS:
- add_specific_symbols (optarg, &strip_specific_list);
+ add_specific_symbols (optarg, strip_specific_htab);
break;
case OPTION_STRIP_UNNEEDED_SYMBOLS:
- add_specific_symbols (optarg, &strip_unneeded_list);
+ add_specific_symbols (optarg, strip_unneeded_htab);
break;
case OPTION_KEEP_SYMBOLS:
- add_specific_symbols (optarg, &keep_specific_list);
+ add_specific_symbols (optarg, keep_specific_htab);
+ break;
+
+ case OPTION_LOCALIZE_HIDDEN:
+ localize_hidden = TRUE;
break;
case OPTION_LOCALIZE_SYMBOLS:
- add_specific_symbols (optarg, &localize_specific_list);
+ add_specific_symbols (optarg, localize_specific_htab);
+ break;
+
+ case OPTION_LONG_SECTION_NAMES:
+ if (!strcmp ("enable", optarg))
+ long_section_names = ENABLE;
+ else if (!strcmp ("disable", optarg))
+ long_section_names = DISABLE;
+ else if (!strcmp ("keep", optarg))
+ long_section_names = KEEP;
+ else
+ fatal (_("unknown long section names option '%s'"), optarg);
break;
case OPTION_GLOBALIZE_SYMBOLS:
- add_specific_symbols (optarg, &globalize_specific_list);
+ add_specific_symbols (optarg, globalize_specific_htab);
break;
case OPTION_KEEPGLOBAL_SYMBOLS:
- add_specific_symbols (optarg, &keepglobal_specific_list);
+ add_specific_symbols (optarg, keepglobal_specific_htab);
break;
case OPTION_WEAKEN_SYMBOLS:
- add_specific_symbols (optarg, &weaken_specific_list);
+ add_specific_symbols (optarg, weaken_specific_htab);
break;
case OPTION_ALT_MACH_CODE:
bfd_flags_to_set &= ~D_PAGED;
break;
+ case OPTION_EXTRACT_SYMBOL:
+ extract_symbol = TRUE;
+ break;
+
+ case OPTION_REVERSE_BYTES:
+ {
+ int prev = reverse_bytes;
+
+ reverse_bytes = atoi (optarg);
+ if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0))
+ fatal (_("number of bytes to reverse must be positive and even"));
+
+ if (prev && prev != reverse_bytes)
+ non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"),
+ prev);
+ break;
+ }
+
+ case OPTION_FILE_ALIGNMENT:
+ pe_file_alignment = parse_vma (optarg, "--file-alignment");
+ break;
+
+ case OPTION_HEAP:
+ {
+ char *end;
+ pe_heap_reserve = strtoul (optarg, &end, 0);
+ if (end == optarg
+ || (*end != '.' && *end != '\0'))
+ non_fatal (_("%s: invalid reserve value for --heap"),
+ optarg);
+ else if (*end != '\0')
+ {
+ pe_heap_commit = strtoul (end + 1, &end, 0);
+ if (*end != '\0')
+ non_fatal (_("%s: invalid commit value for --heap"),
+ optarg);
+ }
+ }
+ break;
+
+ case OPTION_IMAGE_BASE:
+ pe_image_base = parse_vma (optarg, "--image-base");
+ break;
+
+ case OPTION_SECTION_ALIGNMENT:
+ pe_section_alignment = parse_vma (optarg,
+ "--section-alignment");
+ break;
+
+ case OPTION_SUBSYSTEM:
+ set_pe_subsystem (optarg);
+ break;
+
+ case OPTION_STACK:
+ {
+ char *end;
+ pe_stack_reserve = strtoul (optarg, &end, 0);
+ if (end == optarg
+ || (*end != '.' && *end != '\0'))
+ non_fatal (_("%s: invalid reserve value for --stack"),
+ optarg);
+ else if (*end != '\0')
+ {
+ pe_stack_commit = strtoul (end + 1, &end, 0);
+ if (*end != '\0')
+ non_fatal (_("%s: invalid commit value for --stack"),
+ optarg);
+ }
+ }
+ break;
+
case 0:
/* We've been given a long option. */
break;
display_info ();
return 0;
}
-
+
if (show_version)
print_version ("objcopy");
if (output_target == NULL)
output_target = input_target;
- if (binary_architecture != NULL)
+ /* Convert input EFI target to PEI target. */
+ if (input_target != NULL
+ && strncmp (input_target, "efi-", 4) == 0)
{
- if (input_target && strcmp (input_target, "binary") == 0)
- {
- const bfd_arch_info_type * temp_arch_info;
+ char *efi;
- temp_arch_info = bfd_scan_arch (binary_architecture);
+ efi = xstrdup (output_target + 4);
+ if (strncmp (efi, "bsdrv-", 6) == 0
+ || strncmp (efi, "rtdrv-", 6) == 0)
+ efi += 2;
+ else if (strncmp (efi, "app-", 4) != 0)
+ fatal (_("unknown input EFI target: %s"), input_target);
- if (temp_arch_info != NULL)
- {
- bfd_external_binary_architecture = temp_arch_info->arch;
- bfd_external_machine = temp_arch_info->mach;
- }
- else
- fatal (_("architecture %s unknown"), binary_architecture);
+ input_target = efi;
+ convert_efi_target (efi);
+ }
+
+ /* Convert output EFI target to PEI target. */
+ if (output_target != NULL
+ && strncmp (output_target, "efi-", 4) == 0)
+ {
+ char *efi;
+
+ efi = xstrdup (output_target + 4);
+ if (strncmp (efi, "app-", 4) == 0)
+ {
+ if (pe_subsystem == -1)
+ pe_subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
}
- else
+ else if (strncmp (efi, "bsdrv-", 6) == 0)
+ {
+ if (pe_subsystem == -1)
+ pe_subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
+ efi += 2;
+ }
+ else if (strncmp (efi, "rtdrv-", 6) == 0)
{
- non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
- non_fatal (_(" Argument %s ignored"), binary_architecture);
+ if (pe_subsystem == -1)
+ pe_subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
+ efi += 2;
}
+ else
+ fatal (_("unknown output EFI target: %s"), output_target);
+
+ if (pe_file_alignment == (bfd_vma) -1)
+ pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
+ if (pe_section_alignment == (bfd_vma) -1)
+ pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
+
+ output_target = efi;
+ convert_efi_target (efi);
}
if (preserve_dates)
/* If there is no destination file, or the source and destination files
are the same, then create a temp and rename the result into the input. */
if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
- {
- char *tmpname = make_tempname (input_filename);
-
- copy_file (input_filename, tmpname, input_target, output_target);
- if (status == 0)
- {
- if (preserve_dates)
- set_times (tmpname, &statbuf);
- smart_rename (tmpname, input_filename, preserve_dates);
- }
- else
- unlink (tmpname);
- }
+ tmpname = make_tempname (input_filename);
else
- {
- copy_file (input_filename, output_filename, input_target, output_target);
+ tmpname = output_filename;
+
+ if (tmpname == NULL)
+ fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
+ input_filename, strerror (errno));
- if (status == 0 && preserve_dates)
- set_times (output_filename, &statbuf);
- else if (status != 0)
- unlink_if_ordinary (output_filename);
+ copy_file (input_filename, tmpname, input_target, output_target, input_arch);
+ if (status == 0)
+ {
+ if (preserve_dates)
+ set_times (tmpname, &statbuf);
+ if (tmpname != output_filename)
+ status = (smart_rename (tmpname, input_filename,
+ preserve_dates) != 0);
}
+ else
+ unlink_if_ordinary (tmpname);
if (change_warn)
{
is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
}
+ create_symbol_htabs ();
+
if (is_strip)
strip_main (argc, argv);
else