X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=5760d06a85959ce53ea7e52b46504cd721bfc1f5;hb=af0b2a3e85df9f49a3528e5b7578fcf9412f1acc;hp=7bdd4478931d68c2d925ae826e219da1596c90d9;hpb=1cc3da765d24068ef9046c19c9d23b1e69e30f6e;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 7bdd447893..5760d06a85 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1,5 +1,5 @@ /* objcopy.c -- copy object file from input to output, optionally massaging it. - Copyright (C) 1991-2019 Free Software Foundation, Inc. + Copyright (C) 1991-2020 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -68,7 +68,7 @@ struct addsym_node long symval; flagword flags; char * section; - char * othersym; + const char * othersym; }; typedef struct section_rename @@ -143,13 +143,14 @@ struct section_list COPY and REMOVE are mutually exlusive. SET and ALTER are mutually exclusive. */ #define SECTION_CONTEXT_REMOVE (1 << 0) /* Remove this section. */ #define SECTION_CONTEXT_COPY (1 << 1) /* Copy this section, delete all non-copied section. */ -#define SECTION_CONTEXT_SET_VMA (1 << 2) /* Set the sections' VMA address. */ -#define SECTION_CONTEXT_ALTER_VMA (1 << 3) /* Increment or decrement the section's VMA address. */ -#define SECTION_CONTEXT_SET_LMA (1 << 4) /* Set the sections' LMA address. */ -#define SECTION_CONTEXT_ALTER_LMA (1 << 5) /* Increment or decrement the section's LMA address. */ -#define SECTION_CONTEXT_SET_FLAGS (1 << 6) /* Set the section's flags. */ -#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 7) /* Remove relocations for this section. */ -#define SECTION_CONTEXT_SET_ALIGNMENT (1 << 8) /* Set alignment for section. */ +#define SECTION_CONTEXT_KEEP (1 << 2) /* Keep this section. */ +#define SECTION_CONTEXT_SET_VMA (1 << 3) /* Set the sections' VMA address. */ +#define SECTION_CONTEXT_ALTER_VMA (1 << 4) /* Increment or decrement the section's VMA address. */ +#define SECTION_CONTEXT_SET_LMA (1 << 5) /* Set the sections' LMA address. */ +#define SECTION_CONTEXT_ALTER_LMA (1 << 6) /* Increment or decrement the section's LMA address. */ +#define SECTION_CONTEXT_SET_FLAGS (1 << 7) /* Set the section's flags. */ +#define SECTION_CONTEXT_REMOVE_RELOCS (1 << 8) /* Remove relocations for this section. */ +#define SECTION_CONTEXT_SET_ALIGNMENT (1 << 9) /* Set alignment for section. */ bfd_vma vma_val; /* Amount to change by or set to. */ bfd_vma lma_val; /* Amount to change by or set to. */ @@ -332,6 +333,7 @@ enum command_line_switch OPTION_INTERLEAVE_WIDTH, OPTION_KEEPGLOBAL_SYMBOLS, OPTION_KEEP_FILE_SYMBOLS, + OPTION_KEEP_SECTION, OPTION_KEEP_SYMBOLS, OPTION_LOCALIZE_HIDDEN, OPTION_LOCALIZE_SYMBOLS, @@ -386,6 +388,7 @@ static struct option strip_options[] = {"input-format", required_argument, 0, 'I'}, /* Obsolete */ {"input-target", required_argument, 0, 'I'}, {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, + {"keep-section", required_argument, 0, OPTION_KEEP_SECTION}, {"keep-symbol", required_argument, 0, 'K'}, {"merge-notes", no_argument, 0, 'M'}, {"no-merge-notes", no_argument, 0, OPTION_NO_MERGE_NOTES}, @@ -457,6 +460,7 @@ static struct option copy_options[] = {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, {"keep-global-symbol", required_argument, 0, 'G'}, {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS}, + {"keep-section", required_argument, 0, OPTION_KEEP_SECTION}, {"keep-symbol", required_argument, 0, 'K'}, {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS}, {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN}, @@ -589,6 +593,7 @@ copy_usage (FILE *stream, int exit_status) --only-keep-debug Strip everything but the debug information\n\ --extract-dwo Copy only DWO sections\n\ --extract-symbol Remove section contents but keep symbols\n\ + --keep-section Do not strip section \n\ -K --keep-symbol Do not strip symbol \n\ --keep-file-symbols Do not strip file symbol(s)\n\ --localize-hidden Turn all ELF hidden symbols into locals\n\ @@ -722,6 +727,7 @@ strip_usage (FILE *stream, int exit_status) -M --merge-notes Remove redundant entries in note sections (default)\n\ --no-merge-notes Do not attempt to remove redundant notes\n\ -N --strip-symbol= Do not copy symbol \n\ + --keep-section= Do not strip section \n\ -K --keep-symbol= Do not strip symbol \n\ --keep-file-symbols Do not strip file symbol(s)\n\ -w --wildcard Permit wildcard in symbol comparison\n\ @@ -774,6 +780,7 @@ parse_flags (const char *s) PARSE_FLAG ("code", SEC_CODE); PARSE_FLAG ("data", SEC_DATA); PARSE_FLAG ("rom", SEC_ROM); + PARSE_FLAG ("exclude", SEC_EXCLUDE); PARSE_FLAG ("share", SEC_COFF_SHARED); PARSE_FLAG ("contents", SEC_HAS_CONTENTS); PARSE_FLAG ("merge", SEC_MERGE); @@ -788,7 +795,7 @@ parse_flags (const char *s) copy[len] = '\0'; non_fatal (_("unrecognized section flag `%s'"), copy); fatal (_("supported flags: %s"), - "alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings"); + "alloc, load, noload, readonly, debug, code, data, rom, exclude, share, contents, merge, strings"); } s = snext; @@ -802,7 +809,7 @@ parse_flags (const char *s) string can't be parsed. */ static flagword -parse_symflags (const char *s, char **other) +parse_symflags (const char *s, const char **other) { flagword ret; const char *snext; @@ -1311,6 +1318,10 @@ is_mergeable_note_section (bfd * abfd, asection * sec) static bfd_boolean is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { + if (find_section_list (bfd_section_name (sec), FALSE, SECTION_CONTEXT_KEEP) + != NULL) + return FALSE; + if (sections_removed || sections_copied) { struct section_list *p; @@ -1411,16 +1422,16 @@ static bfd_boolean is_nondebug_keep_contents_section (bfd *ibfd, asection *isection) { /* Always keep ELF note sections. */ - if (ibfd->xvec->flavour == bfd_target_elf_flavour) - return (elf_section_type (isection) == SHT_NOTE); + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour) + return elf_section_type (isection) == SHT_NOTE; /* Always keep the .buildid section for PE/COFF. Strictly, this should be written "always keep the section storing the debug directory", but that may be the .text section for objects produced by some tools, which it is not sensible to keep. */ - if (ibfd->xvec->flavour == bfd_target_coff_flavour) - return (strcmp (bfd_section_name (isection), ".buildid") == 0); + if (bfd_get_flavour (ibfd) == bfd_target_coff_flavour) + return strcmp (bfd_section_name (isection), ".buildid") == 0; return FALSE; } @@ -1443,6 +1454,9 @@ is_hidden_symbol (asymbol *sym) return FALSE; } +/* Empty name is hopefully never a valid symbol name. */ +static const char * empty_name = ""; + static bfd_boolean need_sym_before (struct addsym_node **node, const char *sym) { @@ -1454,10 +1468,12 @@ need_sym_before (struct addsym_node **node, const char *sym) { if (!ptr->othersym) break; + if (ptr->othersym == empty_name) + continue; else if (strcmp (ptr->othersym, sym) == 0) { - free (ptr->othersym); - ptr->othersym = ""; /* Empty name is hopefully never a valid symbol name. */ + free ((char *) ptr->othersym); + ptr->othersym = empty_name; *node = ptr; return TRUE; } @@ -1533,12 +1549,13 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, /* Check if we will remove the current leading character. */ rem_leading_char = - (name[0] == bfd_get_symbol_leading_char (abfd)) - && (change_leading_char - || (remove_leading_char - && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0 - || undefined - || bfd_is_com_section (bfd_asymbol_section (sym))))); + (name[0] != '\0' + && name[0] == bfd_get_symbol_leading_char (abfd) + && (change_leading_char + || (remove_leading_char + && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0 + || undefined + || bfd_is_com_section (bfd_asymbol_section (sym)))))); /* Check if we will add a new leading character. */ add_leading_char = @@ -1564,9 +1581,14 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, if (add_leading_char || prefix_symbols_string) { char *n, *ptr; + size_t len = strlen (name) + 1; + + if (add_leading_char) + len++; + if (prefix_symbols_string) + len += strlen (prefix_symbols_string); - ptr = n = (char *) xmalloc (1 + strlen (prefix_symbols_string) - + strlen (name) + 1); + ptr = n = (char *) xmalloc (len); if (add_leading_char) *ptr++ = bfd_get_symbol_leading_char (obfd); @@ -1685,7 +1707,7 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, { if (ptr->othersym) { - if (strcmp (ptr->othersym, "")) + if (ptr->othersym != empty_name) fatal (_("'before=%s' not found"), ptr->othersym); } else @@ -1930,7 +1952,7 @@ typedef struct objcopy_internal_note bfd_vma start; bfd_vma end; } objcopy_internal_note; - + #define DEBUG_MERGE 0 #if DEBUG_MERGE @@ -2026,7 +2048,7 @@ compare_gnu_build_notes (const void * data1, const void * data2) pnote1->note.namesz - 3 : pnote2->note.namesz - 3); if (cmp) return cmp; - + if (pnote1->end < pnote2->start) return -1; if (pnote1->start > pnote2->end) @@ -2037,13 +2059,15 @@ compare_gnu_build_notes (const void * data1, const void * data2) return -1; if (pnote1->end > pnote2->end) return 1; - + if (pnote1->end < pnote2->end) + return -1; + /* Put OPEN notes before function notes. */ if (is_open_note (pnote1) && ! is_open_note (pnote2)) return -1; if (! is_open_note (pnote1) && is_open_note (pnote2)) return 1; - + return 0; } @@ -2071,7 +2095,7 @@ sort_gnu_build_notes (const void * data1, const void * data2) return 1; /* 1: F 2: O */ } - + /* Sort by starting address. */ if (pnote1->start < pnote2->start) return -1; @@ -2089,7 +2113,7 @@ sort_gnu_build_notes (const void * data1, const void * data2) && pnote2->note.namesz > 4 && pnote1->note.namedata[3] != pnote2->note.namedata[3]) return pnote1->note.namedata[3] - pnote2->note.namedata[3]; - + return 0; } @@ -2136,7 +2160,7 @@ merge_gnu_build_notes (bfd * abfd, goto done; } } - + /* Make a copy of the notes and convert to our internal format. Minimum size of a note is 12 bytes. Also locate the version notes and check them. */ @@ -2217,7 +2241,7 @@ merge_gnu_build_notes (bfd * abfd, address. */ end = (bfd_vma) -1; break; - + case 8: if (! is_64bit (abfd)) { @@ -2242,7 +2266,7 @@ merge_gnu_build_notes (bfd * abfd, start = bfd_get_64 (abfd, pnote->note.descdata); end = bfd_get_64 (abfd, pnote->note.descdata + 8); break; - + default: err = _("corrupt GNU build attribute note: bad description size"); goto done; @@ -2381,7 +2405,7 @@ merge_gnu_build_notes (bfd * abfd, || memcmp (back->note.namedata, pnote->note.namedata, pnote->note.namesz) != 0) break; - + if (back->start == pnote->start && back->end == pnote->end) { @@ -2435,7 +2459,7 @@ merge_gnu_build_notes (bfd * abfd, if (! is_deleted_note (pnote)) merge_debug ("Unable to do anything with note at %#08lx\n", (pnote->note.namedata - (char *) contents) - 12); -#endif +#endif } /* Resort the notes. */ @@ -2450,7 +2474,9 @@ merge_gnu_build_notes (bfd * abfd, bfd_vma prev_start = 0; bfd_vma prev_end = 0; - new = new_contents = xmalloc (size); + /* Not sure how, but the notes might grow in size. + (eg see PR 1774507). Allow for this here. */ + new = new_contents = xmalloc (size * 2); for (pnote = pnotes, old = contents; pnote < pnotes_end; pnote ++) @@ -2515,10 +2541,13 @@ merge_gnu_build_notes (bfd * abfd, pnote->note.namesz ); #endif - + new_size = new - new_contents; - memcpy (contents, new_contents, new_size); - size = new_size; + if (new_size < size) + { + memcpy (contents, new_contents, new_size); + size = new_size; + } free (new_contents); done: @@ -2533,6 +2562,23 @@ merge_gnu_build_notes (bfd * abfd, return size; } +static flagword +check_new_section_flags (flagword flags, bfd * abfd, const char * secname) +{ + /* Only set the SEC_COFF_SHARED flag on COFF files. + The same bit value is used by ELF targets to indicate + compressed sections, and setting that flag here breaks + things. */ + if ((flags & SEC_COFF_SHARED) + && bfd_get_flavour (abfd) != bfd_target_coff_flavour) + { + non_fatal (_("%s[%s]: Note - dropping 'share' flag as output format is not COFF"), + bfd_get_filename (abfd), secname); + flags &= ~ SEC_COFF_SHARED; + } + return flags; +} + /* Copy object file IBFD onto OBFD. Returns TRUE upon success, FALSE otherwise. */ @@ -2550,7 +2596,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) void *dhandle; enum bfd_architecture iarch; unsigned int imach; - unsigned int c, i; + unsigned int num_sec, i; if (ibfd->xvec->byteorder != obfd->xvec->byteorder && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN @@ -2575,7 +2621,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) return FALSE; } - if (ibfd->xvec->flavour != bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) { if ((do_debug_sections & compress) != 0 && do_debug_sections != compress) @@ -2636,8 +2682,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) imach = bfd_get_mach (ibfd); if (input_arch) { - if (bfd_get_arch_info (ibfd) == NULL - || bfd_get_arch_info (ibfd)->arch == bfd_arch_unknown) + if (iarch == bfd_arch_unknown) { iarch = input_arch->arch; imach = input_arch->mach; @@ -2646,6 +2691,14 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) non_fatal (_("Input file `%s' ignores binary architecture parameter."), bfd_get_archive_filename (ibfd)); } + if (iarch == bfd_arch_unknown + && bfd_get_flavour (ibfd) != bfd_target_elf_flavour + && bfd_get_flavour (obfd) == bfd_target_elf_flavour) + { + const struct elf_backend_data *bed = get_elf_backend_data (obfd); + iarch = bed->arch; + imach = 0; + } if (!bfd_set_arch_mach (obfd, iarch, imach) && (ibfd->target_defaulted || bfd_get_arch (ibfd) != bfd_get_arch (obfd))) @@ -2673,7 +2726,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) pe_data_type *pe = pe_data (obfd); /* Copy PE parameters before changing them. */ - if (ibfd->xvec->flavour == bfd_target_coff_flavour + if (bfd_get_flavour (ibfd) == bfd_target_coff_flavour && bfd_pei_p (ibfd)) pe->pe_opthdr = pe_data (ibfd)->pe_opthdr; @@ -2721,6 +2774,11 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) file_alignment, section_alignment); } + + if (preserve_dates + && bfd_get_flavour (ibfd) == bfd_target_coff_flavour + && bfd_pei_p (ibfd)) + pe->timestamp = pe_data (ibfd)->coff.timestamp; } if (isympp) @@ -2774,7 +2832,10 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) pset = find_section_list (padd->name, FALSE, SECTION_CONTEXT_SET_FLAGS); if (pset != NULL) - flags = pset->flags | SEC_HAS_CONTENTS; + { + flags = pset->flags | SEC_HAS_CONTENTS; + flags = check_new_section_flags (flags, obfd, padd->name); + } else flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; @@ -2868,6 +2929,11 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) if (! is_mergeable_note_section (ibfd, osec)) continue; + /* If the section is going to be completly deleted then + do not bother to merge it. */ + if (osec->output_section == NULL) + continue; + bfd_size_type size = bfd_section_size (osec); if (size == 0) @@ -2883,25 +2949,19 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) { bfd_nonfatal_message (NULL, ibfd, osec, _("warning: could not load note section")); - free (merged->contents); free (merged); continue; } merged->size = merge_gnu_build_notes (ibfd, osec, size, merged->contents); - if (merged->size == size) - { - /* Merging achieves nothing. */ - merge_debug ("Merge of section %s achieved nothing - skipping\n", - bfd_section_name (osec)); - free (merged->contents); - free (merged); - continue; - } - if (osec->output_section == NULL - || !bfd_set_section_size (osec->output_section, merged->size)) + /* FIXME: Once we have read the contents in, we must write + them out again. So even if the mergeing has achieved + nothing we still add this entry to the merge list. */ + + if (size != merged->size + && !bfd_set_section_size (osec->output_section, merged->size)) { bfd_nonfatal_message (NULL, obfd, osec, _("warning: failed to set merged notes size")); @@ -2923,6 +2983,9 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) for (pdump = dump_sections; pdump != NULL; pdump = pdump->next) { + FILE * f; + bfd_byte *contents; + osec = bfd_get_section_by_name (ibfd, pdump->name); if (osec == NULL) { @@ -2940,14 +3003,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) } bfd_size_type size = bfd_section_size (osec); - if (size == 0) - { - bfd_nonfatal_message (NULL, ibfd, osec, - _("can't dump section - it is empty")); - continue; - } + /* Note - we allow the dumping of zero-sized sections. */ - FILE * f; f = fopen (pdump->filename, FOPEN_WB); if (f == NULL) { @@ -2956,7 +3013,6 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) continue; } - bfd_byte *contents; if (bfd_malloc_and_get_section (ibfd, osec, &contents)) { if (fwrite (contents, 1, size, f) != size) @@ -3046,8 +3102,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) } } - c = bfd_count_sections (obfd); - if (c != 0 + num_sec = bfd_count_sections (obfd); + if (num_sec != 0 && (gap_fill_set || pad_to_set)) { asection **set; @@ -3058,22 +3114,24 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) increasing the section sizes as required to fill the gaps. We write out the gap contents below. */ - osections = (asection **) xmalloc (c * sizeof (asection *)); + osections = xmalloc (num_sec * sizeof (*osections)); set = osections; bfd_map_over_sections (obfd, get_sections, &set); - qsort (osections, c, sizeof (asection *), compare_section_lma); + qsort (osections, num_sec, sizeof (*osections), compare_section_lma); - gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type)); - memset (gaps, 0, c * sizeof (bfd_size_type)); + gaps = xmalloc (num_sec * sizeof (*gaps)); + memset (gaps, 0, num_sec * sizeof (*gaps)); if (gap_fill_set) { - for (i = 0; i < c - 1; i++) + for (i = 0; i < num_sec - 1; i++) { flagword flags; - bfd_size_type size; - bfd_vma gap_start, gap_stop; + bfd_size_type size; /* Octets. */ + bfd_vma gap_start, gap_stop; /* Octets. */ + unsigned int opb1 = bfd_octets_per_byte (obfd, osections[i]); + unsigned int opb2 = bfd_octets_per_byte (obfd, osections[i+1]); flags = bfd_section_flags (osections[i]); if ((flags & SEC_HAS_CONTENTS) == 0 @@ -3081,8 +3139,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) continue; size = bfd_section_size (osections[i]); - gap_start = bfd_section_lma (osections[i]) + size; - gap_stop = bfd_section_lma (osections[i + 1]); + gap_start = bfd_section_lma (osections[i]) * opb1 + size; + gap_stop = bfd_section_lma (osections[i + 1]) * opb2; if (gap_start < gap_stop) { if (!bfd_set_section_size (osections[i], @@ -3102,24 +3160,26 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) if (pad_to_set) { - bfd_vma lma; - bfd_size_type size; - - lma = bfd_section_lma (osections[c - 1]); - size = bfd_section_size (osections[c - 1]); - if (lma + size < pad_to) + bfd_vma lma; /* Octets. */ + bfd_size_type size; /* Octets. */ + unsigned int opb = bfd_octets_per_byte (obfd, osections[num_sec - 1]); + bfd_vma _pad_to = pad_to * opb; + + lma = bfd_section_lma (osections[num_sec - 1]) * opb; + size = bfd_section_size (osections[num_sec - 1]); + if (lma + size < _pad_to) { - if (!bfd_set_section_size (osections[c - 1], pad_to - lma)) + if (!bfd_set_section_size (osections[num_sec - 1], _pad_to - lma)) { - bfd_nonfatal_message (NULL, obfd, osections[c - 1], + bfd_nonfatal_message (NULL, obfd, osections[num_sec - 1], _("can't add padding")); status = 1; } else { - gaps[c - 1] = pad_to - (lma + size); - if (max_gap < pad_to - (lma + size)) - max_gap = pad_to - (lma + size); + gaps[num_sec - 1] = _pad_to - (lma + size); + if (max_gap < _pad_to - (lma + size)) + max_gap = _pad_to - (lma + size); } } } @@ -3267,16 +3327,16 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) { bfd_nonfatal_message (NULL, obfd, osec, - _("error: failed to copy merged notes into output")); + _("error: failed to locate merged notes")); continue; } } - if (! is_mergeable_note_section (obfd, osec)) + if (merged->contents == NULL) { bfd_nonfatal_message (NULL, obfd, osec, - _("error: failed to copy merged notes into output")); + _("error: failed to merge notes")); continue; } @@ -3317,7 +3377,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) } } - if (gap_fill_set || pad_to_set) + if (gaps != NULL) { bfd_byte *buf; @@ -3327,8 +3387,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) buf = (bfd_byte *) xmalloc (max_gap); memset (buf, gap_fill, max_gap); - c = bfd_count_sections (obfd); - for (i = 0; i < c; i++) + for (i = 0; i < num_sec; i++) { if (gaps[i] != 0) { @@ -3736,6 +3795,14 @@ copy_file (const char *input_filename, const char *output_filename, status = 1; return; } + + if (gnu_debuglink_filename != NULL) + { + non_fatal (_("--add-gnu-debuglink ignored for archive %s"), + bfd_get_filename (ibfd)); + gnu_debuglink_filename = NULL; + } + /* This is a no-op on non-Coff targets. */ set_long_section_mode (obfd, ibfd, long_section_names); @@ -3903,6 +3970,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) flagword flags; const char *err; const char * name; + const char * new_name; char *prefix = NULL; bfd_boolean make_nobits; unsigned int alignment; @@ -3913,11 +3981,21 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) /* Get the, possibly new, name of the output section. */ name = bfd_section_name (isection); flags = bfd_section_flags (isection); - name = find_section_rename (name, &flags); + if (bfd_get_flavour (ibfd) != bfd_get_flavour (obfd)) + { + flags &= bfd_applicable_section_flags (ibfd); + flags &= bfd_applicable_section_flags (obfd); + } + new_name = find_section_rename (name, &flags); + if (new_name != name) + { + name = new_name; + flags = check_new_section_flags (flags, obfd, name); + } /* Prefix sections. */ - if ((prefix_alloc_sections_string) - && (bfd_section_flags (isection) & SEC_ALLOC)) + if (prefix_alloc_sections_string + && (bfd_section_flags (isection) & SEC_ALLOC) != 0) prefix = prefix_alloc_sections_string; else if (prefix_sections_string) prefix = prefix_sections_string; @@ -3937,13 +4015,16 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) p = find_section_list (bfd_section_name (isection), FALSE, SECTION_CONTEXT_SET_FLAGS); if (p != NULL) - flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC)); + { + flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC)); + flags = check_new_section_flags (flags, obfd, bfd_section_name (isection)); + } else if (strip_symbols == STRIP_NONDEBUG && (flags & (SEC_ALLOC | SEC_GROUP)) != 0 && !is_nondebug_keep_contents_section (ibfd, isection)) { flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP); - if (obfd->xvec->flavour == bfd_target_elf_flavour) + if (bfd_get_flavour (obfd) == bfd_target_elf_flavour) { make_nobits = TRUE; @@ -4018,7 +4099,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) alignment = p->alignment; else alignment = bfd_section_alignment (isection); - + /* FIXME: This is probably not enough. If we change the LMA we may have to recompute the header for the file as well. */ if (!bfd_set_section_alignment (osection, alignment)) @@ -4046,7 +4127,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) if (gsym != NULL) { gsym->flags |= BSF_KEEP; - if (ibfd->xvec->flavour == bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour) elf_group_id (isection) = gsym; } } @@ -4584,6 +4665,9 @@ strip_main (int argc, char *argv[]) case 'R': handle_remove_section_option (optarg); break; + case OPTION_KEEP_SECTION: + find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP); + break; case OPTION_REMOVE_RELOCS: handle_remove_relocations_option (optarg); break; @@ -5010,6 +5094,10 @@ copy_main (int argc, char *argv[]) handle_remove_section_option (optarg); break; + case OPTION_KEEP_SECTION: + find_section_list (optarg, TRUE, SECTION_CONTEXT_KEEP); + break; + case OPTION_REMOVE_RELOCS: handle_remove_relocations_option (optarg); break; @@ -5422,7 +5510,7 @@ copy_main (int argc, char *argv[]) s = strchr (optarg, '='); if (s == NULL) fatal (_("bad format for --set-section-alignment: argument needed")); - + align = atoi (s + 1); if (align <= 0) fatal (_("bad format for --set-section-alignment: numeric argument needed")); @@ -5434,7 +5522,7 @@ copy_main (int argc, char *argv[]) align >>= 1; ++palign; } - + if (align != 1) /* Number has more than on 1, i.e. wasn't a power of 2. */ fatal (_("bad format for --set-section-alignment: alignment is not a power of two")); @@ -5450,7 +5538,7 @@ copy_main (int argc, char *argv[]) p->alignment = palign; } break; - + case OPTION_RENAME_SECTION: { flagword flags;