Compare commits

...

11 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
Chris Webb
bc189e2914 Update upstream files from elfutils 0.192 2024-10-19 14:32:37 +01:00
Chris Webb
f918d99c1e Merge from upstream libelf 0.192 2024-10-19 14:32:37 +01:00
Chris Webb
95564b26d3 Include upstream eu-search.h and locks.h 2024-10-19 14:32:25 +01:00
Chris Webb
b3ab1bd9a4 Add maintainer update script
This script captures my process for merging changes from new upstream
elfutils releases. It isn't obfuscated for portability as it is only
intended for maintainer use and documentation.
2024-07-18 10:48:35 +01:00
34 changed files with 785 additions and 241 deletions

View File

@ -6,7 +6,7 @@ LDFLAGS =
LDLIBS = -lz -lzstd
MAJOR = 1
MINOR = 0.191
MINOR = 0.194
HEADERS = $(wildcard include/*.h src/*.h)
SOURCES = $(wildcard src/*.c)
@ -23,7 +23,7 @@ clean:
libelf.a: $(LIBOBJS) Makefile
$(AR) rcs $@ $(LIBOBJS)
libelf.so: $(PICOBJS) Makefile
libelf.so: $(PICOBJS) Makefile
$(CC) $(LDFLAGS) -shared -Wl,-soname,libelf.so.$(MAJOR) \
-o $@ $(PICOBJS) $(LDLIBS)

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

@ -89,30 +89,34 @@ allocate_elf (int fildes, void *map_address, int64_t offset, size_t maxsize,
}
/* Acquire lock for the descriptor and all children. */
/* Caller must hold a lock for ELF. If there are children then a lock
will be acquired for each of them (recursively). */
static void
__attribute__ ((unused))
libelf_acquire_all (Elf *elf)
libelf_acquire_all_children (Elf *elf)
{
rwlock_wrlock (elf->lock);
if (elf->kind == ELF_K_AR)
{
Elf *child = elf->state.ar.children;
while (child != NULL)
{
rwlock_wrlock (child->lock);
if (child->ref_count != 0)
libelf_acquire_all (child);
libelf_acquire_all_children (child);
child = child->next;
}
}
}
/* Release own lock and those of the children. */
/* Caller must hold a lock for ELF. If there are children then a lock
will be released for each of them (recursively). */
static void
__attribute__ ((unused))
libelf_release_all (Elf *elf)
libelf_release_all_children (Elf *elf)
{
if (elf->kind == ELF_K_AR)
{
@ -121,12 +125,12 @@ libelf_release_all (Elf *elf)
while (child != NULL)
{
if (child->ref_count != 0)
libelf_release_all (child);
libelf_release_all_children (child);
rwlock_unlock (child->lock);
child = child->next;
}
}
rwlock_unlock (elf->lock);
}

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

@ -98,4 +98,136 @@
#define GNU_BUILD_ATTRIBUTE_PIC 7
#define GNU_BUILD_ATTRIBUTE_SHORT_ENUM 8
/* Hexagon specific declarations. */
/* Processor specific flags for the Ehdr e_flags field. */
#define EF_HEXAGON_MACH_V2 0x00000001 /* Hexagon V2 */
#define EF_HEXAGON_MACH_V3 0x00000002 /* Hexagon V3 */
#define EF_HEXAGON_MACH_V4 0x00000003 /* Hexagon V4 */
#define EF_HEXAGON_MACH_V5 0x00000004 /* Hexagon V5 */
#define EF_HEXAGON_MACH_V55 0x00000005 /* Hexagon V55 */
#define EF_HEXAGON_MACH_V60 0x00000060 /* Hexagon V60 */
#define EF_HEXAGON_MACH_V61 0x00000061 /* Hexagon V61 */
#define EF_HEXAGON_MACH_V62 0x00000062 /* Hexagon V62 */
#define EF_HEXAGON_MACH_V65 0x00000065 /* Hexagon V65 */
#define EF_HEXAGON_MACH_V66 0x00000066 /* Hexagon V66 */
#define EF_HEXAGON_MACH_V67 0x00000067 /* Hexagon V67 */
#define EF_HEXAGON_MACH_V67T 0x00008067 /* Hexagon V67T */
#define EF_HEXAGON_MACH_V68 0x00000068 /* Hexagon V68 */
#define EF_HEXAGON_MACH_V69 0x00000069 /* Hexagon V68 */
#define EF_HEXAGON_MACH_V71 0x00000071 /* Hexagon V71 */
#define EF_HEXAGON_MACH_V71T 0x00008071 /* Hexagon V71T */
#define EF_HEXAGON_MACH_V73 0x00000073 /* Hexagon V73 */
#define EF_HEXAGON_MACH 0x000003ff /* Hexagon V.. */
#define EF_HEXAGON_TINY 0x00008000 /* Hexagon V..T */
/* Special section indices. */
#define SHN_HEXAGON_SCOMMON 0xff00 /* Other access sizes */
#define SHN_HEXAGON_SCOMMON_1 0xff01 /* Byte-sized access */
#define SHN_HEXAGON_SCOMMON_2 0xff02 /* Half-word-sized access */
#define SHN_HEXAGON_SCOMMON_4 0xff03 /* Word-sized access */
#define SHN_HEXAGON_SCOMMON_8 0xff04 /* Double-word-size access */
/* Hexagon specific relocs. */
#define R_HEX_NONE 0
#define R_HEX_B22_PCREL 1
#define R_HEX_B15_PCREL 2
#define R_HEX_B7_PCREL 3
#define R_HEX_LO16 4
#define R_HEX_HI16 5
#define R_HEX_32 6
#define R_HEX_16 7
#define R_HEX_8 8
#define R_HEX_GPREL16_0 9
#define R_HEX_GPREL16_1 10
#define R_HEX_GPREL16_2 11
#define R_HEX_GPREL16_3 12
#define R_HEX_HL16 13
#define R_HEX_B13_PCREL 14
#define R_HEX_B9_PCREL 15
#define R_HEX_B32_PCREL_X 16
#define R_HEX_32_6_X 17
#define R_HEX_B22_PCREL_X 18
#define R_HEX_B15_PCREL_X 19
#define R_HEX_B13_PCREL_X 20
#define R_HEX_B9_PCREL_X 21
#define R_HEX_B7_PCREL_X 22
#define R_HEX_16_X 23
#define R_HEX_12_X 24
#define R_HEX_11_X 25
#define R_HEX_10_X 26
#define R_HEX_9_X 27
#define R_HEX_8_X 28
#define R_HEX_7_X 29
#define R_HEX_6_X 30
#define R_HEX_32_PCREL 31
#define R_HEX_COPY 32
#define R_HEX_GLOB_DAT 33
#define R_HEX_JMP_SLOT 34
#define R_HEX_RELATIVE 35
#define R_HEX_PLT_B22_PCREL 36
#define R_HEX_GOTREL_LO16 37
#define R_HEX_GOTREL_HI16 38
#define R_HEX_GOTREL_32 39
#define R_HEX_GOT_LO16 40
#define R_HEX_GOT_HI16 41
#define R_HEX_GOT_32 42
#define R_HEX_GOT_16 43
#define R_HEX_DTPMOD_32 44
#define R_HEX_DTPREL_LO16 45
#define R_HEX_DTPREL_HI16 46
#define R_HEX_DTPREL_32 47
#define R_HEX_DTPREL_16 48
#define R_HEX_GD_PLT_B22_PCREL 49
#define R_HEX_GD_GOT_LO16 50
#define R_HEX_GD_GOT_HI16 51
#define R_HEX_GD_GOT_32 52
#define R_HEX_GD_GOT_16 53
#define R_HEX_IE_LO16 54
#define R_HEX_IE_HI16 55
#define R_HEX_IE_32 56
#define R_HEX_IE_GOT_LO16 57
#define R_HEX_IE_GOT_HI16 58
#define R_HEX_IE_GOT_32 59
#define R_HEX_IE_GOT_16 60
#define R_HEX_TPREL_LO16 61
#define R_HEX_TPREL_HI16 62
#define R_HEX_TPREL_32 63
#define R_HEX_TPREL_16 64
#define R_HEX_6_PCREL_X 65
#define R_HEX_GOTREL_32_6_X 66
#define R_HEX_GOTREL_16_X 67
#define R_HEX_GOTREL_11_X 68
#define R_HEX_GOT_32_6_X 69
#define R_HEX_GOT_16_X 70
#define R_HEX_GOT_11_X 71
#define R_HEX_DTPREL_32_6_X 72
#define R_HEX_DTPREL_16_X 73
#define R_HEX_DTPREL_11_X 74
#define R_HEX_GD_GOT_32_6_X 75
#define R_HEX_GD_GOT_16_X 76
#define R_HEX_GD_GOT_11_X 77
#define R_HEX_IE_32_6_X 78
#define R_HEX_IE_16_X 79
#define R_HEX_IE_GOT_32_6_X 80
#define R_HEX_IE_GOT_16_X 81
#define R_HEX_IE_GOT_11_X 82
#define R_HEX_TPREL_32_6_X 83
#define R_HEX_TPREL_16_X 84
#define R_HEX_TPREL_11_X 85
#define R_HEX_LD_PLT_B22_PCREL 86
#define R_HEX_LD_GOT_LO16 87
#define R_HEX_LD_GOT_HI16 88
#define R_HEX_LD_GOT_32 89
#define R_HEX_LD_GOT_16 90
#define R_HEX_LD_GOT_32_6_X 91
#define R_HEX_LD_GOT_16_X 92
#define R_HEX_LD_GOT_11_X 93
#define R_HEX_23_REG 94
#define R_HEX_GD_PLT_B22_PCREL_X 95
#define R_HEX_GD_PLT_B32_PCREL_X 96
#define R_HEX_LD_PLT_B22_PCREL_X 97
#define R_HEX_LD_PLT_B32_PCREL_X 98
#define R_HEX_27_REG 99
#endif /* elf-knowledge.h */

View File

@ -831,6 +831,10 @@ typedef struct
control. */
#define NT_ARM_PAC_ENABLED_KEYS 0x40a /* AArch64 pointer authentication
enabled keys. */
#define NT_ARM_SSVE 0x40b /* ARM Streaming SVE registers. */
#define NT_ARM_ZA 0x40c /* ARM SME ZA registers. */
#define NT_ARM_ZT 0x40d /* ARM SME ZT registers. */
#define NT_ARM_FPMR 0x40e /* ARM floating point mode register. */
#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note. */
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */
#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */
@ -1234,6 +1238,10 @@ typedef struct
#define AT_RSEQ_FEATURE_SIZE 27 /* rseq supported feature size. */
#define AT_RSEQ_ALIGN 28 /* rseq allocation alignment. */
/* More machine-dependent hints about processor capabilities. */
#define AT_HWCAP3 29 /* extension of AT_HWCAP. */
#define AT_HWCAP4 30 /* extension of AT_HWCAP. */
#define AT_EXECFN 31 /* Filename of executable. */
/* Pointer to the global system page used for system calls and other
@ -1333,9 +1341,13 @@ typedef struct
#define NT_GNU_PROPERTY_TYPE_0 5
/* Packaging metadata as defined on
https://systemd.io/COREDUMP_PACKAGE_METADATA/ */
https://systemd.io/ELF_PACKAGE_METADATA/ */
#define NT_FDO_PACKAGING_METADATA 0xcafe1a7e
/* dlopen metadata as defined on
https://systemd.io/ELF_DLOPEN_METADATA/ */
#define NT_FDO_DLOPEN_METADATA 0x407c0c0a
/* Note section name of program property. */
#define NOTE_GNU_PROPERTY_SECTION_NAME ".note.gnu.property"
@ -4237,6 +4249,8 @@ enum
#define R_LARCH_TLS_TPREL32 10
#define R_LARCH_TLS_TPREL64 11
#define R_LARCH_IRELATIVE 12
#define R_LARCH_TLS_DESC32 13
#define R_LARCH_TLS_DESC64 14
/* Reserved for future relocs that the dynamic linker must understand. */

View File

@ -126,7 +126,7 @@ load_shdr_wrlock (Elf_Scn *scn)
if (unlikely (notcvt == NULL))
{
__libelf_seterrno (ELF_E_NOMEM);
goto out;
goto free_and_out;
}
memcpy (notcvt, ((char *) elf->map_address
+ elf->start_offset + ehdr->e_shoff),
@ -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

@ -45,13 +45,26 @@ Elf_Data *
elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
unsigned int encode)
{
if (src == NULL || dest == NULL)
return NULL;
if (src->d_type >= ELF_T_NUM)
{
__libelf_seterrno (ELF_E_UNKNOWN_TYPE);
return NULL;
}
/* First test whether the input data is really suitable for this
type. This means, whether there is an integer number of records.
Note that for this implementation the memory and file size of the
data types are identical. */
size_t recsize = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
if (src->d_size % recsize != 0)
/* We shouldn't require integer number of records when processing
notes. Payload bytes follow the header immediately, it's not an
array of records as is the case otherwise. */
if (src->d_type != ELF_T_NHDR && src->d_type != ELF_T_NHDR8
&& src->d_size % recsize != 0)
{
__libelf_seterrno (ELF_E_INVALID_DATA);
return NULL;

View File

@ -45,6 +45,15 @@ Elf_Data *
elfw2(LIBELFBITS, xlatetom) (Elf_Data *dest, const Elf_Data *src,
unsigned int encode)
{
if (src == NULL || dest == NULL)
return NULL;
if (src->d_type >= ELF_T_NUM)
{
__libelf_seterrno (ELF_E_UNKNOWN_TYPE);
return NULL;
}
/* First test whether the input data is really suitable for this
type. This means, whether there is an integer number of records.
Note that for this implementation the memory and file size of the

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
@ -439,6 +426,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
/* So far only one block with sections. */
elf->state.elf32.scns_last = &elf->state.elf32.scns;
eu_search_tree_init (&elf->state.elf32.rawchunk_tree);
}
else
{
@ -509,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
@ -536,6 +511,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
/* So far only one block with sections. */
elf->state.elf64.scns_last = &elf->state.elf64.scns;
eu_search_tree_init (&elf->state.elf64.rawchunk_tree);
}
return elf;
@ -839,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
@ -886,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. */
@ -1079,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

@ -42,19 +42,11 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
if (elf == NULL)
return -1;
if (elf->fildes == -1)
{
__libelf_seterrno (ELF_E_INVALID_HANDLE);
return -1;
}
rwlock_wrlock (elf->lock);
switch (cmd)
{
case ELF_C_FDREAD:
/* If not all of the file is in the memory read it now. */
if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
if (__libelf_readall (elf) == NULL)
{
/* We were not able to read everything. */
result = -1;
@ -64,7 +56,9 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
case ELF_C_FDDONE:
/* Mark the file descriptor as not usable. */
rwlock_wrlock (elf->lock);
elf->fildes = -1;
rwlock_unlock (elf->lock);
break;
default:
@ -73,7 +67,5 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
break;
}
rwlock_unlock (elf->lock);
return result;
}

View File

@ -519,7 +519,17 @@ __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size, size_t align,
scn->rawdata.d.d_align = align;
scn->rawdata.d.d_type = type;
/* Remove the old data. */
Elf_Data_List *runp = scn->data_list.next;
while (runp != NULL)
{
Elf_Data_List *oldp = runp;
runp = runp->next;
if ((oldp->flags & ELF_F_MALLOCED) != 0)
free (oldp);
}
/* Existing existing data is no longer valid. */
scn->data_list.next = NULL;
scn->data_list_rear = NULL;
if (scn->data_base != scn->rawdata_base)
free (scn->data_base);
@ -574,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)
@ -669,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);
@ -721,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)
{
@ -126,13 +132,14 @@ elf_end (Elf *elf)
case ELF_K_ELF:
{
void *rawchunks
search_tree *rawchunk_tree
= (elf->class == ELFCLASS32
|| (offsetof (struct Elf, state.elf32.rawchunks)
== offsetof (struct Elf, state.elf64.rawchunks))
? elf->state.elf32.rawchunks
: elf->state.elf64.rawchunks);
tdestroy (rawchunks, free_chunk);
|| (offsetof (struct Elf, state.elf32.rawchunk_tree)
== offsetof (struct Elf, state.elf64.rawchunk_tree))
? &elf->state.elf32.rawchunk_tree
: &elf->state.elf64.rawchunk_tree);
eu_search_tree_fini (rawchunk_tree, free_chunk);
Elf_ScnList *list = (elf->class == ELFCLASS32
|| (offsetof (struct Elf, state.elf32.scns)

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

@ -33,12 +33,11 @@
#include <assert.h>
#include <errno.h>
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include "libelfP.h"
#include "common.h"
#include "eu-search.h"
static int
chunk_compare (const void *a, const void *b)
@ -88,15 +87,16 @@ 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;
key.offset = offset;
key.data.d.d_size = size;
key.data.d.d_type = type;
Elf_Data_Chunk **found = tsearch (&key, &elf->state.elf.rawchunks,
&chunk_compare);
Elf_Data_Chunk **found
= 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:
tdelete (&key, &elf->state.elf.rawchunks, &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. */
tdelete (&key, &elf->state.elf.rawchunks, &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

@ -46,5 +46,6 @@ elf_memory (char *image, size_t size)
return NULL;
}
return __libelf_read_mmaped_file (-1, image, 0, size, ELF_C_READ_MMAP, NULL);
return __libelf_read_mmaped_file (-1, image, 0, size,
ELF_C_READ_MMAP_PRIVATE, NULL);
}

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

@ -84,7 +84,7 @@ __libelf_readall (Elf *elf)
/* If this is an archive and we have derived descriptors get the
locks for all of them. */
libelf_acquire_all (elf);
libelf_acquire_all_children (elf);
if (elf->maximum_size == ~((size_t) 0))
{
@ -141,7 +141,7 @@ __libelf_readall (Elf *elf)
__libelf_seterrno (ELF_E_NOMEM);
/* Free the locks on the children. */
libelf_release_all (elf);
libelf_release_all_children (elf);
}
rwlock_unlock (elf->lock);

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);

View File

@ -29,35 +29,7 @@
#ifndef EU_CONFIG_H
#define EU_CONFIG_H 1
#ifdef USE_LOCKS
# include <pthread.h>
# include <assert.h>
# define rwlock_define(class,name) class pthread_rwlock_t name
# define once_define(class,name) class pthread_once_t name = PTHREAD_ONCE_INIT
# define RWLOCK_CALL(call) \
({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
# define ONCE_CALL(call) \
({ int _err = pthread_ ## call; assert_perror (_err); })
# define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL))
# define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock))
# 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 once(once_control, init_routine) \
ONCE_CALL (once (&once_control, init_routine))
#else
/* Eventually we will allow multi-threaded applications to use the
libraries. Therefore we will add the necessary locking although
the macros used expand to nothing for now. */
# define rwlock_define(class,name) class int name
# define rwlock_init(lock) ((void) (lock))
# define rwlock_fini(lock) ((void) (lock))
# define rwlock_rdlock(lock) ((void) (lock))
# define rwlock_wrlock(lock) ((void) (lock))
# define rwlock_unlock(lock) ((void) (lock))
# define once_define(class,name)
# define once(once_control, init_routine) init_routine()
#endif /* USE_LOCKS */
#include "locks.h"
#include <libintl.h>
/* gettext helper macros. */

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);
}

88
src/eu-search.h Normal file
View File

@ -0,0 +1,88 @@
/* Calls 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/>. */
#ifndef EU_SEARCH_H
#define EU_SEARCH_H 1
#include <stdlib.h>
#include <search.h>
#include <locks.h>
typedef struct
{
void *root;
rwlock_define (, lock);
} search_tree;
/* Search TREE for KEY and add KEY if not found. Synchronized using
TREE's lock. */
extern void *eu_tsearch (const void *key, search_tree *tree,
int (*compare)(const void *, const void *));
/* Search TREE for KEY. Synchronized with TREE's lock. */
extern void *eu_tfind (const void *key, search_tree *tree,
int (*compare)(const void *, const void *));
/* Delete key from TREE. Synchronized with TREE's lock. */
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 *));
/* Initialize TREE's root and lock. */
void eu_search_tree_init (search_tree *tree);
/* Free all nodes from TREE as well as TREE's lock. */
void eu_search_tree_fini (search_tree *tree, void (*free_node)(void *));
#endif

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

@ -33,6 +33,7 @@
#include <ar.h>
#include <gelf.h>
#include "eu-search.h"
#include <errno.h>
#include <stdbool.h>
@ -217,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. */
@ -308,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);
@ -323,7 +324,8 @@ struct Elf
Elf_ScnList *scns_last; /* Last element in the section list.
If NULL the data has not yet been
read from the file. */
void *rawchunks; /* Tree of elf_getdata_rawchunk results. */
search_tree rawchunk_tree; /* Tree and lock for elf_getdata_rawchunk
results. */
unsigned int scnincr; /* Number of sections allocate the last
time. */
int ehdr_flags; /* Flags (dirty) for ELF header. */
@ -342,7 +344,8 @@ struct Elf
Elf_ScnList *scns_last; /* Last element in the section list.
If NULL the data has not yet been
read from the file. */
void *rawchunks; /* Tree of elf_getdata_rawchunk results. */
search_tree rawchunk_tree; /* Tree and lock for
elf_getdata_rawchunk results. */
unsigned int scnincr; /* Number of sections allocate the last
time. */
int ehdr_flags; /* Flags (dirty) for ELF header. */
@ -367,7 +370,8 @@ struct Elf
Elf_ScnList *scns_last; /* Last element in the section list.
If NULL the data has not yet been
read from the file. */
void *rawchunks; /* Tree of elf_getdata_rawchunk results. */
search_tree rawchunk_tree; /* Tree and lock for
elf_getdata_rawchunk results. */
unsigned int scnincr; /* Number of sections allocate the last
time. */
int ehdr_flags; /* Flags (dirty) for ELF header. */
@ -393,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
@ -520,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)
@ -617,4 +621,7 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
#define INVALID_NDX(ndx, type, data) \
unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff)
#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
#endif /* libelfP.h */

