Compare commits

..

No commits in common. "master" and "v0.192" have entirely different histories.

24 changed files with 172 additions and 372 deletions

View File

@ -6,7 +6,7 @@ LDFLAGS =
LDLIBS = -lz -lzstd
MAJOR = 1
MINOR = 0.194
MINOR = 0.192
HEADERS = $(wildcard include/*.h src/*.h)
SOURCES = $(wildcard src/*.c)

View File

@ -315,14 +315,7 @@ extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
extern Elf_Scn *elf_newscn (Elf *__elf);
/* Get the section index of the extended section index table for the
given symbol table. Returns -1 when the given Elf_Scn is NULL or
if an error occurred during lookup, elf_errno will be set. Returns
0 if the given Elf_Scn isn't a symbol table (sh_type is not
SHT_SYMTAB) or no extended section index table could be
found. Otherwise the section index of the extended section index
table for the given Elf_Scn is returned. An extended index table
has a sh_type of SHT_SYMTAB_SHNDX and a sh_link equal to the given
symbol table section index. */
given symbol table. */
extern int elf_scnshndx (Elf_Scn *__scn);
/* Get the number of sections in the ELF file. If the file uses more

View File

@ -25,7 +25,7 @@
the GNU Lesser General Public License along with this program. If
not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
#if HAVE_CONFIG_H
#include <config.h>
#endif

View File

@ -146,6 +146,20 @@ load_shdr_wrlock (Elf_Scn *scn)
CONVERT_TO (shdr[cnt].sh_addralign,
notcvt[cnt].sh_addralign);
CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
/* If this is a section with an extended index add a
reference in the section which uses the extended
index. */
if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
&& shdr[cnt].sh_link < shnum)
elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
= cnt;
/* Set the own shndx_index field in case it has not yet
been set. */
if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
= -1;
}
if (copy)

View File

@ -73,15 +73,14 @@ elfw2(LIBELFBITS,offscn) (Elf *elf, ElfW2(LIBELFBITS,Off) offset)
for (unsigned int i = 0; i < runp->cnt; ++i)
if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_offset == offset)
{
result = &runp->data[i];
/* If this section is empty, the following one has the same
sh_offset. We presume the caller is looking for a nonempty
section, so keep looking if this one is empty. */
if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_size != 0
&& runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_type != SHT_NOBITS)
{
result = &runp->data[i];
goto out;
}
goto out;
}
runp = runp->next;

View File

