summaryrefslogtreecommitdiff
path: root/elfutils/libelf/elf32_updatefile.c
diff options
context:
space:
mode:
Diffstat (limited to 'elfutils/libelf/elf32_updatefile.c')
-rw-r--r--elfutils/libelf/elf32_updatefile.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/elfutils/libelf/elf32_updatefile.c b/elfutils/libelf/elf32_updatefile.c
index 7561a685..68253651 100644
--- a/elfutils/libelf/elf32_updatefile.c
+++ b/elfutils/libelf/elf32_updatefile.c
@@ -112,7 +112,7 @@ sort_sections (Elf_Scn **scns, Elf_ScnList *list)
int
-internal_function_def
+internal_function
__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
{
ElfW2(LIBELFBITS,Ehdr) *ehdr;
@@ -239,6 +239,32 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
sizeof (ElfW2(LIBELFBITS,Shdr)));
}
+
+ /* If the file is mmaped and the original position of the
+ section in the file is lower than the new position we
+ need to save the section content since otherwise it is
+ overwritten before it can be copied. If there are
+ multiple data segments in the list only the first can be
+ from the file. */
+ if (((char *) elf->map_address + elf->start_offset
+ <= (char *) scn->data_list.data.d.d_buf)
+ && ((char *) scn->data_list.data.d.d_buf
+ < ((char *) elf->map_address + elf->start_offset
+ + elf->maximum_size))
+ && (((char *) elf->map_address + elf->start_offset
+ + scn->shdr.ELFW(e,LIBELFBITS)->sh_offset)
+ > (char *) scn->data_list.data.d.d_buf))
+ {
+ void *p = malloc (scn->data_list.data.d.d_size);
+ if (p == NULL)
+ {
+ __libelf_seterrno (ELF_E_NOMEM);
+ return -1;
+ }
+ scn->data_list.data.d.d_buf = scn->data_base
+ = memcpy (p, scn->data_list.data.d.d_buf,
+ scn->data_list.data.d.d_size);
+ }
}
/* Iterate over all the section in the order in which they
@@ -364,10 +390,10 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
/* Make sure the content hits the disk. */
char *msync_start = ((char *) elf->map_address
- + elf->start_offset / sysconf (_SC_PAGESIZE));
+ + (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1)));
char *msync_end = ((char *) elf->map_address
+ elf->start_offset + ehdr->e_shoff
- * ehdr->e_shentsize * shnum);
+ + ehdr->e_shentsize * shnum);
(void) msync (msync_start, msync_end - msync_start, MS_SYNC);
return 0;
@@ -418,7 +444,7 @@ fill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
int
-internal_function_def
+internal_function
__elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
{
char fillbuf[FILLBUFSIZE];