Compare commits

...

7 Commits

Author SHA1 Message Date
Chris Webb
f38ceb5a8a Merge from upstream libelf 0.194 2025-10-27 20:39:21 +00:00
Chris Webb
6188fbeb25 Update upstream files from elfutils 0.194 2025-10-27 20:39:21 +00:00
Chris Webb
288355d104 Merge from upstream libelf 0.193 2025-04-26 11:09:35 +01:00
Chris Webb
e12821ffb2 Update upstream files from elfutils 0.193 2025-04-26 11:09:35 +01:00
Chris Webb
b5edd4a1e4 Merge from upstream libelf 0.192 2024-10-20 10:25:43 +01:00
Chris Webb
4015076fe6 Add missing upstream eu-search.c from elfutils 0.192 2024-10-20 09:18:18 +01:00
Chris Webb
c682a83511 Include missing eu-search.c from upstream 2024-10-20 09:14:49 +01:00
24 changed files with 373 additions and 173 deletions

View File

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

View File

@ -315,7 +315,14 @@ 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. */
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. */
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/>. */
#if HAVE_CONFIG_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

View File

@ -146,20 +146,6 @@ 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,14 +73,15 @@ 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)
goto out;
{
result = &runp->data[i];
goto out;
}
}
runp = runp->next;

View File

