X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=dd16b9b0f4b181cfbc7268d3dd9583c40226d4f9;hb=02893727c56378bb9c723096a58fd6dfc6f0d02b;hp=1dd36114e908fc95733702d73fa4cd87adff8bd4;hpb=a8da6403829d6f87867da6a737dfdaa736a37dfa;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 1dd36114e9..dd16b9b0f4 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, 2008 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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,11 +77,6 @@ section_rename; /* List of sections to be renamed. */ static section_rename *section_rename_list; -#define RETURN_NONFATAL(bfd) \ - do { \ - status = 1; bfd_nonfatal_message (NULL, bfd, NULL, NULL); return; \ - } while (0) - static asymbol **isympp = NULL; /* Input symbols. */ static asymbol **osympp = NULL; /* Output symbols that survive stripping. */ @@ -199,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). */ @@ -226,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 @@ -257,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, @@ -275,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". */ @@ -350,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}, @@ -388,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} }; @@ -408,11 +442,6 @@ extern unsigned int Chunk; 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 *); @@ -432,7 +461,7 @@ copy_usage (FILE *stream, int exit_status) fprintf (stream, _("\ -I --input-target Assume input file is in format \n\ -O --output-target Create an output file in format \n\ - -B --binary-architecture Set arch of output file, when input is binary\n\ + -B --binary-architecture Set output arch, when input is arch-less\n\ -F --target Set both input and output format to \n\ --debugging Convert debugging information, if possible\n\ -p --preserve-dates Copy modified/access timestamps to the output\n\ @@ -480,6 +509,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\ @@ -507,6 +538,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\ @@ -595,7 +635,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); @@ -624,7 +664,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; @@ -642,17 +682,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. */ @@ -661,7 +722,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; @@ -676,7 +737,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)); @@ -762,7 +823,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. */ @@ -771,36 +832,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. */ @@ -877,8 +957,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; } @@ -972,8 +1052,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); @@ -999,7 +1079,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 @@ -1026,7 +1107,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. */ @@ -1041,12 +1122,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))) @@ -1055,7 +1136,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; @@ -1063,9 +1144,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); @@ -1074,7 +1155,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; @@ -1123,7 +1204,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); @@ -1151,7 +1232,7 @@ add_redefine_syms_file (const char *filename) filename, strerror (errno)); bufsize = 100; - buf = xmalloc (bufsize); + buf = (char *) xmalloc (bufsize + 1 /* For the terminating NUL. */); lineno = 1; c = getc (file); @@ -1168,7 +1249,7 @@ add_redefine_syms_file (const char *filename) if (len >= bufsize) { bufsize *= 2; - buf = xrealloc (buf, bufsize); + buf = (char *) xrealloc (buf, bufsize + 1); } c = getc (file); } @@ -1194,7 +1275,7 @@ add_redefine_syms_file (const char *filename) if (len >= bufsize) { bufsize *= 2; - buf = xrealloc (buf, bufsize); + buf = (char *) xrealloc (buf, bufsize + 1); } c = getc (file); } @@ -1257,7 +1338,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) if (bfd_stat_arch_elt (ibfd, &buf) != 0) { - bfd_nonfatal_message (bfd_get_archive_filename (ibfd), NULL, NULL, NULL); + bfd_nonfatal_message (NULL, ibfd, NULL, NULL); return FALSE; } @@ -1279,7 +1360,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) { @@ -1290,8 +1371,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd) != (bfd_size_type) tocopy) { - bfd_nonfatal_message (bfd_get_archive_filename (ibfd), - NULL, NULL, NULL); + bfd_nonfatal_message (NULL, ibfd, NULL, NULL); free (cbuf); return FALSE; } @@ -1316,7 +1396,7 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) 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; @@ -1367,11 +1447,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_message (bfd_get_archive_filename (ibfd), - NULL, NULL, NULL); + bfd_nonfatal_message (NULL, ibfd, NULL, NULL); return FALSE; } } @@ -1379,6 +1461,18 @@ copy_object (bfd *ibfd, bfd *obfd) /* 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))) @@ -1387,7 +1481,7 @@ copy_object (bfd *ibfd, bfd *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; @@ -1395,10 +1489,67 @@ copy_object (bfd *ibfd, bfd *obfd) if (!bfd_set_format (obfd, bfd_get_format (ibfd))) { - bfd_nonfatal_message (bfd_get_archive_filename (ibfd), NULL, NULL, NULL); + 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); @@ -1411,11 +1562,11 @@ copy_object (bfd *ibfd, bfd *obfd) symsize = bfd_get_symtab_upper_bound (ibfd); if (symsize < 0) { - bfd_nonfatal_message (bfd_get_archive_filename (ibfd), NULL, NULL, NULL); + 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) { @@ -1427,7 +1578,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) { @@ -1568,13 +1720,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) @@ -1640,7 +1792,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 @@ -1648,12 +1800,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 @@ -1675,7 +1827,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); } @@ -1728,7 +1880,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); @@ -1811,7 +1963,8 @@ copy_object (bfd *ibfd, bfd *obfd) 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 { @@ -1821,7 +1974,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)); @@ -1837,7 +1991,11 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, this_element = bfd_openr_next_archived_file (ibfd, NULL); if (!bfd_set_format (obfd, bfd_get_format (ibfd))) - RETURN_NONFATAL (obfd); + { + status = 1; + bfd_nonfatal_message (NULL, obfd, NULL, NULL); + return; + } while (!status && this_element != NULL) { @@ -1846,7 +2004,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, "/", @@ -1860,7 +2018,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; @@ -1878,7 +2036,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; @@ -1900,14 +2058,14 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 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_message (NULL, output_bfd, NULL, NULL); + bfd_nonfatal_message (output_name, NULL, NULL, NULL); /* Error in new object file. Don't change archive. */ status = 1; } @@ -1917,22 +2075,21 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, } else { - bfd_nonfatal_message (bfd_get_archive_filename (this_element), - NULL, NULL, + 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_message (NULL, output_bfd, NULL, NULL); + 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; @@ -1959,11 +2116,21 @@ copy_unknown_element: } *ptr = NULL; + filename = bfd_get_filename (obfd); if (!bfd_close (obfd)) - RETURN_NONFATAL (obfd); + { + status = 1; + bfd_nonfatal_message (filename, NULL, NULL, NULL); + return; + } + filename = bfd_get_filename (ibfd); if (!bfd_close (ibfd)) - RETURN_NONFATAL (obfd); + { + 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) @@ -1979,18 +2146,36 @@ 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 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; } @@ -2027,8 +2212,10 @@ copy_file (const char *input_filename, const char *output_filename, 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)) { @@ -2047,15 +2234,25 @@ copy_file (const char *input_filename, const char *output_filename, 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)) + if (! copy_object (ibfd, obfd, input_arch)) status = 1; if (!bfd_close (obfd)) - RETURN_NONFATAL (obfd); + { + status = 1; + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + return; + } if (!bfd_close (ibfd)) - RETURN_NONFATAL (ibfd); + { + status = 1; + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + return; + } } else { @@ -2098,28 +2295,28 @@ static void 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 @@ -2131,18 +2328,18 @@ find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection, 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; @@ -2160,7 +2357,7 @@ setup_bfd_headers (bfd *ibfd, bfd *obfd) { status = 1; bfd_nonfatal_message (NULL, ibfd, NULL, - _("error in private h eader data")); + _("error in private header data")); return; } @@ -2174,7 +2371,7 @@ setup_bfd_headers (bfd *ibfd, bfd *obfd) 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; @@ -2207,7 +2404,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; @@ -2264,7 +2461,7 @@ 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 = _("failed to set vma"); goto loser; @@ -2283,7 +2480,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. */ @@ -2302,13 +2499,25 @@ 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)) @@ -2316,13 +2525,6 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 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; @@ -2339,7 +2541,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; @@ -2366,6 +2568,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. */ @@ -2393,7 +2598,7 @@ 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) { @@ -2411,10 +2616,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); @@ -2426,9 +2631,6 @@ 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) { @@ -2471,7 +2673,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) @@ -2516,7 +2718,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); @@ -2529,8 +2731,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. */ @@ -2573,7 +2775,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; @@ -2594,7 +2796,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)); @@ -2716,10 +2918,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; @@ -2774,7 +2976,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) @@ -2816,15 +3018,17 @@ strip_main (int argc, char *argv[]) } 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); @@ -2835,10 +3039,120 @@ 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[]) { - char * binary_architecture = NULL; char *input_filename = NULL; char *output_filename = NULL; char *tmpname; @@ -2850,6 +3164,7 @@ copy_main (int argc, char *argv[]) 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) @@ -2863,7 +3178,9 @@ copy_main (int argc, char *argv[]) break; case 'B': - binary_architecture = optarg; + input_arch = bfd_scan_arch (optarg); + if (input_arch == NULL) + fatal (_("architecture %s unknown"), optarg); break; case 'i': @@ -2927,31 +3244,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': @@ -3007,17 +3324,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); @@ -3077,7 +3394,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'; @@ -3175,13 +3492,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); @@ -3206,7 +3523,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'; @@ -3233,7 +3550,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; @@ -3253,7 +3570,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; @@ -3275,15 +3592,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: @@ -3291,19 +3608,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: @@ -3362,6 +3690,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; @@ -3401,27 +3782,57 @@ copy_main (int argc, char *argv[]) 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) { - 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_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 (preserve_dates) @@ -3440,13 +3851,14 @@ copy_main (int argc, char *argv[]) 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); @@ -3530,6 +3942,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