diff options
author | Richard Henderson <rth@redhat.com> | 1997-10-09 04:34:59 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 1997-10-09 04:34:59 +0000 |
commit | 8d2e72a1c8919c8e54bfe4d5b508c382586ed4cd (patch) | |
tree | 38b6a537eac11b5c62144f8b3e526c422c6dda88 /binutils | |
parent | 2875c6c6853325552cd9fb35c6d4842da47ca9cc (diff) | |
download | gdb-8d2e72a1c8919c8e54bfe4d5b508c382586ed4cd.zip gdb-8d2e72a1c8919c8e54bfe4d5b508c382586ed4cd.tar.gz gdb-8d2e72a1c8919c8e54bfe4d5b508c382586ed4cd.tar.bz2 |
* 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.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 22 | ||||
-rw-r--r-- | binutils/binutils.texi | 14 | ||||
-rw-r--r-- | binutils/objcopy.1 | 12 | ||||
-rw-r--r-- | binutils/objcopy.c | 431 |
4 files changed, 372 insertions, 107 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index f0fcac8..961ee02 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -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> diff --git a/binutils/binutils.texi b/binutils/binutils.texi index 4efadda..5892fa8 100644 --- a/binutils/binutils.texi +++ b/binutils/binutils.texi @@ -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 diff --git a/binutils/objcopy.1 b/binutils/objcopy.1 index d3b8bb3..dd5cf68 100644 --- a/binutils/objcopy.1 +++ b/binutils/objcopy.1 @@ -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. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index e812ac8..324a040 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -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; + + if (preserve_dates) + { + if (stat (argv[i], &statbuf) < 0) + { + fprintf (stderr, "%s: ", argv[i]); + perror ("cannot stat"); + continue; + } + } - char *tmpname = make_tempname (argv[i]); + 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) { |