* objcopy.c (keep_specific_list, privatize_specific_list,
weaken_specific_list): New variables. (keep_symbols): Removed. (add_specific_symbol): New function from the carcas of add_strip_symbol. Takes a list as an argument. (is_specified_symbol): Likewise from is_strip_symbol. (filter_symbols): Honor the new privatize and weaken lists. Optimize bfd_asymbol_name handling. (copy_object, copy_options, copy_usage): Add privatize-symbol & weaken-symbol options. * objcopy.1, binutils.texi: Update docs.
This commit is contained in:
parent
2875c6c685
commit
8d2e72a1c8
@ -1,8 +1,24 @@
|
||||
Wed Oct 8 21:19:11 1997 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* objcopy.c (keep_specific_list, privatize_specific_list,
|
||||
weaken_specific_list): New variables.
|
||||
(keep_symbols): Removed.
|
||||
(add_specific_symbol): New function from the carcas of
|
||||
add_strip_symbol. Takes a list as an argument.
|
||||
(is_specified_symbol): Likewise from is_strip_symbol.
|
||||
(filter_symbols): Honor the new privatize and weaken lists.
|
||||
Optimize bfd_asymbol_name handling.
|
||||
(copy_object, copy_options, copy_usage): Add privatize-symbol &
|
||||
weaken-symbol options.
|
||||
|
||||
* objcopy.1, binutils.texi: Update docs.
|
||||
|
||||
Sun Oct 5 09:05:44 1997 Frank Ch. Eigler <fche@cygnus.com>
|
||||
|
||||
* objdump.c (disassemble_data): Add "0x" prefix for
|
||||
symbol-offsets in disassembly. Make "--prefix-addresses"
|
||||
disassembly adjust to mixed-length instructions.
|
||||
* objdump.c (disassemble_data): Make "--prefix-addresses"
|
||||
disassembly adjust to mixed-length instructions.
|
||||
(objdump_print_addr_with_sym): Add "0x" prefix for hexadecimal
|
||||
symbol-offsets in disassembly.
|
||||
|
||||
Fri Oct 3 12:04:25 1997 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
|
@ -816,6 +816,8 @@ objcopy [ -F @var{bfdname} | --target=@var{bfdname} ]
|
||||
[ -S | --strip-all ] [ -g | --strip-debug ]
|
||||
[ -K @var{symbolname} | --keep-symbol=@var{symbolname} ]
|
||||
[ -N @var{symbolname} | --strip-symbol=@var{symbolname} ]
|
||||
[ -P @var{symbolname} | --privatize-symbol=@var{symbolname} ]
|
||||
[ -W @var{symbolname} | --weaken-symbol=@var{symbolname} ]
|
||||
[ -x | --discard-all ] [ -X | --discard-locals ]
|
||||
[ -b @var{byte} | --byte=@var{byte} ]
|
||||
[ -i @var{interleave} | --interleave=@var{interleave} ]
|
||||
@ -910,8 +912,16 @@ be given more than once.
|
||||
@item -N @var{symbolname}
|
||||
@itemx --strip-symbol=@var{symbolname}
|
||||
Do not copy symbol @var{symbolname} from the source file. This option
|
||||
may be given more than once, and may be combined with strip options
|
||||
other than @code{-K}.
|
||||
may be given more than once.
|
||||
|
||||
@item -P @var{symbolname}
|
||||
@itemx --privatize-symbol=@var{symbolname}
|
||||
Make symbol @var{symbolname} local to the file, so that it is not
|
||||
visible externally. This option may be given more than once.
|
||||
|
||||
@item -W @var{symbolname}
|
||||
@itemx --weaken-symbol=@var{symbolname}
|
||||
Make symbol @var{symbolname} weak. This option may be given more than once.
|
||||
|
||||
@item -x
|
||||
@itemx --discard-all
|
||||
|
@ -24,6 +24,8 @@ objcopy \- copy and translate object files
|
||||
.RB "[\|" \-\-strip\-unneeded\fR "\|]"
|
||||
.RB "[\|" \-K\ \fIsymbolname\fR\ |\ \fB\-\-keep\-symbol=\fIsymbolname\fR "\|]"
|
||||
.RB "[\|" \-N\ \fIsymbolname\fR\ |\ \fB\-\-strip\-symbol=\fIsymbolname\fR "\|]"
|
||||
.RB "[\|" \-P\ \fIsymbolname\fR\ |\ \fB\-\-privatize\-symbol=\fIsymbolname\fR "\|]"
|
||||
.RB "[\|" \-W\ \fIsymbolname\fR\ |\ \fB\-\-weaken\-symbol=\fIsymbolname\fR "\|]"
|
||||
.RB "[\|" \-x\fR\ |\ \fB\-\-discard\-all\fR "\|]"
|
||||
.RB "[\|" \-X\fR\ |\ \fB\-\-discard\-locals\fR "\|]"
|
||||
.RB "[\|" \-b\ \fIbyte\fR\ |\ \fB\-\-byte=\fIbyte\fR "\|]"
|
||||
@ -139,8 +141,14 @@ may be given more than once.
|
||||
.TP
|
||||
.B \-N \fIsymbolname\fR, \fB\-\-strip\-symbol=\fIsymbolname
|
||||
Do not copy symbol \fIsymbolname\fP from the source file. This option
|
||||
may be given more than once, and may be combined with strip options
|
||||
other than \fB\-K\fR.
|
||||
may be given more than once.
|
||||
.TP
|
||||
.B \-P \fIsymbolname\fR, \fB\-\-privatize\-symbol=\fIsymbolname
|
||||
Make symbol \fIsymbolname\fP local to the file, so that it is not
|
||||
visible externally. This option may be given more than once.
|
||||
.TP
|
||||
.B \-W \fIsymbolname\fR, \fB\-\-weaken\-symbol=\fIsymbolname
|
||||
Make symbol \fIsymbolname\fP weak. This option may be given more than once.
|
||||
.TP
|
||||
.B \-x\fR, \fB \-\-discard\-all
|
||||
Do not copy non-global symbols from the source file.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* objcopy.c -- copy object file from input to output, optionally massaging it.
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
|
||||
@ -25,6 +25,16 @@
|
||||
#include "budbg.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_GOOD_UTIME_H
|
||||
#include <utime.h>
|
||||
#else /* ! HAVE_GOOD_UTIME_H */
|
||||
#ifdef HAVE_UTIMES
|
||||
#include <sys/time.h>
|
||||
#endif /* HAVE_UTIMES */
|
||||
#endif /* ! HAVE_GOOD_UTIME_H */
|
||||
|
||||
static void copy_usage PARAMS ((FILE *, int));
|
||||
static void strip_usage PARAMS ((FILE *, int));
|
||||
static flagword parse_flags PARAMS ((const char *));
|
||||
static struct section_list *find_section_list PARAMS ((const char *, boolean));
|
||||
static void setup_section PARAMS ((bfd *, asection *, PTR));
|
||||
@ -35,9 +45,19 @@ static void add_strip_symbol PARAMS ((const char *));
|
||||
static boolean is_strip_symbol PARAMS ((const char *));
|
||||
static boolean is_strip_section PARAMS ((bfd *, asection *));
|
||||
static unsigned int filter_symbols
|
||||
PARAMS ((bfd *, asymbol **, asymbol **, long));
|
||||
PARAMS ((bfd *, bfd *, asymbol **, asymbol **, long));
|
||||
static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
|
||||
static void filter_bytes PARAMS ((char *, bfd_size_type *));
|
||||
static boolean write_debugging_info PARAMS ((bfd *, PTR, long *, asymbol ***));
|
||||
static void copy_object PARAMS ((bfd *, bfd *));
|
||||
static void copy_archive PARAMS ((bfd *, bfd *, const char *));
|
||||
static void copy_file
|
||||
PARAMS ((const char *, const char *, const char *, const char *));
|
||||
static int simple_copy PARAMS ((const char *, const char *));
|
||||
static int smart_rename PARAMS ((const char *, const char *));
|
||||
static void set_times PARAMS ((const char *, const struct stat *));
|
||||
static int strip_main PARAMS ((int, char **));
|
||||
static int copy_main PARAMS ((int, char **));
|
||||
|
||||
#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
|
||||
|
||||
@ -138,6 +158,14 @@ static struct section_add *add_sections;
|
||||
|
||||
static boolean convert_debugging = false;
|
||||
|
||||
/* Whether to change the leading character in symbol names. */
|
||||
|
||||
static boolean change_leading_char = false;
|
||||
|
||||
/* Whether to remove the leading character from global symbol names. */
|
||||
|
||||
static boolean remove_leading_char = false;
|
||||
|
||||
/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
|
||||
|
||||
#define OPTION_ADD_SECTION 150
|
||||
@ -145,13 +173,16 @@ static boolean convert_debugging = false;
|
||||
#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1)
|
||||
#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1)
|
||||
#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1)
|
||||
#define OPTION_DEBUGGING (OPTION_ADJUST_WARNINGS + 1)
|
||||
#define OPTION_CHANGE_LEADING_CHAR (OPTION_ADJUST_WARNINGS + 1)
|
||||
#define OPTION_DEBUGGING (OPTION_CHANGE_LEADING_CHAR + 1)
|
||||
#define OPTION_GAP_FILL (OPTION_DEBUGGING + 1)
|
||||
#define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1)
|
||||
#define OPTION_PAD_TO (OPTION_NO_ADJUST_WARNINGS + 1)
|
||||
#define OPTION_SET_SECTION_FLAGS (OPTION_PAD_TO + 1)
|
||||
#define OPTION_REMOVE_LEADING_CHAR (OPTION_PAD_TO + 1)
|
||||
#define OPTION_SET_SECTION_FLAGS (OPTION_REMOVE_LEADING_CHAR + 1)
|
||||
#define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1)
|
||||
#define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1)
|
||||
#define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1)
|
||||
|
||||
/* Options to handle if running as "strip". */
|
||||
|
||||
@ -166,6 +197,7 @@ static struct option strip_options[] =
|
||||
{"keep-symbol", required_argument, 0, 'K'},
|
||||
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
|
||||
{"output-target", required_argument, 0, 'O'},
|
||||
{"preserve-dates", no_argument, 0, 'p'},
|
||||
{"remove-section", required_argument, 0, 'R'},
|
||||
{"strip-all", no_argument, 0, 's'},
|
||||
{"strip-debug", no_argument, 0, 'S'},
|
||||
@ -187,6 +219,7 @@ static struct option copy_options[] =
|
||||
{"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA},
|
||||
{"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS},
|
||||
{"byte", required_argument, 0, 'b'},
|
||||
{"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
|
||||
{"debugging", no_argument, 0, OPTION_DEBUGGING},
|
||||
{"discard-all", no_argument, 0, 'x'},
|
||||
{"discard-locals", no_argument, 0, 'X'},
|
||||
@ -201,6 +234,9 @@ static struct option copy_options[] =
|
||||
{"output-format", required_argument, 0, 'O'}, /* Obsolete */
|
||||
{"output-target", required_argument, 0, 'O'},
|
||||
{"pad-to", required_argument, 0, OPTION_PAD_TO},
|
||||
{"preserve-dates", no_argument, 0, 'p'},
|
||||
{"privatize-symbol", required_argument, 0, 'P'},
|
||||
{"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
|
||||
{"remove-section", required_argument, 0, 'R'},
|
||||
{"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
|
||||
{"set-start", required_argument, 0, OPTION_SET_START},
|
||||
@ -211,12 +247,13 @@ static struct option copy_options[] =
|
||||
{"target", required_argument, 0, 'F'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"weaken", no_argument, 0, OPTION_WEAKEN},
|
||||
{"weaken-symbol", required_argument, 0, 'W'},
|
||||
{0, no_argument, 0, 0}
|
||||
};
|
||||
|
||||
/* IMPORTS */
|
||||
extern char *program_name;
|
||||
extern char *program_version;
|
||||
|
||||
/* This flag distinguishes between strip and objcopy:
|
||||
1 means this is 'strip'; 0 means this is 'objcopy'.
|
||||
@ -230,22 +267,25 @@ copy_usage (stream, exit_status)
|
||||
int exit_status;
|
||||
{
|
||||
fprintf (stream, "\
|
||||
Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
|
||||
Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
|
||||
[-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\
|
||||
[--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
|
||||
[--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\
|
||||
[--discard-locals] [--debugging] [--remove-section=section]\n",
|
||||
program_name);
|
||||
fprintf (stream, "\
|
||||
[--gap-fill=val] [--pad-to=address]\n\
|
||||
[--gap-fill=val] [--pad-to=address] [--preserve-dates]\n\
|
||||
[--set-start=val] [--adjust-start=incr]\n\
|
||||
[--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\
|
||||
[--adjust-warnings] [--no-adjust-warnings]\n\
|
||||
[--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\
|
||||
[--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\
|
||||
[--verbose] [--version] [--help]\n\
|
||||
in-file [out-file]\n");
|
||||
[--privatize-symbol symbol] [-P symbol] [--weaken-symbol symbol]\n\
|
||||
[-W symbol] [--change-leading-char] [--remove-leading-char] [--weaken]\n\
|
||||
[--verbose] [--version] [--help] in-file [out-file]\n");
|
||||
list_supported_targets (program_name, stream);
|
||||
if (exit_status == 0)
|
||||
fprintf (stream, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n");
|
||||
exit (exit_status);
|
||||
}
|
||||
|
||||
@ -255,14 +295,16 @@ strip_usage (stream, exit_status)
|
||||
int exit_status;
|
||||
{
|
||||
fprintf (stream, "\
|
||||
Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
|
||||
Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\
|
||||
[--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
|
||||
[--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\
|
||||
[--discard-locals] [--keep-symbol symbol] [-K symbol]\n\
|
||||
[--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\
|
||||
[--verbose] [--version] [--help] file...\n",
|
||||
[-o file] [--preserve-dates] [--verbose] [--version] [--help] file...\n",
|
||||
program_name);
|
||||
list_supported_targets (program_name, stream);
|
||||
if (exit_status == 0)
|
||||
fprintf (stream, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n");
|
||||
exit (exit_status);
|
||||
}
|
||||
|
||||
@ -348,44 +390,48 @@ struct symlist
|
||||
struct symlist *next;
|
||||
};
|
||||
|
||||
/* List of symbols to strip. */
|
||||
/* List of symbols to strip, keep, privatize, and weaken. */
|
||||
|
||||
static struct symlist *strip_specific_list = NULL;
|
||||
static struct symlist *keep_specific_list = NULL;
|
||||
static struct symlist *privatize_specific_list = NULL;
|
||||
static struct symlist *weaken_specific_list = NULL;
|
||||
|
||||
/* If this is false, we strip the symbols in strip_specific_list.
|
||||
Otherwise, we keep only the symbols in the list. */
|
||||
/* If this is true, we weaken global symbols (set BSF_WEAK). */
|
||||
|
||||
static boolean keep_symbols = false;
|
||||
static boolean weaken = false;
|
||||
|
||||
/* Add a symbol to strip_specific_list. */
|
||||
|
||||
static void
|
||||
add_strip_symbol (name)
|
||||
add_specific_symbol (name, list)
|
||||
const char *name;
|
||||
struct symlist **list;
|
||||
{
|
||||
struct symlist *tmp_list;
|
||||
|
||||
tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist));
|
||||
tmp_list->name = name;
|
||||
tmp_list->next = strip_specific_list;
|
||||
strip_specific_list = tmp_list;
|
||||
tmp_list->next = *list;
|
||||
*list = tmp_list;
|
||||
}
|
||||
|
||||
/* See whether a symbol should be stripped or kept based on
|
||||
strip_specific_list and keep_symbols. */
|
||||
|
||||
static boolean
|
||||
is_strip_symbol (name)
|
||||
is_specified_symbol (name, list)
|
||||
const char *name;
|
||||
struct symlist *list;
|
||||
{
|
||||
struct symlist *tmp_list;
|
||||
|
||||
for (tmp_list = strip_specific_list; tmp_list; tmp_list = tmp_list->next)
|
||||
for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
if (strcmp (name, tmp_list->name) == 0)
|
||||
return keep_symbols ? false : true;
|
||||
return true;
|
||||
}
|
||||
return keep_symbols;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See if a section is being removed. */
|
||||
@ -416,8 +462,9 @@ is_strip_section (abfd, sec)
|
||||
Return the number of symbols to print. */
|
||||
|
||||
static unsigned int
|
||||
filter_symbols (abfd, osyms, isyms, symcount)
|
||||
filter_symbols (abfd, obfd, osyms, isyms, symcount)
|
||||
bfd *abfd;
|
||||
bfd *obfd;
|
||||
asymbol **osyms, **isyms;
|
||||
long symcount;
|
||||
{
|
||||
@ -428,11 +475,43 @@ filter_symbols (abfd, osyms, isyms, symcount)
|
||||
{
|
||||
asymbol *sym = from[src_count];
|
||||
flagword flags = sym->flags;
|
||||
const char *name = bfd_asymbol_name (sym);
|
||||
int keep;
|
||||
|
||||
if (change_leading_char
|
||||
&& (bfd_get_symbol_leading_char (abfd)
|
||||
!= bfd_get_symbol_leading_char (obfd))
|
||||
&& (bfd_get_symbol_leading_char (abfd) == '\0'
|
||||
|| (name[0] == bfd_get_symbol_leading_char (abfd))))
|
||||
{
|
||||
if (bfd_get_symbol_leading_char (obfd) == '\0')
|
||||
name = bfd_asymbol_name (sym) = name + 1;
|
||||
else
|
||||
{
|
||||
char *n;
|
||||
|
||||
n = xmalloc (strlen (name) + 2);
|
||||
n[0] = bfd_get_symbol_leading_char (obfd);
|
||||
if (bfd_get_symbol_leading_char (abfd) == '\0')
|
||||
strcpy (n + 1, name);
|
||||
else
|
||||
strcpy (n + 1, name + 1);
|
||||
name = bfd_asymbol_name (sym) = n;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_leading_char
|
||||
&& ((flags & BSF_GLOBAL) != 0
|
||||
|| (flags & BSF_WEAK) != 0
|
||||
|| bfd_is_und_section (bfd_get_section (sym))
|
||||
|| bfd_is_com_section (bfd_get_section (sym)))
|
||||
&& name[0] == bfd_get_symbol_leading_char (abfd))
|
||||
name = bfd_asymbol_name (sym) = name + 1;
|
||||
|
||||
if ((flags & BSF_KEEP) != 0) /* Used in relocation. */
|
||||
keep = 1;
|
||||
else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */
|
||||
|| (flags & BSF_WEAK) != 0
|
||||
|| bfd_is_und_section (bfd_get_section (sym))
|
||||
|| bfd_is_com_section (bfd_get_section (sym)))
|
||||
keep = strip_symbols != strip_unneeded;
|
||||
@ -446,22 +525,39 @@ filter_symbols (abfd, osyms, isyms, symcount)
|
||||
&& (discard_locals != locals_start_L
|
||||
|| ! bfd_is_local_label (abfd, sym))));
|
||||
|
||||
if (keep && is_strip_symbol (bfd_asymbol_name (sym)))
|
||||
if (keep && is_specified_symbol (name, strip_specific_list))
|
||||
keep = 0;
|
||||
if (!keep && is_specified_symbol (name, keep_specific_list))
|
||||
keep = 1;
|
||||
if (keep && is_strip_section (abfd, bfd_get_section (sym)))
|
||||
keep = 0;
|
||||
|
||||
if (keep && (flags & BSF_GLOBAL) != 0
|
||||
&& (weaken || is_specified_symbol (name, weaken_specific_list)))
|
||||
{
|
||||
sym->flags &=~ BSF_GLOBAL;
|
||||
sym->flags |= BSF_WEAK;
|
||||
}
|
||||
if (keep && (flags & (BSF_GLOBAL | BSF_WEAK))
|
||||
&& is_specified_symbol (name, privatize_specific_list))
|
||||
{
|
||||
sym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
|
||||
sym->flags |= BSF_LOCAL;
|
||||
}
|
||||
|
||||
if (keep)
|
||||
to[dst_count++] = sym;
|
||||
}
|
||||
|
||||
to[dst_count] = NULL;
|
||||
|
||||
return dst_count;
|
||||
}
|
||||
|
||||
/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
|
||||
Adjust *SIZE. */
|
||||
|
||||
void
|
||||
static void
|
||||
filter_bytes (memhunk, size)
|
||||
char *memhunk;
|
||||
bfd_size_type *size;
|
||||
@ -514,7 +610,8 @@ copy_object (ibfd, obfd)
|
||||
if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
|
||||
bfd_get_mach (ibfd)))
|
||||
{
|
||||
fprintf (stderr, "Output file cannot represent architecture %s\n",
|
||||
fprintf (stderr,
|
||||
"Warning: Output file cannot represent architecture %s\n",
|
||||
bfd_printable_arch_mach (bfd_get_arch (ibfd),
|
||||
bfd_get_mach (ibfd)));
|
||||
}
|
||||
@ -693,8 +790,14 @@ copy_object (ibfd, obfd)
|
||||
|| strip_symbols == strip_unneeded
|
||||
|| discard_locals != locals_undef
|
||||
|| strip_specific_list != NULL
|
||||
|| keep_specific_list != NULL
|
||||
|| privatize_specific_list != NULL
|
||||
|| weaken_specific_list != NULL
|
||||
|| sections_removed
|
||||
|| convert_debugging)
|
||||
|| convert_debugging
|
||||
|| change_leading_char
|
||||
|| remove_leading_char
|
||||
|| weaken)
|
||||
{
|
||||
/* Mark symbols used in output relocations so that they
|
||||
are kept, even if they are local labels or static symbols.
|
||||
@ -707,8 +810,8 @@ copy_object (ibfd, obfd)
|
||||
bfd_map_over_sections (ibfd,
|
||||
mark_symbols_used_in_relocations,
|
||||
(PTR)isympp);
|
||||
osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
|
||||
symcount = filter_symbols (ibfd, osympp, isympp, symcount);
|
||||
osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
|
||||
symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
|
||||
}
|
||||
|
||||
if (convert_debugging && dhandle != NULL)
|
||||
@ -796,21 +899,6 @@ copy_object (ibfd, obfd)
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
cat (a, b, c)
|
||||
char *a;
|
||||
char *b;
|
||||
char *c;
|
||||
{
|
||||
size_t size = strlen (a) + strlen (b) + strlen (c);
|
||||
char *r = xmalloc (size + 1);
|
||||
|
||||
strcpy (r, a);
|
||||
strcat (r, b);
|
||||
strcat (r, c);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Read each archive element in turn from IBFD, copy the
|
||||
contents to temp file, and keep the temp file handle. */
|
||||
|
||||
@ -818,7 +906,7 @@ static void
|
||||
copy_archive (ibfd, obfd, output_target)
|
||||
bfd *ibfd;
|
||||
bfd *obfd;
|
||||
char *output_target;
|
||||
const char *output_target;
|
||||
{
|
||||
struct name_list
|
||||
{
|
||||
@ -844,7 +932,8 @@ copy_archive (ibfd, obfd, output_target)
|
||||
while (this_element != (bfd *) NULL)
|
||||
{
|
||||
/* Create an output file for this member. */
|
||||
char *output_name = cat (dir, "/", bfd_get_filename(this_element));
|
||||
char *output_name = concat (dir, "/", bfd_get_filename(this_element),
|
||||
(char *) NULL);
|
||||
bfd *output_bfd = bfd_openw (output_name, output_target);
|
||||
bfd *last_element;
|
||||
|
||||
@ -908,10 +997,10 @@ copy_archive (ibfd, obfd, output_target)
|
||||
|
||||
static void
|
||||
copy_file (input_filename, output_filename, input_target, output_target)
|
||||
char *input_filename;
|
||||
char *output_filename;
|
||||
char *input_target;
|
||||
char *output_target;
|
||||
const char *input_filename;
|
||||
const char *output_filename;
|
||||
const char *input_target;
|
||||
const char *output_target;
|
||||
{
|
||||
bfd *ibfd;
|
||||
char **matching;
|
||||
@ -1303,6 +1392,57 @@ write_debugging_info (obfd, dhandle, symcountp, symppp)
|
||||
if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
|
||||
return write_ieee_debugging_info (obfd, dhandle);
|
||||
|
||||
if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
|
||||
|| bfd_get_flavour (obfd) == bfd_target_elf_flavour)
|
||||
{
|
||||
bfd_byte *syms, *strings;
|
||||
bfd_size_type symsize, stringsize;
|
||||
asection *stabsec, *stabstrsec;
|
||||
|
||||
if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
|
||||
&symsize, &strings,
|
||||
&stringsize))
|
||||
return false;
|
||||
|
||||
stabsec = bfd_make_section (obfd, ".stab");
|
||||
stabstrsec = bfd_make_section (obfd, ".stabstr");
|
||||
if (stabsec == NULL
|
||||
|| stabstrsec == NULL
|
||||
|| ! bfd_set_section_size (obfd, stabsec, symsize)
|
||||
|| ! bfd_set_section_size (obfd, stabstrsec, stringsize)
|
||||
|| ! bfd_set_section_alignment (obfd, stabsec, 2)
|
||||
|| ! bfd_set_section_alignment (obfd, stabstrsec, 0)
|
||||
|| ! bfd_set_section_flags (obfd, stabsec,
|
||||
(SEC_HAS_CONTENTS
|
||||
| SEC_READONLY
|
||||
| SEC_DEBUGGING))
|
||||
|| ! bfd_set_section_flags (obfd, stabstrsec,
|
||||
(SEC_HAS_CONTENTS
|
||||
| SEC_READONLY
|
||||
| SEC_DEBUGGING)))
|
||||
{
|
||||
fprintf (stderr, "%s: can't create debugging section: %s\n",
|
||||
bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ()));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We can get away with setting the section contents now because
|
||||
the next thing the caller is going to do is copy over the
|
||||
real sections. We may someday have to split the contents
|
||||
setting out of this function. */
|
||||
if (! bfd_set_section_contents (obfd, stabsec, syms, (file_ptr) 0,
|
||||
symsize)
|
||||
|| ! bfd_set_section_contents (obfd, stabstrsec, strings,
|
||||
(file_ptr) 0, stringsize))
|
||||
{
|
||||
fprintf (stderr, "%s: can't set debugging section contents: %s\n",
|
||||
bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fprintf (stderr,
|
||||
"%s: don't know how to write debugging information for %s\n",
|
||||
bfd_get_filename (obfd), bfd_get_target (obfd));
|
||||
@ -1317,7 +1457,8 @@ write_debugging_info (obfd, dhandle, symcountp, symppp)
|
||||
|
||||
static int
|
||||
simple_copy (from, to)
|
||||
char *from, *to;
|
||||
const char *from;
|
||||
const char *to;
|
||||
{
|
||||
int fromfd, tofd, nread;
|
||||
int saved;
|
||||
@ -1371,7 +1512,8 @@ simple_copy (from, to)
|
||||
|
||||
static int
|
||||
smart_rename (from, to)
|
||||
char *from, *to;
|
||||
const char *from;
|
||||
const char *to;
|
||||
{
|
||||
struct stat s;
|
||||
int ret = 0;
|
||||
@ -1386,9 +1528,20 @@ smart_rename (from, to)
|
||||
ret = rename (from, to);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Try to preserve the permission bits and ownership of TO. */
|
||||
chmod (to, s.st_mode & 07777);
|
||||
chown (to, s.st_uid, s.st_gid);
|
||||
/* Try to preserve the permission bits and ownership of TO.
|
||||
First get the mode right except for the setuid bit. Then
|
||||
change the ownership. Then fix the setuid bit. We do
|
||||
the chmod before the chown because if the chown succeeds,
|
||||
and we are a normal user, we won't be able to do the
|
||||
chmod afterward. We don't bother to fix the setuid bit
|
||||
first because that might introduce a fleeting security
|
||||
problem, and because the chown will clear the setuid bit
|
||||
anyhow. We only fix the setuid bit if the chown
|
||||
succeeds, because we don't want to introduce an
|
||||
unexpected setuid file owned by the user running objcopy. */
|
||||
chmod (to, s.st_mode & 0777);
|
||||
if (chown (to, s.st_uid, s.st_gid) >= 0)
|
||||
chmod (to, s.st_mode & 07777);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1415,6 +1568,49 @@ smart_rename (from, to)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the times of the file DESTINATION to be the same as those in
|
||||
STATBUF. */
|
||||
|
||||
static void
|
||||
set_times (destination, statbuf)
|
||||
const char *destination;
|
||||
const struct stat *statbuf;
|
||||
{
|
||||
int result;
|
||||
|
||||
{
|
||||
#ifdef HAVE_GOOD_UTIME_H
|
||||
struct utimbuf tb;
|
||||
|
||||
tb.actime = statbuf->st_atime;
|
||||
tb.modtime = statbuf->st_mtime;
|
||||
result = utime (destination, &tb);
|
||||
#else /* ! HAVE_GOOD_UTIME_H */
|
||||
#ifndef HAVE_UTIMES
|
||||
long tb[2];
|
||||
|
||||
tb[0] = statbuf->st_atime;
|
||||
tb[1] = statbuf->st_mtime;
|
||||
result = utime (destination, tb);
|
||||
#else /* HAVE_UTIMES */
|
||||
struct timeval tv[2];
|
||||
|
||||
tv[0].tv_sec = statbuf->st_atime;
|
||||
tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = statbuf->st_mtime;
|
||||
tv[1].tv_usec = 0;
|
||||
result = utimes (destination, tv);
|
||||
#endif /* HAVE_UTIMES */
|
||||
#endif /* ! HAVE_GOOD_UTIME_H */
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
fprintf (stderr, "%s: ", destination);
|
||||
perror ("can not set time");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
strip_main (argc, argv)
|
||||
int argc;
|
||||
@ -1422,10 +1618,12 @@ strip_main (argc, argv)
|
||||
{
|
||||
char *input_target = NULL, *output_target = NULL;
|
||||
boolean show_version = false;
|
||||
boolean preserve_dates = false;
|
||||
int c, i;
|
||||
struct section_list *p;
|
||||
char *output_file = NULL;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:sSgxXVv",
|
||||
while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpgxXVv",
|
||||
strip_options, (int *) 0)) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
@ -1455,23 +1653,16 @@ strip_main (argc, argv)
|
||||
strip_symbols = strip_unneeded;
|
||||
break;
|
||||
case 'K':
|
||||
if (! keep_symbols && strip_specific_list != NULL)
|
||||
{
|
||||
fprintf (stderr, "%s: Can not specify both -K and -N\n",
|
||||
program_name);
|
||||
strip_usage (stderr, 1);
|
||||
}
|
||||
keep_symbols = true;
|
||||
add_strip_symbol (optarg);
|
||||
add_specific_symbol (optarg, &keep_specific_list);
|
||||
break;
|
||||
case 'N':
|
||||
if (keep_symbols)
|
||||
{
|
||||
fprintf (stderr, "%s: Can not specify both -K and -N\n",
|
||||
program_name);
|
||||
strip_usage (stderr, 1);
|
||||
}
|
||||
add_strip_symbol (optarg);
|
||||
add_specific_symbol (optarg, &strip_specific_list);
|
||||
break;
|
||||
case 'o':
|
||||
output_file = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
preserve_dates = true;
|
||||
break;
|
||||
case 'x':
|
||||
discard_locals = locals_all;
|
||||
@ -1495,10 +1686,7 @@ strip_main (argc, argv)
|
||||
}
|
||||
|
||||
if (show_version)
|
||||
{
|
||||
printf ("GNU %s version %s\n", program_name, program_version);
|
||||
exit (0);
|
||||
}
|
||||
print_version ("strip");
|
||||
|
||||
/* Default is to strip all symbols. */
|
||||
if (strip_symbols == strip_undef
|
||||
@ -1510,24 +1698,45 @@ strip_main (argc, argv)
|
||||
output_target = input_target;
|
||||
|
||||
i = optind;
|
||||
if (i == argc)
|
||||
if (i == argc
|
||||
|| (output_file != NULL && (i + 1) < argc))
|
||||
strip_usage (stderr, 1);
|
||||
|
||||
for (; i < argc; i++)
|
||||
{
|
||||
int hold_status = status;
|
||||
struct stat statbuf;
|
||||
char *tmpname;
|
||||
|
||||
char *tmpname = make_tempname (argv[i]);
|
||||
if (preserve_dates)
|
||||
{
|
||||
if (stat (argv[i], &statbuf) < 0)
|
||||
{
|
||||
fprintf (stderr, "%s: ", argv[i]);
|
||||
perror ("cannot stat");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_file != NULL)
|
||||
tmpname = output_file;
|
||||
else
|
||||
tmpname = make_tempname (argv[i]);
|
||||
status = 0;
|
||||
|
||||
copy_file (argv[i], tmpname, input_target, output_target);
|
||||
if (status == 0)
|
||||
{
|
||||
smart_rename (tmpname, argv[i]);
|
||||
if (preserve_dates)
|
||||
set_times (tmpname, &statbuf);
|
||||
if (output_file == NULL)
|
||||
smart_rename (tmpname, argv[i]);
|
||||
status = hold_status;
|
||||
}
|
||||
else
|
||||
unlink (tmpname);
|
||||
free (tmpname);
|
||||
if (output_file == NULL)
|
||||
free (tmpname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1542,10 +1751,12 @@ copy_main (argc, argv)
|
||||
char *input_target = NULL, *output_target = NULL;
|
||||
boolean show_version = false;
|
||||
boolean adjust_warn = true;
|
||||
boolean preserve_dates = false;
|
||||
int c;
|
||||
struct section_list *p;
|
||||
struct stat statbuf;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:R:SgxXVv",
|
||||
while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:P:R:SpgxXVvW:",
|
||||
copy_options, (int *) 0)) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
@ -1594,23 +1805,19 @@ copy_main (argc, argv)
|
||||
strip_symbols = strip_unneeded;
|
||||
break;
|
||||
case 'K':
|
||||
if (! keep_symbols && strip_specific_list != NULL)
|
||||
{
|
||||
fprintf (stderr, "%s: Can not specify both -K and -N\n",
|
||||
program_name);
|
||||
strip_usage (stderr, 1);
|
||||
}
|
||||
keep_symbols = true;
|
||||
add_strip_symbol (optarg);
|
||||
add_specific_symbol (optarg, &keep_specific_list);
|
||||
break;
|
||||
case 'N':
|
||||
if (keep_symbols)
|
||||
{
|
||||
fprintf (stderr, "%s: Can not specify both -K and -N\n",
|
||||
program_name);
|
||||
strip_usage (stderr, 1);
|
||||
}
|
||||
add_strip_symbol (optarg);
|
||||
add_specific_symbol (optarg, &strip_specific_list);
|
||||
break;
|
||||
case 'P':
|
||||
add_specific_symbol (optarg, &privatize_specific_list);
|
||||
break;
|
||||
case 'W':
|
||||
add_specific_symbol (optarg, &weaken_specific_list);
|
||||
break;
|
||||
case 'p':
|
||||
preserve_dates = true;
|
||||
break;
|
||||
case 'x':
|
||||
discard_locals = locals_all;
|
||||
@ -1624,6 +1831,9 @@ copy_main (argc, argv)
|
||||
case 'V':
|
||||
show_version = true;
|
||||
break;
|
||||
case OPTION_WEAKEN:
|
||||
weaken = true;
|
||||
break;
|
||||
case OPTION_ADD_SECTION:
|
||||
{
|
||||
const char *s;
|
||||
@ -1734,6 +1944,9 @@ copy_main (argc, argv)
|
||||
case OPTION_ADJUST_WARNINGS:
|
||||
adjust_warn = true;
|
||||
break;
|
||||
case OPTION_CHANGE_LEADING_CHAR:
|
||||
change_leading_char = true;
|
||||
break;
|
||||
case OPTION_DEBUGGING:
|
||||
convert_debugging = true;
|
||||
break;
|
||||
@ -1760,6 +1973,9 @@ copy_main (argc, argv)
|
||||
pad_to = parse_vma (optarg, "--pad-to");
|
||||
pad_to_set = true;
|
||||
break;
|
||||
case OPTION_REMOVE_LEADING_CHAR:
|
||||
remove_leading_char = true;
|
||||
break;
|
||||
case OPTION_SET_SECTION_FLAGS:
|
||||
{
|
||||
const char *s;
|
||||
@ -1799,10 +2015,7 @@ copy_main (argc, argv)
|
||||
}
|
||||
|
||||
if (show_version)
|
||||
{
|
||||
printf ("GNU %s version %s\n", program_name, program_version);
|
||||
exit (0);
|
||||
}
|
||||
print_version ("objcopy");
|
||||
|
||||
if (copy_byte >= interleave)
|
||||
{
|
||||
@ -1825,21 +2038,38 @@ copy_main (argc, argv)
|
||||
if (output_target == (char *) NULL)
|
||||
output_target = input_target;
|
||||
|
||||
if (preserve_dates)
|
||||
{
|
||||
if (stat (input_filename, &statbuf) < 0)
|
||||
{
|
||||
fprintf (stderr, "%s: ", input_filename);
|
||||
perror ("cannot stat");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no destination file then create a temp and rename
|
||||
the result into the input. */
|
||||
|
||||
if (output_filename == (char *) NULL)
|
||||
{
|
||||
char *tmpname = make_tempname (input_filename);
|
||||
|
||||
copy_file (input_filename, tmpname, input_target, output_target);
|
||||
if (status == 0)
|
||||
smart_rename (tmpname, input_filename);
|
||||
{
|
||||
if (preserve_dates)
|
||||
set_times (tmpname, &statbuf);
|
||||
smart_rename (tmpname, input_filename);
|
||||
}
|
||||
else
|
||||
unlink (tmpname);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_file (input_filename, output_filename, input_target, output_target);
|
||||
if (status == 0 && preserve_dates)
|
||||
set_times (output_filename, &statbuf);
|
||||
}
|
||||
|
||||
if (adjust_warn)
|
||||
@ -1874,6 +2104,7 @@ main (argc, argv)
|
||||
discard_locals = locals_undef;
|
||||
|
||||
bfd_init ();
|
||||
set_default_bfd_target ();
|
||||
|
||||
if (is_strip < 0)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user