summaryrefslogtreecommitdiffstats
path: root/rtemstoolkit/elftoolchain/libelf/elf_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemstoolkit/elftoolchain/libelf/elf_update.c')
-rw-r--r--rtemstoolkit/elftoolchain/libelf/elf_update.c69
1 files changed, 47 insertions, 22 deletions
diff --git a/rtemstoolkit/elftoolchain/libelf/elf_update.c b/rtemstoolkit/elftoolchain/libelf/elf_update.c
index 34b944e..9806131 100644
--- a/rtemstoolkit/elftoolchain/libelf/elf_update.c
+++ b/rtemstoolkit/elftoolchain/libelf/elf_update.c
@@ -25,6 +25,7 @@
*/
#include <sys/mman.h>
+#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
@@ -36,7 +37,7 @@
#include "_libelf.h"
-LIBELF_VCSID("$Id$");
+LIBELF_VCSID("$Id: elf_update.c 1922 2011-09-23 08:04:33Z jkoshy $");
/*
* Layout strategy:
@@ -986,7 +987,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
struct _Elf_Extent *ex;
assert(e->e_kind == ELF_K_ELF);
- assert(e->e_cmd != ELF_C_READ);
+ assert(e->e_cmd == ELF_C_RDWR || e->e_cmd == ELF_C_WRITE);
assert(e->e_fd >= 0);
if ((newfile = malloc((size_t) newsize)) == NULL) {
@@ -1037,35 +1038,57 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
assert(rc == newsize);
/*
- * Write out the constructed contents and remap the file in
- * read-only.
+ * For regular files, throw away existing file content and
+ * unmap any existing mappings.
*/
-
- if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) {
- LIBELF_SET_ERROR(IO, errno);
- goto error;
+ if ((e->e_flags & LIBELF_F_SPECIAL_FILE) == 0) {
+ if (ftruncate(e->e_fd, (off_t) 0) < 0 ||
+ lseek(e->e_fd, (off_t) 0, SEEK_SET)) {
+ LIBELF_SET_ERROR(IO, errno);
+ goto error;
+ }
+ if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
+ assert(e->e_rawfile != NULL);
+ assert(e->e_cmd == ELF_C_RDWR);
+ if (munmap(e->e_rawfile, e->e_rawsize) < 0) {
+ LIBELF_SET_ERROR(IO, errno);
+ goto error;
+ }
+ }
}
- if (write(e->e_fd, newfile, (size_t) newsize) != newsize ||
- lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) {
+ /*
+ * Write out the new contents.
+ */
+ if (write(e->e_fd, newfile, (size_t) newsize) != newsize) {
LIBELF_SET_ERROR(IO, errno);
goto error;
}
- if (e->e_cmd != ELF_C_WRITE) {
-
- if (e->e_rawsize > (size_t) newsize &&
- ftruncate(e->e_fd, newsize) < 0) {
- LIBELF_SET_ERROR(IO, errno);
- goto error;
+ /*
+ * For files opened in ELF_C_RDWR mode, set up the new 'raw'
+ * contents.
+ */
+ if (e->e_cmd == ELF_C_RDWR) {
+ assert(e->e_rawfile != NULL);
+ if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
+ if ((e->e_rawfile = mmap(NULL, (size_t) newsize,
+ PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) ==
+ MAP_FAILED) {
+ LIBELF_SET_ERROR(IO, errno);
+ goto error;
+ }
+ } else if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) {
+ free(e->e_rawfile);
+ e->e_rawfile = newfile;
+ newfile = NULL;
}
- if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ,
- MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) {
- LIBELF_SET_ERROR(IO, errno);
- goto error;
- }
+ /* Record the new size of the file. */
e->e_rawsize = newsize;
+ } else {
+ /* File opened in ELF_C_WRITE mode. */
+ assert(e->e_rawfile == NULL);
}
/*
@@ -1095,7 +1118,9 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
e->e_u.e_elf.e_phdr.e_phdr64 = NULL;
}
- free(newfile);
+ /* Free the temporary buffer. */
+ if (newfile)
+ free(newfile);
return (rc);