diff options
| -rw-r--r-- | libelf/ChangeLog | 6 | ||||
| -rw-r--r-- | libelf/elf32_updatefile.c | 30 |
2 files changed, 34 insertions, 2 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 46083253..d42bf18b 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,9 @@ +2006-05-28 Ulrich Drepper <[email protected]> + + * elf32_updatefile.c (updatemmap): Preserve section content if + copying would overwrite them. + Fix msync paramters. + 2006-04-04 Roland McGrath <[email protected]> * elf32_updatefile.c (updatemmap): Handle other-endian case. diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c index 7561a685..6eab3cf0 100644 --- a/libelf/elf32_updatefile.c +++ b/libelf/elf32_updatefile.c @@ -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; |
