/* objcopy.c -- copy object file from input to output, optionally massaging it.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
Free Software Foundation, Inc.
This file is part of GNU Binutils.
#include "budbg.h"
#include <sys/stat.h>
-#include "elf/internal.h"
-#include "elf-bfd.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 */
-
/* A list of symbols to explicitly strip out, or to keep. A linked
list is good enough for a small number from the command line, but
this will slow things down a lot if many symbols are being
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 **));
&& name[0] == bfd_get_symbol_leading_char (abfd))
name = bfd_asymbol_name (sym) = name + 1;
- if ((flags & BSF_KEEP) != 0) /* Used in relocation. */
+ if (strip_symbols == STRIP_ALL)
+ keep = 0;
+ 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;
else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */
|| (flags & BSF_WEAK) != 0
for (; from < end; from += interleave)
*to++ = *from;
- *size /= interleave;
+ if (*size % interleave > copy_byte)
+ *size = (*size / interleave) + 1;
+ else
+ *size /= interleave;
}
/* Copy object file IBFD onto OBFD. */
asection **osections = NULL;
bfd_size_type *gaps = NULL;
bfd_size_type max_gap = 0;
+ long symsize;
+ PTR dhandle;
+
if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
RETURN_NONFATAL (bfd_get_filename (obfd));
/* Symbol filtering must happen after the output sections have
been created, but before their contents are set. */
- if (strip_symbols == STRIP_ALL)
+ dhandle = NULL;
+ symsize = bfd_get_symtab_upper_bound (ibfd);
+ if (symsize < 0)
+ RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+ osympp = isympp = (asymbol **) xmalloc (symsize);
+ symcount = bfd_canonicalize_symtab (ibfd, isympp);
+ if (symcount < 0)
+ RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+ if (convert_debugging)
+ dhandle = read_debugging_info (ibfd, isympp, symcount);
+
+ if (strip_symbols == STRIP_DEBUG
+ || strip_symbols == STRIP_ALL
+ || strip_symbols == STRIP_UNNEEDED
+ || discard_locals != LOCALS_UNDEF
+ || strip_specific_list != NULL
+ || keep_specific_list != NULL
+ || localize_specific_list != NULL
+ || weaken_specific_list != NULL
+ || sections_removed
+ || convert_debugging
+ || change_leading_char
+ || remove_leading_char
+ || weaken)
{
- osympp = isympp = NULL;
- symcount = 0;
+ /* Mark symbols used in output relocations so that they
+ are kept, even if they are local labels or static symbols.
+
+ Note we iterate over the input sections examining their
+ relocations since the relocations for the output sections
+ haven't been set yet. mark_symbols_used_in_relocations will
+ ignore input sections which have no corresponding output
+ section. */
+ if (strip_symbols != STRIP_ALL)
+ bfd_map_over_sections (ibfd,
+ mark_symbols_used_in_relocations,
+ (PTR)isympp);
+ osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
+ symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
}
- else
- {
- long symsize;
- PTR dhandle = NULL;
- symsize = bfd_get_symtab_upper_bound (ibfd);
- if (symsize < 0)
- RETURN_NONFATAL (bfd_get_filename (ibfd));
-
- osympp = isympp = (asymbol **) xmalloc (symsize);
- symcount = bfd_canonicalize_symtab (ibfd, isympp);
- if (symcount < 0)
- RETURN_NONFATAL (bfd_get_filename (ibfd));
-
- if (convert_debugging)
- dhandle = read_debugging_info (ibfd, isympp, symcount);
-
- if (strip_symbols == STRIP_DEBUG
- || strip_symbols == STRIP_UNNEEDED
- || discard_locals != LOCALS_UNDEF
- || strip_specific_list != NULL
- || keep_specific_list != NULL
- || localize_specific_list != NULL
- || weaken_specific_list != NULL
- || sections_removed
- || 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.
-
- Note we iterate over the input sections examining their
- relocations since the relocations for the output sections
- haven't been set yet. mark_symbols_used_in_relocations will
- ignore input sections which have no corresponding output
- section. */
- bfd_map_over_sections (ibfd,
- mark_symbols_used_in_relocations,
- (PTR)isympp);
- osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
- symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
- }
-
- if (convert_debugging && dhandle != NULL)
+ if (convert_debugging && dhandle != NULL)
+ {
+ if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
{
- if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
- {
- status = 1;
- return;
- }
+ status = 1;
+ return;
}
}
long relcount;
sec_ptr osection;
bfd_size_type size;
+ long relsize;
/* If we have already failed earlier on, do not keep on generating
complaints now. */
if (size == 0 || osection == 0)
return;
- if (strip_symbols == STRIP_ALL)
+
+ relsize = bfd_get_reloc_upper_bound (ibfd, isection);
+ if (relsize < 0)
+ RETURN_NONFATAL (bfd_get_filename (ibfd));
+
+ if (relsize == 0)
bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
else
{
- long relsize;
-
- relsize = bfd_get_reloc_upper_bound (ibfd, isection);
- if (relsize < 0)
+ relpp = (arelent **) xmalloc (relsize);
+ relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
+ if (relcount < 0)
RETURN_NONFATAL (bfd_get_filename (ibfd));
-
- if (relsize == 0)
- bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
- else
+
+ if (strip_symbols == STRIP_ALL)
{
- relpp = (arelent **) xmalloc (relsize);
- relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
- if (relcount < 0)
- RETURN_NONFATAL (bfd_get_filename (ibfd));
-
- bfd_set_reloc (obfd, osection, relpp, relcount);
+ /* Remove relocations which are not in
+ keep_strip_specific_list. */
+ arelent **temp_relpp;
+ long temp_relcount = 0;
+ long i;
+
+ temp_relpp = (arelent **) xmalloc (relsize);
+ for (i = 0; i < relcount; i++)
+ if (is_specified_symbol
+ (bfd_asymbol_name (*relpp [i]->sym_ptr_ptr),
+ keep_specific_list))
+ temp_relpp [temp_relcount++] = relpp [i];
+ relcount = temp_relcount;
+ free (relpp);
+ relpp = temp_relpp;
}
+ bfd_set_reloc (obfd, osection,
+ (relcount == 0 ? (arelent **) NULL : relpp), relcount);
}
-
+
isection->_cooked_size = isection->_raw_size;
isection->reloc_done = true;
return false;
}
-/* The number of bytes to copy at once. */
-#define COPY_BUF 8192
-
-/* Copy file FROM to file TO, performing no translations.
- Return 0 if ok, -1 if error. */
-
-static int
-simple_copy (from, to)
- const char *from;
- const char *to;
-{
- int fromfd, tofd, nread;
- int saved;
- char buf[COPY_BUF];
-
- fromfd = open (from, O_RDONLY);
- if (fromfd < 0)
- return -1;
- tofd = creat (to, 0777);
- if (tofd < 0)
- {
- saved = errno;
- close (fromfd);
- errno = saved;
- return -1;
- }
- while ((nread = read (fromfd, buf, sizeof buf)) > 0)
- {
- if (write (tofd, buf, nread) != nread)
- {
- saved = errno;
- close (fromfd);
- close (tofd);
- errno = saved;
- return -1;
- }
- }
- saved = errno;
- close (fromfd);
- close (tofd);
- if (nread < 0)
- {
- errno = saved;
- return -1;
- }
- return 0;
-}
-
-#ifndef S_ISLNK
-#ifdef S_IFLNK
-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
-#else
-#define S_ISLNK(m) 0
-#define lstat stat
-#endif
-#endif
-
-/* Rename FROM to TO, copying if TO is a link.
- Assumes that TO already exists, because FROM is a temp file.
- Return 0 if ok, -1 if error. */
-
-static int
-smart_rename (from, to)
- const char *from;
- const char *to;
-{
- struct stat s;
- int ret = 0;
-
- if (lstat (to, &s))
- return -1;
-
-#if defined (_WIN32) && !defined (__CYGWIN32__)
- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
- fail instead. Also, chown is not present. */
-
- if (stat (to, &s) == 0)
- remove (to);
-
- ret = rename (from, to);
- if (ret != 0)
- {
- /* We have to clean up here. */
-
- non_fatal (_("%s: rename: %s"), to, strerror (errno));
- unlink (from);
- }
-#else
- /* Use rename only if TO is not a symbolic link and has
- only one hard link. */
- if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
- {
- ret = rename (from, to);
- if (ret == 0)
- {
- /* 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
- {
- /* We have to clean up here. */
- non_fatal (_("%s: rename: %s"), to, strerror (errno));
- unlink (from);
- }
- }
- else
- {
- ret = simple_copy (from, to);
- if (ret != 0)
- non_fatal (_("%s: simple_copy: %s"), to, strerror (errno));
-
- if (preserve_dates)
- set_times (to, &s);
- unlink (from);
- }
-#endif /* _WIN32 && !__CYGWIN32__ */
-
- 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)
- non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
-}
-
static int
strip_main (argc, argv)
int argc;
/* Default is to strip all symbols. */
if (strip_symbols == STRIP_UNDEF
&& discard_locals == LOCALS_UNDEF
- && strip_specific_list == NULL
- && keep_specific_list == NULL)
+ && strip_specific_list == NULL)
strip_symbols = STRIP_ALL;
if (output_target == (char *) NULL)
if (preserve_dates)
set_times (tmpname, &statbuf);
if (output_file == NULL)
- smart_rename (tmpname, argv[i]);
+ smart_rename (tmpname, argv[i], preserve_dates);
status = hold_status;
}
else
{
if (preserve_dates)
set_times (tmpname, &statbuf);
- smart_rename (tmpname, input_filename);
+ smart_rename (tmpname, input_filename, preserve_dates);
}
else
unlink (tmpname);
int argc;
char *argv[];
{
-#ifdef HAVE_SETLOCALE
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);