summaryrefslogtreecommitdiff
path: root/binutils/objcopy.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2010-01-20 00:09:13 +0000
committerIan Lance Taylor <ian@airs.com>2010-01-20 00:09:13 +0000
commit500ee42ee091d6e8860d237bd5e74e8cdcf61d70 (patch)
tree60cf2ebadc06364c7e00c8ae0010e00b887b9c8e /binutils/objcopy.c
parent1696f399f791173c5714c877514861b706f2f6ad (diff)
downloadbinutils-gdb-500ee42ee091d6e8860d237bd5e74e8cdcf61d70.tar.gz
binutils/:
* objcopy.c (copy_main): Rewrite OPTION_ADD_SECTION code to work with non-ordinary files like /dev/null. binutils/testsuite/: * lib/utils-lib.exp (run_dump_test): Permit option values to use $srcdir to refer to the source directory. * binutils-all/add-section.d: New test. * binutils-all/add-empty-section.d: New test. * binutils-all/empty-file: New test input file. * binutils-all/objcopy.exp: Run new tests.
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r--binutils/objcopy.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index dd16b9b0f4b..5df1449dbf5 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3306,10 +3306,8 @@ copy_main (int argc, char *argv[])
case OPTION_ADD_SECTION:
{
const char *s;
- off_t size;
+ size_t off, alloc;
struct section_add *pa;
- int len;
- char *name;
FILE *f;
s = strchr (optarg, '=');
@@ -3317,34 +3315,40 @@ copy_main (int argc, char *argv[])
if (s == NULL)
fatal (_("bad format for %s"), "--add-section");
- size = get_file_size (s + 1);
- if (size < 1)
- {
- status = 1;
- break;
- }
-
pa = (struct section_add *) xmalloc (sizeof (struct section_add));
-
- len = s - optarg;
- name = (char *) xmalloc (len + 1);
- strncpy (name, optarg, len);
- name[len] = '\0';
- pa->name = name;
-
+ pa->name = xstrndup (optarg, s - optarg);
pa->filename = s + 1;
- pa->size = size;
- pa->contents = (bfd_byte *) xmalloc (size);
- f = fopen (pa->filename, FOPEN_RB);
+ /* We don't use get_file_size so that we can do
+ --add-section .note.GNU_stack=/dev/null
+ get_file_size doesn't work on /dev/null. */
+ f = fopen (pa->filename, FOPEN_RB);
if (f == NULL)
fatal (_("cannot open: %s: %s"),
pa->filename, strerror (errno));
- if (fread (pa->contents, 1, pa->size, f) == 0
- || ferror (f))
- fatal (_("%s: fread failed"), pa->filename);
+ off = 0;
+ alloc = 4096;
+ pa->contents = (bfd_byte *) xmalloc (alloc);
+ while (!feof (f))
+ {
+ off_t got;
+
+ if (off == alloc)
+ {
+ alloc <<= 1;
+ pa->contents = (bfd_byte *) xrealloc (pa->contents, alloc);
+ }
+
+ got = fread (pa->contents + off, 1, alloc - off, f);
+ if (ferror (f))
+ fatal (_("%s: fread failed"), pa->filename);
+
+ off += got;
+ }
+
+ pa->size = off;
fclose (f);