summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/binutils/objcopy.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.25/binutils/objcopy.c')
-rw-r--r--binutils-2.25/binutils/objcopy.c136
1 files changed, 128 insertions, 8 deletions
diff --git a/binutils-2.25/binutils/objcopy.c b/binutils-2.25/binutils/objcopy.c
index 14f6b96c..07794cbb 100644
--- a/binutils-2.25/binutils/objcopy.c
+++ b/binutils-2.25/binutils/objcopy.c
@@ -1,5 +1,5 @@
/* objcopy.c -- copy object file from input to output, optionally massaging it.
- Copyright 1991-2013 Free Software Foundation, Inc.
+ Copyright (C) 1991-2014 Free Software Foundation, Inc.
This file is part of GNU Binutils.
@@ -186,6 +186,9 @@ struct section_add
/* List of sections to add to the output BFD. */
static struct section_add *add_sections;
+/* List of sections to dump from the output BFD. */
+static struct section_add *dump_sections;
+
/* If non-NULL the argument to --add-gnu-debuglink.
This should be the filename to store in the .gnu_debuglink section. */
static const char * gnu_debuglink_filename = NULL;
@@ -259,6 +262,7 @@ static enum long_section_name_handling long_section_names = KEEP;
enum command_line_switch
{
OPTION_ADD_SECTION=150,
+ OPTION_DUMP_SECTION,
OPTION_CHANGE_ADDRESSES,
OPTION_CHANGE_LEADING_CHAR,
OPTION_CHANGE_START,
@@ -377,6 +381,7 @@ static struct option copy_options[] =
{"disable-deterministic-archives", no_argument, 0, 'U'},
{"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'},
+ {"dump-section", required_argument, 0, OPTION_DUMP_SECTION},
{"enable-deterministic-archives", no_argument, 0, 'D'},
{"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
{"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
@@ -548,6 +553,7 @@ copy_usage (FILE *stream, int exit_status)
--set-section-flags <name>=<flags>\n\
Set section <name>'s properties to <flags>\n\
--add-section <name>=<file> Add section <name> found in <file> to output\n\
+ --dump-section <name>=<file> Dump the contents of section <name> into <file>\n\
--rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
--long-section-names {enable|disable|keep}\n\
Handle long section names in Coff objects.\n\
@@ -1135,6 +1141,24 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
return FALSE;
}
+static bfd_boolean
+is_nondebug_keep_contents_section (bfd *ibfd, asection *isection)
+{
+ /* Always keep ELF note sections. */
+ if (ibfd->xvec->flavour == bfd_target_elf_flavour)
+ return (elf_section_type (isection) == SHT_NOTE);
+
+ /* Always keep the .buildid section for PE/COFF.
+
+ Strictly, this should be written "always keep the section storing the debug
+ directory", but that may be the .text section for objects produced by some
+ tools, which it is not sensible to keep. */
+ if (ibfd->xvec->flavour == bfd_target_coff_flavour)
+ return (strcmp (bfd_get_section_name (ibfd, isection), ".buildid") == 0);
+
+ return FALSE;
+}
+
/* Return true if SYM is a hidden symbol. */
static bfd_boolean
@@ -1592,6 +1616,13 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
return FALSE;
}
+ if (ibfd->sections == NULL)
+ {
+ non_fatal (_("error: the input file '%s' has no sections"),
+ bfd_get_archive_filename (ibfd));
+ return FALSE;
+ }
+
if (verbose)
printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
@@ -1826,6 +1857,64 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
}
}
+ if (dump_sections != NULL)
+ {
+ struct section_add * pdump;
+
+ for (pdump = dump_sections; pdump != NULL; pdump = pdump->next)
+ {
+ asection * sec;
+
+ sec = bfd_get_section_by_name (ibfd, pdump->name);
+ if (sec == NULL)
+ {
+ bfd_nonfatal_message (NULL, ibfd, NULL,
+ _("can't dump section '%s' - it does not exist"),
+ pdump->name);
+ continue;
+ }
+
+ if ((bfd_get_section_flags (ibfd, sec) & SEC_HAS_CONTENTS) == 0)
+ {
+ bfd_nonfatal_message (NULL, ibfd, sec,
+ _("can't dump section - it has no contents"));
+ continue;
+ }
+
+ bfd_size_type size = bfd_get_section_size (sec);
+ if (size == 0)
+ {
+ bfd_nonfatal_message (NULL, ibfd, sec,
+ _("can't dump section - it is empty"));
+ continue;
+ }
+
+ FILE * f;
+ f = fopen (pdump->filename, FOPEN_WB);
+ if (f == NULL)
+ {
+ bfd_nonfatal_message (pdump->filename, NULL, NULL,
+ _("could not open section dump file"));
+ continue;
+ }
+
+ bfd_byte * contents = xmalloc (size);
+ if (bfd_get_section_contents (ibfd, sec, contents, 0, size))
+ {
+ if (fwrite (contents, 1, size, f) != size)
+ fatal (_("error writing section contents to %s (error: %s)"),
+ pdump->filename,
+ strerror (errno));
+ }
+ else
+ bfd_nonfatal_message (NULL, ibfd, sec,
+ _("could not retrieve section contents"));
+
+ fclose (f);
+ free (contents);
+ }
+ }
+
if (gnu_debuglink_filename != NULL)
{
/* PR 15125: Give a helpful warning message if
@@ -2206,6 +2295,16 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
bfd_boolean del = TRUE;
bfd_boolean ok_object;
+ /* PR binutils/17533: Do not allow directory traversal
+ outside of the current directory tree by archive members. */
+ if (! is_valid_archive_path (bfd_get_filename (this_element)))
+ {
+ non_fatal (_("illegal pathname found in archive member: %s"),
+ bfd_get_filename (this_element));
+ status = 1;
+ goto cleanup_and_exit;
+ }
+
/* Create an output file for this member. */
output_name = concat (dir, "/",
bfd_get_filename (this_element), (char *) 0);
@@ -2215,8 +2314,12 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
{
output_name = make_tempdir (output_name);
if (output_name == NULL)
- fatal (_("cannot create tempdir for archive copying (error: %s)"),
- strerror (errno));
+ {
+ non_fatal (_("cannot create tempdir for archive copying (error: %s)"),
+ strerror (errno));
+ status = 1;
+ goto cleanup_and_exit;
+ }
l = (struct name_list *) xmalloc (sizeof (struct name_list));
l->name = output_name;
@@ -2258,7 +2361,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
{
bfd_nonfatal_message (output_name, NULL, NULL, NULL);
status = 1;
- return;
+ goto cleanup_and_exit;
}
if (ok_object)
@@ -2319,7 +2422,6 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
{
status = 1;
bfd_nonfatal_message (filename, NULL, NULL, NULL);
- return;
}
filename = bfd_get_filename (ibfd);
@@ -2327,9 +2429,9 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
{
status = 1;
bfd_nonfatal_message (filename, NULL, NULL, NULL);
- return;
}
+ cleanup_and_exit:
/* Delete all the files that we opened. */
for (l = list; l != NULL; l = l->next)
{
@@ -2624,8 +2726,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
else if (strip_symbols == STRIP_NONDEBUG
&& (flags & (SEC_ALLOC | SEC_GROUP)) != 0
- && !(ibfd->xvec->flavour == bfd_target_elf_flavour
- && elf_section_type (isection) == SHT_NOTE))
+ && !is_nondebug_keep_contents_section (ibfd, isection))
{
flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP);
if (obfd->xvec->flavour == bfd_target_elf_flavour)
@@ -3653,6 +3754,25 @@ copy_main (int argc, char *argv[])
}
break;
+ case OPTION_DUMP_SECTION:
+ {
+ const char *s;
+ struct section_add *pa;
+
+ s = strchr (optarg, '=');
+
+ if (s == NULL)
+ fatal (_("bad format for %s"), "--dump-section");
+
+ pa = (struct section_add *) xmalloc (sizeof * pa);
+ pa->name = xstrndup (optarg, s - optarg);
+ pa->filename = s + 1;
+ pa->next = dump_sections;
+ pa->contents = NULL;
+ dump_sections = pa;
+ }
+ break;
+
case OPTION_CHANGE_START:
change_start = parse_vma (optarg, "--change-start");
break;