/* 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
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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,
#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. */
/* 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). */
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_KEEP_SYMBOLS,
OPTION_LOCALIZE_HIDDEN,
OPTION_LOCALIZE_SYMBOLS,
+ OPTION_LONG_SECTION_NAMES,
OPTION_GLOBALIZE_SYMBOL,
OPTION_GLOBALIZE_SYMBOLS,
OPTION_KEEPGLOBAL_SYMBOLS,
OPTION_PURE,
OPTION_IMPURE,
OPTION_EXTRACT_SYMBOL,
- OPTION_REVERSE_BYTES
+ 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". */
{"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},
{"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\
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\
--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\
{
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;
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. */
else
gname = sec->name;
if ((strip_symbols == STRIP_ALL
- && !is_specified_symbol (gname, keep_specific_list))
- || is_specified_symbol (gname, strip_specific_list))
+ && !is_specified_symbol (gname, keep_specific_htab))
+ || is_specified_symbol (gname, strip_specific_htab))
return TRUE;
}
{
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);
used_in_reloc = TRUE;
}
else if (relocatable /* Relocatable file. */
- && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
+ && ((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
&& (discard_locals != LOCALS_START_L
|| ! bfd_is_local_label (abfd, sym))));
- if (keep && is_specified_symbol (name, strip_specific_list))
+ 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 (keep
&& !(flags & BSF_KEEP)
- && is_specified_symbol (name, strip_unneeded_list))
+ && is_specified_symbol (name, strip_unneeded_htab))
keep = FALSE;
if (!keep
&& ((keep_file_symbols && (flags & BSF_FILE))
- || is_specified_symbol (name, keep_specific_list)))
+ || is_specified_symbol (name, keep_specific_htab)))
keep = TRUE;
if (keep && is_strip_section (abfd, bfd_get_section (sym)))
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);
if (!undefined
&& (flags & BSF_LOCAL)
- && is_specified_symbol (name, globalize_specific_list))
+ && 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);
lineno = 1;
c = getc (file);
if (len >= bufsize)
{
bufsize *= 2;
- buf = xrealloc (buf, bufsize);
+ buf = (char *) xrealloc (buf, bufsize);
}
c = getc (file);
}
if (len >= bufsize)
{
bufsize *= 2;
- buf = xrealloc (buf, bufsize);
+ buf = (char *) xrealloc (buf, bufsize);
}
c = getc (file);
}
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;
}
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)))
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);
symsize = bfd_get_symtab_upper_bound (ibfd);
if (symsize < 0)
{
- bfd_nonfatal (bfd_get_archive_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
return FALSE;
}
- osympp = isympp = xmalloc (symsize);
+ osympp = isympp = (asymbol **) xmalloc (symsize);
symcount = bfd_canonicalize_symtab (ibfd, isympp);
if (symcount < 0)
{
- bfd_nonfatal (bfd_get_filename (ibfd));
+ bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
return FALSE;
}
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);
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;
}
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
have been created, but before their contents are set. */
dhandle = NULL;
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_NONDEBUG
|| discard_locals != LOCALS_UNDEF
|| localize_hidden
- || strip_specific_list != NULL
- || keep_specific_list != NULL
- || localize_specific_list != NULL
- || globalize_specific_list != NULL
- || keepglobal_specific_list != NULL
- || weaken_specific_list != NULL
+ || 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;
}
important for the ECOFF code at least. */
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 ()));
+ bfd_nonfatal_message (NULL, obfd, NULL,
+ _("error copying private BFD data"));
return FALSE;
}
static void
copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
- bfd_boolean force_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;
+ char *dir;
+ const char *filename;
/* Make a temp directory to hold the contents. */
dir = make_tempdir (bfd_get_filename (obfd));
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, "/",
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));
}
- 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;
output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
if (output_bfd == NULL)
- RETURN_NONFATAL (output_name);
+ {
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
- delete = ! copy_object (this_element, output_bfd);
+ del = ! copy_object (this_element, output_bfd, input_arch);
- if (! delete
+ 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;
}
*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)
{
+ 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))
{
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, force_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
- && obfd->xvec->flavour != bfd_target_elf_flavour
- && (flags & SEC_ALLOC) != 0)
- flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
+ && (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
- && elf_section_type (osection) != SHT_NOTE
- && (ibfd->xvec->flavour != bfd_target_elf_flavour
- || elf_section_type (isection) != SHT_NOTE)
- && (p == NULL || !p->set_flags))
+ if (make_nobits)
elf_section_type (osection) = SHT_NOBITS;
size = bfd_section_size (ibfd, isection);
size = 0;
if (! bfd_set_section_size (obfd, osection, size))
{
- err = _("size");
+ err = _("failed to set size");
goto loser;
}
else
vma += change_section_address;
- if (! bfd_set_section_vma (obfd, osection, extract_symbol ? 0 : vma))
+ if (! bfd_set_section_vma (obfd, osection, vma))
{
- err = _("vma");
+ err = _("failed to set vma");
goto loser;
}
else
lma += change_section_address;
- osection->lma = extract_symbol ? 0 : lma;
+ osection->lma = lma;
/* FIXME: This is probably not enough. If we change the LMA we
may have to recompute the header for the file as well. */
osection,
bfd_section_alignment (ibfd, isection)))
{
- err = _("alignment");
+ err = _("failed to set alignment");
goto loser;
}
bfd_get_section_by_name since some formats allow multiple
sections with the same name. */
isection->output_section = osection;
- isection->output_offset = extract_symbol ? vma : 0;
+ 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_copy_private_section_data (ibfd, isection, obfd, osection))
{
- err = _("private data");
+ err = _("failed to copy private data");
goto loser;
}
- else if ((isection->flags & SEC_GROUP) != 0)
- {
- asymbol *gsym = group_signature (isection);
-
- if (gsym != NULL)
- gsym->flags |= BSF_KEEP;
- }
/* All went well. */
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);
free (relpp);
}
- if (extract_symbol)
- return;
-
if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
{
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)
{
{
/* 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;
/* 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)
if (tmpname == NULL)
{
- non_fatal (_("could not create temporary file to hold stripped copy of '%s'"),
- argv[i]);
+ bfd_nonfatal_message (argv[i], NULL, NULL,
+ _("could not create temporary file to hold stripped copy"));
status = 1;
continue;
}
status = 0;
- copy_file (argv[i], tmpname, input_target, output_target);
+ copy_file (argv[i], tmpname, input_target, output_target, NULL);
if (status == 0)
{
if (preserve_dates)
set_times (tmpname, &statbuf);
if (output_file != tmpname)
- smart_rename (tmpname, output_file ? output_file : argv[i],
- preserve_dates);
- status = hold_status;
+ status = (smart_rename (tmpname,
+ output_file ? output_file : argv[i],
+ preserve_dates) != 0);
+ if (status == 0)
+ status = hold_status;
}
else
unlink_if_ordinary (tmpname);
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;
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':
break;
}
- pa = xmalloc (sizeof (struct section_add));
+ pa = (struct section_add *) xmalloc (sizeof (struct section_add));
len = s - optarg;
- name = xmalloc (len + 1);
+ name = (char *) xmalloc (len + 1);
strncpy (name, optarg, len);
name[len] = '\0';
pa->name = name;
pa->filename = s + 1;
pa->size = size;
- pa->contents = xmalloc (size);
+ pa->contents = (bfd_byte *) xmalloc (size);
f = fopen (pa->filename, FOPEN_RB);
}
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:
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:
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;
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)
fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
input_filename, strerror (errno));
- copy_file (input_filename, tmpname, input_target, output_target);
+ 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)
- smart_rename (tmpname, input_filename, preserve_dates);
+ status = (smart_rename (tmpname, input_filename,
+ preserve_dates) != 0);
}
else
unlink_if_ordinary (tmpname);
is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
}
+ create_symbol_htabs ();
+
if (is_strip)
strip_main (argc, argv);
else