mirror of
https://github.com/arachsys/libelf.git
synced 2026-01-27 01:44:27 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f38ceb5a8a | ||
|
|
6188fbeb25 | ||
|
|
288355d104 | ||
|
|
e12821ffb2 | ||
|
|
b5edd4a1e4 | ||
|
|
4015076fe6 | ||
|
|
c682a83511 | ||
|
|
bc189e2914 | ||
|
|
f918d99c1e | ||
|
|
95564b26d3 | ||
|
|
b3ab1bd9a4 |
4
Makefile
4
Makefile
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
24
src/common.h
24
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
16
src/elf.h
16
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. */
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
107
src/elf_begin.c
107
src/elf_begin.c
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
85
src/eu-search.c
Normal 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
88
src/eu-search.h
Normal 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
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
78
src/locks.h
Normal 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 */
|
||||
@ -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>
|
||||
|
||||
|
||||
|
||||
34
src/system.h
34
src/system.h
@ -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
57
update
Executable 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
|
||||
Loading…
x
Reference in New Issue
Block a user