diff options
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r-- | binutils/objcopy.c | 286 |
1 files changed, 168 insertions, 118 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c index e2e6bd7..3c1bcf6 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -30,6 +30,7 @@ #include "coff/internal.h" #include "libcoff.h" #include "safe-ctype.h" +#include "plugin.h" /* FIXME: See bfd/peXXigen.c for why we include an architecture specific header in generic PE code. */ @@ -359,6 +360,7 @@ enum command_line_switch OPTION_RENAME_SECTION, OPTION_REVERSE_BYTES, OPTION_PE_SECTION_ALIGNMENT, + OPTION_PLUGIN, OPTION_SET_SECTION_FLAGS, OPTION_SET_SECTION_ALIGNMENT, OPTION_SET_START, @@ -402,6 +404,7 @@ static struct option strip_options[] = {"output-file", required_argument, 0, 'o'}, {"output-format", required_argument, 0, 'O'}, /* Obsolete */ {"output-target", required_argument, 0, 'O'}, + {"plugin", required_argument, 0, OPTION_PLUGIN}, {"preserve-dates", no_argument, 0, 'p'}, {"remove-section", required_argument, 0, 'R'}, {"remove-relocations", required_argument, 0, OPTION_REMOVE_RELOCS}, @@ -533,7 +536,9 @@ extern char *program_name; /* This flag distinguishes between strip and objcopy: 1 means this is 'strip'; 0 means this is 'objcopy'. -1 means if we should use argv[0] to decide. */ +#ifndef is_strip extern int is_strip; +#endif /* The maximum length of an S record. This variable is defined in srec.c and can be modified by the --srec-len parameter. */ @@ -756,6 +761,9 @@ strip_usage (FILE *stream, int exit_status) --info List object formats & architectures supported\n\ -o <file> Place stripped output into <file>\n\ ")); + if (bfd_plugin_enabled ()) + fprintf (stream, _("\ + --plugin NAME Load the specified plugin\n")); list_supported_targets (program_name, stream); if (REPORT_BUGS_TO[0] && exit_status == 0) @@ -1914,20 +1922,11 @@ add_redefine_syms_file (const char *filename) Returns TRUE upon success, FALSE otherwise. */ static bool -copy_unknown_object (bfd *ibfd, bfd *obfd) +copy_unknown_file (bfd *ibfd, bfd *obfd, off_t size, unsigned int mode) { char *cbuf; bfd_size_type tocopy; - off_t size; - struct stat buf; - if (bfd_stat_arch_elt (ibfd, &buf) != 0) - { - bfd_nonfatal_message (NULL, ibfd, NULL, NULL); - return false; - } - - size = buf.st_size; if (size < 0) { non_fatal (_("stat returns negative size for `%s'"), @@ -1972,11 +1971,31 @@ copy_unknown_object (bfd *ibfd, bfd *obfd) /* We should at least to be able to read it back when copying an unknown object in an archive. */ - chmod (bfd_get_filename (obfd), buf.st_mode | S_IRUSR); + chmod (bfd_get_filename (obfd), mode | S_IRUSR); free (cbuf); return true; } +/* Copy unknown object file archive member IBFD onto OBFD. + Returns TRUE upon success, FALSE otherwise. */ + +static bool +copy_unknown_object (bfd *ibfd, bfd *obfd) +{ + struct stat buf; + + if (bfd_stat_arch_elt (ibfd, &buf) != 0) + { + bfd_nonfatal_message (NULL, ibfd, NULL, NULL); + return false; + } + + if (!copy_unknown_file (ibfd, obfd, buf.st_size, buf.st_mode)) + return false; + + return true; +} + typedef struct objcopy_internal_note { Elf_Internal_Note note; @@ -2503,7 +2522,6 @@ merge_gnu_build_notes (bfd * abfd, /* Reconstruct the ELF notes. */ bfd_byte * new_contents; - bfd_byte * old; bfd_byte * new; bfd_vma prev_start = 0; bfd_vma prev_end = 0; @@ -2511,12 +2529,8 @@ merge_gnu_build_notes (bfd * abfd, /* 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 ++) + for (pnote = pnotes; pnote < pnotes_end; pnote ++) { - bfd_size_type note_size = 12 + pnote->padded_namesz + pnote->note.descsz; - if (! is_deleted_note (pnote)) { /* Create the note, potentially using the @@ -2559,8 +2573,6 @@ merge_gnu_build_notes (bfd * abfd, prev_end = pnote->end; } } - - old += note_size; } #if DEBUG_MERGE @@ -2792,17 +2804,20 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) iarch = bed->arch; imach = 0; } + if (iarch == bfd_arch_unknown + && bfd_get_flavour (ibfd) == bfd_target_elf_flavour + && ibfd->target_defaulted) + { + non_fatal (_("Unable to recognise the architecture of the input file `%s'"), + bfd_get_archive_filename (ibfd)); + return false; + } if (!bfd_set_arch_mach (obfd, iarch, imach) - && (ibfd->target_defaulted - || bfd_get_arch (ibfd) != bfd_get_arch (obfd))) + && iarch != bfd_arch_unknown) { - if (bfd_get_arch (ibfd) == bfd_arch_unknown) - non_fatal (_("Unable to recognise the format of the input file `%s'"), - bfd_get_archive_filename (ibfd)); - else - non_fatal (_("Output file cannot represent architecture `%s'"), - bfd_printable_arch_mach (bfd_get_arch (ibfd), - bfd_get_mach (ibfd))); + non_fatal (_("Output file cannot represent architecture `%s'"), + bfd_printable_arch_mach (bfd_get_arch (ibfd), + bfd_get_mach (ibfd))); return false; } @@ -2832,7 +2847,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) if (pe_file_alignment != (bfd_vma) -1) pe->pe_opthdr.FileAlignment = pe_file_alignment; - else + else if (!is_strip) pe_file_alignment = PE_DEF_FILE_ALIGNMENT; if (pe_heap_commit != (bfd_vma) -1) @@ -2846,7 +2861,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) if (pe_section_alignment != (bfd_vma) -1) pe->pe_opthdr.SectionAlignment = pe_section_alignment; - else + else if (!is_strip) pe_section_alignment = PE_DEF_SECTION_ALIGNMENT; if (pe_stack_commit != (bfd_vma) -1) @@ -3722,10 +3737,8 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, l->obfd = NULL; list = l; + this_element->plugin_format = bfd_plugin_no; ok_object = bfd_check_format (this_element, bfd_object); - if (!ok_object) - bfd_nonfatal_message (NULL, this_element, NULL, - _("Unable to recognise the format of file")); /* PR binutils/3110: Cope with archives containing multiple target types. */ @@ -3742,6 +3755,9 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, goto cleanup_and_exit; } + /* Copy slim LTO IR file as unknown object. */ + if (this_element->lto_type == lto_slim_ir_object) + ok_object = false; if (ok_object) { ok = copy_object (this_element, output_element, input_arch); @@ -3775,7 +3791,8 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, set_times (output_name, &buf); /* Open the newly created output file and attach to our list. */ - output_element = bfd_openr (output_name, output_target); + const char *targ = force_output_target ? output_target : NULL; + output_element = bfd_openr (output_name, targ); list->obfd = output_element; @@ -3843,6 +3860,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, char **obj_matching; char **core_matching; off_t size = get_file_size (input_filename); + const char *target = input_target; if (size < 1) { @@ -3855,10 +3873,13 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, /* To allow us to do "strip *" without dying on the first non-object file, failures are nonfatal. */ - ibfd = bfd_openr (input_filename, input_target); + ibfd = bfd_openr (input_filename, target); if (ibfd == NULL || bfd_stat (ibfd, in_stat) != 0) { - bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + if (bfd_get_error () == bfd_error_invalid_target && target != NULL) + bfd_nonfatal_message (target, NULL, NULL, NULL); + else + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); if (ibfd != NULL) bfd_close (ibfd); status = 1; @@ -3906,6 +3927,8 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, break; } + ibfd->plugin_format = bfd_plugin_no; + if (bfd_check_format (ibfd, bfd_archive)) { bool force_output_target; @@ -3913,7 +3936,8 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, /* bfd_get_target does not return the correct value until bfd_check_format succeeds. */ - if (output_target == NULL) + if (output_target == NULL + || strcmp (output_target, "default") == 0) { output_target = bfd_get_target (ibfd); force_output_target = false; @@ -3930,7 +3954,10 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, { if (ofd >= 0) close (ofd); - bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + if (force_output_target && bfd_get_error () == bfd_error_invalid_target) + bfd_nonfatal_message (output_target, NULL, NULL, NULL); + else + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); bfd_close (ibfd); status = 1; return; @@ -3946,15 +3973,64 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, if (!copy_archive (ibfd, obfd, output_target, force_output_target, input_arch)) status = 1; + return; } - else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching)) + + bool ok_plugin = false; + bool ok_object = bfd_check_format_matches (ibfd, bfd_object, &obj_matching); + bfd_error_type obj_error = bfd_get_error (); + bfd_error_type core_error = bfd_error_no_error; + if (!ok_object) + { + ok_object = bfd_check_format_matches (ibfd, bfd_core, &core_matching); + core_error = bfd_get_error (); + if (ok_object) + { + if (obj_error == bfd_error_file_ambiguously_recognized) + free (obj_matching); + obj_error = bfd_error_no_error; + } + else if (bfd_plugin_enabled ()) + { + /* This is for LLVM bytecode files, which are not ELF objects. + Since objcopy/strip does nothing with these files except + copy them whole perhaps we ought to just reject them? */ + bfd_find_target ("plugin", ibfd); + ibfd->plugin_format = bfd_plugin_unknown; + ok_plugin = bfd_check_format (ibfd, bfd_object); + } + } + + if (obj_error == bfd_error_file_ambiguously_recognized) + { + if (core_error == bfd_error_file_ambiguously_recognized) + free (core_matching); + bfd_set_error (obj_error); + status = 1; + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + list_matching_formats (obj_matching); + } + else if (core_error == bfd_error_file_ambiguously_recognized) + { + status = 1; + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + list_matching_formats (core_matching); + } + else if (!ok_object && !ok_plugin) + { + status = 1; + bfd_set_error (obj_error); + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + } + else { bfd *obfd; - do_copy: /* bfd_get_target does not return the correct value until bfd_check_format succeeds. */ - if (output_target == NULL) + if (ok_object + && (output_target == NULL + || strcmp (output_target, "default") == 0)) output_target = bfd_get_target (ibfd); if (ofd >= 0) @@ -3966,58 +4042,39 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, { if (ofd >= 0) close (ofd); - bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + if (bfd_get_error () == bfd_error_invalid_target) + bfd_nonfatal_message (output_target, NULL, NULL, NULL); + else + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); bfd_close (ibfd); status = 1; return; } - if (! copy_object (ibfd, obfd, input_arch)) + /* Copy slim LTO IR file as unknown file. */ + if (ibfd->lto_type == lto_slim_ir_object) + ok_object = false; + if (ok_object + ? !copy_object (ibfd, obfd, input_arch) + : !copy_unknown_file (ibfd, obfd, + in_stat->st_size, in_stat->st_mode)) status = 1; /* PR 17512: file: 0f15796a. If the file could not be copied it may not be in a writeable state. So use bfd_close_all_done to avoid the possibility of writing uninitialised data into the file. */ - if (! (status ? bfd_close_all_done (obfd) : bfd_close (obfd))) + if (!(ok_object && !status ? bfd_close : bfd_close_all_done) (obfd)) { status = 1; bfd_nonfatal_message (output_filename, NULL, NULL, NULL); } - - if (!bfd_close (ibfd)) - { - status = 1; - bfd_nonfatal_message (input_filename, NULL, NULL, NULL); - } } - else - { - bfd_error_type obj_error = bfd_get_error (); - bfd_error_type core_error; - - if (bfd_check_format_matches (ibfd, bfd_core, &core_matching)) - { - /* This probably can't happen.. */ - if (obj_error == bfd_error_file_ambiguously_recognized) - free (obj_matching); - goto do_copy; - } - - core_error = bfd_get_error (); - /* Report the object error in preference to the core error. */ - if (obj_error != core_error) - bfd_set_error (obj_error); - bfd_nonfatal_message (input_filename, NULL, NULL, NULL); - - if (obj_error == bfd_error_file_ambiguously_recognized) - list_matching_formats (obj_matching); - if (core_error == bfd_error_file_ambiguously_recognized) - list_matching_formats (core_matching); - - bfd_close (ibfd); + if (!bfd_close (ibfd)) + { status = 1; + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); } } @@ -4112,29 +4169,6 @@ power_of_two (bfd_vma val) return result; } -static unsigned int -image_scn_align (unsigned int alignment) -{ - switch (alignment) - { - case 8192: return IMAGE_SCN_ALIGN_8192BYTES; - case 4096: return IMAGE_SCN_ALIGN_4096BYTES; - case 2048: return IMAGE_SCN_ALIGN_2048BYTES; - case 1024: return IMAGE_SCN_ALIGN_1024BYTES; - case 512: return IMAGE_SCN_ALIGN_512BYTES; - case 256: return IMAGE_SCN_ALIGN_256BYTES; - case 128: return IMAGE_SCN_ALIGN_128BYTES; - case 64: return IMAGE_SCN_ALIGN_64BYTES; - case 32: return IMAGE_SCN_ALIGN_32BYTES; - case 16: return IMAGE_SCN_ALIGN_16BYTES; - case 8: return IMAGE_SCN_ALIGN_8BYTES; - case 4: return IMAGE_SCN_ALIGN_4BYTES; - case 2: return IMAGE_SCN_ALIGN_2BYTES; - case 1: return IMAGE_SCN_ALIGN_1BYTES; - default: return 0; - } -} - /* Create a section in OBFD with the same name and attributes as ISECTION in IBFD. */ @@ -4300,24 +4334,9 @@ setup_section (bfd *ibfd, sec_ptr isection, bfd *obfd) if (p != NULL) alignment = p->alignment; else if (pe_section_alignment != (bfd_vma) -1 - && bfd_get_flavour (ibfd) == bfd_target_coff_flavour - && bfd_get_flavour (obfd) == bfd_target_coff_flavour) - { - alignment = power_of_two (pe_section_alignment); - - if (coff_section_data (ibfd, isection)) - { - struct pei_section_tdata * pei_data = pei_section_data (ibfd, isection); - - if (pei_data != NULL) - { - /* Set the alignment flag of the input section, which will - be copied to the output section later on. */ - pei_data->pe_flags &= ~IMAGE_SCN_ALIGN_POWER_BIT_MASK; - pei_data->pe_flags |= image_scn_align (pe_section_alignment); - } - } - } + && bfd_get_flavour (obfd) == bfd_target_coff_flavour + && bfd_pei_p (obfd)) + alignment = power_of_two (pe_section_alignment); else alignment = bfd_section_alignment (isection); @@ -4382,7 +4401,7 @@ setup_section (bfd *ibfd, sec_ptr isection, bfd *obfd) /* 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)) + if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection, NULL)) err = _("failed to copy private data"); if (make_nobits) @@ -4634,6 +4653,7 @@ copy_section (bfd *ibfd, sec_ptr isection, bfd *obfd) char *to = (char *) memhunk; char *end = (char *) memhunk + size; int i; + bfd_size_type memhunk_size = size; /* If the section address is not exactly divisible by the interleave, then we must bias the from address. If the copy_byte is less than @@ -4653,6 +4673,11 @@ copy_section (bfd *ibfd, sec_ptr isection, bfd *obfd) } size = (size + interleave - 1 - copy_byte) / interleave * copy_width; + + /* Don't extend the output section size. */ + if (size > memhunk_size) + size = memhunk_size; + osection->lma /= interleave; if (copy_byte < extra) osection->lma++; @@ -4873,6 +4898,8 @@ strip_main (int argc, char *argv[]) char *output_file = NULL; bool merge_notes_set = false; + bfd_plugin_set_program_name (argv[0]); + while ((c = getopt_long (argc, argv, "I:O:F:K:MN:R:o:sSpdgxXHhVvwDU", strip_options, (int *) 0)) != EOF) { @@ -4963,6 +4990,11 @@ strip_main (int argc, char *argv[]) case OPTION_KEEP_SECTION_SYMBOLS: keep_section_symbols = true; break; + case OPTION_PLUGIN: /* --plugin */ + if (!bfd_plugin_enabled ()) + fatal (_("sorry - this program has been built without plugin support\n")); + bfd_plugin_set_plugin (optarg); + break; case 0: /* We've been given a long option. */ break; @@ -5007,6 +5039,16 @@ strip_main (int argc, char *argv[]) if (output_target == NULL) output_target = input_target; + /* Check if all GCC LTO sections should be removed, assuming all LTO + sections will be removed with -R .gnu.lto_.*. Remove .gnu.lto_.* + sections will also remove .gnu.debuglto_.* sections. + + NB: Must keep .gnu.debuglto_* sections unless all GCC LTO sections + will be removed to avoid undefined references to symbols in GCC LTO + debug sections. */ + if (!find_section_list (".gnu.lto_.*", false, SECTION_CONTEXT_REMOVE)) + find_section_list (".gnu.debuglto_*", true, SECTION_CONTEXT_KEEP); + i = optind; if (i == argc || (output_file != NULL && (i + 1) < argc)) @@ -5979,6 +6021,11 @@ copy_main (int argc, char *argv[]) case OPTION_FILE_ALIGNMENT: pe_file_alignment = parse_vma (optarg, "--file-alignment"); + if (power_of_two (pe_file_alignment) == -1) + { + non_fatal (_("--file-alignment argument is not a power of two: %s - ignoring"), optarg); + pe_file_alignment = (bfd_vma) -1; + } break; case OPTION_HEAP: @@ -6222,9 +6269,11 @@ main (int argc, char *argv[]) fatal (_("fatal error: libbfd ABI mismatch")); set_default_bfd_target (); +#ifndef is_strip if (is_strip < 0) { - int i = strlen (program_name); + size_t i = strlen (program_name); + #ifdef HAVE_DOS_BASED_FILE_SYSTEM /* Drop the .exe suffix, if any. */ if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0) @@ -6235,6 +6284,7 @@ main (int argc, char *argv[]) #endif is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0); } +#endif /* is_strip */ create_symbol_htabs (); xatexit (delete_symbol_htabs); |