mirror of
https://github.com/arachsys/libelf.git
synced 2026-01-27 18:04:48 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f38ceb5a8a | ||
|
|
6188fbeb25 | ||
|
|
288355d104 | ||
|
|
e12821ffb2 | ||
|
|
b5edd4a1e4 | ||
|
|
4015076fe6 | ||
|
|
c682a83511 | ||
|
|
bc189e2914 | ||
|
|
f918d99c1e | ||
|
|
95564b26d3 | ||
|
|
b3ab1bd9a4 | ||
|
|
b80c36da9d | ||
|
|
bc9698efd5 | ||
|
|
a75f3a59d7 | ||
|
|
97a43e81a7 | ||
|
|
4a1923298d | ||
|
|
520244d664 | ||
|
|
4afb73a7af | ||
|
|
a78fcc53c1 |
6
Makefile
6
Makefile
@ -3,10 +3,10 @@ LIBDIR = $(PREFIX)/lib
|
||||
|
||||
CFLAGS = -O2 -Wall
|
||||
LDFLAGS =
|
||||
LDLIBS = -lz
|
||||
LDLIBS = -lz -lzstd
|
||||
|
||||
MAJOR = 1
|
||||
MINOR = 0.187
|
||||
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)
|
||||
|
||||
|
||||
7
README
7
README
@ -7,7 +7,8 @@ elfutils, along with a simple Makefile to build and install it.
|
||||
Unlike the upstream package, this libelf builds cleanly on both musl and
|
||||
glibc, using either clang or gcc. Users are spared the joy of autotools,
|
||||
and on musl systems it does not require extra libraries for argp, fts or
|
||||
obstack. The sole dependency is zlib for handling compressed ELF sections.
|
||||
obstack. The sole dependencies are zlib and (by default) zstd for handling
|
||||
compressed ELF sections.
|
||||
|
||||
The elfutils tools, libdwarf and libasm are not included: you will need the
|
||||
full upstream distribution to build those. However, they are a much more
|
||||
@ -28,7 +29,9 @@ similarly the install-shared target installs only the shared library.
|
||||
|
||||
The build should work out of the box on reasonably recent musl/glibc and
|
||||
clang/gcc. On very old or non-Linux systems, some manual adjustment of
|
||||
src/config.h may be needed.
|
||||
src/config.h may be needed. For example, to build without zstd support,
|
||||
remove the definitions of USE_ZSTD and USE_ZSTD_COMPRESS from config.h and
|
||||
drop -lzstd from LDLIBS in the Makefile.
|
||||
|
||||
Please report any problems or bugs to Chris Webb <chris@arachsys.com> rather
|
||||
than to the upstream elfutils maintainers, who are not to blame for issues
|
||||
|
||||
@ -82,6 +82,9 @@ typedef Elf64_Rel GElf_Rel;
|
||||
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||||
typedef Elf64_Rela GElf_Rela;
|
||||
|
||||
/* Relative relocation entry (in section of type SHT_RELR). */
|
||||
typedef Elf64_Relr GElf_Relr;
|
||||
|
||||
/* Program segment header. */
|
||||
typedef Elf64_Phdr GElf_Phdr;
|
||||
|
||||
|
||||
@ -64,6 +64,24 @@
|
||||
#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */
|
||||
#endif
|
||||
|
||||
#ifndef ELFCOMPRESS_ZSTD
|
||||
/* So ZSTD compression can be used even with an old system elf.h. */
|
||||
#define ELFCOMPRESS_ZSTD 2 /* Zstandard algorithm. */
|
||||
#endif
|
||||
|
||||
#ifndef SHT_RELR
|
||||
/* So RELR defines/typedefs can be used even with an old system elf.h. */
|
||||
#define SHT_RELR 19 /* RELR relative relocations */
|
||||
|
||||
/* RELR relocation table entry */
|
||||
typedef Elf32_Word Elf32_Relr;
|
||||
typedef Elf64_Xword Elf64_Relr;
|
||||
|
||||
#define DT_RELRSZ 35 /* Total size of RELR relative relocations */
|
||||
#define DT_RELR 36 /* Address of RELR relative relocations */
|
||||
#define DT_RELRENT 37 /* Size of one RELR relative relocaction */
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
|
||||
# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
|
||||
# define __deprecated_attribute__ __attribute__ ((__deprecated__))
|
||||
@ -119,6 +137,7 @@ typedef enum
|
||||
ELF_T_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
|
||||
ELF_T_NHDR8, /* Special GNU Properties note. Same as Nhdr,
|
||||
except padding. */
|
||||
ELF_T_RELR, /* Relative relocation entry. */
|
||||
/* Keep this the last entry. */
|
||||
ELF_T_NUM
|
||||
} Elf_Type;
|
||||
@ -283,7 +302,7 @@ extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
|
||||
|
||||
/* Get section at OFFSET. */
|
||||
extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
|
||||
/* Similar bug this time the binary calls is ELFCLASS64. */
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
|
||||
|
||||
/* Get index of section. */
|
||||
@ -296,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
|
||||
@ -348,10 +374,10 @@ extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
|
||||
|
||||
elf_compress takes a compression type that should be either zero to
|
||||
decompress or an ELFCOMPRESS algorithm to use for compression.
|
||||
Currently only ELFCOMPRESS_ZLIB is supported. elf_compress_gnu
|
||||
will compress in the traditional GNU compression format when
|
||||
compress is one and decompress the section data when compress is
|
||||
zero.
|
||||
Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
|
||||
elf_compress_gnu will compress in the traditional GNU compression
|
||||
format when compress is one and decompress the section data when
|
||||
compress is zero.
|
||||
|
||||
The FLAGS argument can be zero or ELF_CHF_FORCE. If FLAGS contains
|
||||
ELF_CHF_FORCE then it will always compress the section, even if
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#define HAVE_DECL_RAWMEMCHR 0
|
||||
#define HAVE_DECL_REALLOCARRAY 1
|
||||
#define HAVE_VISIBILITY 1
|
||||
#define USE_ZSTD 1
|
||||
#define USE_ZSTD_COMPRESS 1
|
||||
|
||||
#undef HAVE_GCC_STRUCT
|
||||
#undef USE_LOCKS
|
||||
|
||||
@ -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 */
|
||||
|
||||
254
src/elf.h
254
src/elf.h
@ -1,5 +1,5 @@
|
||||
/* This file defines standard ELF types, structures, and macros.
|
||||
Copyright (C) 1995-2022 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-2024 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@ -210,7 +210,7 @@ typedef struct
|
||||
#define EM_68HC12 53 /* Motorola M68HC12 */
|
||||
#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */
|
||||
#define EM_PCP 55 /* Siemens PCP */
|
||||
#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
|
||||
#define EM_NCPU 56 /* Sony nCPU embedded RISC */
|
||||
#define EM_NDR1 57 /* Denso NDR1 microprocessor */
|
||||
#define EM_STARCORE 58 /* Motorola Start*Core processor */
|
||||
#define EM_ME16 59 /* Toyota ME16 processor */
|
||||
@ -559,7 +559,7 @@ typedef struct
|
||||
|
||||
/* Possible bitmasks for si_flags. */
|
||||
#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
|
||||
#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
|
||||
#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-through symbol for translator */
|
||||
#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
|
||||
#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
|
||||
loaded */
|
||||
@ -728,6 +728,7 @@ typedef struct
|
||||
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
#define PT_GNU_PROPERTY 0x6474e553 /* GNU property */
|
||||
#define PT_GNU_SFRAME 0x6474e554 /* SFrame segment. */
|
||||
#define PT_LOSUNW 0x6ffffffa
|
||||
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
|
||||
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
|
||||
@ -790,9 +791,12 @@ typedef struct
|
||||
Register */
|
||||
#define NT_PPC_PKEY 0x110 /* Memory Protection Keys
|
||||
registers. */
|
||||
#define NT_PPC_DEXCR 0x111 /* PowerPC DEXCR registers. */
|
||||
#define NT_PPC_HASHKEYR 0x112 /* PowerPC HASHKEYR register. */
|
||||
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
|
||||
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
|
||||
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
|
||||
#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */
|
||||
#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
|
||||
#define NT_S390_TIMER 0x301 /* s390 timer register */
|
||||
#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
|
||||
@ -827,10 +831,16 @@ 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. */
|
||||
#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers. */
|
||||
#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */
|
||||
#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
|
||||
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
|
||||
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
|
||||
status registers. */
|
||||
@ -840,6 +850,8 @@ typedef struct
|
||||
SIMD Extension registers. */
|
||||
#define NT_LOONGARCH_LBT 0xa04 /* LoongArch Loongson Binary
|
||||
Translation registers. */
|
||||
#define NT_LOONGARCH_HW_BREAK 0xa05 /* LoongArch hardware breakpoint registers */
|
||||
#define NT_LOONGARCH_HW_WATCH 0xa06 /* LoongArch hardware watchpoint registers */
|
||||
|
||||
/* Legal values for the note segment descriptor types for object files. */
|
||||
|
||||
@ -1223,6 +1235,13 @@ typedef struct
|
||||
#define AT_HWCAP2 26 /* More machine-dependent hints about
|
||||
processor capabilities. */
|
||||
|
||||
#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
|
||||
@ -1322,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"
|
||||
|
||||
@ -1681,11 +1704,25 @@ typedef struct
|
||||
#define EF_MIPS_PIC 2 /* Contains PIC code. */
|
||||
#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */
|
||||
#define EF_MIPS_XGOT 8
|
||||
#define EF_MIPS_64BIT_WHIRL 16
|
||||
#define EF_MIPS_UCODE 16
|
||||
#define EF_MIPS_ABI2 32
|
||||
#define EF_MIPS_ABI_ON32 64
|
||||
#define EF_MIPS_OPTIONS_FIRST 0x00000080 /* Process the .MIPS.options
|
||||
section first by ld. */
|
||||
#define EF_MIPS_32BITMODE 0x00000100 /* Indicates code compiled for
|
||||
a 64-bit machine in 32-bit
|
||||
mode (regs are 32-bits
|
||||
wide). */
|
||||
#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */
|
||||
#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */
|
||||
#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural Extensions
|
||||
used by this file. */
|
||||
#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* Use MDMX multimedia
|
||||
extensions. */
|
||||
#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* Use MIPS-16 ISA
|
||||
extensions. */
|
||||
#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 /* Use MICROMIPS ISA
|
||||
extensions. */
|
||||
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */
|
||||
|
||||
/* Legal values for MIPS architecture level. */
|
||||
@ -1699,6 +1736,38 @@ typedef struct
|
||||
#define EF_MIPS_ARCH_64 0x60000000 /* MIPS64 code. */
|
||||
#define EF_MIPS_ARCH_32R2 0x70000000 /* MIPS32r2 code. */
|
||||
#define EF_MIPS_ARCH_64R2 0x80000000 /* MIPS64r2 code. */
|
||||
#define EF_MIPS_ARCH_32R6 0x90000000 /* MIPS32r6 code. */
|
||||
#define EF_MIPS_ARCH_64R6 0xa0000000 /* MIPS64r6 code. */
|
||||
#define EF_MIPS_ABI 0x0000F000 /* The ABI of the file. Also
|
||||
see EF_MIPS_ABI2 above. */
|
||||
#define EF_MIPS_ABI_O32 0x00001000 /* The original o32 abi. */
|
||||
#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended to work on
|
||||
64 bit architectures. */
|
||||
#define EF_MIPS_ABI_EABI32 0x00003000 /* EABI in 32 bit mode. */
|
||||
#define EF_MIPS_ABI_EABI64 0x00004000 /* EABI in 64 bit mode. */
|
||||
#define EF_MIPS_MACH 0x00FF0000
|
||||
#define EF_MIPS_MACH_3900 0x00810000
|
||||
#define EF_MIPS_MACH_4010 0x00820000
|
||||
#define EF_MIPS_MACH_4100 0x00830000
|
||||
#define EF_MIPS_MACH_ALLEGREX 0x00840000
|
||||
#define EF_MIPS_MACH_4650 0x00850000
|
||||
#define EF_MIPS_MACH_4120 0x00870000
|
||||
#define EF_MIPS_MACH_4111 0x00880000
|
||||
#define EF_MIPS_MACH_SB1 0x008a0000
|
||||
#define EF_MIPS_MACH_OCTEON 0x008b0000
|
||||
#define EF_MIPS_MACH_XLR 0x008c0000
|
||||
#define EF_MIPS_MACH_OCTEON2 0x008d0000
|
||||
#define EF_MIPS_MACH_OCTEON3 0x008e0000
|
||||
#define EF_MIPS_MACH_5400 0x00910000
|
||||
#define EF_MIPS_MACH_5900 0x00920000
|
||||
#define EF_MIPS_MACH_IAMR2 0x00930000
|
||||
#define EF_MIPS_MACH_5500 0x00980000
|
||||
#define EF_MIPS_MACH_9000 0x00990000
|
||||
#define EF_MIPS_MACH_LS2E 0x00A00000
|
||||
#define EF_MIPS_MACH_LS2F 0x00A10000
|
||||
#define EF_MIPS_MACH_GS464 0x00A20000
|
||||
#define EF_MIPS_MACH_GS464E 0x00A30000
|
||||
#define EF_MIPS_MACH_GS264E 0x00A40000
|
||||
|
||||
/* The following are unofficial names and should not be used. */
|
||||
|
||||
@ -1759,6 +1828,7 @@ typedef struct
|
||||
#define SHT_MIPS_EH_REGION 0x70000027
|
||||
#define SHT_MIPS_XLATE_OLD 0x70000028
|
||||
#define SHT_MIPS_PDR_EXCEPTION 0x70000029
|
||||
#define SHT_MIPS_ABIFLAGS 0x7000002a
|
||||
#define SHT_MIPS_XHASH 0x7000002b
|
||||
|
||||
/* Legal values for sh_flags field of Elf32_Shdr. */
|
||||
@ -1927,10 +1997,68 @@ typedef struct
|
||||
#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
|
||||
#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
|
||||
#define R_MIPS_GLOB_DAT 51
|
||||
#define R_MIPS_PC21_S2 60
|
||||
#define R_MIPS_PC26_S2 61
|
||||
#define R_MIPS_PC18_S3 62
|
||||
#define R_MIPS_PC19_S2 63
|
||||
#define R_MIPS_PCHI16 64
|
||||
#define R_MIPS_PCLO16 65
|
||||
#define R_MIPS16_26 100
|
||||
#define R_MIPS16_GPREL 101
|
||||
#define R_MIPS16_GOT16 102
|
||||
#define R_MIPS16_CALL16 103
|
||||
#define R_MIPS16_HI16 104
|
||||
#define R_MIPS16_LO16 105
|
||||
#define R_MIPS16_TLS_GD 106
|
||||
#define R_MIPS16_TLS_LDM 107
|
||||
#define R_MIPS16_TLS_DTPREL_HI16 108
|
||||
#define R_MIPS16_TLS_DTPREL_LO16 109
|
||||
#define R_MIPS16_TLS_GOTTPREL 110
|
||||
#define R_MIPS16_TLS_TPREL_HI16 111
|
||||
#define R_MIPS16_TLS_TPREL_LO16 112
|
||||
#define R_MIPS16_PC16_S1 113
|
||||
#define R_MIPS_COPY 126
|
||||
#define R_MIPS_JUMP_SLOT 127
|
||||
#define R_MIPS_RELATIVE 128
|
||||
#define R_MICROMIPS_26_S1 133
|
||||
#define R_MICROMIPS_HI16 134
|
||||
#define R_MICROMIPS_LO16 135
|
||||
#define R_MICROMIPS_GPREL16 136
|
||||
#define R_MICROMIPS_LITERAL 137
|
||||
#define R_MICROMIPS_GOT16 138
|
||||
#define R_MICROMIPS_PC7_S1 139
|
||||
#define R_MICROMIPS_PC10_S1 140
|
||||
#define R_MICROMIPS_PC16_S1 141
|
||||
#define R_MICROMIPS_CALL16 142
|
||||
#define R_MICROMIPS_GOT_DISP 145
|
||||
#define R_MICROMIPS_GOT_PAGE 146
|
||||
#define R_MICROMIPS_GOT_OFST 147
|
||||
#define R_MICROMIPS_GOT_HI16 148
|
||||
#define R_MICROMIPS_GOT_LO16 149
|
||||
#define R_MICROMIPS_SUB 150
|
||||
#define R_MICROMIPS_HIGHER 151
|
||||
#define R_MICROMIPS_HIGHEST 152
|
||||
#define R_MICROMIPS_CALL_HI16 153
|
||||
#define R_MICROMIPS_CALL_LO16 154
|
||||
#define R_MICROMIPS_SCN_DISP 155
|
||||
#define R_MICROMIPS_JALR 156
|
||||
#define R_MICROMIPS_HI0_LO16 157
|
||||
#define R_MICROMIPS_TLS_GD 162
|
||||
#define R_MICROMIPS_TLS_LDM 163
|
||||
#define R_MICROMIPS_TLS_DTPREL_HI16 164
|
||||
#define R_MICROMIPS_TLS_DTPREL_LO16 165
|
||||
#define R_MICROMIPS_TLS_GOTTPREL 166
|
||||
#define R_MICROMIPS_TLS_TPREL_HI16 169
|
||||
#define R_MICROMIPS_TLS_TPREL_LO16 170
|
||||
#define R_MICROMIPS_GPREL7_S2 172
|
||||
#define R_MICROMIPS_PC23_S2 173
|
||||
#define R_MIPS_PC32 248
|
||||
#define R_MIPS_EH 249
|
||||
#define R_MIPS_GNU_REL16_S2 250
|
||||
#define R_MIPS_GNU_VTINHERIT 253
|
||||
#define R_MIPS_GNU_VTENTRY 254
|
||||
/* Keep this the last entry. */
|
||||
#define R_MIPS_NUM 128
|
||||
#define R_MIPS_NUM 255
|
||||
|
||||
/* Legal values for p_type field of Elf32_Phdr. */
|
||||
|
||||
@ -3523,6 +3651,11 @@ enum
|
||||
/* x86-64 sh_type values. */
|
||||
#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
|
||||
|
||||
/* x86-64 d_tag values. */
|
||||
#define DT_X86_64_PLT (DT_LOPROC + 0)
|
||||
#define DT_X86_64_PLTSZ (DT_LOPROC + 1)
|
||||
#define DT_X86_64_PLTENT (DT_LOPROC + 3)
|
||||
#define DT_X86_64_NUM 4
|
||||
|
||||
/* AM33 relocations. */
|
||||
#define R_MN10300_NONE 0 /* No reloc. */
|
||||
@ -3998,8 +4131,11 @@ enum
|
||||
#define R_RISCV_SET32 56
|
||||
#define R_RISCV_32_PCREL 57
|
||||
#define R_RISCV_IRELATIVE 58
|
||||
#define R_RISCV_PLT32 59
|
||||
#define R_RISCV_SET_ULEB128 60
|
||||
#define R_RISCV_SUB_ULEB128 61
|
||||
|
||||
#define R_RISCV_NUM 59
|
||||
#define R_RISCV_NUM 62
|
||||
|
||||
/* RISC-V specific values for the st_other field. */
|
||||
#define STO_RISCV_VARIANT_CC 0x80 /* Function uses variant calling
|
||||
@ -4093,8 +4229,11 @@ enum
|
||||
#define R_NDS32_TLS_DESC 119
|
||||
|
||||
/* LoongArch ELF Flags */
|
||||
#define EF_LARCH_ABI 0x07
|
||||
#define EF_LARCH_ABI_LP64D 0x03
|
||||
#define EF_LARCH_ABI_MODIFIER_MASK 0x07
|
||||
#define EF_LARCH_ABI_SOFT_FLOAT 0x01
|
||||
#define EF_LARCH_ABI_SINGLE_FLOAT 0x02
|
||||
#define EF_LARCH_ABI_DOUBLE_FLOAT 0x03
|
||||
#define EF_LARCH_OBJABI_V1 0x40
|
||||
|
||||
/* LoongArch specific dynamic relocations */
|
||||
#define R_LARCH_NONE 0
|
||||
@ -4110,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. */
|
||||
|
||||
@ -4156,6 +4297,81 @@ enum
|
||||
#define R_LARCH_GNU_VTINHERIT 57
|
||||
#define R_LARCH_GNU_VTENTRY 58
|
||||
|
||||
/* reserved 59-63 */
|
||||
|
||||
#define R_LARCH_B16 64
|
||||
#define R_LARCH_B21 65
|
||||
#define R_LARCH_B26 66
|
||||
#define R_LARCH_ABS_HI20 67
|
||||
#define R_LARCH_ABS_LO12 68
|
||||
#define R_LARCH_ABS64_LO20 69
|
||||
#define R_LARCH_ABS64_HI12 70
|
||||
#define R_LARCH_PCALA_HI20 71
|
||||
#define R_LARCH_PCALA_LO12 72
|
||||
#define R_LARCH_PCALA64_LO20 73
|
||||
#define R_LARCH_PCALA64_HI12 74
|
||||
#define R_LARCH_GOT_PC_HI20 75
|
||||
#define R_LARCH_GOT_PC_LO12 76
|
||||
#define R_LARCH_GOT64_PC_LO20 77
|
||||
#define R_LARCH_GOT64_PC_HI12 78
|
||||
#define R_LARCH_GOT_HI20 79
|
||||
#define R_LARCH_GOT_LO12 80
|
||||
#define R_LARCH_GOT64_LO20 81
|
||||
#define R_LARCH_GOT64_HI12 82
|
||||
#define R_LARCH_TLS_LE_HI20 83
|
||||
#define R_LARCH_TLS_LE_LO12 84
|
||||
#define R_LARCH_TLS_LE64_LO20 85
|
||||
#define R_LARCH_TLS_LE64_HI12 86
|
||||
#define R_LARCH_TLS_IE_PC_HI20 87
|
||||
#define R_LARCH_TLS_IE_PC_LO12 88
|
||||
#define R_LARCH_TLS_IE64_PC_LO20 89
|
||||
#define R_LARCH_TLS_IE64_PC_HI12 90
|
||||
#define R_LARCH_TLS_IE_HI20 91
|
||||
#define R_LARCH_TLS_IE_LO12 92
|
||||
#define R_LARCH_TLS_IE64_LO20 93
|
||||
#define R_LARCH_TLS_IE64_HI12 94
|
||||
#define R_LARCH_TLS_LD_PC_HI20 95
|
||||
#define R_LARCH_TLS_LD_HI20 96
|
||||
#define R_LARCH_TLS_GD_PC_HI20 97
|
||||
#define R_LARCH_TLS_GD_HI20 98
|
||||
#define R_LARCH_32_PCREL 99
|
||||
#define R_LARCH_RELAX 100
|
||||
#define R_LARCH_DELETE 101
|
||||
#define R_LARCH_ALIGN 102
|
||||
#define R_LARCH_PCREL20_S2 103
|
||||
#define R_LARCH_CFA 104
|
||||
#define R_LARCH_ADD6 105
|
||||
#define R_LARCH_SUB6 106
|
||||
#define R_LARCH_ADD_ULEB128 107
|
||||
#define R_LARCH_SUB_ULEB128 108
|
||||
#define R_LARCH_64_PCREL 109
|
||||
#define R_LARCH_CALL36 110
|
||||
#define R_LARCH_TLS_DESC_PC_HI20 111
|
||||
#define R_LARCH_TLS_DESC_PC_LO12 112
|
||||
#define R_LARCH_TLS_DESC64_PC_LO20 113
|
||||
#define R_LARCH_TLS_DESC64_PC_HI12 114
|
||||
#define R_LARCH_TLS_DESC_HI20 115
|
||||
#define R_LARCH_TLS_DESC_LO12 116
|
||||
#define R_LARCH_TLS_DESC64_LO20 117
|
||||
#define R_LARCH_TLS_DESC64_HI12 118
|
||||
#define R_LARCH_TLS_DESC_LD 119
|
||||
#define R_LARCH_TLS_DESC_CALL 120
|
||||
#define R_LARCH_TLS_LE_HI20_R 121
|
||||
#define R_LARCH_TLS_LE_ADD_R 122
|
||||
#define R_LARCH_TLS_LE_LO12_R 123
|
||||
#define R_LARCH_TLS_LD_PCREL20_S2 124
|
||||
#define R_LARCH_TLS_GD_PCREL20_S2 125
|
||||
#define R_LARCH_TLS_DESC_PCREL20_S2 126
|
||||
|
||||
/* ARC specific declarations. */
|
||||
|
||||
/* Processor specific flags for the Ehdr e_flags field. */
|
||||
#define EF_ARC_MACH_MSK 0x000000ff
|
||||
#define EF_ARC_OSABI_MSK 0x00000f00
|
||||
#define EF_ARC_ALL_MSK (EF_ARC_MACH_MSK | EF_ARC_OSABI_MSK)
|
||||
|
||||
/* Processor specific values for the Shdr sh_type field. */
|
||||
#define SHT_ARC_ATTRIBUTES (SHT_LOPROC + 1) /* ARC attributes section. */
|
||||
|
||||
/* ARCompact/ARCv2 specific relocs. */
|
||||
#define R_ARC_NONE 0x0
|
||||
@ -4163,7 +4379,7 @@ enum
|
||||
#define R_ARC_16 0x2
|
||||
#define R_ARC_24 0x3
|
||||
#define R_ARC_32 0x4
|
||||
#define R_ARC_B26 0x5
|
||||
|
||||
#define R_ARC_B22_PCREL 0x6
|
||||
#define R_ARC_H30 0x7
|
||||
#define R_ARC_N8 0x8
|
||||
@ -4203,16 +4419,23 @@ enum
|
||||
#define R_ARC_SECTOFF_ME_2 0x2A
|
||||
#define R_ARC_SECTOFF_1 0x2B
|
||||
#define R_ARC_SECTOFF_2 0x2C
|
||||
#define R_ARC_SDA_12 0x2D
|
||||
#define R_ARC_SDA16_ST2 0x30
|
||||
#define R_ARC_32_PCREL 0x31
|
||||
#define R_ARC_PC32 0x32
|
||||
#define R_ARC_GOTPC32 0x33
|
||||
#define R_ARC_PLT32 0x34
|
||||
#define R_ARC_COPY 0x35
|
||||
#define R_ARC_GLOB_DAT 0x36
|
||||
#define R_ARC_JUMP_SLOT 0x37
|
||||
#define R_ARC_JMP_SLOT 0x37
|
||||
#define R_ARC_RELATIVE 0x38
|
||||
#define R_ARC_GOTOFF 0x39
|
||||
#define R_ARC_GOTPC 0x3A
|
||||
#define R_ARC_GOT32 0x3B
|
||||
#define R_ARC_S21W_PCREL_PLT 0x3C
|
||||
#define R_ARC_S25H_PCREL_PLT 0x3D
|
||||
|
||||
#define R_ARC_JLI_SECTOFF 0x3F
|
||||
|
||||
#define R_ARC_TLS_DTPMOD 0x42
|
||||
#define R_ARC_TLS_DTPOFF 0x43
|
||||
@ -4221,9 +4444,12 @@ enum
|
||||
#define R_ARC_TLS_GD_LD 0x46
|
||||
#define R_ARC_TLS_GD_CALL 0x47
|
||||
#define R_ARC_TLS_IE_GOT 0x48
|
||||
#define R_ARC_TLS_DTPOFF_S9 0x4a
|
||||
#define R_ARC_TLS_LE_S9 0x4a
|
||||
#define R_ARC_TLS_LE_32 0x4b
|
||||
#define R_ARC_TLS_DTPOFF_S9 0x49
|
||||
#define R_ARC_TLS_LE_S9 0x4A
|
||||
#define R_ARC_TLS_LE_32 0x4B
|
||||
#define R_ARC_S25W_PCREL_PLT 0x4C
|
||||
#define R_ARC_S21H_PCREL_PLT 0x4D
|
||||
#define R_ARC_NPS_CMEM16 0x4E
|
||||
|
||||
/* OpenRISC 1000 specific relocs. */
|
||||
#define R_OR1K_NONE 0
|
||||
|
||||
@ -38,46 +38,8 @@
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
#define ELF_WRLOCK_HELD 1
|
||||
#include "elf32_getchdr.h"
|
||||
|
||||
ElfW2(LIBELFBITS,Chdr) *
|
||||
elfw2(LIBELFBITS,getchdr) (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = elfw2(LIBELFBITS,getshdr) (scn);
|
||||
if (shdr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Must have SHF_COMPRESSED flag set. Allocated or no bits sections
|
||||
can never be compressed. */
|
||||
if ((shdr->sh_flags & SHF_ALLOC) != 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (shdr->sh_type == SHT_NULL
|
||||
|| shdr->sh_type == SHT_NOBITS)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOT_COMPRESSED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This makes sure the data is in the correct format, so we don't
|
||||
need to swap fields. */
|
||||
Elf_Data *d = elf_getdata (scn, NULL);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf;
|
||||
}
|
||||
#define ELF_WRLOCK_HELD 0
|
||||
#include "elf32_getchdr.h"
|
||||
61
src/elf32_getchdr.h
Normal file
61
src/elf32_getchdr.h
Normal file
@ -0,0 +1,61 @@
|
||||
#undef ADD_ROUTINE_PREFIX
|
||||
#undef ADD_ROUTINE_SUFFIX
|
||||
|
||||
#if ELF_WRLOCK_HELD
|
||||
#define CONCAT(x,y) x##y
|
||||
#define ADD_ROUTINE_PREFIX(y) CONCAT(__,y)
|
||||
#define ADD_ROUTINE_SUFFIX(x) x ## _wrlock
|
||||
#define INTERNAL internal_function
|
||||
#else
|
||||
#define ADD_ROUTINE_PREFIX(y) y
|
||||
#define ADD_ROUTINE_SUFFIX(x) x
|
||||
#define INTERNAL
|
||||
#endif
|
||||
|
||||
ElfW2(LIBELFBITS,Chdr) *
|
||||
INTERNAL
|
||||
ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getchdr))) (Elf_Scn *scn)
|
||||
{
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getshdr)))(scn);
|
||||
|
||||
if (shdr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Must have SHF_COMPRESSED flag set. Allocated or no bits sections
|
||||
can never be compressed. */
|
||||
if ((shdr->sh_flags & SHF_ALLOC) != 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (shdr->sh_type == SHT_NULL
|
||||
|| shdr->sh_type == SHT_NOBITS)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOT_COMPRESSED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This makes sure the data is in the correct format, so we don't
|
||||
need to swap fields. */
|
||||
Elf_Data *d = ADD_ROUTINE_PREFIX(ADD_ROUTINE_SUFFIX(elf_getdata)) (scn, NULL);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf;
|
||||
}
|
||||
#undef INTERNAL
|
||||
#undef ELF_WRLOCK_HELD
|
||||
@ -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. */
|
||||
@ -256,6 +257,9 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
|
||||
case SHT_SUNW_syminfo:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
|
||||
break;
|
||||
case SHT_RELR:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELR, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -404,7 +408,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
|
||||
else
|
||||
{
|
||||
ElfW2(LIBELFBITS,Chdr) *chdr;
|
||||
chdr = elfw2(LIBELFBITS,getchdr) (scn);
|
||||
chdr = __elfw2(LIBELFBITS,getchdr_wrlock) (scn);
|
||||
if (unlikely (chdr == NULL))
|
||||
return -1;
|
||||
sh_size = chdr->ch_size;
|
||||
|
||||
@ -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
|
||||
|
||||
132
src/elf_begin.c
132
src/elf_begin.c
@ -38,6 +38,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -61,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;
|
||||
@ -341,15 +342,15 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
{
|
||||
/* This pointer might not be directly usable if the alignment is
|
||||
not sufficient for the architecture. */
|
||||
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
|
||||
uintptr_t ehdr = (uintptr_t) map_address + offset;
|
||||
|
||||
/* This is a 32-bit binary. */
|
||||
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
|
||||
|| (ehdr & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
|
||||
{
|
||||
/* We can use the mmapped memory. */
|
||||
elf->state.elf32.ehdr = ehdr;
|
||||
elf->state.elf32.ehdr = (Elf32_Ehdr *) ehdr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -382,8 +383,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& cmd != ELF_C_READ_MMAP /* We need a copy to be able to write. */
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| ((((uintptr_t) ehdr + e_shoff)
|
||||
& (__alignof__ (Elf32_Shdr) - 1)) == 0)))
|
||||
|| (((ehdr + e_shoff) & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
|
||||
{
|
||||
if (unlikely (scncnt > 0 && e_shoff >= maxsize)
|
||||
|| unlikely (maxsize - e_shoff
|
||||
@ -396,8 +396,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
}
|
||||
|
||||
if (scncnt > 0)
|
||||
elf->state.elf32.shdr
|
||||
= (Elf32_Shdr *) ((char *) ehdr + e_shoff);
|
||||
elf->state.elf32.shdr = (Elf32_Shdr *) (ehdr + e_shoff);
|
||||
|
||||
for (size_t cnt = 0; cnt < scncnt; ++cnt)
|
||||
{
|
||||
@ -413,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
|
||||
@ -440,20 +426,21 @@ 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
|
||||
{
|
||||
/* This pointer might not be directly usable if the alignment is
|
||||
not sufficient for the architecture. */
|
||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
|
||||
uintptr_t ehdr = (uintptr_t) map_address + offset;
|
||||
|
||||
/* This is a 64-bit binary. */
|
||||
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
|
||||
|| (ehdr & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
|
||||
{
|
||||
/* We can use the mmapped memory. */
|
||||
elf->state.elf64.ehdr = ehdr;
|
||||
elf->state.elf64.ehdr = (Elf64_Ehdr *) ehdr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -486,8 +473,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& cmd != ELF_C_READ_MMAP /* We need a copy to be able to write. */
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| ((((uintptr_t) ehdr + e_shoff)
|
||||
& (__alignof__ (Elf64_Shdr) - 1)) == 0)))
|
||||
|| (((ehdr + e_shoff) & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
|
||||
{
|
||||
if (unlikely (scncnt > 0 && e_shoff >= maxsize)
|
||||
|| unlikely (maxsize - e_shoff
|
||||
@ -495,8 +481,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
goto free_and_out;
|
||||
|
||||
if (scncnt > 0)
|
||||
elf->state.elf64.shdr
|
||||
= (Elf64_Shdr *) ((char *) ehdr + e_shoff);
|
||||
elf->state.elf64.shdr = (Elf64_Shdr *) (ehdr + (ptrdiff_t) e_shoff);
|
||||
|
||||
for (size_t cnt = 0; cnt < scncnt; ++cnt)
|
||||
{
|
||||
@ -512,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
|
||||
@ -539,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;
|
||||
@ -842,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
|
||||
@ -889,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. */
|
||||
@ -1082,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;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Compress or decompress a section.
|
||||
Copyright (C) 2015, 2016 Red Hat, Inc.
|
||||
Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
@ -39,6 +40,10 @@
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef USE_ZSTD
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
|
||||
/* Cleanup and return result. Don't leak memory. */
|
||||
static void *
|
||||
do_deflate_cleanup (void *result, z_stream *z, void *out_buf,
|
||||
@ -54,53 +59,14 @@ do_deflate_cleanup (void *result, z_stream *z, void *out_buf,
|
||||
#define deflate_cleanup(result, cdata) \
|
||||
do_deflate_cleanup(result, &z, out_buf, cdata)
|
||||
|
||||
/* Given a section, uses the (in-memory) Elf_Data to extract the
|
||||
original data size (including the given header size) and data
|
||||
alignment. Returns a buffer that has at least hsize bytes (for the
|
||||
caller to fill in with a header) plus zlib compressed date. Also
|
||||
returns the new buffer size in new_size (hsize + compressed data
|
||||
size). Returns (void *) -1 when FORCE is false and the compressed
|
||||
data would be bigger than the original data. */
|
||||
static
|
||||
void *
|
||||
internal_function
|
||||
__libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
size_t *orig_size, size_t *orig_addralign,
|
||||
size_t *new_size, bool force)
|
||||
__libelf_compress_zlib (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
size_t *orig_size, size_t *orig_addralign,
|
||||
size_t *new_size, bool force,
|
||||
Elf_Data *data, Elf_Data *next_data,
|
||||
void *out_buf, size_t out_size, size_t block)
|
||||
{
|
||||
/* The compressed data is the on-disk data. We simplify the
|
||||
implementation a bit by asking for the (converted) in-memory
|
||||
data (which might be all there is if the user created it with
|
||||
elf_newdata) and then convert back to raw if needed before
|
||||
compressing. Should be made a bit more clever to directly
|
||||
use raw if that is directly available. */
|
||||
Elf_Data *data = elf_getdata (scn, NULL);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
/* When not forced and we immediately know we would use more data by
|
||||
compressing, because of the header plus zlib overhead (five bytes
|
||||
per 16 KB block, plus a one-time overhead of six bytes for the
|
||||
entire stream), don't do anything. */
|
||||
Elf_Data *next_data = elf_getdata (scn, data);
|
||||
if (next_data == NULL && !force
|
||||
&& data->d_size <= hsize + 5 + 6)
|
||||
return (void *) -1;
|
||||
|
||||
*orig_addralign = data->d_align;
|
||||
*orig_size = data->d_size;
|
||||
|
||||
/* Guess an output block size. 1/8th of the original Elf_Data plus
|
||||
hsize. Make the first chunk twice that size (25%), then increase
|
||||
by a block (12.5%) when necessary. */
|
||||
size_t block = (data->d_size / 8) + hsize;
|
||||
size_t out_size = 2 * block;
|
||||
void *out_buf = malloc (out_size);
|
||||
if (out_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Caller gets to fill in the header at the start. Just skip it here. */
|
||||
size_t used = hsize;
|
||||
|
||||
@ -205,9 +171,189 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
#ifdef USE_ZSTD_COMPRESS
|
||||
/* Cleanup and return result. Don't leak memory. */
|
||||
static void *
|
||||
do_zstd_cleanup (void *result, ZSTD_CCtx * const cctx, void *out_buf,
|
||||
Elf_Data *cdatap)
|
||||
{
|
||||
ZSTD_freeCCtx (cctx);
|
||||
free (out_buf);
|
||||
if (cdatap != NULL)
|
||||
free (cdatap->d_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define zstd_cleanup(result, cdata) \
|
||||
do_zstd_cleanup(result, cctx, out_buf, cdata)
|
||||
|
||||
static
|
||||
void *
|
||||
__libelf_compress_zstd (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
size_t *orig_size, size_t *orig_addralign,
|
||||
size_t *new_size, bool force,
|
||||
Elf_Data *data, Elf_Data *next_data,
|
||||
void *out_buf, size_t out_size, size_t block)
|
||||
{
|
||||
/* Caller gets to fill in the header at the start. Just skip it here. */
|
||||
size_t used = hsize;
|
||||
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
Elf_Data cdata;
|
||||
cdata.d_buf = NULL;
|
||||
|
||||
/* Loop over data buffers. */
|
||||
ZSTD_EndDirective mode = ZSTD_e_continue;
|
||||
|
||||
do
|
||||
{
|
||||
/* Convert to raw if different endianness. */
|
||||
cdata = *data;
|
||||
bool convert = ei_data != MY_ELFDATA && data->d_size > 0;
|
||||
if (convert)
|
||||
{
|
||||
/* Don't do this conversion in place, we might want to keep
|
||||
the original data around, caller decides. */
|
||||
cdata.d_buf = malloc (data->d_size);
|
||||
if (cdata.d_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return zstd_cleanup (NULL, NULL);
|
||||
}
|
||||
if (gelf_xlatetof (scn->elf, &cdata, data, ei_data) == NULL)
|
||||
return zstd_cleanup (NULL, &cdata);
|
||||
}
|
||||
|
||||
ZSTD_inBuffer ib = { cdata.d_buf, cdata.d_size, 0 };
|
||||
|
||||
/* Get next buffer to see if this is the last one. */
|
||||
data = next_data;
|
||||
if (data != NULL)
|
||||
{
|
||||
*orig_addralign = MAX (*orig_addralign, data->d_align);
|
||||
*orig_size += data->d_size;
|
||||
next_data = elf_getdata (scn, data);
|
||||
}
|
||||
else
|
||||
mode = ZSTD_e_end;
|
||||
|
||||
/* Flush one data buffer. */
|
||||
for (;;)
|
||||
{
|
||||
ZSTD_outBuffer ob = { out_buf + used, out_size - used, 0 };
|
||||
size_t ret = ZSTD_compressStream2 (cctx, &ob, &ib, mode);
|
||||
if (ZSTD_isError (ret))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
|
||||
return zstd_cleanup (NULL, convert ? &cdata : NULL);
|
||||
}
|
||||
used += ob.pos;
|
||||
|
||||
/* Bail out if we are sure the user doesn't want the
|
||||
compression forced and we are using more compressed data
|
||||
than original data. */
|
||||
if (!force && mode == ZSTD_e_end && used >= *orig_size)
|
||||
return zstd_cleanup ((void *) -1, convert ? &cdata : NULL);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
void *bigger = realloc (out_buf, out_size + block);
|
||||
if (bigger == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return zstd_cleanup (NULL, convert ? &cdata : NULL);
|
||||
}
|
||||
out_buf = bigger;
|
||||
out_size += block;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (convert)
|
||||
{
|
||||
free (cdata.d_buf);
|
||||
cdata.d_buf = NULL;
|
||||
}
|
||||
}
|
||||
while (mode != ZSTD_e_end); /* More data blocks. */
|
||||
|
||||
ZSTD_freeCCtx (cctx);
|
||||
*new_size = used;
|
||||
return out_buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Given a section, uses the (in-memory) Elf_Data to extract the
|
||||
original data size (including the given header size) and data
|
||||
alignment. Returns a buffer that has at least hsize bytes (for the
|
||||
caller to fill in with a header) plus zlib compressed date. Also
|
||||
returns the new buffer size in new_size (hsize + compressed data
|
||||
size). Returns (void *) -1 when FORCE is false and the compressed
|
||||
data would be bigger than the original data. */
|
||||
void *
|
||||
internal_function
|
||||
__libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
|
||||
__libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
size_t *orig_size, size_t *orig_addralign,
|
||||
size_t *new_size, bool force, bool use_zstd)
|
||||
{
|
||||
/* The compressed data is the on-disk data. We simplify the
|
||||
implementation a bit by asking for the (converted) in-memory
|
||||
data (which might be all there is if the user created it with
|
||||
elf_newdata) and then convert back to raw if needed before
|
||||
compressing. Should be made a bit more clever to directly
|
||||
use raw if that is directly available. */
|
||||
Elf_Data *data = elf_getdata (scn, NULL);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
/* When not forced and we immediately know we would use more data by
|
||||
compressing, because of the header plus zlib overhead (five bytes
|
||||
per 16 KB block, plus a one-time overhead of six bytes for the
|
||||
entire stream), don't do anything.
|
||||
Size estimation for ZSTD compression would be similar. */
|
||||
Elf_Data *next_data = elf_getdata (scn, data);
|
||||
if (next_data == NULL && !force
|
||||
&& data->d_size <= hsize + 5 + 6)
|
||||
return (void *) -1;
|
||||
|
||||
*orig_addralign = data->d_align;
|
||||
*orig_size = data->d_size;
|
||||
|
||||
/* Guess an output block size. 1/8th of the original Elf_Data plus
|
||||
hsize. Make the first chunk twice that size (25%), then increase
|
||||
by a block (12.5%) when necessary. */
|
||||
size_t block = (data->d_size / 8) + hsize;
|
||||
size_t out_size = 2 * block;
|
||||
void *out_buf = malloc (out_size);
|
||||
if (out_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (use_zstd)
|
||||
{
|
||||
#ifdef USE_ZSTD_COMPRESS
|
||||
return __libelf_compress_zstd (scn, hsize, ei_data, orig_size,
|
||||
orig_addralign, new_size, force,
|
||||
data, next_data, out_buf, out_size,
|
||||
block);
|
||||
#else
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return __libelf_compress_zlib (scn, hsize, ei_data, orig_size,
|
||||
orig_addralign, new_size, force,
|
||||
data, next_data, out_buf, out_size,
|
||||
block);
|
||||
}
|
||||
|
||||
void *
|
||||
internal_function
|
||||
__libelf_decompress_zlib (void *buf_in, size_t size_in, size_t size_out)
|
||||
{
|
||||
/* Catch highly unlikely compression ratios so we don't allocate
|
||||
some giant amount of memory for nothing. The max compression
|
||||
@ -218,7 +364,7 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Malloc might return NULL when requestion zero size. This is highly
|
||||
/* Malloc might return NULL when requesting zero size. This is highly
|
||||
unlikely, it would only happen when the compression was forced.
|
||||
But we do need a non-NULL buffer to return and set as result.
|
||||
Just make sure to always allocate at least 1 byte. */
|
||||
@ -260,6 +406,50 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
|
||||
return buf_out;
|
||||
}
|
||||
|
||||
#ifdef USE_ZSTD
|
||||
static void *
|
||||
__libelf_decompress_zstd (void *buf_in, size_t size_in, size_t size_out)
|
||||
{
|
||||
/* Malloc might return NULL when requesting zero size. This is highly
|
||||
unlikely, it would only happen when the compression was forced.
|
||||
But we do need a non-NULL buffer to return and set as result.
|
||||
Just make sure to always allocate at least 1 byte. */
|
||||
void *buf_out = malloc (size_out ?: 1);
|
||||
if (unlikely (buf_out == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t ret = ZSTD_decompress (buf_out, size_out, buf_in, size_in);
|
||||
if (unlikely (ZSTD_isError (ret)) || unlikely (ret != size_out))
|
||||
{
|
||||
free (buf_out);
|
||||
__libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return buf_out;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *
|
||||
internal_function
|
||||
__libelf_decompress (int chtype, void *buf_in, size_t size_in, size_t size_out)
|
||||
{
|
||||
if (chtype == ELFCOMPRESS_ZLIB)
|
||||
return __libelf_decompress_zlib (buf_in, size_in, size_out);
|
||||
else
|
||||
{
|
||||
#ifdef USE_ZSTD
|
||||
return __libelf_decompress_zstd (buf_in, size_in, size_out);
|
||||
#else
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
internal_function
|
||||
__libelf_decompress_elf (Elf_Scn *scn, size_t *size_out, size_t *addralign)
|
||||
@ -268,7 +458,19 @@ __libelf_decompress_elf (Elf_Scn *scn, size_t *size_out, size_t *addralign)
|
||||
if (gelf_getchdr (scn, &chdr) == NULL)
|
||||
return NULL;
|
||||
|
||||
bool unknown_compression = false;
|
||||
if (chdr.ch_type != ELFCOMPRESS_ZLIB)
|
||||
{
|
||||
if (chdr.ch_type != ELFCOMPRESS_ZSTD)
|
||||
unknown_compression = true;
|
||||
|
||||
#ifndef USE_ZSTD
|
||||
if (chdr.ch_type == ELFCOMPRESS_ZSTD)
|
||||
unknown_compression = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (unknown_compression)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
|
||||
return NULL;
|
||||
@ -295,7 +497,9 @@ __libelf_decompress_elf (Elf_Scn *scn, size_t *size_out, size_t *addralign)
|
||||
? sizeof (Elf32_Chdr) : sizeof (Elf64_Chdr));
|
||||
size_t size_in = data->d_size - hsize;
|
||||
void *buf_in = data->d_buf + hsize;
|
||||
void *buf_out = __libelf_decompress (buf_in, size_in, chdr.ch_size);
|
||||
void *buf_out
|
||||
= __libelf_decompress (chdr.ch_type, buf_in, size_in, chdr.ch_size);
|
||||
|
||||
*size_out = chdr.ch_size;
|
||||
*addralign = chdr.ch_addralign;
|
||||
return buf_out;
|
||||
@ -315,15 +519,35 @@ __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);
|
||||
scn->data_base = NULL;
|
||||
if (scn->zdata_base != buf
|
||||
&& scn->zdata_base != scn->rawdata_base)
|
||||
{
|
||||
free (scn->zdata_base);
|
||||
scn->zdata_base = NULL;
|
||||
}
|
||||
if (scn->elf->map_address == NULL
|
||||
|| scn->rawdata_base == scn->zdata_base
|
||||
|| (scn->flags & ELF_F_MALLOCED) != 0)
|
||||
free (scn->rawdata_base);
|
||||
{
|
||||
free (scn->rawdata_base);
|
||||
scn->rawdata_base = NULL;
|
||||
scn->zdata_base = NULL;
|
||||
}
|
||||
|
||||
scn->rawdata_base = buf;
|
||||
scn->flags |= ELF_F_MALLOCED;
|
||||
@ -360,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)
|
||||
@ -394,7 +623,7 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
|
||||
}
|
||||
|
||||
int compressed = (sh_flags & SHF_COMPRESSED);
|
||||
if (type == ELFCOMPRESS_ZLIB)
|
||||
if (type == ELFCOMPRESS_ZLIB || type == ELFCOMPRESS_ZSTD)
|
||||
{
|
||||
/* Compress/Deflate. */
|
||||
if (compressed == 1)
|
||||
@ -408,7 +637,8 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
|
||||
size_t orig_size, orig_addralign, new_size;
|
||||
void *out_buf = __libelf_compress (scn, hsize, elfdata,
|
||||
&orig_size, &orig_addralign,
|
||||
&new_size, force);
|
||||
&new_size, force,
|
||||
type == ELFCOMPRESS_ZSTD);
|
||||
|
||||
/* Compression would make section larger, don't change anything. */
|
||||
if (out_buf == (void *) -1)
|
||||
@ -422,7 +652,7 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
|
||||
if (elfclass == ELFCLASS32)
|
||||
{
|
||||
Elf32_Chdr chdr;
|
||||
chdr.ch_type = ELFCOMPRESS_ZLIB;
|
||||
chdr.ch_type = type;
|
||||
chdr.ch_size = orig_size;
|
||||
chdr.ch_addralign = orig_addralign;
|
||||
if (elfdata != MY_ELFDATA)
|
||||
@ -436,7 +666,7 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
|
||||
else
|
||||
{
|
||||
Elf64_Chdr chdr;
|
||||
chdr.ch_type = ELFCOMPRESS_ZLIB;
|
||||
chdr.ch_type = type;
|
||||
chdr.ch_reserved = 0;
|
||||
chdr.ch_size = orig_size;
|
||||
chdr.ch_addralign = sh_addralign;
|
||||
@ -454,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);
|
||||
@ -473,6 +703,7 @@ elf_compress (Elf_Scn *scn, int type, unsigned int flags)
|
||||
data around, but since that might have been multiple Elf_Data
|
||||
buffers let the user uncompress it explicitly again if they
|
||||
want it to simplify bookkeeping. */
|
||||
free (scn->zdata_base);
|
||||
scn->zdata_base = NULL;
|
||||
|
||||
return 1;
|
||||
@ -505,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
|
||||
@ -103,7 +108,8 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
|
||||
size_t orig_size, new_size, orig_addralign;
|
||||
void *out_buf = __libelf_compress (scn, hsize, elfdata,
|
||||
&orig_size, &orig_addralign,
|
||||
&new_size, force);
|
||||
&new_size, force,
|
||||
/* use_zstd */ false);
|
||||
|
||||
/* Compression would make section larger, don't change anything. */
|
||||
if (out_buf == (void *) -1)
|
||||
@ -121,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);
|
||||
|
||||
@ -178,7 +178,7 @@ elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
|
||||
size_t size = gsize;
|
||||
size_t size_in = data->d_size - hsize;
|
||||
void *buf_in = data->d_buf + hsize;
|
||||
void *buf_out = __libelf_decompress (buf_in, size_in, size);
|
||||
void *buf_out = __libelf_decompress (ELFCOMPRESS_ZLIB, buf_in, size_in, size);
|
||||
if (buf_out == NULL)
|
||||
return -1;
|
||||
|
||||
@ -186,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,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Free resources associated with Elf descriptor.
|
||||
Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc.
|
||||
Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -32,12 +33,22 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <search.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
|
||||
static void
|
||||
free_chunk (void *n)
|
||||
{
|
||||
Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n;
|
||||
if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED)
|
||||
free (rawchunk->data.d.d_buf);
|
||||
free (rawchunk);
|
||||
}
|
||||
|
||||
int
|
||||
elf_end (Elf *elf)
|
||||
{
|
||||
@ -71,7 +82,10 @@ elf_end (Elf *elf)
|
||||
elf->state.ar.ar_sym = NULL;
|
||||
|
||||
if (elf->state.ar.children != NULL)
|
||||
return 0;
|
||||
{
|
||||
rwlock_unlock(elf->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this structure from the children list. */
|
||||
@ -102,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)
|
||||
{
|
||||
@ -112,20 +132,14 @@ elf_end (Elf *elf)
|
||||
|
||||
case ELF_K_ELF:
|
||||
{
|
||||
Elf_Data_Chunk *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);
|
||||
while (rawchunks != NULL)
|
||||
{
|
||||
Elf_Data_Chunk *next = rawchunks->next;
|
||||
if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
|
||||
free (rawchunks->data.d.d_buf);
|
||||
free (rawchunks);
|
||||
rawchunks = next;
|
||||
}
|
||||
|| (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)
|
||||
@ -153,7 +167,10 @@ elf_end (Elf *elf)
|
||||
rawdata_base. If it is already used it will be
|
||||
freed below. */
|
||||
if (scn->zdata_base != scn->rawdata_base)
|
||||
free (scn->zdata_base);
|
||||
{
|
||||
free (scn->zdata_base);
|
||||
scn->zdata_base = NULL;
|
||||
}
|
||||
|
||||
/* If the file has the same byte order and the
|
||||
architecture doesn't require overly stringent
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -582,4 +582,18 @@ elf_getdata (Elf_Scn *scn, Elf_Data *data)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Elf_Data *
|
||||
internal_function
|
||||
__elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data)
|
||||
{
|
||||
Elf_Data *result;
|
||||
|
||||
if (scn == NULL)
|
||||
return NULL;
|
||||
|
||||
result = __elf_getdata_rdlock (scn, data);
|
||||
|
||||
return result;
|
||||
}
|
||||
INTDEF(elf_getdata)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* Return converted data from raw chunk of ELF file.
|
||||
Copyright (C) 2007, 2014, 2015 Red Hat, Inc.
|
||||
Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
Copyright (C) 2022, 2023 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
@ -33,11 +33,26 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.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)
|
||||
{
|
||||
Elf_Data_Chunk *da = (Elf_Data_Chunk *)a;
|
||||
Elf_Data_Chunk *db = (Elf_Data_Chunk *)b;
|
||||
|
||||
if (da->offset != db->offset)
|
||||
return da->offset - db->offset;
|
||||
|
||||
if (da->data.d.d_size != db->data.d.d_size)
|
||||
return da->data.d.d_size - db->data.d.d_size;
|
||||
|
||||
return da->data.d.d_type - db->data.d.d_type;
|
||||
}
|
||||
|
||||
Elf_Data *
|
||||
elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
@ -72,22 +87,31 @@ 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 *rawchunks = elf->state.elf.rawchunks;
|
||||
while (rawchunks != NULL)
|
||||
Elf_Data_Chunk key;
|
||||
key.offset = offset;
|
||||
key.data.d.d_size = size;
|
||||
key.data.d.d_type = type;
|
||||
Elf_Data_Chunk **found
|
||||
= eu_tsearch_nolock (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
|
||||
|
||||
if (found == NULL)
|
||||
goto nomem;
|
||||
|
||||
/* Existing entry. */
|
||||
if (*found != &key && *found != NULL)
|
||||
{
|
||||
if ((rawchunks->offset == offset || size == 0)
|
||||
&& rawchunks->data.d.d_size == size
|
||||
&& rawchunks->data.d.d_type == type)
|
||||
{
|
||||
result = &rawchunks->data.d;
|
||||
goto out;
|
||||
}
|
||||
rawchunks = rawchunks->next;
|
||||
result = &(*found)->data.d;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* New entry. Note that *found will point to the newly inserted
|
||||
(dummy) key. We'll replace it with a real rawchunk when that is
|
||||
setup. Make sure to tdelete the dummy key if anything goes
|
||||
wrong. */
|
||||
|
||||
size_t align = __libelf_type_align (elf->class, type);
|
||||
if (elf->map_address != NULL)
|
||||
{
|
||||
@ -112,6 +136,8 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
if (rawchunk == NULL)
|
||||
{
|
||||
nomem:
|
||||
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
|
||||
&chunk_compare);
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
@ -122,6 +148,8 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
!= size))
|
||||
{
|
||||
/* Something went wrong. */
|
||||
eu_tdelete_nolock (&key, &elf->state.elf.rawchunk_tree,
|
||||
&chunk_compare);
|
||||
free (rawchunk);
|
||||
__libelf_seterrno (ELF_E_READ_ERROR);
|
||||
goto out;
|
||||
@ -149,6 +177,8 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
|
||||
/* The copy will be appropriately aligned for direct access. */
|
||||
memcpy (buffer, rawchunk, size);
|
||||
|
||||
free (rawchunk);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -165,6 +195,9 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
|
||||
/* Call the conversion function. */
|
||||
(*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0);
|
||||
|
||||
if (!flags)
|
||||
free (rawchunk);
|
||||
}
|
||||
|
||||
/* Allocate the dummy container to point at this buffer. */
|
||||
@ -186,11 +219,7 @@ 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);
|
||||
|
||||
chunk->next = elf->state.elf.rawchunks;
|
||||
elf->state.elf.rawchunks = chunk;
|
||||
*found = chunk;
|
||||
result = &chunk->data.d;
|
||||
|
||||
out:
|
||||
|
||||
@ -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, NULL);
|
||||
return __libelf_read_mmaped_file (-1, image, 0, size,
|
||||
ELF_C_READ_MMAP_PRIVATE, NULL);
|
||||
}
|
||||
|
||||
@ -94,9 +94,9 @@ elf_newscn (Elf *elf)
|
||||
1
|
||||
#endif
|
||||
)
|
||||
newp = calloc (sizeof (Elf_ScnList)
|
||||
+ ((elf->state.elf.scnincr *= 2)
|
||||
* sizeof (Elf_Scn)), 1);
|
||||
newp = calloc (1, sizeof (Elf_ScnList)
|
||||
+ ((elf->state.elf.scnincr *= 2)
|
||||
* sizeof (Elf_Scn)));
|
||||
if (newp == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -32,12 +32,21 @@
|
||||
#endif
|
||||
|
||||
#include <libelfP.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* Multiple threads may initialize __libelf_version.
|
||||
pthread_once() ensures that __libelf_version is initialized only once. */
|
||||
once_define(static, version_once);
|
||||
|
||||
/* Currently selected version. Should be EV_CURRENT.
|
||||
Will be EV_NONE if elf_version () has not been called yet. */
|
||||
unsigned int __libelf_version = EV_NONE;
|
||||
|
||||
static void initialize_version(void)
|
||||
{
|
||||
__libelf_version = EV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
elf_version (unsigned int version)
|
||||
{
|
||||
@ -49,7 +58,7 @@ elf_version (unsigned int version)
|
||||
/* Phew, we know this version. */
|
||||
|
||||
/* Signal that the version is now initialized. */
|
||||
__libelf_version = EV_CURRENT;
|
||||
once(version_once, initialize_version);
|
||||
|
||||
/* And return the last (or initial) version. */
|
||||
return EV_CURRENT;
|
||||
|
||||
@ -29,28 +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 RWLOCK_CALL(call) \
|
||||
({ int _err = pthread_rwlock_ ## 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))
|
||||
#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))
|
||||
#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
|
||||
@ -69,7 +69,8 @@ const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||||
[ELF_T_LIB] = sizeof (ElfW2(LIBELFBITS, Ext_Lib)), \
|
||||
[ELF_T_AUXV] = sizeof (ElfW2(LIBELFBITS, Ext_auxv_t)), \
|
||||
[ELF_T_CHDR] = sizeof (ElfW2(LIBELFBITS, Ext_Chdr)), \
|
||||
[ELF_T_GNUHASH] = ELFW2(LIBELFBITS, FSZ_WORD)
|
||||
[ELF_T_GNUHASH] = ELFW2(LIBELFBITS, FSZ_WORD), \
|
||||
[ELF_T_RELR] = ELFW2(LIBELFBITS, FSZ_RELR)
|
||||
TYPE_SIZES (32)
|
||||
},
|
||||
[ELFCLASS64 - 1] = {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -204,7 +204,8 @@ const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||||
[ELF_T_MOVE] = ElfW2(Bits, cvt_Move), \
|
||||
[ELF_T_LIB] = ElfW2(Bits, cvt_Lib), \
|
||||
[ELF_T_AUXV] = ElfW2(Bits, cvt_auxv_t), \
|
||||
[ELF_T_CHDR] = ElfW2(Bits, cvt_chdr)
|
||||
[ELF_T_CHDR] = ElfW2(Bits, cvt_chdr), \
|
||||
[ELF_T_RELR] = ElfW2(Bits, cvt_Relr)
|
||||
define_xfcts (32),
|
||||
[ELF_T_GNUHASH] = Elf32_cvt_Word
|
||||
},
|
||||
|
||||
@ -36,6 +36,7 @@ FUNDAMENTAL (WORD, Word, LIBELFBITS);
|
||||
FUNDAMENTAL (SWORD, Sword, LIBELFBITS);
|
||||
FUNDAMENTAL (XWORD, Xword, LIBELFBITS);
|
||||
FUNDAMENTAL (SXWORD, Sxword, LIBELFBITS);
|
||||
FUNDAMENTAL (RELR, Relr, LIBELFBITS);
|
||||
|
||||
/* The structured types. */
|
||||
TYPE (Ehdr, LIBELFBITS)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Conversion functions for versioning information.
|
||||
Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2006.
|
||||
|
||||
@ -36,6 +37,7 @@
|
||||
static void
|
||||
elf_cvt_gnuhash (void *dest, const void *src, size_t len, int encode)
|
||||
{
|
||||
size_t size = len;
|
||||
/* The GNU hash table format on 64 bit machines mixes 32 bit and 64 bit
|
||||
words. We must detangle them here. */
|
||||
Elf32_Word *dest32 = dest;
|
||||
@ -45,7 +47,7 @@ elf_cvt_gnuhash (void *dest, const void *src, size_t len, int encode)
|
||||
for (unsigned int cnt = 0; cnt < 4; ++cnt)
|
||||
{
|
||||
if (len < 4)
|
||||
return;
|
||||
goto done;
|
||||
dest32[cnt] = bswap_32 (src32[cnt]);
|
||||
len -= 4;
|
||||
}
|
||||
@ -58,7 +60,7 @@ elf_cvt_gnuhash (void *dest, const void *src, size_t len, int encode)
|
||||
for (unsigned int cnt = 0; cnt < bitmask_words; ++cnt)
|
||||
{
|
||||
if (len < 8)
|
||||
return;
|
||||
goto done;
|
||||
dest64[cnt] = bswap_64 (src64[cnt]);
|
||||
len -= 8;
|
||||
}
|
||||
@ -71,4 +73,10 @@ elf_cvt_gnuhash (void *dest, const void *src, size_t len, int encode)
|
||||
*dest32++ = bswap_32 (*src32++);
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
done:
|
||||
/* If there are any bytes left, we weren't able to convert the
|
||||
partial structures, just copy them over. */
|
||||
if (len > 0)
|
||||
memmove (dest + size - len, src + size - len, len);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Internal interfaces for libelf.
|
||||
Copyright (C) 1998-2010, 2015, 2016 Red Hat, Inc.
|
||||
Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -32,6 +33,7 @@
|
||||
|
||||
#include <ar.h>
|
||||
#include <gelf.h>
|
||||
#include "eu-search.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
@ -62,6 +64,7 @@
|
||||
#define ELF32_FSZ_SWORD 4
|
||||
#define ELF32_FSZ_XWORD 8
|
||||
#define ELF32_FSZ_SXWORD 8
|
||||
#define ELF32_FSZ_RELR 4
|
||||
|
||||
/* Same for 64 bits objects. */
|
||||
#define ELF64_FSZ_ADDR 8
|
||||
@ -71,6 +74,7 @@
|
||||
#define ELF64_FSZ_SWORD 4
|
||||
#define ELF64_FSZ_XWORD 8
|
||||
#define ELF64_FSZ_SXWORD 8
|
||||
#define ELF64_FSZ_RELR 8
|
||||
|
||||
|
||||
/* This is an extension of the ELF_F_* enumeration. The values here are
|
||||
@ -214,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. */
|
||||
@ -262,11 +263,7 @@ typedef struct Elf_ScnList
|
||||
typedef struct Elf_Data_Chunk
|
||||
{
|
||||
Elf_Data_Scn data;
|
||||
union
|
||||
{
|
||||
Elf_Scn dummy_scn;
|
||||
struct Elf_Data_Chunk *next;
|
||||
};
|
||||
Elf_Scn dummy_scn;
|
||||
int64_t offset; /* The original raw offset in the Elf image. */
|
||||
} Elf_Data_Chunk;
|
||||
|
||||
@ -309,6 +306,9 @@ struct Elf
|
||||
/* Reference counting for the descriptor. */
|
||||
int ref_count;
|
||||
|
||||
/* Structure returned by 'elf_getarhdr'. */
|
||||
Elf_Arhdr elf_ar_hdr;
|
||||
|
||||
/* Lock to handle multithreaded programs. */
|
||||
rwlock_define (,lock);
|
||||
|
||||
@ -324,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. */
|
||||
Elf_Data_Chunk *rawchunks; /* List 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. */
|
||||
@ -343,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. */
|
||||
Elf_Data_Chunk *rawchunks; /* List 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. */
|
||||
@ -368,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. */
|
||||
Elf_Data_Chunk *rawchunks; /* List 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. */
|
||||
@ -394,7 +397,8 @@ struct Elf
|
||||
int64_t offset; /* Offset in file we are currently at.
|
||||
elf_next() advances this to the next
|
||||
member of the archive. */
|
||||
Elf_Arhdr elf_ar_hdr; /* Structure returned by 'elf_getarhdr'. */
|
||||
Elf_Arhdr cur_ar_hdr; /* Copy of current archive member's structure
|
||||
returned by 'elf_getarhdr'. */
|
||||
struct ar_hdr ar_hdr; /* Header read from file. */
|
||||
char ar_name[16]; /* NUL terminated ar_name of elf_ar_hdr. */
|
||||
char raw_name[17]; /* This is a buffer for the NUL terminated
|
||||
@ -515,15 +519,18 @@ extern Elf32_Shdr *__elf32_getshdr_rdlock (Elf_Scn *__scn) internal_function;
|
||||
extern Elf64_Shdr *__elf64_getshdr_rdlock (Elf_Scn *__scn) internal_function;
|
||||
extern Elf32_Shdr *__elf32_getshdr_wrlock (Elf_Scn *__scn) internal_function;
|
||||
extern Elf64_Shdr *__elf64_getshdr_wrlock (Elf_Scn *__scn) internal_function;
|
||||
extern Elf32_Chdr *__elf32_getchdr_wrlock (Elf_Scn *__scn) internal_function;
|
||||
extern Elf64_Chdr *__elf64_getchdr_wrlock (Elf_Scn *__scn) internal_function;
|
||||
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)
|
||||
internal_function;
|
||||
extern Elf_Data *__elf_getdata_wrlock (Elf_Scn *__scn, Elf_Data *__data)
|
||||
internal_function;
|
||||
extern Elf_Data *__elf_rawdata_internal (Elf_Scn *__scn, Elf_Data *__data)
|
||||
attribute_hidden;
|
||||
/* Should be called to setup first section data element if
|
||||
@ -574,10 +581,10 @@ extern uint32_t __libelf_crc32 (uint32_t crc, unsigned char *buf, size_t len)
|
||||
|
||||
extern void * __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
|
||||
size_t *orig_size, size_t *orig_addralign,
|
||||
size_t *size, bool force)
|
||||
size_t *size, bool force, bool use_zstd)
|
||||
internal_function;
|
||||
|
||||
extern void * __libelf_decompress (void *buf_in, size_t size_in,
|
||||
extern void * __libelf_decompress (int chtype, void *buf_in, size_t size_in,
|
||||
size_t size_out) internal_function;
|
||||
extern void * __libelf_decompress_elf (Elf_Scn *scn,
|
||||
size_t *size_out, size_t *addralign)
|
||||
@ -614,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>
|
||||
|
||||
|
||||
|
||||
48
src/system.h
48
src/system.h
@ -1,6 +1,7 @@
|
||||
/* Declarations for common convenience functions.
|
||||
Copyright (C) 2006-2011 Red Hat, Inc.
|
||||
Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
Copyright (C) 2023 Khem Raj.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
@ -30,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>
|
||||
@ -97,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), '|'); \
|
||||
@ -192,4 +225,17 @@ extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
|
||||
extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] \
|
||||
__attribute__ ((unused))
|
||||
|
||||
/* We really want a basename implementation that doesn't modify the
|
||||
input argument. Normally you get that from string.h with _GNU_SOURCE
|
||||
define. But some libc implementations don't define it and other
|
||||
define it, but provide an implementation that still modifies the
|
||||
argument. So define our own and poison a bare basename symbol. */
|
||||
static inline const char *
|
||||
xbasename(const char *s)
|
||||
{
|
||||
const char *p = strrchr(s, '/');
|
||||
return p ? p+1 : s;
|
||||
}
|
||||
#pragma GCC poison basename
|
||||
|
||||
#endif /* system.h */
|
||||
|
||||
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