@ -135,8 +135,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
/* Set the default values. */
if (ehdr == NULL
|| ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
return -1;
/* At least the ELF header is there. */

View File

@ -62,7 +62,7 @@ file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
happen on demand. */
elf->state.ar.offset = offset + SARMAG;
elf->state.ar.cur_ar_hdr.ar_rawname = elf->state.ar.raw_name;
elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
}
return elf;
@ -412,6 +412,19 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
((char *) map_address + offset
+ elf->state.elf32.shdr[cnt].sh_offset);
elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
/* If this is a section with an extended index add a
reference in the section which uses the extended
index. */
if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
&& elf->state.elf32.shdr[cnt].sh_link < scncnt)
elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
= cnt;
/* Set the own shndx_index field in case it has not yet
been set. */
if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
elf->state.elf32.scns.data[cnt].shndx_index = -1;
}
}
else
@ -497,6 +510,19 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
((char *) map_address + offset
+ elf->state.elf64.shdr[cnt].sh_offset);
elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
/* If this is a section with an extended index add a
reference in the section which uses the extended
index. */
if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
&& elf->state.elf64.shdr[cnt].sh_link < scncnt)
elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
= cnt;
/* Set the own shndx_index field in case it has not yet
been set. */
if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
elf->state.elf64.scns.data[cnt].shndx_index = -1;
}
}
else
@ -815,50 +841,6 @@ read_long_names (Elf *elf)
}
/* Copy archive header from parent archive ref to member descriptor elf. */
static int
copy_arhdr (Elf_Arhdr *dest, Elf *ref)
{
Elf_Arhdr *hdr;
hdr = &ref->state.ar.cur_ar_hdr;
char *ar_name = hdr->ar_name;
char *ar_rawname = hdr->ar_rawname;
if (ar_name == NULL || ar_rawname == NULL)
{
/* ref doesn't have an Elf_Arhdr or it was marked as unusable. */
return 0;
}
/* Allocate copies of ar_name and ar_rawname. */
size_t name_len = strlen (ar_name) + 1;
char *name_copy = malloc (MAX (name_len, 16));
if (name_copy == NULL)
{
__libelf_seterrno (ELF_E_NOMEM);
return -1;
}
memcpy (name_copy, ar_name, name_len);
size_t rawname_len = strlen (ar_rawname) + 1;
char *rawname_copy = malloc (MAX (rawname_len, 17));
if (rawname_copy == NULL)
{
free (name_copy);
__libelf_seterrno (ELF_E_NOMEM);
return -1;
}
memcpy (rawname_copy, ar_rawname, rawname_len);
*dest = *hdr;
dest->ar_name = name_copy;
dest->ar_rawname = rawname_copy;
return 0;
}
/* Read the next archive header. */
int
internal_function
@ -906,7 +888,7 @@ __libelf_next_arhdr_wrlock (Elf *elf)
/* Copy the raw name over to a NUL terminated buffer. */
*((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
elf_ar_hdr = &elf->state.ar.cur_ar_hdr;
elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
/* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
Determine whether this is a special entry. */
@ -1099,42 +1081,21 @@ dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
member the internal pointer of the archive file descriptor is
pointing to. First read the header of the next member if this
has not happened already. */
if (ref->state.ar.cur_ar_hdr.ar_name == NULL
if (ref->state.ar.elf_ar_hdr.ar_name == NULL
&& __libelf_next_arhdr_wrlock (ref) != 0)
/* Something went wrong. Maybe there is no member left. */
return NULL;
/* We have all the information we need about the next archive member.
Now create a descriptor for it. Check parent size can contain member. */
if (ref->state.ar.offset < ref->start_offset)
return NULL;
size_t max_size = ref->maximum_size;
size_t offset = (size_t) (ref->state.ar.offset - ref->start_offset);
size_t hdr_size = sizeof (struct ar_hdr);
size_t ar_size = (size_t) ref->state.ar.cur_ar_hdr.ar_size;
if (max_size < hdr_size || max_size - hdr_size < offset)
return NULL;
Elf_Arhdr ar_hdr = {0};
if (copy_arhdr (&ar_hdr, ref) != 0)
/* Out of memory. */
return NULL;
Now create a descriptor for it. */
result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
MIN (max_size - hdr_size - offset, ar_size), cmd, ref);
ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
/* Enlist this new descriptor in the list of children. */
if (result != NULL)
{
/* Enlist this new descriptor in the list of children. */
result->next = ref->state.ar.children;
ref->state.ar.children = result;
result->elf_ar_hdr = ar_hdr;
}
else
{
free (ar_hdr.ar_name);
free (ar_hdr.ar_rawname);
}
return result;

View File

@ -584,30 +584,25 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
Elf64_Xword sh_flags;
Elf64_Word sh_type;
Elf64_Xword sh_addralign;
union shdr
{
Elf32_Shdr *s32;
Elf64_Shdr *s64;
} shdr;
if (elfclass == ELFCLASS32)
{
shdr.s32 = elf32_getshdr (scn);
if (shdr.s32 == NULL)
Elf32_Shdr *shdr = elf32_getshdr (scn);
if (shdr == NULL)
return -1;
sh_flags = shdr.s32->sh_flags;
sh_type = shdr.s32->sh_type;
sh_addralign = shdr.s32->sh_addralign;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
}
else
{
shdr.s64 = elf64_getshdr (scn);
if (shdr.s64 == NULL)
Elf64_Shdr *shdr = elf64_getshdr (scn);
if (shdr == NULL)
return -1;
sh_flags = shdr.s64->sh_flags;
sh_type = shdr.s64->sh_type;
sh_addralign = shdr.s64->sh_addralign;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
}
if ((sh_flags & SHF_ALLOC) != 0)
@ -684,17 +679,17 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
correctly and ignored when SHF_COMPRESSED is set. */
if (elfclass == ELFCLASS32)
{
shdr.s32->sh_size = new_size;
shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32,
ELF_T_CHDR);
shdr.s32->sh_flags |= SHF_COMPRESSED;
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = new_size;
shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR);
shdr->sh_flags |= SHF_COMPRESSED;
}
else
{
shdr.s64->sh_size = new_size;
shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64,
ELF_T_CHDR);
shdr.s64->sh_flags |= SHF_COMPRESSED;
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = new_size;
shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR);
shdr->sh_flags |= SHF_COMPRESSED;
}
__libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR);
@ -736,15 +731,17 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
correctly and ignored when SHF_COMPRESSED is set. */
if (elfclass == ELFCLASS32)
{
shdr.s32->sh_size = scn->zdata_size;
shdr.s32->sh_addralign = scn->zdata_align;
shdr.s32->sh_flags &= ~SHF_COMPRESSED;
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = scn->zdata_size;
shdr->sh_addralign = scn->zdata_align;
shdr->sh_flags &= ~SHF_COMPRESSED;
}
else
{
shdr.s64->sh_size = scn->zdata_size;
shdr.s64->sh_addralign = scn->zdata_align;
shdr.s64->sh_flags &= ~SHF_COMPRESSED;
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = scn->zdata_size;
shdr->sh_addralign = scn->zdata_align;
shdr->sh_flags &= ~SHF_COMPRESSED;
}
__libelf_reset_rawdata (scn, scn->zdata_base,

View File

@ -59,30 +59,25 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
Elf64_Xword sh_flags;
Elf64_Word sh_type;
Elf64_Xword sh_addralign;
union shdr
{
Elf32_Shdr *s32;
Elf64_Shdr *s64;
} shdr;
if (elfclass == ELFCLASS32)
{
shdr.s32 = elf32_getshdr (scn);
if (shdr.s32 == NULL)
Elf32_Shdr *shdr = elf32_getshdr (scn);
if (shdr == NULL)
return -1;
sh_flags = shdr.s32->sh_flags;
sh_type = shdr.s32->sh_type;
sh_addralign = shdr.s32->sh_addralign;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
}
else
{
shdr.s64 = elf64_getshdr (scn);
if (shdr.s64 == NULL)
Elf64_Shdr *shdr = elf64_getshdr (scn);
if (shdr == NULL)
return -1;
sh_flags = shdr.s64->sh_flags;
sh_type = shdr.s64->sh_type;
sh_addralign = shdr.s64->sh_addralign;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
}
/* Allocated sections, or sections that are already are compressed
@ -127,9 +122,15 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
Just adjust the sh_size. */
if (elfclass == ELFCLASS32)
shdr.s32->sh_size = new_size;
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = new_size;
}
else
shdr.s64->sh_size = new_size;
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = new_size;
}
__libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE);
@ -186,9 +187,15 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
Just adjust the sh_size. */
if (elfclass == ELFCLASS32)
shdr.s32->sh_size = size;
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = size;
}
else
shdr.s64->sh_size = size;
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = size;
}
__libelf_reset_rawdata (scn, buf_out, size, sh_addralign,
__libelf_data_type (&ehdr, sh_type,

View File

@ -116,12 +116,6 @@ elf_end (Elf *elf)
rwlock_unlock (parent->lock);
}
if (elf->elf_ar_hdr.ar_name != NULL)
free (elf->elf_ar_hdr.ar_name);
if (elf->elf_ar_hdr.ar_rawname != NULL)
free (elf->elf_ar_hdr.ar_rawname);
/* This was the last activation. Free all resources. */
switch (elf->kind)
{

View File

@ -44,12 +44,30 @@ elf_getarhdr (Elf *elf)
if (elf == NULL)
return NULL;
Elf *parent = elf->parent;
/* Calling this function is not ok for any file type but archives. */
if (elf->parent == NULL || elf->parent->kind != ELF_K_AR)
if (parent == NULL)
{
__libelf_seterrno (ELF_E_INVALID_OP);
return NULL;
}
return &elf->elf_ar_hdr;
/* Make sure we have read the archive header. */
if (parent->state.ar.elf_ar_hdr.ar_name == NULL
&& __libelf_next_arhdr_wrlock (parent) != 0)
{
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);
return &parent->state.ar.elf_ar_hdr;
}

View File

@ -43,7 +43,7 @@ elf_getaroff (Elf *elf)
{
/* Be gratious, the specs demand it. */
if (elf == NULL || elf->parent == NULL)
return -1;
return ELF_C_NULL;
/* We can be sure the parent is an archive. */
Elf *parent = elf->parent;

View File

@ -87,7 +87,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
int flags = 0;
Elf_Data *result = NULL;
rwlock_wrlock (elf->lock);
rwlock_rdlock (elf->lock);
/* Maybe we already got this chunk? */
Elf_Data_Chunk key;
@ -95,7 +95,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
key.data.d.d_size = size;
key.data.d.d_type = type;
Elf_Data_Chunk **found
= eu_tsearch_nolock (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
= eu_tsearch (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
if (found == NULL)
goto nomem;
@ -136,8 +136,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
if (rawchunk == NULL)
{
nomem:
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
&chunk_compare);
eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
__libelf_seterrno (ELF_E_NOMEM);
goto out;
}
@ -148,8 +147,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
!= size))
{
/* Something went wrong. */
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
&chunk_compare);
eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
free (rawchunk);
__libelf_seterrno (ELF_E_READ_ERROR);
goto out;
@ -219,6 +217,9 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
chunk->data.d.d_version = EV_CURRENT;
chunk->offset = offset;
rwlock_unlock (elf->lock);
rwlock_wrlock (elf->lock);
*found = chunk;
result = &chunk->data.d;

View File

@ -56,7 +56,7 @@ elf_next (Elf *elf)
/* Now advance the offset. */
parent->state.ar.offset += (sizeof (struct ar_hdr)
+ ((parent->state.ar.cur_ar_hdr.ar_size + 1)
+ ((parent->state.ar.elf_ar_hdr.ar_size + 1)
& ~1l));
/* Get the next archive header. */
@ -64,7 +64,7 @@ elf_next (Elf *elf)
/* If necessary, mark the archive header as unusable. */
if (ret == ELF_C_NULL)
parent->state.ar.cur_ar_hdr.ar_name = NULL;
parent->state.ar.elf_ar_hdr.ar_name = NULL;
rwlock_unlock (parent->lock);

View File

@ -53,7 +53,7 @@ elf_rand (Elf *elf, size_t offset)
if (__libelf_next_arhdr_wrlock (elf) != 0)
{
/* Mark the archive header as unusable. */
elf->elf_ar_hdr.ar_name = NULL;
elf->state.ar.elf_ar_hdr.ar_name = NULL;
return 0;
}

View File

@ -1,6 +1,5 @@
/* Get the section index of the extended section index table.
Copyright (C) 2007 Red Hat, Inc.
Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org>
This file is part of elfutils.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
@ -38,53 +37,14 @@
int
elf_scnshndx (Elf_Scn *scn)
{
size_t scnndx;
GElf_Shdr shdr_mem;
GElf_Shdr *shdr;
Elf *elf;
Elf_Scn *nscn;
if (scn == NULL)
return -1;
scnndx = scn->index;
elf = scn->elf;
shdr = gelf_getshdr (scn, &shdr_mem);
if (shdr == NULL)
return -1;
/* Only SYMTAB sections can have a SHNDX section. */
if (shdr->sh_type != SHT_SYMTAB)
return 0;
/* By convention the SHT_SYMTAB_SHNDX section is right after the the
SHT_SYMTAB section, so start there. */
nscn = scn;
while ((nscn = elf_nextscn (elf, nscn)) != NULL)
if (unlikely (scn->shndx_index == 0))
{
shdr = gelf_getshdr (nscn, &shdr_mem);
if (shdr == NULL)
return -1;
if (shdr->sh_type == SHT_SYMTAB_SHNDX && shdr->sh_link == scnndx)
return nscn->index;
/* We do not have the value yet. We get it as a side effect of
getting a section header. */
GElf_Shdr shdr_mem;
(void) INTUSE(gelf_getshdr) (scn, &shdr_mem);
}
/* OK, not found, start from the top. */
nscn = NULL;
while ((nscn = elf_nextscn (elf, nscn)) != NULL
&& nscn->index != scnndx)
{
shdr = gelf_getshdr (nscn, &shdr_mem);
if (shdr == NULL)
return -1;
if (shdr->sh_type == SHT_SYMTAB_SHNDX && shdr->sh_link == scnndx)
return nscn->index;
}
/* No shndx found, but no errors. */
return 0;
return scn->shndx_index;
}
INTDEF(elf_scnshndx)

View File

@ -1,6 +1,5 @@
/* Return string pointer from string section.
Copyright (C) 1998-2002, 2004, 2008, 2009, 2015 Red Hat, Inc.
Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org>
This file is part of elfutils.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
@ -54,6 +53,24 @@ get_zdata (Elf_Scn *strscn)
return zdata;
}
static bool validate_str (const char *str, size_t from, size_t to)
{
#if HAVE_DECL_MEMRCHR
// Check end first, which is likely a zero terminator, to prevent function call
return ((to > 0 && str[to - 1] == '\0')
|| (to - from > 0 && memrchr (&str[from], '\0', to - from - 1) != NULL));
#else
do {
if (to <= from)
return false;
to--;
} while (str[to]);
return true;
#endif
}
char *
elf_strptr (Elf *elf, size_t idx, size_t offset)
{
@ -184,12 +201,9 @@ elf_strptr (Elf *elf, size_t idx, size_t offset)
// initialized yet (when data_read is zero). So we cannot just
// look at the rawdata.d.d_size.
/* First check there actually is any data. This could be a new
section which hasn't had any data set yet. Then make sure
the string is at a valid offset and NUL terminated. */
if (unlikely (strscn->rawdata_base == NULL))
__libelf_seterrno (ELF_E_INVALID_SECTION);
else if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
/* Make sure the string is NUL terminated. Start from the end,
which very likely is a NUL char. */
if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
result = &strscn->rawdata_base[offset];
else
__libelf_seterrno (ELF_E_INVALID_INDEX);

View File

@ -1,85 +0,0 @@
/* Definitions for thread-safe tsearch/tfind
Copyright (C) 2023 Rice University
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
it under the terms of either
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at
your option) any later version
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at
your option) any later version
or both in parallel, as here.
elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "eu-search.h"
void *eu_tsearch (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
rwlock_wrlock (tree->lock);
void *ret = tsearch (key, &tree->root, compare);
rwlock_unlock (tree->lock);
return ret;
}
void *eu_tfind (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
rwlock_rdlock (tree->lock);
void *ret = tfind (key, &tree->root, compare);
rwlock_unlock (tree->lock);
return ret;
}
void *eu_tdelete (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
rwlock_wrlock (tree->lock);
void *ret = tdelete (key, &tree->root, compare);
rwlock_unlock (tree->lock);
return ret;
}
void eu_tdestroy (search_tree *tree, void (*free_node)(void *))
{
rwlock_wrlock (tree->lock);
tdestroy (tree->root, free_node);
tree->root = NULL;
rwlock_unlock (tree->lock);
}
void eu_search_tree_init (search_tree *tree)
{
tree->root = NULL;
rwlock_init (tree->lock);
}
void eu_search_tree_fini (search_tree *tree, void (*free_node)(void *))
{
eu_tdestroy (tree, free_node);
rwlock_fini (tree->lock);
}

View File

@ -52,30 +52,6 @@ extern void *eu_tfind (const void *key, search_tree *tree,
extern void *eu_tdelete (const void *key, search_tree *tree,
int (*compare)(const void *, const void *));
/* Search TREE for KEY and add KEY if not found. No locking is performed. */
static inline void *
eu_tsearch_nolock (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
return tsearch (key, &tree->root, compare);
}
/* Search TREE for KEY. No locking is performed. */
static inline void *
eu_tfind_nolock (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
return tfind (key, &tree->root, compare);
}
/* Delete key from TREE. No locking is performed. */
static inline void *
eu_tdelete_nolock (const void *key, search_tree *tree,
int (*compare)(const void *, const void *))
{
return tdelete (key, &tree->root, compare);
}
/* Free all nodes from TREE. */
void eu_tdestroy (search_tree *tree, void (*free_node)(void *));

View File

@ -51,8 +51,8 @@ gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
/* It's easy to handle this type. It has the same size for 32 and
64 bit objects. */
eu_static_assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
eu_static_assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);

