blob: 553a52dd28ba4f529db63e8058dbbc10a3ff5ad8 [file] [log] [blame]
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;