diff options
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r-- | binutils/objcopy.c | 121 |
1 files changed, 99 insertions, 22 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 31933e1..2e98ba4 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -30,6 +30,8 @@ #include "coff/internal.h" #include "libcoff.h" #include "safe-ctype.h" +#include "plugin-api.h" +#include "plugin.h" /* FIXME: See bfd/peXXigen.c for why we include an architecture specific header in generic PE code. */ @@ -165,6 +167,11 @@ static struct section_list *change_sections; /* TRUE if some sections are to be removed. */ static bool sections_removed; +#if BFD_SUPPORTS_PLUGINS +/* TRUE if all GCC LTO sections are to be removed. */ +static bool lto_sections_removed; +#endif + /* TRUE if only some sections are to be copied. */ static bool sections_copied; @@ -359,6 +366,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 +410,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}, @@ -758,6 +767,10 @@ strip_usage (FILE *stream, int exit_status) --info List object formats & architectures supported\n\ -o <file> Place stripped output into <file>\n\ ")); +#if BFD_SUPPORTS_PLUGINS + fprintf (stream, _("\ + --plugin NAME Load the specified plugin\n")); +#endif list_supported_targets (program_name, stream); if (REPORT_BUGS_TO[0] && exit_status == 0) @@ -1916,20 +1929,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'"), @@ -1974,11 +1978,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; @@ -3744,6 +3768,12 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, goto cleanup_and_exit; } +#if BFD_SUPPORTS_PLUGINS + /* Copy LTO IR file as unknown object. */ + if (bfd_plugin_target_p (this_element->xvec)) + ok_object = false; + else +#endif if (ok_object) { ok = copy_object (this_element, output_element, input_arch); @@ -3845,6 +3875,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,9 +3886,16 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, return; } +#if BFD_SUPPORTS_PLUGINS + /* Enable LTO plugin in strip unless all LTO sections should be + removed. */ + if (is_strip && !target && !lto_sections_removed) + target = "plugin"; +#endif + /* 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); @@ -3974,17 +4012,31 @@ copy_file (const char *input_filename, const char *output_filename, int ofd, return; } - if (! copy_object (ibfd, obfd, input_arch)) - 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 BFD_SUPPORTS_PLUGINS + if (bfd_plugin_target_p (ibfd->xvec)) { - status = 1; - bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + /* Copy LTO IR file as unknown file. */ + if (!copy_unknown_file (ibfd, obfd, in_stat->st_size, + in_stat->st_mode)) + status = 1; + else if (!bfd_close_all_done (obfd)) + status = 1; + } + else +#endif + { + if (! copy_object (ibfd, obfd, input_arch)) + 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))) + { + status = 1; + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + } } if (!bfd_close (ibfd)) @@ -4598,6 +4650,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 @@ -4617,6 +4670,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++; @@ -4837,6 +4895,10 @@ strip_main (int argc, char *argv[]) char *output_file = NULL; bool merge_notes_set = false; +#if BFD_SUPPORTS_PLUGINS + bfd_plugin_set_program_name (argv[0]); +#endif + while ((c = getopt_long (argc, argv, "I:O:F:K:MN:R:o:sSpdgxXHhVvwDU", strip_options, (int *) 0)) != EOF) { @@ -4927,6 +4989,13 @@ strip_main (int argc, char *argv[]) case OPTION_KEEP_SECTION_SYMBOLS: keep_section_symbols = true; break; + case OPTION_PLUGIN: /* --plugin */ +#if BFD_SUPPORTS_PLUGINS + bfd_plugin_set_plugin (optarg); +#else + fatal (_("sorry - this program has been built without plugin support\n")); +#endif + break; case 0: /* We've been given a long option. */ break; @@ -4971,6 +5040,14 @@ strip_main (int argc, char *argv[]) if (output_target == NULL) output_target = input_target; +#if BFD_SUPPORTS_PLUGINS + /* 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. */ + lto_sections_removed = !!find_section_list (".gnu.lto_.*", false, + SECTION_CONTEXT_REMOVE); +#endif + i = optind; if (i == argc || (output_file != NULL && (i + 1) < argc)) |