propagate from branch 'com.redhat.elfutils.roland.pending.libelf-threads' (head fc97c9c202b5d7d7699a3b1d5c53007a2ef37bb1)
to branch 'com.redhat.elfutils' (head 67cccb9bfffc1a7fe3d8d355a2d9b6d0e489ff81)
diff --git a/libasm/ChangeLog b/libasm/ChangeLog
index c98deb6..2894970 100644
--- a/libasm/ChangeLog
+++ b/libasm/ChangeLog
@@ -1,7 +1,3 @@
-2008-12-03 Ulrich Drepper <drepper@redhat.com>
-
- * Makefile.am [USE_TLS]: Like libasm.so with libpthread.
-
2008-01-11 Ulrich Drepper <drepper@redhat.com>
* libasm.h (DisasmGetSymCB_t): Change type of fourth and fifth
diff --git a/libasm/Makefile.am b/libasm/Makefile.am
index 62b5ee2..bd5779e 100644
--- a/libasm/Makefile.am
+++ b/libasm/Makefile.am
@@ -65,17 +65,12 @@
libasm_pic_a_SOURCES =
am_libasm_pic_a_OBJECTS = $(libasm_a_SOURCES:.c=.os)
-libasm_so_LDLIBS =
-if USE_TLS
-libasm_so_LDLIBS += -lpthread
-endif
-
libasm_so_SOURCES =
libasm.so: libasm_pic.a libasm.map
$(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
-Wl,--version-script,$(srcdir)/libasm.map,--no-undefined \
-Wl,--soname,$@.$(VERSION) \
- ../libebl/libebl.a ../libelf/libelf.so $(libasm_so_LDLIBS)
+ ../libebl/libebl.a ../libelf/libelf.so
if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
ln -fs $@ $@.$(VERSION)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index e8069db..f4da129 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,44 @@
+2008-10-22 Petr Machata <pmachata@redhat.com>
+
+ * elf_rawfile.c (elf_rawfile): Lock around elf-> references.
+
+2008-10-21 Petr Machata <pmachata@redhat.com>
+
+ * libelfP.h: Rename getehdr_rdlock to getehdr_wrlock.
+ * elf32_getehdr.c (getehdr_rdlock): Move the code to new function
+ getehdr_impl and make it a wrapper. Rename to getehdr_wrlock.
+ (getehdr_impl): Guard elf->class init with wrlock.
+ (getehdr): Also make it a wrapper of getehdr_impl.
+ * elf32_updatenull.c (updatenull_wrlock): Call getehdr_wrlock.
+
+2008-10-20 Petr Machata <pmachata@redhat.com>
+
+ * elf_getdata_rawchunk.c (elf_getdata_rawchunk): Lock around the
+ code that reads mutable elf state. Relock to write lock to chain
+ the new chunk on the elf rawchunks list.
+
+2008-10-20 Petr Machata <pmachata@redhat.com>
+
+ * elf32_checksum.c (checksum): Place a lock around the code that
+ processes data. Make it wrlock if the code needs to xlate the
+ data before processing.
+
+2008-10-16 Petr Machata <pmachata@redhat.com>
+
+ * elf_begin.c
+ (__libelf_next_arhdr): Rename to __libelf_next_arhdr_wrlock.
+ (dup_elf): Adjust the call.
+ (elf_begin): New local function lock_dup_elf. Relocks the elf if
+ necessary before calling dup. Call this instead of dup_elf.
+ * elf_getarhdr.c
+ (elf_getarhdr): Lock before calling __libelf_next_arhdr_wrlock.
+ * elf_next.c (elf_next): Likewise.
+ * elf_rand.c (elf_rand): Likewise.
+
+2008-10-14 Petr Machata <pmachata@redhat.com>
+
+ * elf_getdata.c (__elf_getdata_rdlock): Lock before converting.
+
2008-11-26 Roland McGrath <roland@redhat.com>
* elf.h: Update from glibc.
@@ -46,7 +87,7 @@
* elf32_getshdr.c
(__elfNN_getshdr_internal): Drop.
- (load_shdr_rwlock, scn_valid): New functions, contain bits of
+ (load_shdr_wrlock, scn_valid): New functions, contain bits of
behaviour from __elfNN_getshdr_internal.
(__elfNN_getshdr_rdlock, __elfNN_getshdr_wrlock): Replacements for
dropped _internal functions above.
diff --git a/libelf/elf32_checksum.c b/libelf/elf32_checksum.c
index 0e4ab9f..32b4a02 100644
--- a/libelf/elf32_checksum.c
+++ b/libelf/elf32_checksum.c
@@ -105,6 +105,14 @@
|| (ident[EI_DATA] == ELFDATA2MSB
&& __BYTE_ORDER == __BIG_ENDIAN));
+ /* If we don't have native byte order, we will likely need to
+ convert the data with xlate functions. We do it upfront instead
+ of relocking mid-iteration. */
+ if (!likely (same_byte_order))
+ rwlock_wrlock (elf->lock);
+ else
+ rwlock_rdlock (elf->lock);
+
/* Iterate over all sections to find those which are not strippable. */
scn = NULL;
while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL)
@@ -118,7 +126,8 @@
if (shdr == NULL)
{
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
- return -1l;
+ result = -1l;
+ goto out;
}
if (SECTION_STRIP_P (shdr,
@@ -162,17 +171,25 @@
/* Convert the data to file byte order. */
if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA])
== NULL)
- return -1l;
+ {
+ result = -1l;
+ goto out;
+ }
result = process_block (result, data);
/* And convert it back. */
if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA])
== NULL)
- return -1l;
+ {
+ result = -1l;
+ goto out;
+ }
}
}
+ out:
+ rwlock_unlock (elf->lock);
return result;
}
INTDEF(elfw2(LIBELFBITS,checksum))
diff --git a/libelf/elf32_getehdr.c b/libelf/elf32_getehdr.c
index d62e255..8009133 100644
--- a/libelf/elf32_getehdr.c
+++ b/libelf/elf32_getehdr.c
@@ -62,12 +62,11 @@
#endif
-ElfW2(LIBELFBITS,Ehdr) *
-__elfw2(LIBELFBITS,getehdr_rdlock) (elf)
+static ElfW2(LIBELFBITS,Ehdr) *
+getehdr_impl (elf, wrlock)
Elf *elf;
+ int wrlock;
{
- ElfW2(LIBELFBITS,Ehdr) *result;
-
if (elf == NULL)
return NULL;
@@ -77,19 +76,32 @@
return NULL;
}
+ again:
if (elf->class == 0)
- elf->class = ELFW(ELFCLASS,LIBELFBITS);
+ {
+ if (!wrlock)
+ {
+ rwlock_unlock (elf->lock);
+ rwlock_wrlock (elf->lock);
+ wrlock = 1;
+ goto again;
+ }
+ elf->class = ELFW(ELFCLASS,LIBELFBITS);
+ }
else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
{
__libelf_seterrno (ELF_E_INVALID_CLASS);
- result = NULL;
- goto out;
+ return NULL;
}
- result = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+ return elf->state.ELFW(elf,LIBELFBITS).ehdr;
+}
- out:
- return result;
+ElfW2(LIBELFBITS,Ehdr) *
+__elfw2(LIBELFBITS,getehdr_wrlock) (elf)
+ Elf *elf;
+{
+ return getehdr_impl (elf, 1);
}
ElfW2(LIBELFBITS,Ehdr) *
@@ -101,7 +113,7 @@
return NULL;
rwlock_rdlock (elf->lock);
- result = __elfw2(LIBELFBITS,getehdr_rdlock) (elf);
+ result = getehdr_impl (elf, 0);
rwlock_unlock (elf->lock);
return result;
diff --git a/libelf/elf32_getshdr.c b/libelf/elf32_getshdr.c
index b36e543..91f5b3a 100644
--- a/libelf/elf32_getshdr.c
+++ b/libelf/elf32_getshdr.c
@@ -67,7 +67,7 @@
static ElfW2(LIBELFBITS,Shdr) *
-load_shdr_rwlock (Elf_Scn *scn)
+load_shdr_wrlock (Elf_Scn *scn)
{
ElfW2(LIBELFBITS,Shdr) *result;
@@ -243,7 +243,6 @@
__elfw2(LIBELFBITS,getshdr_rdlock) (scn)
Elf_Scn *scn;
{
- /* XXX: no read locking here, figure out why is it not necessary. */
ElfW2(LIBELFBITS,Shdr) *result;
if (!scn_valid (scn))
@@ -256,7 +255,7 @@
rwlock_wrlock (scn->elf->lock);
result = scn->shdr.ELFW(e,LIBELFBITS);
if (result == NULL)
- result = load_shdr_rwlock (scn);
+ result = load_shdr_wrlock (scn);
}
return result;
@@ -273,7 +272,7 @@
result = scn->shdr.ELFW(e,LIBELFBITS);
if (result == NULL)
- result = load_shdr_rwlock (scn);
+ result = load_shdr_wrlock (scn);
return result;
}
diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
index ae8696e..a18d0be 100644
--- a/libelf/elf32_updatenull.c
+++ b/libelf/elf32_updatenull.c
@@ -139,7 +139,7 @@
int changed = 0;
int ehdr_flags = 0;
- ehdr = __elfw2(LIBELFBITS,getehdr_rdlock) (elf);
+ ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
/* Set the default values. */
if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index bd38530..04670a4 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -750,7 +750,7 @@
/* Read the next archive header. */
int
internal_function
-__libelf_next_arhdr (elf)
+__libelf_next_arhdr_wrlock (elf)
Elf *elf;
{
struct ar_hdr *ar_hdr;
@@ -949,7 +949,7 @@
pointing to. First read the header of the next member if this
has not happened already. */
if (ref->state.ar.elf_ar_hdr.ar_name == NULL
- && __libelf_next_arhdr (ref) != 0)
+ && __libelf_next_arhdr_wrlock (ref) != 0)
/* Something went wrong. Maybe there is no member left. */
return NULL;
@@ -1023,6 +1023,19 @@
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:
@@ -1043,8 +1056,7 @@
case ELF_C_READ:
case ELF_C_READ_MMAP:
if (ref != NULL)
- /* Duplicate the descriptor. */
- retval = dup_elf (fildes, cmd, ref);
+ retval = lock_dup_elf ();
else
/* Create descriptor for existing file. */
retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
@@ -1065,8 +1077,7 @@
retval = NULL;
}
else
- /* Duplicate this descriptor. */
- retval = dup_elf (fildes, cmd, ref);
+ retval = lock_dup_elf ();
}
else
/* Create descriptor for existing file. */
diff --git a/libelf/elf_getarhdr.c b/libelf/elf_getarhdr.c
index 875b2a1..6cc6edd 100644
--- a/libelf/elf_getarhdr.c
+++ b/libelf/elf_getarhdr.c
@@ -78,8 +78,15 @@
/* Make sure we have read the archive header. */
if (parent->state.ar.elf_ar_hdr.ar_name == NULL
&& __libelf_next_arhdr (parent) != 0)
- /* Something went wrong. Maybe there is no member left. */
- return NULL;
+ {
+ rwlock_wrlock (parent->lock);
+ int st = __libelf_next_arhdr_wrlock (parent);
+ rwlock_unlock (parent->lock);
+
+ if (st != 0)
+ /* Something went wrong. Maybe there is no member left. */
+ return NULL;
+ }
/* We can be sure the parent is an archive. */
assert (parent->kind == ELF_K_AR);
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 216905a..e083b03 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -364,6 +364,7 @@
{
Elf_Data *result = NULL;
Elf *elf;
+ int locked = 0;
if (scn == NULL)
return NULL;
@@ -431,6 +432,7 @@
modified, therefore start the tests again. */
rwlock_unlock (elf->lock);
rwlock_wrlock (elf->lock);
+ locked = 1;
/* Read the data from the file. There is always a file (or
memory region) associated with this descriptor since
@@ -446,14 +448,24 @@
if (scn->data_list_rear == NULL)
{
if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
- /* Convert according to the version and the type. */
- convert_data (scn, __libelf_version, elf->class,
- (elf->class == ELFCLASS32
- || (offsetof (struct Elf, state.elf32.ehdr)
- == offsetof (struct Elf, state.elf64.ehdr))
- ? elf->state.elf32.ehdr->e_ident[EI_DATA]
- : elf->state.elf64.ehdr->e_ident[EI_DATA]),
- scn->rawdata.d.d_size, scn->rawdata.d.d_type);
+ {
+ if (!locked)
+ {
+ rwlock_unlock (elf->lock);
+ rwlock_wrlock (elf->lock);
+ if (scn->data_list_rear != NULL)
+ goto pass;
+ }
+
+ /* Convert according to the version and the type. */
+ convert_data (scn, __libelf_version, elf->class,
+ (elf->class == ELFCLASS32
+ || (offsetof (struct Elf, state.elf32.ehdr)
+ == offsetof (struct Elf, state.elf64.ehdr))
+ ? elf->state.elf32.ehdr->e_ident[EI_DATA]
+ : elf->state.elf64.ehdr->e_ident[EI_DATA]),
+ scn->rawdata.d.d_size, scn->rawdata.d.d_type);
+ }
else
/* This is an empty or NOBITS section. There is no buffer but
the size information etc is important. */
@@ -464,6 +476,7 @@
/* If no data is present we cannot return any. */
if (scn->data_list_rear != NULL)
+ pass:
/* Return the first data element in the list. */
result = &scn->data_list.data.d;
diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c
index bea0f3f..5af0f7f 100644
--- a/libelf/elf_getdata_rawchunk.c
+++ b/libelf/elf_getdata_rawchunk.c
@@ -95,6 +95,9 @@
/* Get the raw bytes from the file. */
void *rawchunk;
int flags = 0;
+ Elf_Data *result = NULL;
+
+ rwlock_rdlock (elf->lock);
/* If the file is mmap'ed we can use it directly. */
if (elf->map_address != NULL)
@@ -107,7 +110,7 @@
{
nomem:
__libelf_seterrno (ELF_E_NOMEM);
- return NULL;
+ goto out;
}
/* Read the file content. */
@@ -118,7 +121,7 @@
/* Something went wrong. */
free (rawchunk);
__libelf_seterrno (ELF_E_READ_ERROR);
- return NULL;
+ goto out;
}
flags = ELF_F_MALLOCED;
@@ -181,8 +184,14 @@
chunk->data.d.d_align = align;
chunk->data.d.d_version = __libelf_version;
+ rwlock_unlock (elf->lock);
+ rwlock_wrlock (elf->lock);
+
chunk->next = elf->state.elf.rawchunks;
elf->state.elf.rawchunks = chunk;
+ result = &chunk->data.d;
- return &chunk->data.d;
+ out:
+ rwlock_unlock (elf->lock);
+ return result;
}
diff --git a/libelf/elf_next.c b/libelf/elf_next.c
index ec80fad..fbfb272 100644
--- a/libelf/elf_next.c
+++ b/libelf/elf_next.c
@@ -64,6 +64,7 @@
Elf *elf;
{
Elf *parent;
+ Elf_Cmd ret;
/* Be gratious, the specs demand it. */
if (elf == NULL || elf->parent == NULL)
@@ -73,14 +74,17 @@
parent = elf->parent;
assert (parent->kind == ELF_K_AR);
+ rwlock_wrlock (parent->lock);
+
/* Now advance the offset. */
parent->state.ar.offset += (sizeof (struct ar_hdr)
+ ((parent->state.ar.elf_ar_hdr.ar_size + 1)
& ~1l));
/* Get the next archive header. */
- if (__libelf_next_arhdr (parent) != 0)
- return ELF_C_NULL;
+ ret = __libelf_next_arhdr_wrlock (parent) != 0 ? ELF_C_NULL : elf->cmd;
- return elf->cmd;
+ rwlock_unlock (parent->lock);
+
+ return ret;
}
diff --git a/libelf/elf_rand.c b/libelf/elf_rand.c
index 9ba631f..a766d38 100644
--- a/libelf/elf_rand.c
+++ b/libelf/elf_rand.c
@@ -67,16 +67,20 @@
if (elf == NULL || elf->kind != ELF_K_AR)
return 0;
+ rwlock_wrlock (elf->lock);
+
/* Save the old offset and set the offset. */
elf->state.ar.offset = elf->start_offset + offset;
/* Get the next archive header. */
- if (__libelf_next_arhdr (elf) != 0)
+ if (__libelf_next_arhdr_wrlock (elf) != 0)
{
/* Mark the archive header as unusable. */
elf->state.ar.elf_ar_hdr.ar_name = NULL;
return 0;
}
+ rwlock_unlock (elf->lock);
+
return offset;
}
diff --git a/libelf/elf_rawfile.c b/libelf/elf_rawfile.c
index a1c6a1d..a62a354 100644
--- a/libelf/elf_rawfile.c
+++ b/libelf/elf_rawfile.c
@@ -63,6 +63,8 @@
Elf *elf;
size_t *ptr;
{
+ char *result;
+
if (elf == NULL)
{
/* No valid descriptor. */
@@ -77,8 +79,12 @@
if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
goto error_out;
+ rwlock_rdlock (elf->lock);
if (ptr != NULL)
*ptr = elf->maximum_size;
- return (char *) elf->map_address + elf->start_offset;
+ result = (char *) elf->map_address + elf->start_offset;
+ rwlock_unlock (elf->lock);
+
+ return result;
}
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 4cab3f3..e810039 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -486,7 +486,7 @@
extern void __libelf_seterrno (int value) internal_function;
/* Get the next archive header. */
-extern int __libelf_next_arhdr (Elf *elf) internal_function;
+extern int __libelf_next_arhdr_wrlock (Elf *elf) internal_function;
/* Read all of the file associated with the descriptor. */
extern char *__libelf_readall (Elf *elf) internal_function;
@@ -520,8 +520,8 @@
extern int __elf_end_internal (Elf *__elf) attribute_hidden;
extern Elf *__elf_begin_internal (int __fildes, Elf_Cmd __cmd, Elf *__ref)
attribute_hidden;
-extern Elf32_Ehdr *__elf32_getehdr_rdlock (Elf *__elf) internal_function;
-extern Elf64_Ehdr *__elf64_getehdr_rdlock (Elf *__elf) internal_function;
+extern Elf32_Ehdr *__elf32_getehdr_wrlock (Elf *__elf) internal_function;
+extern Elf64_Ehdr *__elf64_getehdr_wrlock (Elf *__elf) internal_function;
extern Elf32_Ehdr *__elf32_newehdr_internal (Elf *__elf) attribute_hidden;
extern Elf64_Ehdr *__elf64_newehdr_internal (Elf *__elf) attribute_hidden;
extern Elf32_Phdr *__elf32_getphdr_internal (Elf *__elf) attribute_hidden;