]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
propagate from branch 'com.redhat.elfutils.roland.pending.libelf-threads' (head fc97c...
authorUlrich Drepper <drepper@redhat.com>
Thu, 4 Dec 2008 05:58:16 +0000 (05:58 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 4 Dec 2008 05:58:16 +0000 (05:58 +0000)
            to branch 'com.redhat.elfutils' (head 67cccb9bfffc1a7fe3d8d355a2d9b6d0e489ff81)

15 files changed:
libasm/ChangeLog
libasm/Makefile.am
libelf/ChangeLog
libelf/elf32_checksum.c
libelf/elf32_getehdr.c
libelf/elf32_getshdr.c
libelf/elf32_updatenull.c
libelf/elf_begin.c
libelf/elf_getarhdr.c
libelf/elf_getdata.c
libelf/elf_getdata_rawchunk.c
libelf/elf_next.c
libelf/elf_rand.c
libelf/elf_rawfile.c
libelf/libelfP.h

index c98deb649b8b226b4aa34df9c02fc56b4624a243..2894970e3006811015af887650b238e2ba184c34 100644 (file)
@@ -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
index 62b5ee29ce4ed1c52a001b737ebdfadfa9dbdfe3..bd5779e8e2f246cdd556141eb43352f953042f6b 100644 (file)
@@ -65,17 +65,12 @@ if !MUDFLAP
 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)
 
index e8069db70c08edd02fbfaa598bf65e584a1947e0..f4da1295210e5f7367b483a45e4b8f4938bd067e 100644 (file)
@@ -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.
index 0e4ab9f71efbc1aa72b6089cb83d172d8639c024..32b4a02de2c185ef3be38ae80aed4210d0bde8fa 100644 (file)
@@ -105,6 +105,14 @@ elfw2(LIBELFBITS,checksum) (elf)
                     || (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 @@ elfw2(LIBELFBITS,checksum) (elf)
       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 @@ elfw2(LIBELFBITS,checksum) (elf)
            /* 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))
index d62e255b9b18998adbfcfad271da039bb2f36b94..8009133b31971aef9c43bf8bf8c76bee8141ab66 100644 (file)
 #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 @@ __elfw2(LIBELFBITS,getehdr_rdlock) (elf)
       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 @@ elfw2(LIBELFBITS,getehdr) (elf)
     return NULL;
 
   rwlock_rdlock (elf->lock);
-  result = __elfw2(LIBELFBITS,getehdr_rdlock) (elf);
+  result = getehdr_impl (elf, 0);
   rwlock_unlock (elf->lock);
 
   return result;
index b36e5437cbf090335edb046a1fb1d50529e56a52..91f5b3a15783085e3a652d444cc5c3d978003ef7 100644 (file)
@@ -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,Shdr) *
 __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 @@ __elfw2(LIBELFBITS,getshdr_rdlock) (scn)
       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 @@ __elfw2(LIBELFBITS,getshdr_wrlock) (scn)
 
   result = scn->shdr.ELFW(e,LIBELFBITS);
   if (result == NULL)
-    result = load_shdr_rwlock (scn);
+    result = load_shdr_wrlock (scn);
 
   return result;
 }
index ae8696e7dbfa0d1607c88e21d57acfd66a688ea7..a18d0bea050e7d590e724f0e08f58036df89765a 100644 (file)
@@ -139,7 +139,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
   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)
index bd385306d4211258038021ee7818003818fa8c84..04670a4554296dafd64f4db6e41cdf44f27b6ed1 100644 (file)
@@ -750,7 +750,7 @@ read_long_names (Elf *elf)
 /* 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 @@ dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
      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 @@ 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:
@@ -1043,8 +1056,7 @@ elf_begin (fildes, cmd, ref)
     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 @@ elf_begin (fildes, cmd, ref)
              retval = NULL;
            }
          else
-           /* Duplicate this descriptor.  */
-           retval = dup_elf (fildes, cmd, ref);
+           retval = lock_dup_elf ();
        }
       else
        /* Create descriptor for existing file.  */
index 875b2a108a9ef58ec9786bc5387c3765a32568d9..6cc6eddbfcbce96aac7788ab8a07be4bbba1ec29 100644 (file)
@@ -78,8 +78,15 @@ elf_getarhdr (elf)
   /* 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);
index 216905a644e8376ad37760450a23b0c75f64c255..e083b033f6cfeb65f35496f9240973771e3692dd 100644 (file)
@@ -364,6 +364,7 @@ __elf_getdata_rdlock (scn, data)
 {
   Elf_Data *result = NULL;
   Elf *elf;
+  int locked = 0;
 
   if (scn == NULL)
     return NULL;
@@ -431,6 +432,7 @@ __elf_getdata_rdlock (scn, data)
          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 @@ __elf_getdata_rdlock (scn, data)
   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 @@ __elf_getdata_rdlock (scn, data)
 
   /* 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;
 
index bea0f3f635736146ae2bb77850535b6080c559e1..5af0f7f3989485dfd2a0e9437c3f9bc296e04075 100644 (file)
@@ -95,6 +95,9 @@ elf_getdata_rawchunk (elf, offset, size, type)
   /* 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 @@ elf_getdata_rawchunk (elf, offset, size, type)
        {
        nomem:
          __libelf_seterrno (ELF_E_NOMEM);
-         return NULL;
+         goto out;
        }
 
       /* Read the file content.  */
@@ -118,7 +121,7 @@ elf_getdata_rawchunk (elf, offset, size, type)
          /* Something went wrong.  */
          free (rawchunk);
          __libelf_seterrno (ELF_E_READ_ERROR);
-         return NULL;
+         goto out;
        }
 
       flags = ELF_F_MALLOCED;
@@ -181,8 +184,14 @@ elf_getdata_rawchunk (elf, offset, size, type)
   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;
 }
index ec80fadf57c3a53b9290ae85ed326f84ccb85310..fbfb27214d3a131c4962bdec1d35134a436e7615 100644 (file)
@@ -64,6 +64,7 @@ elf_next (elf)
      Elf *elf;
 {
   Elf *parent;
+  Elf_Cmd ret;
 
   /* Be gratious, the specs demand it.  */
   if (elf == NULL || elf->parent == NULL)
@@ -73,14 +74,17 @@ elf_next (elf)
   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;
+
+  rwlock_unlock (parent->lock);
 
-  return elf->cmd;
+  return ret;
 }
index 9ba631ff6b24a1bd084a0bc2c36d0a784c82eccb..a766d38fa597c6102bd736b0f0187c216dc8d167 100644 (file)
@@ -67,16 +67,20 @@ elf_rand (elf, offset)
   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;
 }
index a1c6a1d276e600849c61bbaefa380047224e73bd..a62a3549554a9c68ecb367eea0bd975a9d775af7 100644 (file)
@@ -63,6 +63,8 @@ elf_rawfile (elf, ptr)
      Elf *elf;
      size_t *ptr;
 {
+  char *result;
+
   if (elf == NULL)
     {
       /* No valid descriptor.  */
@@ -77,8 +79,12 @@ elf_rawfile (elf, ptr)
   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;
 }
index 4cab3f3882442f85de929cd40df3b00f38070e40..e8100397d3bfee8ff3f381990b375b44f02bc305 100644 (file)
@@ -486,7 +486,7 @@ extern Elf *__libelf_read_mmaped_file (int fildes, void *map_address,
 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 __elf64_updatefile (Elf *elf, int change_bo, size_t shnum)
 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;