diff options
Diffstat (limited to 'libelf/elf32_getehdr.c')
-rw-r--r-- | libelf/elf32_getehdr.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/libelf/elf32_getehdr.c b/libelf/elf32_getehdr.c index bdb2cc41..8009133b 100644 --- a/libelf/elf32_getehdr.c +++ b/libelf/elf32_getehdr.c @@ -62,12 +62,11 @@ #endif -ElfW2(LIBELFBITS,Ehdr) * -elfw2(LIBELFBITS,getehdr) (elf) +static ElfW2(LIBELFBITS,Ehdr) * +getehdr_impl (elf, wrlock) Elf *elf; + int wrlock; { - ElfW2(LIBELFBITS,Ehdr) *result; - if (elf == NULL) return NULL; @@ -77,22 +76,45 @@ elfw2(LIBELFBITS,getehdr) (elf) return NULL; } - rwlock_rdlock (elf->lock); - + 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; +} + +ElfW2(LIBELFBITS,Ehdr) * +__elfw2(LIBELFBITS,getehdr_wrlock) (elf) + Elf *elf; +{ + return getehdr_impl (elf, 1); +} + +ElfW2(LIBELFBITS,Ehdr) * +elfw2(LIBELFBITS,getehdr) (elf) + Elf *elf; +{ + ElfW2(LIBELFBITS,Ehdr) *result; + if (elf == NULL) + return NULL; - out: + rwlock_rdlock (elf->lock); + result = getehdr_impl (elf, 0); rwlock_unlock (elf->lock); return result; } -INTDEF(elfw2(LIBELFBITS,getehdr)) |