View File

@ -218,6 +218,9 @@ struct Elf_Scn
int data_read; /* Nonzero if the section was created by the
user or if the data from the file/memory
is read. */
int shndx_index; /* Index of the extended section index
table for this symbol table (if this
section is a symbol table). */
size_t index; /* Index of this section. */
struct Elf *elf; /* The underlying ELF file. */
@ -306,9 +309,6 @@ struct Elf
/* Reference counting for the descriptor. */
int ref_count;
/* Structure returned by 'elf_getarhdr'. */
Elf_Arhdr elf_ar_hdr;
/* Lock to handle multithreaded programs. */
rwlock_define (,lock);
@ -397,8 +397,7 @@ struct Elf
int64_t offset; /* Offset in file we are currently at.
elf_next() advances this to the next
member of the archive. */
Elf_Arhdr cur_ar_hdr; /* Copy of current archive member's structure
returned by 'elf_getarhdr'. */
Elf_Arhdr elf_ar_hdr; /* Structure returned by 'elf_getarhdr'. */
struct ar_hdr ar_hdr; /* Header read from file. */
char ar_name[16]; /* NUL terminated ar_name of elf_ar_hdr. */
char raw_name[17]; /* This is a buffer for the NUL terminated
@ -525,6 +524,7 @@ extern Elf_Scn *__elf_getscn_internal (Elf *__elf, size_t __index)
attribute_hidden;
extern Elf_Scn *__elf_nextscn_internal (Elf *__elf, Elf_Scn *__scn)
attribute_hidden;
extern int __elf_scnshndx_internal (Elf_Scn *__scn) attribute_hidden;
extern Elf_Data *__elf_getdata_internal (Elf_Scn *__scn, Elf_Data *__data)
attribute_hidden;
extern Elf_Data *__elf_getdata_rdlock (Elf_Scn *__scn, Elf_Data *__data)

View File

@ -43,17 +43,6 @@
# define rwlock_rdlock(lock) RWLOCK_CALL (rdlock (&lock))
# define rwlock_wrlock(lock) RWLOCK_CALL (wrlock (&lock))
# define rwlock_unlock(lock) RWLOCK_CALL (unlock (&lock))
# define mutex_define(class,name) class pthread_mutex_t name
# define MUTEX_CALL(call) \
({ int _err = pthread_mutex_ ## call; assert_perror (_err); })
# define mutex_init(lock) \
({ pthread_mutexattr_t _attr; \
pthread_mutexattr_init (&_attr); \
pthread_mutexattr_settype (&_attr, PTHREAD_MUTEX_RECURSIVE); \
MUTEX_CALL (init (&lock, &_attr)); })
# define mutex_lock(_lock) MUTEX_CALL (lock (&_lock))
# define mutex_unlock(lock) MUTEX_CALL (unlock (&lock))
# define mutex_fini(lock) MUTEX_CALL (destroy (&lock))
# define once(once_control, init_routine) \
ONCE_CALL (once (&once_control, init_routine))
#else
@ -66,11 +55,6 @@
# define rwlock_rdlock(lock) ((void) (lock))
# define rwlock_wrlock(lock) ((void) (lock))
# define rwlock_unlock(lock) ((void) (lock))
# define mutex_define(class,name) class int name
# define mutex_init(lock) ((void) (lock))
# define mutex_lock(lock) ((void) (lock))
# define mutex_unlock(lock) ((void) (lock))
# define mutex_fini(lock) ((void) (lock))
# define once_define(class,name)
# define once(once_control, init_routine) init_routine()
#endif /* USE_LOCKS */

