Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
\f
+#include "sysdep.h"
#include "bfd.h"
#include "progress.h"
-#include "bucomm.h"
#include "getopt.h"
#include "libiberty.h"
+#include "bucomm.h"
#include "budbg.h"
#include "filenames.h"
#include "fnmatch.h"
/* True if --extract-symbol was passed on the command line. */
static bfd_boolean extract_symbol = FALSE;
+/* If `reverse_bytes' is nonzero, then reverse the order of every chunk
+ of <reverse_bytes> bytes within each output section. */
+static int reverse_bytes = 0;
+
+
/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
enum command_line_switch
{
OPTION_WRITABLE_TEXT,
OPTION_PURE,
OPTION_IMPURE,
- OPTION_EXTRACT_SYMBOL
+ OPTION_EXTRACT_SYMBOL,
+ OPTION_REVERSE_BYTES
};
/* Options to handle if running as "strip". */
{"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
{"remove-section", required_argument, 0, 'R'},
{"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
+ {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
{"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
{"set-start", required_argument, 0, OPTION_SET_START},
{"srec-len", required_argument, 0, OPTION_SREC_LEN},
--rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
--change-leading-char Force output format's leading character style\n\
--remove-leading-char Remove leading character from global symbols\n\
+ --reverse-bytes=<num> Reverse <num> bytes at a time, in output sections with content\n\
--redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\
--redefine-syms <file> --redefine-sym for all symbol pairs \n\
listed in <file>\n\
asymbol *sym = from[src_count];
flagword flags = sym->flags;
char *name = (char *) bfd_asymbol_name (sym);
- int keep;
+ bfd_boolean keep;
+ bfd_boolean used_in_reloc = FALSE;
bfd_boolean undefined;
bfd_boolean rem_leading_char;
bfd_boolean add_leading_char;
}
if (strip_symbols == STRIP_ALL)
- keep = 0;
+ keep = FALSE;
else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */
|| ((flags & BSF_SECTION_SYM) != 0
&& ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
& BSF_KEEP) != 0))
- keep = 1;
+ {
+ keep = TRUE;
+ used_in_reloc = TRUE;
+ }
else if (relocatable /* Relocatable file. */
&& (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
- keep = 1;
+ keep = TRUE;
else if (bfd_decode_symclass (sym) == 'I')
/* Global symbols in $idata sections need to be retained
even if relocatable is FALSE. External users of the
library containing the $idata section may reference these
symbols. */
- keep = 1;
+ keep = TRUE;
else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */
|| (flags & BSF_WEAK) != 0
|| undefined
else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
/* COMDAT sections store special information in local
symbols, so we cannot risk stripping any of them. */
- keep = 1;
+ keep = TRUE;
else /* Local symbol. */
keep = (strip_symbols != STRIP_UNNEEDED
&& (discard_locals != LOCALS_ALL
|| ! bfd_is_local_label (abfd, sym))));
if (keep && is_specified_symbol (name, strip_specific_list))
- keep = 0;
+ {
+ /* There are multiple ways to set 'keep' above, but if it
+ was the relocatable symbol case, then that's an error. */
+ if (used_in_reloc)
+ {
+ non_fatal (_("not stripping symbol `%s' because it is named in a relocation"), name);
+ status = 1;
+ }
+ else
+ keep = FALSE;
+ }
+
if (keep
&& !(flags & BSF_KEEP)
&& is_specified_symbol (name, strip_unneeded_list))
- keep = 0;
+ keep = FALSE;
+
if (!keep
&& ((keep_file_symbols && (flags & BSF_FILE))
|| is_specified_symbol (name, keep_specific_list)))
- keep = 1;
+ keep = TRUE;
+
if (keep && is_strip_section (abfd, bfd_get_section (sym)))
- keep = 0;
+ keep = FALSE;
if (keep)
{
}
if (!undefined
- && (flags & BSF_LOCAL)
+ && (flags & BSF_LOCAL)
&& is_specified_symbol (name, globalize_specific_list))
{
sym->flags &= ~ BSF_LOCAL;
if (buf[0] != '\0')
redefine_list_append (filename, &buf[0], &buf[outsym_off]);
- lineno++;
+ lineno++;
len = 0;
outsym_off = 0;
if (c == EOF)
}
}
- if (bfd_count_sections (obfd) == 0)
- {
- non_fatal (_("there are no sections to be copied!"));
- return FALSE;
- }
-
- if (gap_fill_set || pad_to_set)
+ if (bfd_count_sections (obfd) != 0
+ && (gap_fill_set || pad_to_set))
{
asection **set;
unsigned int c, i;
from the input BFD to the output BFD. This is done last to
permit the routine to look at the filtered symbol table, which is
important for the ECOFF code at least. */
- if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
- && strip_symbols == STRIP_NONDEBUG)
- /* Do not copy the private data when creating an ELF format
- debug info file. We do not want the program headers. */
- ;
- else if (! bfd_copy_private_bfd_data (ibfd, obfd))
+ if (! bfd_copy_private_bfd_data (ibfd, obfd))
{
non_fatal (_("%s: error copying private BFD data: %s"),
bfd_get_filename (obfd),
l->obfd = output_bfd;
*ptr = output_bfd;
- ptr = &output_bfd->next;
+ ptr = &output_bfd->archive_next;
last_element = this_element;
if (p != NULL && p->set_flags)
flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
- else if (strip_symbols == STRIP_NONDEBUG && (flags & SEC_ALLOC) != 0)
+ else if (strip_symbols == STRIP_NONDEBUG
+ && obfd->xvec->flavour != bfd_target_elf_flavour
+ && (flags & SEC_ALLOC) != 0)
flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
if (strip_symbols == STRIP_NONDEBUG
&& obfd->xvec->flavour == bfd_target_elf_flavour
&& (flags & SEC_ALLOC) != 0
+ && elf_section_type (osection) != SHT_NOTE
+ && (ibfd->xvec->flavour != bfd_target_elf_flavour
+ || elf_section_type (isection) != SHT_NOTE)
&& (p == NULL || !p->set_flags))
elf_section_type (osection) = SHT_NOBITS;
/* Allow the BFD backend to copy any private data it understands
from the input section to the output section. */
- if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
- && strip_symbols == STRIP_NONDEBUG)
- /* Do not copy the private data when creating an ELF format
- debug info file. We do not want the program headers. */
- ;
- else if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
+ if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
{
err = _("private data");
goto loser;
if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
RETURN_NONFATAL (bfd_get_filename (ibfd));
+ if (reverse_bytes)
+ {
+ /* We don't handle leftover bytes (too many possible behaviors,
+ and we don't know what the user wants). The section length
+ must be a multiple of the number of bytes to swap. */
+ if ((size % reverse_bytes) == 0)
+ {
+ unsigned long i, j;
+ bfd_byte b;
+
+ for (i = 0; i < size; i += reverse_bytes)
+ for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++)
+ {
+ bfd_byte *m = (bfd_byte *) memhunk;
+
+ b = m[i + j];
+ m[i + j] = m[(i + reverse_bytes) - (j + 1)];
+ m[(i + reverse_bytes) - (j + 1)] = b;
+ }
+ }
+ else
+ /* User must pad the section up in order to do this. */
+ fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"),
+ bfd_section_name (ibfd, isection), reverse_bytes);
+ }
+
if (copy_byte >= 0)
{
/* Keep only every `copy_byte'th byte in MEMHUNK. */
display_info ();
return 0;
}
-
+
if (show_version)
print_version ("strip");
It has already been checked in get_file_size(). */
stat (argv[i], &statbuf);
- if (output_file != NULL)
- tmpname = output_file;
- else
+ if (output_file == NULL || strcmp (argv[i], output_file) == 0)
tmpname = make_tempname (argv[i]);
+ else
+ tmpname = output_file;
if (tmpname == NULL)
{
{
if (preserve_dates)
set_times (tmpname, &statbuf);
- if (output_file == NULL)
- smart_rename (tmpname, argv[i], preserve_dates);
+ if (output_file != tmpname)
+ smart_rename (tmpname, output_file ? output_file : argv[i],
+ preserve_dates);
status = hold_status;
}
else
unlink_if_ordinary (tmpname);
- if (output_file == NULL)
+ if (output_file != tmpname)
free (tmpname);
}
char * binary_architecture = NULL;
char *input_filename = NULL;
char *output_filename = NULL;
+ char *tmpname;
char *input_target = NULL;
char *output_target = NULL;
bfd_boolean show_version = FALSE;
extract_symbol = TRUE;
break;
+ case OPTION_REVERSE_BYTES:
+ {
+ int prev = reverse_bytes;
+
+ reverse_bytes = atoi (optarg);
+ if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0))
+ fatal (_("number of bytes to reverse must be positive and even"));
+
+ if (prev && prev != reverse_bytes)
+ non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"),
+ prev);
+ break;
+ }
+
case 0:
/* We've been given a long option. */
break;
display_info ();
return 0;
}
-
+
if (show_version)
print_version ("objcopy");
/* 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)
- {
- char *tmpname = make_tempname (input_filename);
+ tmpname = make_tempname (input_filename);
+ else
+ tmpname = output_filename;
- if (tmpname == NULL)
- fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
- input_filename, strerror (errno));
+ if (tmpname == NULL)
+ fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
+ input_filename, strerror (errno));
- copy_file (input_filename, tmpname, input_target, output_target);
- if (status == 0)
- {
- if (preserve_dates)
- set_times (tmpname, &statbuf);
- smart_rename (tmpname, input_filename, preserve_dates);
- }
- else
- unlink (tmpname);
- }
- else
+ copy_file (input_filename, tmpname, input_target, output_target);
+ if (status == 0)
{
- copy_file (input_filename, output_filename, input_target, output_target);
-
- if (status == 0 && preserve_dates)
- set_times (output_filename, &statbuf);
- else if (status != 0)
- unlink_if_ordinary (output_filename);
+ if (preserve_dates)
+ set_times (tmpname, &statbuf);
+ if (tmpname != output_filename)
+ smart_rename (tmpname, input_filename, preserve_dates);
}
+ else
+ unlink_if_ordinary (tmpname);
if (change_warn)
{