X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=09facf0061ea28865eabe83e6feb36c38bd35dad;hb=a0dcf2970562c19140460a07b2c987714639cd7b;hp=551378da399c8a793a951bb21b9af1b31bd65f99;hpb=dd68a12bc4b19c50c31fe357335bb8ee9a3322fc;p=thirdparty%2Fbinutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 551378da399..09facf0061e 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 @@ -780,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); @@ -794,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; @@ -808,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; @@ -1453,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) { @@ -1464,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; } @@ -1543,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 = @@ -1574,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); @@ -1695,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 @@ -1940,7 +1952,7 @@ typedef struct objcopy_internal_note bfd_vma start; bfd_vma end; } objcopy_internal_note; - + #define DEBUG_MERGE 0 #if DEBUG_MERGE @@ -2036,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) @@ -2047,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; } @@ -2081,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; @@ -2099,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; } @@ -2146,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. */ @@ -2227,7 +2241,7 @@ merge_gnu_build_notes (bfd * abfd, address. */ end = (bfd_vma) -1; break; - + case 8: if (! is_64bit (abfd)) { @@ -2252,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; @@ -2391,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) { @@ -2445,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. */ @@ -2460,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 ++) @@ -2525,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: @@ -2543,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. */ @@ -2646,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; @@ -2656,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))) @@ -2784,7 +2827,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; @@ -3081,8 +3127,10 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) for (i = 0; i < c - 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 @@ -3090,8 +3138,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], @@ -3111,14 +3159,16 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) if (pad_to_set) { - bfd_vma lma; - bfd_size_type size; + bfd_vma lma; /* Octets. */ + bfd_size_type size; /* Octets. */ + unsigned int opb = bfd_octets_per_byte (obfd, osections[c - 1]); + bfd_vma _pad_to = pad_to * opb; - lma = bfd_section_lma (osections[c - 1]); + lma = bfd_section_lma (osections[c - 1]) * opb; size = bfd_section_size (osections[c - 1]); - if (lma + size < pad_to) + if (lma + size < _pad_to) { - if (!bfd_set_section_size (osections[c - 1], pad_to - lma)) + if (!bfd_set_section_size (osections[c - 1], _pad_to - lma)) { bfd_nonfatal_message (NULL, obfd, osections[c - 1], _("can't add padding")); @@ -3126,9 +3176,9 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) } else { - gaps[c - 1] = pad_to - (lma + size); - if (max_gap < pad_to - (lma + size)) - max_gap = pad_to - (lma + size); + gaps[c - 1] = _pad_to - (lma + size); + if (max_gap < _pad_to - (lma + size)) + max_gap = _pad_to - (lma + size); } } } @@ -3745,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); @@ -3912,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; @@ -3927,7 +3986,12 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) flags &= bfd_applicable_section_flags (ibfd); flags &= bfd_applicable_section_flags (obfd); } - name = find_section_rename (name, &flags); + 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 @@ -3951,7 +4015,10 @@ 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)) @@ -4032,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)) @@ -5443,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")); @@ -5455,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")); @@ -5471,7 +5538,7 @@ copy_main (int argc, char *argv[]) p->alignment = palign; } break; - + case OPTION_RENAME_SECTION: { flagword flags;