aboutsummaryrefslogtreecommitdiff
path: root/binutils/objcopy.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r--binutils/objcopy.c226
1 files changed, 152 insertions, 74 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 31933e1..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},
@@ -758,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)
@@ -1916,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'"),
@@ -1974,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;
@@ -2505,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;
@@ -2513,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
@@ -2561,8 +2573,6 @@ merge_gnu_build_notes (bfd * abfd,
prev_end = pnote->end;
}
}
-
- old += note_size;
}
#if DEBUG_MERGE
@@ -2794,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;
}
@@ -3724,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. */
@@ -3744,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);
@@ -3777,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;
@@ -3845,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)
{
@@ -3857,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;
@@ -3908,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;
@@ -3915,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;
@@ -3932,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;
@@ -3948,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)
@@ -3968,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);
}
}
@@ -4346,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)
@@ -4598,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
@@ -4617,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++;
@@ -4837,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)
{
@@ -4927,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;
@@ -4971,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))