| diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c |
| index b39e284..31c4850 100644 |
| --- a/libelf/elf32_updatefile.c |
| +++ b/libelf/elf32_updatefile.c |
| @@ -101,6 +101,33 @@ sort_sections (Elf_Scn **scns, Elf_ScnList *list) |
| } |
| |
| |
| +static void |
| +fill_mmap (char *last_position, |
| + char *shdr_start, |
| + char *shdr_end, |
| + char *scn_start, |
| + size_t offset) |
| +{ |
| + size_t written = 0; |
| + |
| + if (last_position < shdr_start) |
| + { |
| + written = MIN (scn_start + offset - last_position, |
| + shdr_start - last_position); |
| + |
| + memset (last_position, __libelf_fill_byte, written); |
| + } |
| + |
| + if (last_position + written != scn_start + offset |
| + && shdr_end < scn_start + offset) |
| + { |
| + char *fill_start = MAX (shdr_end, scn_start); |
| + memset (fill_start, __libelf_fill_byte, |
| + scn_start + offset - fill_start); |
| + } |
| +} |
| + |
| + |
| int |
| internal_function |
| __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) |
| @@ -290,27 +317,6 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) |
| Elf_Data_List *dl = &scn->data_list; |
| bool scn_changed = false; |
| |
| - void fill_mmap (size_t offset) |
| - { |
| - size_t written = 0; |
| - |
| - if (last_position < shdr_start) |
| - { |
| - written = MIN (scn_start + offset - last_position, |
| - shdr_start - last_position); |
| - |
| - memset (last_position, __libelf_fill_byte, written); |
| - } |
| - |
| - if (last_position + written != scn_start + offset |
| - && shdr_end < scn_start + offset) |
| - { |
| - char *fill_start = MAX (shdr_end, scn_start); |
| - memset (fill_start, __libelf_fill_byte, |
| - scn_start + offset - fill_start); |
| - } |
| - } |
| - |
| if (scn->data_list_rear != NULL) |
| do |
| { |
| @@ -325,7 +331,8 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) |
| || ((scn->flags | dl->flags | elf->flags) |
| & ELF_F_DIRTY) != 0)) |
| { |
| - fill_mmap (dl->data.d.d_off); |
| + fill_mmap (last_position, shdr_start, shdr_end, |
| + scn_start, dl->data.d.d_off); |
| last_position = scn_start + dl->data.d.d_off; |
| } |
| |
| @@ -377,7 +384,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) |
| /* If the previous section (or the ELF/program |
| header) changed we might have to fill the gap. */ |
| if (scn_start > last_position && previous_scn_changed) |
| - fill_mmap (0); |
| + fill_mmap (last_position, shdr_start, shdr_end, scn_start, 0); |
| |
| /* We have to trust the existing section header information. */ |
| last_position = scn_start + shdr->sh_size; |
| diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c |
| index b9d5cea..62aa54a 100644 |
| --- a/libelf/elf_begin.c |
| +++ b/libelf/elf_begin.c |
| @@ -985,6 +985,22 @@ write_file (int fd, Elf_Cmd cmd) |
| } |
| |
| |
| +/* Duplicate the descriptor, with write lock if an archive. */ |
| +static Elf * |
| +lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref) |
| +{ |
| + /* We need wrlock to dup an archive. */ |
| + if (ref->kind == ELF_K_AR) |
| + { |
| + rwlock_unlock (ref->lock); |
| + rwlock_wrlock (ref->lock); |
| + } |
| + |
| + /* Duplicate the descriptor. */ |
| + return dup_elf (fildes, cmd, ref); |
| +} |
| + |
| + |
| /* Return a descriptor for the file belonging to FILDES. */ |
| Elf * |
| elf_begin (fildes, cmd, ref) |
| @@ -1011,19 +1027,6 @@ elf_begin (fildes, cmd, ref) |
| return NULL; |
| } |
| |
| - Elf *lock_dup_elf () |
| - { |
| - /* We need wrlock to dup an archive. */ |
| - if (ref->kind == ELF_K_AR) |
| - { |
| - rwlock_unlock (ref->lock); |
| - rwlock_wrlock (ref->lock); |
| - } |
| - |
| - /* Duplicate the descriptor. */ |
| - return dup_elf (fildes, cmd, ref); |
| - } |
| - |
| switch (cmd) |
| { |
| case ELF_C_NULL: |
| @@ -1044,7 +1047,7 @@ elf_begin (fildes, cmd, ref) |
| case ELF_C_READ: |
| case ELF_C_READ_MMAP: |
| if (ref != NULL) |
| - retval = lock_dup_elf (); |
| + retval = lock_dup_elf (fildes, cmd, ref); |
| else |
| /* Create descriptor for existing file. */ |
| retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL); |
| @@ -1065,7 +1068,7 @@ elf_begin (fildes, cmd, ref) |
| retval = NULL; |
| } |
| else |
| - retval = lock_dup_elf (); |
| + retval = lock_dup_elf (fildes, cmd, ref); |
| } |
| else |
| /* Create descriptor for existing file. */ |
| diff --git a/libelf/elf_getarsym.c b/libelf/elf_getarsym.c |
| index d0bb28a..a9bbb9d 100644 |
| --- a/libelf/elf_getarsym.c |
| +++ b/libelf/elf_getarsym.c |
| @@ -196,18 +196,15 @@ elf_getarsym (elf, ptr) |
| elf->state.ar.ar_sym = (Elf_Arsym *) malloc (ar_sym_len); |
| if (elf->state.ar.ar_sym != NULL) |
| { |
| - union |
| - { |
| - uint32_t u32[n]; |
| - uint64_t u64[n]; |
| - } *file_data; |
| + uint8_t file_data_buffer[n * sizeof(uint64_t)]; |
| + void *file_data = (void *) file_data_buffer; |
| + uint64_t *file_data_u64 = (uint64_t *) file_data; |
| + uint32_t *file_data_u32 = (uint32_t *) file_data; |
| char *str_data; |
| size_t sz = n * w; |
| |
| if (elf->map_address == NULL) |
| { |
| - file_data = alloca (sz); |
| - |
| ar_sym_len += index_size - n * w; |
| Elf_Arsym *newp = (Elf_Arsym *) realloc (elf->state.ar.ar_sym, |
| ar_sym_len); |
| @@ -241,8 +238,12 @@ elf_getarsym (elf, ptr) |
| { |
| file_data = (void *) (elf->map_address + off); |
| if (!ALLOW_UNALIGNED |
| - && ((uintptr_t) file_data & -(uintptr_t) n) != 0) |
| - file_data = memcpy (alloca (sz), elf->map_address + off, sz); |
| + && ((uintptr_t) file_data & -(uintptr_t) n) != 0) { |
| + file_data = (void *) file_data_buffer; |
| + memcpy(file_data, elf->map_address + off, sz); |
| + } |
| + file_data_u64 = (uint64_t *) file_data; |
| + file_data_u32 = (uint32_t *) file_data; |
| str_data = (char *) (elf->map_address + off + sz); |
| } |
| |
| @@ -253,7 +254,7 @@ elf_getarsym (elf, ptr) |
| arsym[cnt].as_name = str_data; |
| if (index64_p) |
| { |
| - uint64_t tmp = file_data->u64[cnt]; |
| + uint64_t tmp = file_data_u64[cnt]; |
| if (__BYTE_ORDER == __LITTLE_ENDIAN) |
| tmp = bswap_64 (tmp); |
| |
| @@ -275,9 +276,9 @@ elf_getarsym (elf, ptr) |
| } |
| } |
| else if (__BYTE_ORDER == __LITTLE_ENDIAN) |
| - arsym[cnt].as_off = bswap_32 (file_data->u32[cnt]); |
| + arsym[cnt].as_off = bswap_32 (file_data_u32[cnt]); |
| else |
| - arsym[cnt].as_off = file_data->u32[cnt]; |
| + arsym[cnt].as_off = file_data_u32[cnt]; |
| |
| arsym[cnt].as_hash = _dl_elf_hash (str_data); |
| str_data = rawmemchr (str_data, '\0') + 1; |