@ -135,7 +135,8 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
/* Set the default values. */
if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
if (ehdr == NULL
|| 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.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
elf->state.ar.cur_ar_hdr.ar_rawname = elf->state.ar.raw_name;
}
return elf;
@ -412,19 +412,6 @@ 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
@ -510,19 +497,6 @@ 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
@ -841,6 +815,50 @@ 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
@ -888,7 +906,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.elf_ar_hdr;
elf_ar_hdr = &elf->state.ar.cur_ar_hdr;
/* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
Determine whether this is a special entry. */
@ -1081,21 +1099,42 @@ 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.elf_ar_hdr.ar_name == NULL
if (ref->state.ar.cur_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. */
result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
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;
result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
MIN (max_size - hdr_size - offset, 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,25 +584,30 @@ 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)
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
if (shdr == NULL)
shdr.s32 = elf32_getshdr (scn);
if (shdr.s32 == NULL)
return -1;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
sh_flags = shdr.s32->sh_flags;
sh_type = shdr.s32->sh_type;
sh_addralign = shdr.s32->sh_addralign;
}
else
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
if (shdr == NULL)
shdr.s64 = elf64_getshdr (scn);
if (shdr.s64 == NULL)
return -1;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
sh_flags = shdr.s64->sh_flags;
sh_type = shdr.s64->sh_type;
sh_addralign = shdr.s64->sh_addralign;
}
if ((sh_flags & SHF_ALLOC) != 0)
@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
correctly and ignored when SHF_COMPRESSED is set. */
if (elfclass == ELFCLASS32)
{
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;
shdr.s32->sh_size = new_size;
shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32,
ELF_T_CHDR);
shdr.s32->sh_flags |= SHF_COMPRESSED;
}
else
{
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;
shdr.s64->sh_size = new_size;
shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64,
ELF_T_CHDR);
shdr.s64->sh_flags |= SHF_COMPRESSED;
}
__libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR);
@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
correctly and ignored when SHF_COMPRESSED is set. */
if (elfclass == ELFCLASS32)
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = scn->zdata_size;
shdr->sh_addralign = scn->zdata_align;
shdr->sh_flags &= ~SHF_COMPRESSED;
shdr.s32->sh_size = scn->zdata_size;
shdr.s32->sh_addralign = scn->zdata_align;
shdr.s32->sh_flags &= ~SHF_COMPRESSED;
}
else
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = scn->zdata_size;
shdr->sh_addralign = scn->zdata_align;
shdr->sh_flags &= ~SHF_COMPRESSED;
shdr.s64->sh_size = scn->zdata_size;
shdr.s64->sh_addralign = scn->zdata_align;
shdr.s64->sh_flags &= ~SHF_COMPRESSED;
}
__libelf_reset_rawdata (scn, scn->zdata_base,

View File

@ -59,25 +59,30 @@ 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)
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
if (shdr == NULL)
shdr.s32 = elf32_getshdr (scn);
if (shdr.s32 == NULL)
return -1;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
sh_flags = shdr.s32->sh_flags;
sh_type = shdr.s32->sh_type;
sh_addralign = shdr.s32->sh_addralign;
}
else
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
if (shdr == NULL)
shdr.s64 = elf64_getshdr (scn);
if (shdr.s64 == NULL)
return -1;
sh_flags = shdr->sh_flags;
sh_type = shdr->sh_type;
sh_addralign = shdr->sh_addralign;
sh_flags = shdr.s64->sh_flags;
sh_type = shdr.s64->sh_type;
sh_addralign = shdr.s64->sh_addralign;
}
/* Allocated sections, or sections that are already are compressed
@ -122,15 +127,9 @@ 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)
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = new_size;
}
shdr.s32->sh_size = new_size;
else
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = new_size;
}
shdr.s64->sh_size = new_size;
__libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE);
@ -187,15 +186,9 @@ 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)
{
Elf32_Shdr *shdr = elf32_getshdr (scn);
shdr->sh_size = size;
}
shdr.s32->sh_size = size;
else
{
Elf64_Shdr *shdr = elf64_getshdr (scn);
shdr->sh_size = size;
}
shdr.s64->sh_size = size;
__libelf_reset_rawdata (scn, buf_out, size, sh_addralign,
__libelf_data_type (&ehdr, sh_type,

View File

@ -116,6 +116,12 @@ 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,30 +44,12 @@ 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 (parent == NULL)
if (elf->parent == NULL || elf->parent->kind != ELF_K_AR)
{
__libelf_seterrno (ELF_E_INVALID_OP);
return NULL;
}
/* 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;
return &elf->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 ELF_C_NULL;
return -1;
/* 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_rdlock (elf->lock);
rwlock_wrlock (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 (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
= eu_tsearch_nolock (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
if (found == NULL)
goto nomem;
@ -136,7 +136,8 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
if (rawchunk == NULL)
{
nomem:
eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
&chunk_compare);
__libelf_seterrno (ELF_E_NOMEM);
goto out;
}
@ -147,7 +148,8 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
!= size))
{
/* Something went wrong. */
eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
&chunk_compare);
free (rawchunk);
__libelf_seterrno (ELF_E_READ_ERROR);
goto out;
@ -217,9 +219,6 @@ 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.elf_ar_hdr.ar_size + 1)
+ ((parent->state.ar.cur_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.elf_ar_hdr.ar_name = NULL;
parent->state.ar.cur_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->state.ar.elf_ar_hdr.ar_name = NULL;
elf->elf_ar_hdr.ar_name = NULL;
return 0;
}

View File

@ -1,5 +1,6 @@
/* 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.
@ -37,14 +38,53 @@
int
elf_scnshndx (Elf_Scn *scn)
{
if (unlikely (scn->shndx_index == 0))
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)
{
/* 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);
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;
}
return scn->shndx_index;
/* 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;
}
INTDEF(elf_scnshndx)

View File

@ -1,5 +1,6 @@
/* 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.
@ -53,24 +54,6 @@ 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)
{
@ -201,9 +184,12 @@ 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.
/* 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)))
/* 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)))
result = &strscn->rawdata_base[offset];
else
__libelf_seterrno (ELF_E_INVALID_INDEX);

85
src/eu-search.c Normal file
View File

@ -0,0 +1,85 @@
/* 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,6 +52,30 @@ 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. */
assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
eu_static_assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
eu_static_assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);

View File

@ -218,9 +218,6 @@ 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. */
@ -309,6 +306,9 @@ 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,7 +397,8 @@ 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 elf_ar_hdr; /* Structure returned by 'elf_getarhdr'. */
Elf_Arhdr cur_ar_hdr; /* Copy of current archive member's 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
@ -524,7 +525,6 @@ 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,6 +43,17 @@
# 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
@ -55,6 +66,11 @@
# 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,9 +31,15 @@
#ifndef LIB_SYSTEM_H
#define LIB_SYSTEM_H 1
#include <config.h>
/* 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 <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@ -98,6 +104,32 @@ 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,next_prime}.c \
for FILE in $TMP/libelf/*.[ch] $TMP/lib/{crc32,eu-search,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##*/}"