diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-12-04 05:58:16 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2008-12-04 05:58:16 +0000 |
commit | 02f66452635df3d01f7e57845c3362ab828e3d89 (patch) | |
tree | 24b5255577524d60a33f79596fa1505379d96901 | |
parent | 593798821113c57fe10f1fdf6593658d99d05ca9 (diff) | |
download | elfutils-02f66452635df3d01f7e57845c3362ab828e3d89.tar.gz |
propagate from branch 'com.redhat.elfutils.roland.pending.libelf-threads' (head fc97c9c202b5d7d7699a3b1d5c53007a2ef37bb1)
to branch 'com.redhat.elfutils' (head 67cccb9bfffc1a7fe3d8d355a2d9b6d0e489ff81)
-rw-r--r-- | libasm/ChangeLog | 4 | ||||
-rw-r--r-- | libasm/Makefile.am | 7 | ||||
-rw-r--r-- | libelf/ChangeLog | 43 | ||||
-rw-r--r-- | libelf/elf32_checksum.c | 23 | ||||
-rw-r--r-- | libelf/elf32_getehdr.c | 34 | ||||
-rw-r--r-- | libelf/elf32_getshdr.c | 7 | ||||
-rw-r--r-- | libelf/elf32_updatenull.c | 2 | ||||
-rw-r--r-- | libelf/elf_begin.c | 23 | ||||
-rw-r--r-- | libelf/elf_getarhdr.c | 11 | ||||
-rw-r--r-- | libelf/elf_getdata.c | 29 | ||||
-rw-r--r-- | libelf/elf_getdata_rawchunk.c | 15 | ||||
-rw-r--r-- | libelf/elf_next.c | 10 | ||||
-rw-r--r-- | libelf/elf_rand.c | 6 | ||||
-rw-r--r-- | libelf/elf_rawfile.c | 8 | ||||
-rw-r--r-- | libelf/libelfP.h | 6 |
15 files changed, 171 insertions, 57 deletions
diff --git a/libasm/ChangeLog b/libasm/ChangeLog index c98deb64..2894970e 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 62b5ee29..bd5779e8 100644 --- a/libasm/Makefile.am +++ b/libasm/Makefile.am @@ -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) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index e8069db7..f4da1295 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 0e4ab9f7..32b4a02d 100644 --- a/libelf/elf32_checksum.c +++ b/libelf/elf32_checksum.c @@ -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)) diff --git a/libelf/elf32_getehdr.c b/libelf/elf32_getehdr.c index d62e255b..8009133b 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 @@ __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; diff --git a/libelf/elf32_getshdr.c b/libelf/elf32_getshdr.c index b36e5437..91f5b3a1 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,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; } diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c index ae8696e7..a18d0bea 100644 --- a/libelf/elf32_updatenull.c +++ b/libelf/elf32_updatenull.c @@ -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) diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index bd385306..04670a45 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -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. */ diff --git a/libelf/elf_getarhdr.c b/libelf/elf_getarhdr.c index 875b2a10..6cc6eddb 100644 --- a/libelf/elf_getarhdr.c +++ b/libelf/elf_getarhdr.c @@ -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); diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c index 216905a6..e083b033 100644 --- a/libelf/elf_getdata.c +++ b/libelf/elf_getdata.c @@ -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; diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c index bea0f3f6..5af0f7f3 100644 --- a/libelf/elf_getdata_rawchunk.c +++ b/libelf/elf_getdata_rawchunk.c @@ -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; } diff --git a/libelf/elf_next.c b/libelf/elf_next.c index ec80fadf..fbfb2721 100644 --- a/libelf/elf_next.c +++ b/libelf/elf_next.c @@ -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; } diff --git a/libelf/elf_rand.c b/libelf/elf_rand.c index 9ba631ff..a766d38f 100644 --- a/libelf/elf_rand.c +++ b/libelf/elf_rand.c @@ -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; } diff --git a/libelf/elf_rawfile.c b/libelf/elf_rawfile.c index a1c6a1d2..a62a3549 100644 --- a/libelf/elf_rawfile.c +++ b/libelf/elf_rawfile.c @@ -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; } diff --git a/libelf/libelfP.h b/libelf/libelfP.h index 4cab3f38..e8100397 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -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; |