/* objcopy.c -- copy object file from input to output, optionally massaging it.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GNU Binutils.
static asymbol **isympp = NULL; /* Input symbols. */
static asymbol **osympp = NULL; /* Output symbols that survive stripping. */
-/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
+/* If `copy_byte' >= 0, copy 'copy_width' byte(s) of every `interleave' bytes. */
static int copy_byte = -1;
-static int interleave = 4;
+static int interleave = 0; /* Initialised to 4 in copy_main(). */
+static int copy_width = 1;
static bfd_boolean verbose; /* Print file and target names. */
static bfd_boolean preserve_dates; /* Preserve input file timestamp. */
/* Whether to convert debugging information. */
static bfd_boolean convert_debugging = FALSE;
+/* Whether to compress/decompress DWARF debug sections. */
+static enum
+{
+ nothing,
+ compress,
+ decompress
+} do_debug_sections = nothing;
+
/* Whether to change the leading character in symbol names. */
static bfd_boolean change_leading_char = FALSE;
OPTION_CHANGE_SECTION_LMA,
OPTION_CHANGE_SECTION_VMA,
OPTION_CHANGE_WARNINGS,
+ OPTION_COMPRESS_DEBUG_SECTIONS,
OPTION_DEBUGGING,
+ OPTION_DECOMPRESS_DEBUG_SECTIONS,
OPTION_GAP_FILL,
OPTION_NO_CHANGE_WARNINGS,
OPTION_PAD_TO,
OPTION_IMAGE_BASE,
OPTION_SECTION_ALIGNMENT,
OPTION_STACK,
+ OPTION_INTERLEAVE_WIDTH,
OPTION_SUBSYSTEM
};
{"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
{"change-start", required_argument, 0, OPTION_CHANGE_START},
{"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
+ {"compress-debug-sections", no_argument, 0, OPTION_COMPRESS_DEBUG_SECTIONS},
{"debugging", no_argument, 0, OPTION_DEBUGGING},
+ {"decompress-debug-sections", no_argument, 0, OPTION_DECOMPRESS_DEBUG_SECTIONS},
{"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'},
{"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
{"info", no_argument, 0, OPTION_FORMATS_INFO},
{"input-format", required_argument, 0, 'I'}, /* Obsolete */
{"input-target", required_argument, 0, 'I'},
- {"interleave", required_argument, 0, 'i'},
+ {"interleave", optional_argument, 0, 'i'},
+ {"interleave-width", required_argument, 0, OPTION_INTERLEAVE_WIDTH},
{"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
{"keep-global-symbol", required_argument, 0, 'G'},
{"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
-w --wildcard Permit wildcard in symbol comparison\n\
-x --discard-all Remove all non-global symbols\n\
-X --discard-locals Remove any compiler-generated symbols\n\
- -i --interleave <number> Only copy one out of every <number> bytes\n\
+ -i --interleave [<number>] Only copy N out of every <number> bytes\n\
+ --interleave-width <number> Set N for --interleave\n\
-b --byte <num> Select byte <num> in every interleaved block\n\
--gap-fill <val> Fill gaps between sections with <val>\n\
--pad-to <addr> Pad the last section up to address <addr>\n\
--stack <reserve>[,<commit>] Set PE reserve/commit stack to <reserve>/\n\
<commit>\n\
--subsystem <name>[:<version>]\n\
- Set PE subsystem to <name> [& <version>]\n]\
+ Set PE subsystem to <name> [& <version>]\n\
+ --compress-debug-sections Compress DWARF debug sections using zlib\n\
+ --decompress-debug-sections Decompress DWARF debug sections using zlib\n\
-v --verbose List all object files modified\n\
@<file> Read options from <file>\n\
-V --version Display this program's version number\n\
ncopied += tocopy;
}
- chmod (bfd_get_filename (obfd), buf.st_mode);
+ /* 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);
free (cbuf);
return TRUE;
}
struct stat buf;
int stat_status = 0;
bfd_boolean del = TRUE;
+ bfd_boolean ok_object;
/* Create an output file for this member. */
output_name = concat (dir, "/",
l->obfd = NULL;
list = l;
- if (bfd_check_format (this_element, bfd_object))
+ 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. */
+ if (force_output_target || !ok_object)
+ output_bfd = bfd_openw (output_name, output_target);
+ else
+ output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
+
+ if (output_bfd == NULL)
{
- /* PR binutils/3110: Cope with archives
- containing multiple target types. */
- if (force_output_target)
- output_bfd = bfd_openw (output_name, output_target);
- else
- output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
+ bfd_nonfatal_message (output_name, NULL, NULL, NULL);
+ status = 1;
+ return;
+ }
+
+ if (ok_object)
+ {
+ del = !copy_object (this_element, output_bfd, input_arch);
- if (output_bfd == NULL)
+ 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;
- return;
}
-
- del = ! copy_object (this_element, output_bfd, input_arch);
-
- if (! del
- || bfd_get_arch (this_element) != bfd_arch_unknown)
- {
- if (!bfd_close (output_bfd))
- {
- bfd_nonfatal_message (output_name, NULL, NULL, NULL);
- /* Error in new object file. Don't change archive. */
- status = 1;
- }
- }
- else
- goto copy_unknown_element;
}
- else
- {
- bfd_nonfatal_message (NULL, this_element, NULL,
- _("Unable to recognise the format of file"));
- output_bfd = bfd_openw (output_name, output_target);
-copy_unknown_element:
+ if (!ok_object)
+ {
del = !copy_unknown_object (this_element, output_bfd);
if (!bfd_close_all_done (output_bfd))
{
return;
}
+ switch (do_debug_sections)
+ {
+ case compress:
+ ibfd->flags |= BFD_COMPRESS;
+ break;
+ case decompress:
+ ibfd->flags |= BFD_DECOMPRESS;
+ break;
+ default:
+ break;
+ }
+
if (bfd_check_format (ibfd, bfd_archive))
{
bfd_boolean force_output_target;
size = bfd_section_size (ibfd, isection);
if (copy_byte >= 0)
- size = (size + interleave - 1) / interleave;
+ size = (size + interleave - 1) / interleave * copy_width;
else if (extract_symbol)
size = 0;
if (! bfd_set_section_size (obfd, osection, size))
if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
{
- void *memhunk = xmalloc (size);
+ bfd_byte *memhunk = NULL;
- if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
+ if (!bfd_get_full_section_contents (ibfd, isection, &memhunk))
{
status = 1;
bfd_nonfatal_message (NULL, ibfd, isection, NULL);
char *from = (char *) memhunk + copy_byte;
char *to = (char *) memhunk;
char *end = (char *) memhunk + size;
+ int i;
for (; from < end; from += interleave)
- *to++ = *from;
+ for (i = 0; i < copy_width; i++)
+ *to++ = from[i];
- size = (size + interleave - 1 - copy_byte) / interleave;
+ size = (size + interleave - 1 - copy_byte) / interleave * copy_width;
osection->lma /= interleave;
}
It has already been checked in get_file_size(). */
stat (argv[i], &statbuf);
- if (output_file == NULL || strcmp (argv[i], output_file) == 0)
+ if (output_file == NULL
+ || filename_cmp (argv[i], output_file) == 0)
tmpname = make_tempname (argv[i]);
else
tmpname = output_file;
pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
break;
}
+ if (s != subsystem)
+ free ((char *) subsystem);
}
/* Convert EFI target to PEI target. */
break;
case 'i':
- interleave = atoi (optarg);
- if (interleave < 1)
- fatal (_("interleave must be positive"));
+ if (optarg)
+ {
+ interleave = atoi (optarg);
+ if (interleave < 1)
+ fatal (_("interleave must be positive"));
+ }
+ else
+ interleave = 4;
+ break;
+
+ case OPTION_INTERLEAVE_WIDTH:
+ copy_width = atoi (optarg);
+ if (copy_width < 1)
+ fatal(_("interleave width must be positive"));
break;
case 'I':
change_leading_char = TRUE;
break;
+ case OPTION_COMPRESS_DEBUG_SECTIONS:
+ do_debug_sections = compress;
+ break;
+
case OPTION_DEBUGGING:
convert_debugging = TRUE;
break;
+ case OPTION_DECOMPRESS_DEBUG_SECTIONS:
+ do_debug_sections = decompress;
+ break;
+
case OPTION_GAP_FILL:
{
bfd_vma gap_fill_vma;
if (show_version)
print_version ("objcopy");
+ if (interleave && copy_byte == -1)
+ fatal (_("interleave start byte must be set with --byte"));
+
if (copy_byte >= interleave)
fatal (_("byte number must be less than interleave"));
+ if (copy_width > interleave - copy_byte)
+ fatal (_("interleave width must be less than or equal to interleave - byte`"));
+
if (optind == argc || optind + 2 < argc)
copy_usage (stderr, 1);
/* If there is no destination file, or the source and destination files
are the same, then create a temp and rename the result into the input. */
- if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
+ if (output_filename == NULL
+ || filename_cmp (input_filename, output_filename) == 0)
tmpname = make_tempname (input_filename);
else
tmpname = output_filename;