/* 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, 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,
#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 ();
+}
- tmp_list = xmalloc (sizeof (struct symlist));
- tmp_list->name = name;
- tmp_list->next = *list;
- *list = tmp_list;
+/* Add a symbol to strip_specific_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;
}
{
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++)
{
{
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))
+ && (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;
}
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);
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);
- /* Don't copy headers when creating an ELF format debug info file. */
- if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
- && strip_symbols == STRIP_NONDEBUG)
- ;
- else
+ 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;
}
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;
}
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;
}
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;
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)
{
+ 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 && (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);
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;
- /* 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");
- goto loser;
- }
- else if ((isection->flags & SEC_GROUP) != 0)
+ if ((isection->flags & SEC_GROUP) != 0)
{
asymbol *gsym = group_signature (isection);
if (gsym != NULL)
- gsym->flags |= BSF_KEEP;
+ {
+ 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 = _("failed to copy private data");
+ goto loser;
}
/* 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;
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)
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;
+ 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)
- {
- status = 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:
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;
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)
tmpname = make_tempname (input_filename);
else
tmpname = output_filename;
-
+
if (tmpname == NULL)
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