/* objcopy.c -- copy object file from input to output, optionally massaging it.
- Copyright (C) 1991-2022 Free Software Foundation, Inc.
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
This file is part of GNU Binutils.
\f
#include "sysdep.h"
#include "bfd.h"
-#include "progress.h"
#include "getopt.h"
#include "libiberty.h"
#include "bucomm.h"
compress_zlib = compress | 1 << 1,
compress_gnu_zlib = compress | 1 << 2,
compress_gabi_zlib = compress | 1 << 3,
- decompress = 1 << 4
+ compress_zstd = compress | 1 << 4,
+ decompress = 1 << 5
} do_debug_sections = nothing;
/* Whether to generate ELF common symbols with the STT_COMMON type. */
the --verilog-data-width parameter. */
extern unsigned int VerilogDataWidth;
+/* Endianness of data for verilog output.
+ This variable is declared in bfd/verilog.c and is set in the
+ copy_object() function. */
+extern enum bfd_endian VerilogDataEndianness;
+
/* Forward declarations. */
static void setup_section (bfd *, asection *, void *);
static void setup_bfd_headers (bfd *, bfd *);
<commit>\n\
--subsystem <name>[:<version>]\n\
Set PE subsystem to <name> [& <version>]\n\
- --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
- Compress DWARF debug sections using zlib\n\
+ --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi|zstd}]\n\
+ Compress DWARF debug sections\n\
--decompress-debug-sections Decompress DWARF debug sections using zlib\n\
--elf-stt-common=[yes|no] Generate ELF common symbols with STT_COMMON\n\
type\n\
return needle->start >= haystack->start && needle->end <= haystack->end;
}
-static bool
+static inline bool
is_open_note (objcopy_internal_note * pnote)
{
return pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
}
-static bool
+static inline bool
is_func_note (objcopy_internal_note * pnote)
{
return pnote->note.type == NT_GNU_BUILD_ATTRIBUTE_FUNC;
}
-static bool
+static inline bool
is_deleted_note (objcopy_internal_note * pnote)
{
return pnote->note.type == 0;
other note then if they are both of the same type (open
or func) then they can be merged and one deleted. If
they are of different types then they cannot be merged. */
+ objcopy_internal_note * prev_note = NULL;
+
for (pnote = pnotes; pnote < pnotes_end; pnote ++)
{
/* Skip already deleted notes.
objcopy_internal_note * back;
/* Rule 2: Check to see if there is an identical previous note. */
- for (iter = 0, back = pnote - 1; back >= pnotes; back --)
+ for (iter = 0, back = prev_note ? prev_note : pnote - 1;
+ back >= pnotes;
+ back --)
{
if (is_deleted_note (back))
continue;
break;
}
}
-#if DEBUG_MERGE
+
if (! is_deleted_note (pnote))
- merge_debug ("Unable to do anything with note at %#08lx\n",
- (pnote->note.namedata - (char *) contents) - 12);
+ {
+ /* Keep a pointer to this note, so that we can
+ start the next search for rule 2 matches here. */
+ prev_note = pnote;
+#if DEBUG_MERGE
+ merge_debug ("Unable to do anything with note at %#08lx\n",
+ (pnote->note.namedata - (char *) contents) - 12);
#endif
+ }
}
/* Resort the notes. */
return flags;
}
+static void
+set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_handling style)
+{
+ /* This is only relevant to Coff targets. */
+ if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
+ {
+ if (style == KEEP
+ && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
+ style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
+ bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
+ }
+}
+
/* Copy object file IBFD onto OBFD.
Returns TRUE upon success, FALSE otherwise. */
return false;
}
+ /* This is a no-op on non-Coff targets. */
+ set_long_section_mode (obfd, ibfd, long_section_names);
+
+ /* Set the Verilog output endianness based upon the input file's
+ endianness. We may not be producing verilog format output,
+ but testing this just adds extra code this is not really
+ necessary. */
+ VerilogDataEndianness = ibfd->xvec->byteorder;
+
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
{
if ((do_debug_sections & compress) != 0
&& do_debug_sections != compress)
{
- non_fatal (_("--compress-debug-sections=[zlib|zlib-gnu|zlib-gabi] is unsupported on `%s'"),
+ non_fatal (_ ("--compress-debug-sections=[zlib|zlib-gnu|zlib-gabi|"
+ "zstd] is unsupported on `%s'"),
bfd_get_archive_filename (ibfd));
return false;
}
bfd_size_type size = bfd_section_size (osec);
if (size == 0)
- {
- bfd_nonfatal_message (NULL, ibfd, osec,
- _("warning: note section is empty"));
- continue;
- }
+ /* This can happen, eg when stripping a binary for a second
+ time. See BZ 2121365 for an example. */
+ continue;
merged_note_section * merged = xmalloc (sizeof * merged);
merged->contents = NULL;
if (bfd_get_section_by_name (obfd, ".gnu_debuglink"))
{
non_fatal (_("%s: debuglink section already exists"),
- bfd_get_filename (obfd));
+ bfd_get_filename (ibfd));
gnu_debuglink_filename = NULL;
}
else
/* This has to happen before section positions are set. */
bfd_map_over_sections (ibfd, copy_relocations_in_section, obfd);
+ if (status != 0)
+ return false;
/* This has to happen after the symbol table has been set. */
bfd_map_over_sections (ibfd, copy_section, obfd);
+ if (status != 0)
+ return false;
if (add_sections != NULL)
{
bfd **ptr = &obfd->archive_head;
bfd *this_element;
char *dir;
- const char *filename;
+ char *filename;
/* PR 24281: It is not clear what should happen when copying a thin archive.
One part is straight forward - if the output archive is in a different
if (del && bfd_get_arch (this_element) == bfd_arch_unknown)
/* Try again as an unknown object file. */
ok_object = false;
- else if (!bfd_close (output_bfd))
- {
- bfd_nonfatal_message (output_name, NULL, NULL, NULL);
- /* Error in new object file. Don't change archive. */
- status = 1;
- }
}
if (!ok_object)
+ del = !copy_unknown_object (this_element, output_bfd);
+
+ if (!(ok_object && !del && !status
+ ? bfd_close : bfd_close_all_done) (output_bfd))
{
- del = !copy_unknown_object (this_element, output_bfd);
- if (!bfd_close_all_done (output_bfd))
- {
- bfd_nonfatal_message (output_name, NULL, NULL, NULL);
- /* Error in new object file. Don't change archive. */
- status = 1;
- }
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
+ /* Error in new object file. Don't change archive. */
+ status = 1;
}
if (del)
}
*ptr = NULL;
- filename = bfd_get_filename (obfd);
- if (!bfd_close (obfd))
+ filename = xstrdup (bfd_get_filename (obfd));
+ if (!(status == 0 ? bfd_close : bfd_close_all_done) (obfd))
{
status = 1;
bfd_nonfatal_message (filename, NULL, NULL, NULL);
}
+ free (filename);
- filename = bfd_get_filename (ibfd);
+ filename = xstrdup (bfd_get_filename (ibfd));
if (!bfd_close (ibfd))
{
status = 1;
bfd_nonfatal_message (filename, NULL, NULL, NULL);
}
+ free (filename);
cleanup_and_exit:
/* Delete all the files that we opened. */
bfd_close (l->obfd);
unlink (l->name);
}
+ free ((char *) l->name);
next = l->next;
free (l);
}
free (dir);
}
-static void
-set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_handling style)
-{
- /* This is only relevant to Coff targets. */
- if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
- {
- if (style == KEEP
- && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
- style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
- bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
- }
-}
-
/* The top-level control. */
static void
switch (do_debug_sections)
{
+ case compress_gnu_zlib:
+ ibfd->flags |= BFD_COMPRESS;
+ break;
case compress:
case compress_zlib:
- case compress_gnu_zlib:
+ /* The above two cases ought to just set BFD_COMPRESS for non-ELF
+ but we can't tell whether a file is ELF or not until after
+ bfd_check_format_matches. FIXME maybe: decide compression
+ style in BFD after bfd_check_format_matches. */
case compress_gabi_zlib:
- ibfd->flags |= BFD_COMPRESS;
- /* Don't check if input is ELF here since this information is
- only available after bfd_check_format_matches is called. */
- if (do_debug_sections != compress_gnu_zlib)
- ibfd->flags |= BFD_COMPRESS_GABI;
+ ibfd->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI;
+ break;
+ case compress_zstd:
+ ibfd->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD;
+#ifndef HAVE_ZSTD
+ fatal (_ ("--compress-debug-sections=zstd: binutils is not built with "
+ "zstd support"));
+#endif
break;
case decompress:
ibfd->flags |= BFD_DECOMPRESS;
gnu_debuglink_filename = NULL;
}
- /* This is a no-op on non-Coff targets. */
- set_long_section_mode (obfd, ibfd, long_section_names);
-
copy_archive (ibfd, obfd, output_target, force_output_target, input_arch);
}
else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
return;
}
- /* This is a no-op on non-Coff targets. */
- set_long_section_mode (obfd, ibfd, long_section_names);
-
if (! copy_object (ibfd, obfd, input_arch))
status = 1;
{
status = 1;
bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
- return;
}
if (!bfd_close (ibfd))
{
status = 1;
bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
- return;
}
}
else
&& (flags & (SEC_ALLOC | SEC_GROUP)) != 0
&& !is_nondebug_keep_contents_section (ibfd, isection))
{
- flagword remove = SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP;
+ flagword clr = SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP;
if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
{
being used with GDB, if they were based upon files that
originally contained groups. */
if (flags & SEC_GROUP)
- remove = SEC_LOAD;
+ clr = SEC_LOAD;
else
make_nobits = true;
elf.c:copy_private_bfd_data that section flags have not
changed between input and output sections. This hack
prevents wholesale rewriting of the program headers. */
- isection->flags &= ~remove;
+ isection->flags &= ~clr;
}
- flags &= ~remove;
+ flags &= ~clr;
+ }
+
+ if (!bfd_convert_section_setup (ibfd, isection, obfd, &name, &size))
+ {
+ osection = NULL;
+ err = _("failed to create output section");
+ goto loser;
}
osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
goto loser;
}
- size = bfd_section_size (isection);
- size = bfd_convert_section_size (ibfd, isection, obfd, size);
if (copy_byte >= 0)
size = (size + interleave - 1) / interleave * copy_width;
else if (extract_symbol)
}
if (relsize == 0)
- {
- bfd_set_reloc (obfd, osection, NULL, 0);
- osection->flags &= ~SEC_RELOC;
- }
+ bfd_set_reloc (obfd, osection, NULL, 0);
else
{
if (isection->orelocation != NULL)
}
bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
- if (relcount == 0)
- osection->flags &= ~SEC_RELOC;
}
}
|| !bfd_convert_section_contents (ibfd, isection, obfd,
&memhunk, &size))
{
+ bfd_set_section_size (osection, 0);
status = 1;
bfd_nonfatal_message (NULL, ibfd, isection, NULL);
free (memhunk);
do_debug_sections = compress_gnu_zlib;
else if (strcasecmp (optarg, "zlib-gabi") == 0)
do_debug_sections = compress_gabi_zlib;
+ else if (strcasecmp (optarg, "zstd") == 0)
+ do_debug_sections = compress_zstd;
else
fatal (_("unrecognized --compress-debug-sections type `%s'"),
optarg);
case OPTION_VERILOG_DATA_WIDTH:
VerilogDataWidth = parse_vma (optarg, "--verilog-data-width");
- if (VerilogDataWidth < 1)
- fatal (_("verilog data width must be at least 1 byte"));
+ switch (VerilogDataWidth)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16: /* We do not support widths > 16 because the verilog
+ data is handled internally in 16 byte wide packets. */
+ break;
+ default:
+ fatal (_("error: verilog data width must be 1, 2, 4, 8 or 16"));
+ }
break;
case 0:
program_name = argv[0];
xmalloc_set_program_name (program_name);
- START_PROGRESS (program_name, 0);
-
expandargv (&argc, &argv);
strip_symbols = STRIP_UNDEF;
else
copy_main (argc, argv);
- END_PROGRESS (program_name);
-
+ xexit (status);
return status;
}