X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=binutils%2Fobjcopy.c;fp=binutils%2Fobjcopy.c;h=2048827f8e17f21d9bdf06545466247f7b2b1fc2;hp=e577dd30160b55bed773cae29f09da23324542ab;hb=d5da4f291af551c0b8b79e1d4a9b173d60e5c10e;hpb=7b5ea4fcdf2819e070665ab5610f8b48e3867c10 diff --git a/binutils/objcopy.c b/binutils/objcopy.c index e577dd3..2048827 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1,6 +1,6 @@ /* 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. @@ -32,16 +32,29 @@ #include "elf-bfd.h" #include #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. */ @@ -64,8 +77,6 @@ section_rename; /* 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. */ @@ -196,13 +207,13 @@ static bfd_boolean localize_hidden = FALSE; /* List of symbols to strip, keep, localize, keep-global, weaken, or redefine. */ -static struct symlist *strip_specific_list = NULL; -static struct symlist *strip_unneeded_list = NULL; -static struct symlist *keep_specific_list = NULL; -static struct symlist *localize_specific_list = NULL; -static struct symlist *globalize_specific_list = NULL; -static struct symlist *keepglobal_specific_list = NULL; -static struct symlist *weaken_specific_list = NULL; +static htab_t strip_specific_htab = NULL; +static htab_t strip_unneeded_htab = NULL; +static htab_t keep_specific_htab = NULL; +static htab_t localize_specific_htab = NULL; +static htab_t globalize_specific_htab = NULL; +static htab_t keepglobal_specific_htab = NULL; +static htab_t weaken_specific_htab = NULL; static struct redefine_node *redefine_sym_list = NULL; /* If this is TRUE, we weaken global symbols (set BSF_WEAK). */ @@ -223,6 +234,18 @@ static bfd_boolean extract_symbol = FALSE; of 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 @@ -254,6 +277,7 @@ 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, @@ -272,7 +296,13 @@ enum command_line_switch 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". */ @@ -347,6 +377,7 @@ static struct option copy_options[] = {"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}, @@ -385,6 +416,12 @@ static struct option copy_options[] = {"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} }; @@ -477,6 +514,8 @@ copy_usage (FILE *stream, int exit_status) Set section 's properties to \n\ --add-section = Add section found in to output\n\ --rename-section =[,] Rename section to \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= Reverse bytes at a time, in output sections with content\n\ @@ -504,6 +543,15 @@ copy_usage (FILE *stream, int exit_status) --prefix-alloc-sections \n\ Add to start of every allocatable\n\ section name\n\ + --file-alignment Set PE file alignment to \n\ + --heap [,] Set PE reserve/commit heap to /\n\ + \n\ + --image-base
Set PE image base to
\n\ + --section-alignment Set PE section alignment to \n\ + --stack [,] Set PE reserve/commit stack to /\n\ + \n\ + --subsystem [:]\n\ + Set PE subsystem to [& ]\n]\ -v --verbose List all object files modified\n\ @ Read options from \n\ -V --version Display this program's version number\n\ @@ -592,7 +640,7 @@ parse_flags (const char *s) { 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); @@ -621,7 +669,7 @@ find_section_list (const char *name, bfd_boolean add) 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; @@ -639,17 +687,38 @@ find_section_list (const char *name, bfd_boolean add) 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. */ @@ -658,7 +727,7 @@ add_specific_symbol (const char *name, struct symlist **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; @@ -673,7 +742,7 @@ add_specific_symbols (const char *filename, struct symlist **list) 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)); @@ -759,7 +828,7 @@ add_specific_symbols (const char *filename, struct symlist **list) * 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. */ @@ -768,36 +837,55 @@ add_specific_symbols (const char *filename, struct symlist **list) } } -/* 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. */ @@ -874,8 +962,8 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) 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; } @@ -969,8 +1057,8 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, { 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); @@ -996,7 +1084,8 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 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 @@ -1023,7 +1112,7 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, && (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. */ @@ -1038,12 +1127,12 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 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))) @@ -1052,7 +1141,7 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 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; @@ -1060,9 +1149,9 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 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); @@ -1071,7 +1160,7 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 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; @@ -1120,7 +1209,7 @@ redefine_list_append (const char *cause, const char *source, const char *target) 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); @@ -1148,7 +1237,7 @@ add_redefine_syms_file (const char *filename) filename, strerror (errno)); bufsize = 100; - buf = xmalloc (bufsize); + buf = (char *) xmalloc (bufsize); lineno = 1; c = getc (file); @@ -1165,7 +1254,7 @@ add_redefine_syms_file (const char *filename) if (len >= bufsize) { bufsize *= 2; - buf = xrealloc (buf, bufsize); + buf = (char *) xrealloc (buf, bufsize); } c = getc (file); } @@ -1191,7 +1280,7 @@ add_redefine_syms_file (const char *filename) if (len >= bufsize) { bufsize *= 2; - buf = xrealloc (buf, bufsize); + buf = (char *) xrealloc (buf, bufsize); } c = getc (file); } @@ -1254,7 +1343,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) if (bfd_stat_arch_elt (ibfd, &buf) != 0) { - bfd_nonfatal (bfd_get_archive_filename (ibfd)); + bfd_nonfatal_message (NULL, ibfd, NULL, NULL); return FALSE; } @@ -1276,7 +1365,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) 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) { @@ -1287,7 +1376,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) 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; } @@ -1295,7 +1384,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) 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; } @@ -1332,7 +1421,7 @@ copy_object (bfd *ibfd, bfd *obfd) if (!bfd_set_format (obfd, bfd_get_format (ibfd))) { - bfd_nonfatal (bfd_get_filename (obfd)); + bfd_nonfatal_message (NULL, obfd, NULL, NULL); return FALSE; } @@ -1363,10 +1452,13 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } } @@ -1390,10 +1482,67 @@ copy_object (bfd *ibfd, bfd *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); @@ -1406,15 +1555,15 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1422,7 +1571,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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) { @@ -1445,7 +1595,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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 @@ -1453,15 +1604,16 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1471,7 +1623,7 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1483,7 +1635,7 @@ copy_object (bfd *ibfd, bfd *obfd) (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; } } @@ -1498,7 +1650,9 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1559,13 +1713,13 @@ copy_object (bfd *ibfd, bfd *obfd) 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) @@ -1589,9 +1743,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1614,9 +1767,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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 @@ -1633,7 +1785,7 @@ copy_object (bfd *ibfd, bfd *obfd) 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 @@ -1641,12 +1793,12 @@ copy_object (bfd *ibfd, bfd *obfd) || 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 @@ -1668,7 +1820,7 @@ copy_object (bfd *ibfd, bfd *obfd) 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); } @@ -1695,7 +1847,7 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } } @@ -1706,7 +1858,9 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } } @@ -1719,7 +1873,7 @@ copy_object (bfd *ibfd, bfd *obfd) /* 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); @@ -1745,7 +1899,7 @@ copy_object (bfd *ibfd, bfd *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; } @@ -1767,9 +1921,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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; } @@ -1813,7 +1966,8 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, } *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)); @@ -1822,13 +1976,18 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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) { @@ -1837,7 +1996,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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, "/", @@ -1851,7 +2010,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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; @@ -1869,7 +2028,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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; @@ -1885,16 +2044,20 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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); - 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; } @@ -1904,21 +2067,21 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, } 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; @@ -1945,11 +2108,21 @@ copy_unknown_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) @@ -1965,6 +2138,19 @@ copy_unknown_element: 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 @@ -1974,9 +2160,13 @@ copy_file (const char *input_filename, const char *output_filename, 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; } @@ -1985,7 +2175,11 @@ copy_file (const char *input_filename, const char *output_filename, 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)) { @@ -2004,7 +2198,13 @@ copy_file (const char *input_filename, const char *output_filename, 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); } @@ -2020,17 +2220,30 @@ copy_file (const char *input_filename, const char *output_filename, 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); if (! copy_object (ibfd, obfd)) 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 { @@ -2050,7 +2263,7 @@ copy_file (const char *input_filename, const char *output_filename, 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) { @@ -2087,7 +2300,7 @@ add_section_rename (const char * old_name, const char * new_name, fatal (_("Multiple renames of section %s"), old_name); } - rename = xmalloc (sizeof (* rename)); + rename = (section_rename *) xmalloc (sizeof (* rename)); rename->old_name = old_name; rename->new_name = new_name; @@ -2129,24 +2342,18 @@ find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection, 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 @@ -2155,7 +2362,7 @@ loser: 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; @@ -2188,7 +2395,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) { 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; @@ -2219,7 +2426,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) if (osection == NULL) { - err = _("making"); + err = _("failed to create output section"); goto loser; } @@ -2233,7 +2440,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) size = 0; if (! bfd_set_section_size (obfd, osection, size)) { - err = _("size"); + err = _("failed to set size"); goto loser; } @@ -2245,9 +2452,9 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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; } @@ -2264,7 +2471,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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. */ @@ -2272,7 +2479,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) osection, bfd_section_alignment (ibfd, isection))) { - err = _("alignment"); + err = _("failed to set alignment"); goto loser; } @@ -2283,37 +2490,39 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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 @@ -2323,7 +2532,7 @@ loser: 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; @@ -2350,6 +2559,9 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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. */ @@ -2365,7 +2577,11 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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; + } } } @@ -2373,10 +2589,15 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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) { @@ -2386,10 +2607,10 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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); @@ -2401,16 +2622,17 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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) { @@ -2442,7 +2664,7 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) { /* 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) @@ -2453,8 +2675,11 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) } 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) @@ -2469,7 +2694,11 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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); } } @@ -2480,7 +2709,7 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) static void get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg) { - asection ***secppp = secppparg; + asection ***secppp = (asection ***) secppparg; **secppp = osection; ++(*secppp); @@ -2493,8 +2722,8 @@ get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg) 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. */ @@ -2537,7 +2766,7 @@ compare_section_lma (const void *arg1, const void *arg2) 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; @@ -2558,7 +2787,7 @@ mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg) 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)); @@ -2610,9 +2839,8 @@ write_debugging_info (bfd *obfd, void *dhandle, || ! 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; } @@ -2624,17 +2852,17 @@ write_debugging_info (bfd *obfd, void *dhandle, || ! 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; } @@ -2681,10 +2909,10 @@ strip_main (int argc, char *argv[]) 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; @@ -2739,7 +2967,7 @@ strip_main (int argc, char *argv[]) /* 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) @@ -2774,8 +3002,8 @@ strip_main (int argc, char *argv[]) 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; } @@ -2787,9 +3015,11 @@ strip_main (int argc, char *argv[]) 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); @@ -2800,6 +3030,117 @@ strip_main (int argc, char *argv[]) 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[]) { @@ -2892,31 +3233,31 @@ copy_main (int argc, char *argv[]) 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': @@ -2972,17 +3313,17 @@ copy_main (int argc, char *argv[]) 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); @@ -3042,7 +3383,7 @@ copy_main (int argc, char *argv[]) } len = s - optarg; - name = xmalloc (len + 1); + name = (char *) xmalloc (len + 1); strncpy (name, optarg, len); name[len] = '\0'; @@ -3140,13 +3481,13 @@ copy_main (int argc, char *argv[]) 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); @@ -3171,7 +3512,7 @@ copy_main (int argc, char *argv[]) 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'; @@ -3198,7 +3539,7 @@ copy_main (int argc, char *argv[]) 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; @@ -3218,7 +3559,7 @@ copy_main (int argc, char *argv[]) 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; @@ -3240,15 +3581,15 @@ copy_main (int argc, char *argv[]) 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: @@ -3256,19 +3597,30 @@ copy_main (int argc, char *argv[]) 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: @@ -3327,6 +3679,59 @@ copy_main (int argc, char *argv[]) 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; @@ -3366,6 +3771,59 @@ copy_main (int argc, char *argv[]) if (output_target == NULL) output_target = input_target; + /* Convert input EFI target to PEI target. */ + if (input_target != NULL + && strncmp (input_target, "efi-", 4) == 0) + { + char *efi; + + 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); + + 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 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) + { + 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 (binary_architecture != NULL) { if (input_target && strcmp (input_target, "binary") == 0) @@ -3411,7 +3869,8 @@ copy_main (int argc, char *argv[]) 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); @@ -3495,6 +3954,8 @@ main (int argc, char *argv[]) is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0); } + create_symbol_htabs (); + if (is_strip) strip_main (argc, argv); else