From bc189e2914fd5d3909ff1883e157fb106522ca9d Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Sat, 19 Oct 2024 14:32:37 +0100 Subject: [PATCH] Update upstream files from elfutils 0.192 --- src/common.h | 24 ++++--- src/elf-knowledge.h | 132 +++++++++++++++++++++++++++++++++++++ src/elf.h | 16 ++++- src/elf32_getshdr.c | 2 +- src/elf32_xlatetof.c | 15 ++++- src/elf32_xlatetom.c | 9 +++ src/elf_begin.c | 2 + src/elf_cntl.c | 14 +--- src/elf_compress.c | 10 +++ src/elf_end.c | 13 ++-- src/elf_getdata_rawchunk.c | 12 ++-- src/elf_memory.c | 3 +- src/elf_readall.c | 4 +- src/eu-config.h | 30 +-------- src/eu-search.h | 64 ++++++++++++++++++ src/libelfP.h | 13 +++- src/locks.h | 62 +++++++++++++++++ src/next_prime.c | 4 ++ 18 files changed, 358 insertions(+), 71 deletions(-) create mode 100644 src/eu-search.h create mode 100644 src/locks.h diff --git a/src/common.h b/src/common.h index 9b2a856..8e33a70 100644 --- a/src/common.h +++ b/src/common.h @@ -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); } diff --git a/src/elf-knowledge.h b/src/elf-knowledge.h index 6e005fa..23e34ca 100644 --- a/src/elf-knowledge.h +++ b/src/elf-knowledge.h @@ -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 */ diff --git a/src/elf.h b/src/elf.h index f2206e5..33aea7f 100644 --- a/src/elf.h +++ b/src/elf.h @@ -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. */ diff --git a/src/elf32_getshdr.c b/src/elf32_getshdr.c index fc69630..19b690a 100644 --- a/src/elf32_getshdr.c +++ b/src/elf32_getshdr.c @@ -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), diff --git a/src/elf32_xlatetof.c b/src/elf32_xlatetof.c index ab85740..44c75ef 100644 --- a/src/elf32_xlatetof.c +++ b/src/elf32_xlatetof.c @@ -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; diff --git a/src/elf32_xlatetom.c b/src/elf32_xlatetom.c index fa3dc9a..a1eea84 100644 --- a/src/elf32_xlatetom.c +++ b/src/elf32_xlatetom.c @@ -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 diff --git a/src/elf_begin.c b/src/elf_begin.c index 8a49f35..2b3b465 100644 --- a/src/elf_begin.c +++ b/src/elf_begin.c @@ -439,6 +439,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 { @@ -536,6 +537,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; diff --git a/src/elf_cntl.c b/src/elf_cntl.c index 04aa913..da4ea99 100644 --- a/src/elf_cntl.c +++ b/src/elf_cntl.c @@ -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; } diff --git a/src/elf_compress.c b/src/elf_compress.c index 0ad6a32..2cd32a6 100644 --- a/src/elf_compress.c +++ b/src/elf_compress.c @@ -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); diff --git a/src/elf_end.c b/src/elf_end.c index 80f4d13..da8f3a2 100644 --- a/src/elf_end.c +++ b/src/elf_end.c @@ -126,13 +126,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) diff --git a/src/elf_getdata_rawchunk.c b/src/elf_getdata_rawchunk.c index 1751878..010fac9 100644 --- a/src/elf_getdata_rawchunk.c +++ b/src/elf_getdata_rawchunk.c @@ -33,12 +33,11 @@ #include #include -#include -#include #include #include "libelfP.h" #include "common.h" +#include "eu-search.h" static int chunk_compare (const void *a, const void *b) @@ -95,8 +94,9 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) 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 (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); + if (found == NULL) goto nomem; @@ -136,7 +136,7 @@ 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 (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); __libelf_seterrno (ELF_E_NOMEM); goto out; } @@ -147,7 +147,7 @@ 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 (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); free (rawchunk); __libelf_seterrno (ELF_E_READ_ERROR); goto out; diff --git a/src/elf_memory.c b/src/elf_memory.c index 13d77cb..1df49d7 100644 --- a/src/elf_memory.c +++ b/src/elf_memory.c @@ -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); } diff --git a/src/elf_readall.c b/src/elf_readall.c index d0f9a28..4ef8fe9 100644 --- a/src/elf_readall.c +++ b/src/elf_readall.c @@ -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); diff --git a/src/eu-config.h b/src/eu-config.h index feb079d..0bf2aa7 100644 --- a/src/eu-config.h +++ b/src/eu-config.h @@ -29,35 +29,7 @@ #ifndef EU_CONFIG_H #define EU_CONFIG_H 1 -#ifdef USE_LOCKS -# include -# include -# 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 /* gettext helper macros. */ diff --git a/src/eu-search.h b/src/eu-search.h new file mode 100644 index 0000000..67b54c1 --- /dev/null +++ b/src/eu-search.h @@ -0,0 +1,64 @@ +/* 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 . */ + +#ifndef EU_SEARCH_H +#define EU_SEARCH_H 1 + +#include +#include +#include + +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 *)); + +/* 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 diff --git a/src/libelfP.h b/src/libelfP.h index ed061ab..a9213ab 100644 --- a/src/libelfP.h +++ b/src/libelfP.h @@ -33,6 +33,7 @@ #include #include +#include "eu-search.h" #include #include @@ -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. */ @@ -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 */ diff --git a/src/locks.h b/src/locks.h new file mode 100644 index 0000000..90fe3f1 --- /dev/null +++ b/src/locks.h @@ -0,0 +1,62 @@ +/* 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 . */ + +#ifndef LOCKS_H +#define LOCKS_H 1 + +#ifdef USE_LOCKS +# include +# include +# 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 */ + +#endif /* locks.h */ diff --git a/src/next_prime.c b/src/next_prime.c index f2c921e..97c425e 100644 --- a/src/next_prime.c +++ b/src/next_prime.c @@ -27,6 +27,10 @@ the GNU Lesser General Public License along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include