mirror of
https://github.com/arachsys/libelf.git
synced 2026-01-26 15:39:09 +00:00
Update upstream files from elfutils 0.194
This commit is contained in:
parent
e12821ffb2
commit
6188fbeb25
@ -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;
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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;
|
||||
@ -815,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
|
||||
@ -862,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. */
|
||||
@ -1055,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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 *));
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -306,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);
|
||||
|
||||
@ -394,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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user