78
src/locks.h Normal file
View File

@ -0,0 +1,78 @@
/* Configuration definitions.
Copyright (C) 2024 Red Hat, Inc.
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/>. */
#ifndef LOCKS_H
#define LOCKS_H 1
#ifdef USE_LOCKS
# include <pthread.h>
# include <assert.h>
# define rwlock_define(class,name) class pthread_rwlock_t name
# define once_define(class,name) class pthread_once_t name = PTHREAD_ONCE_INIT
# define RWLOCK_CALL(call) \
({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
# define ONCE_CALL(call) \
({ int _err = pthread_ ## call; assert_perror (_err); })
# define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL))
# define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock))
# 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
/* Eventually we will allow multi-threaded applications to use the
libraries. Therefore we will add the necessary locking although
the macros used expand to nothing for now. */
# define rwlock_define(class,name) class int name
# define rwlock_init(lock) ((void) (lock))
# define rwlock_fini(lock) ((void) (lock))
# 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 */
#endif /* locks.h */

View File

@ -27,6 +27,10 @@
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 <stddef.h>

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), '|'); \

57
update Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
set -e -o pipefail
shopt -s dotglob extglob nullglob
cd -- "$(git -C "${0%/*}" rev-parse --show-toplevel)"
if [[ $@ != +([0-9])*(.+([0-9])) ]]; then
echo "Usage: ${0##*/} UPSTREAM-VERSION"
echo "Update upstream branch then merge changes into master."
echo "This maintainer script does not attempt to be portable."
exit 64
elif ! git diff --exit-code --quiet; then
echo "Uncommitted changes in the working directory"
exit 1
elif ! git diff --cached --exit-code --quiet; then
echo "Uncommitted changes in the index"
exit 1
fi >&2
TMP=$(mktemp -d tmp-XXXXXX)
trap 'rm -r $TMP' EXIT
echo "Downloading upstream files for version $1:"
URL=https://sourceware.org/elfutils/ftp/$1/elfutils-$1.tar.bz2
COLUMNS=64 curl -L -# "$URL" | tar -x -f - -C $TMP --strip-components=1
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 \
$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##*/}"
done
git mv src/gelf.h src/libelf.h src/nlist.h include
cp $TMP/COPYING-GPLV2 $TMP/COPYING-LGPLV3 .
git add COPYING-GPLV2 COPYING-LGPLV3
if git diff --cached --exit-code --quiet; then
echo "No upstream changes to merge"
git checkout master
else
git commit -m "Update upstream files from elfutils $1"
git checkout master
git merge --no-commit upstream
sed -i "s/^MINOR *=.*/MINOR = $1/" Makefile
git add Makefile
git commit -m "Merge from upstream libelf $1"
echo "Merged libelf ready to review, build and test"
echo "Sign: git tag -m v$1 -s v$1"
echo "Push: git push --tags origin upstream master"
fi