View File

@ -31,15 +31,9 @@
#ifndef LIB_SYSTEM_H
#define LIB_SYSTEM_H 1
/* Prevent double inclusion of config.h, config.h includes eu-config.h. */
#ifdef HAVE_CONFIG_H
#ifndef EU_CONFIG_H
# include <config.h>
#endif
#endif
#include <config.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@ -104,32 +98,6 @@ startswith (const char *str, const char *prefix)
return strncmp (str, prefix, strlen (prefix)) == 0;
}
/* Return TRUE if STR[FROM] is a valid string with a zero terminator
at or before STR[TO - 1]. Note FROM is an index into the STR
array, while TO is the maximum size of the STR array. This
function returns FALSE when TO is zero or FROM >= TO. */
static inline bool
validate_str (const char *str, size_t from, size_t to)
{
#if HAVE_DECL_MEMRCHR
// Check end first, which is likely a zero terminator,
// to prevent function call
return (to > 0
&& (str[to - 1] == '\0'
|| (to > from
&& memrchr (&str[from], '\0', to - from - 1) != NULL)));
#else
do {
if (to <= from)
return false;
to--;
} while (str[to]);
return true;
#endif
}
/* A special gettext function we use if the strings are too short. */
#define sgettext(Str) \
({ const char *__res = strrchr (_(Str), '|'); \

2
update
View File

@ -28,7 +28,7 @@ git checkout upstream
git rm -q -r include src
mkdir -p include src
for FILE in $TMP/libelf/*.[ch] $TMP/lib/{crc32,eu-search,next_prime}.c \
for FILE in $TMP/libelf/*.[ch] $TMP/lib/{crc32,next_prime}.c \
$TMP/lib/{eu-config,eu-search,fixedsizehash,locks,system}.h; do
sed ':a;s/[ \t]*$//;/^\n*$/{$d;N;ba}' "$FILE" >"src/${FILE##*/}"
git add "src/${FILE##*/}"