mirror of
https://github.com/arachsys/libelf.git
synced 2026-01-28 10:24:34 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f38ceb5a8a | ||
|
|
6188fbeb25 | ||
|
|
288355d104 | ||
|
|
e12821ffb2 | ||
|
|
b5edd4a1e4 | ||
|
|
4015076fe6 | ||
|
|
c682a83511 | ||
|
|
bc189e2914 | ||
|
|
f918d99c1e | ||
|
|
95564b26d3 | ||
|
|
b3ab1bd9a4 | ||
|
|
b80c36da9d | ||
|
|
bc9698efd5 | ||
|
|
a75f3a59d7 | ||
|
|
97a43e81a7 | ||
|
|
4a1923298d | ||
|
|
520244d664 | ||
|
|
4afb73a7af | ||
|
|
a78fcc53c1 | ||
|
|
cf90fc56dc | ||
|
|
0183a162e8 | ||
|
|
21614b61f3 | ||
|
|
9f7bd2e6f3 |
6
Makefile
6
Makefile
@ -3,10 +3,10 @@ LIBDIR = $(PREFIX)/lib
|
||||
|
||||
CFLAGS = -O2 -Wall
|
||||
LDFLAGS =
|
||||
LDLIBS = -lz
|
||||
LDLIBS = -lz -lzstd
|
||||
|
||||
MAJOR = 1
|
||||
MINOR = 0.185
|
||||
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
|
||||
|
||||
29
src/common.h
29
src/common.h
@ -30,9 +30,6 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H 1
|
||||
|
||||
#include <ar.h>
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -92,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)
|
||||
{
|
||||
@ -124,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);
|
||||
}
|
||||
|
||||
|
||||
@ -154,7 +155,7 @@ libelf_release_all (Elf *elf)
|
||||
: bswap_64 (Var))))
|
||||
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define MY_ELFDATA ELFDATA2LSB
|
||||
#else
|
||||
# define MY_ELFDATA ELFDATA2MSB
|
||||
|
||||
@ -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 */
|
||||
|
||||
470
src/elf.h
470
src/elf.h
@ -1,5 +1,5 @@
|
||||
/* This file defines standard ELF types, structures, and macros.
|
||||
Copyright (C) 1995-2020 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 */
|
||||
@ -336,7 +336,8 @@ typedef struct
|
||||
#define EM_BA2 202 /* Beyond BA2 */
|
||||
#define EM_XCORE 203 /* XMOS xCORE */
|
||||
#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) */
|
||||
/* reserved 205-209 */
|
||||
#define EM_INTELGT 205 /* Intel Graphics Technology */
|
||||
/* reserved 206-209 */
|
||||
#define EM_KM32 210 /* KM211 KM32 */
|
||||
#define EM_KMX32 211 /* KM211 KMX32 */
|
||||
#define EM_EMX16 212 /* KM211 KMX16 */
|
||||
@ -357,8 +358,9 @@ typedef struct
|
||||
|
||||
#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */
|
||||
#define EM_CSKY 252 /* C-SKY */
|
||||
#define EM_LOONGARCH 258 /* LoongArch */
|
||||
|
||||
#define EM_NUM 253
|
||||
#define EM_NUM 259
|
||||
|
||||
/* Old spellings/synonyms. */
|
||||
|
||||
@ -442,7 +444,8 @@ typedef struct
|
||||
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
||||
#define SHT_GROUP 17 /* Section group */
|
||||
#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */
|
||||
#define SHT_NUM 19 /* Number of defined types. */
|
||||
#define SHT_RELR 19 /* RELR relative relocations */
|
||||
#define SHT_NUM 20 /* Number of defined types. */
|
||||
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
|
||||
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
|
||||
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
|
||||
@ -503,6 +506,7 @@ typedef struct
|
||||
|
||||
/* Legal values for ch_type (compression algorithm). */
|
||||
#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */
|
||||
#define ELFCOMPRESS_ZSTD 2 /* Zstandard algorithm. */
|
||||
#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */
|
||||
#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */
|
||||
#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */
|
||||
@ -555,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 */
|
||||
@ -661,6 +665,11 @@ typedef struct
|
||||
Elf64_Sxword r_addend; /* Addend */
|
||||
} Elf64_Rela;
|
||||
|
||||
/* RELR relocation table entry */
|
||||
|
||||
typedef Elf32_Word Elf32_Relr;
|
||||
typedef Elf64_Xword Elf64_Relr;
|
||||
|
||||
/* How to extract and insert information held in the r_info field. */
|
||||
|
||||
#define ELF32_R_SYM(val) ((val) >> 8)
|
||||
@ -719,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 */
|
||||
@ -781,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 */
|
||||
@ -800,6 +813,7 @@ typedef struct
|
||||
#define NT_S390_GS_BC 0x30c /* s390 guarded storage
|
||||
broadcast control block. */
|
||||
#define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation. */
|
||||
#define NT_S390_PV_CPU_DATA 0x30e /* s390 protvirt cpu dump data. */
|
||||
#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
|
||||
#define NT_ARM_TLS 0x401 /* ARM TLS register */
|
||||
#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */
|
||||
@ -813,10 +827,31 @@ typedef struct
|
||||
address keys. */
|
||||
#define NT_ARM_PACG_KEYS 0x408 /* ARM pointer authentication
|
||||
generic key. */
|
||||
#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* AArch64 tagged address
|
||||
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. */
|
||||
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD
|
||||
Extension registers. */
|
||||
#define NT_LOONGARCH_LASX 0xa03 /* LoongArch Loongson Advanced
|
||||
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. */
|
||||
|
||||
@ -882,7 +917,10 @@ typedef struct
|
||||
#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
|
||||
#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
|
||||
#define DT_SYMTAB_SHNDX 34 /* Address of SYMTAB_SHNDX section */
|
||||
#define DT_NUM 35 /* Number used */
|
||||
#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 */
|
||||
#define DT_NUM 38 /* Number used */
|
||||
#define DT_LOOS 0x6000000d /* Start of OS-specific */
|
||||
#define DT_HIOS 0x6ffff000 /* End of OS-specific */
|
||||
#define DT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||
@ -1039,7 +1077,8 @@ typedef struct
|
||||
|
||||
/* Legal values for vd_flags (version information flags). */
|
||||
#define VER_FLG_BASE 0x1 /* Version definition of file itself */
|
||||
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
|
||||
#define VER_FLG_WEAK 0x2 /* Weak version identifier. Also
|
||||
used by vna_flags below. */
|
||||
|
||||
/* Versym symbol index values. */
|
||||
#define VER_NDX_LOCAL 0 /* Symbol is local. */
|
||||
@ -1117,10 +1156,6 @@ typedef struct
|
||||
} Elf64_Vernaux;
|
||||
|
||||
|
||||
/* Legal values for vna_flags. */
|
||||
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
|
||||
|
||||
|
||||
/* Auxiliary vector. */
|
||||
|
||||
/* This vector is normally only used by the program interpreter. The
|
||||
@ -1200,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
|
||||
@ -1226,8 +1268,7 @@ typedef struct
|
||||
#define AT_L3_CACHESIZE 46
|
||||
#define AT_L3_CACHEGEOMETRY 47
|
||||
|
||||
#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery
|
||||
(AArch64). */
|
||||
#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery */
|
||||
|
||||
/* Note section contents. Each entry in the note section begins with
|
||||
a header of a fixed form. */
|
||||
@ -1254,6 +1295,8 @@ typedef struct
|
||||
/* Note entries for GNU systems have this name. */
|
||||
#define ELF_NOTE_GNU "GNU"
|
||||
|
||||
/* Note entries for freedesktop.org have this name. */
|
||||
#define ELF_NOTE_FDO "FDO"
|
||||
|
||||
/* Defined types of notes for Solaris. */
|
||||
|
||||
@ -1297,6 +1340,14 @@ typedef struct
|
||||
/* Program property. */
|
||||
#define NT_GNU_PROPERTY_TYPE_0 5
|
||||
|
||||
/* Packaging metadata as defined on
|
||||
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"
|
||||
|
||||
@ -1307,6 +1358,23 @@ typedef struct
|
||||
/* No copy relocation on protected data symbol. */
|
||||
#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
|
||||
|
||||
/* A 4-byte unsigned integer property: A bit is set if it is set in all
|
||||
relocatable inputs. */
|
||||
#define GNU_PROPERTY_UINT32_AND_LO 0xb0000000
|
||||
#define GNU_PROPERTY_UINT32_AND_HI 0xb0007fff
|
||||
|
||||
/* A 4-byte unsigned integer property: A bit is set if it is set in any
|
||||
relocatable inputs. */
|
||||
#define GNU_PROPERTY_UINT32_OR_LO 0xb0008000
|
||||
#define GNU_PROPERTY_UINT32_OR_HI 0xb000ffff
|
||||
|
||||
/* The needed properties by the object file. */
|
||||
#define GNU_PROPERTY_1_NEEDED GNU_PROPERTY_UINT32_OR_LO
|
||||
|
||||
/* Set if the object file requires canonical function pointers and
|
||||
cannot be used with copy relocation. */
|
||||
#define GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS (1U << 0)
|
||||
|
||||
/* Processor-specific semantics, lo */
|
||||
#define GNU_PROPERTY_LOPROC 0xc0000000
|
||||
/* Processor-specific semantics, hi */
|
||||
@ -1324,31 +1392,26 @@ typedef struct
|
||||
|
||||
/* The x86 instruction sets indicated by the corresponding bits are
|
||||
used in program. Their support in the hardware is optional. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_USED 0xc0000000
|
||||
#define GNU_PROPERTY_X86_ISA_1_USED 0xc0010002
|
||||
/* The x86 instruction sets indicated by the corresponding bits are
|
||||
used in program and they must be supported by the hardware. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001
|
||||
#define GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0008002
|
||||
/* X86 processor-specific features used in program. */
|
||||
#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002
|
||||
|
||||
#define GNU_PROPERTY_X86_ISA_1_486 (1U << 0)
|
||||
#define GNU_PROPERTY_X86_ISA_1_586 (1U << 1)
|
||||
#define GNU_PROPERTY_X86_ISA_1_686 (1U << 2)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSE (1U << 3)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSE2 (1U << 4)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSE3 (1U << 5)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSSE3 (1U << 6)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSE4_1 (1U << 7)
|
||||
#define GNU_PROPERTY_X86_ISA_1_SSE4_2 (1U << 8)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX (1U << 9)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX2 (1U << 10)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512F (1U << 11)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512CD (1U << 12)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512ER (1U << 13)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512PF (1U << 14)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512VL (1U << 15)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512DQ (1U << 16)
|
||||
#define GNU_PROPERTY_X86_ISA_1_AVX512BW (1U << 17)
|
||||
/* GNU_PROPERTY_X86_ISA_1_BASELINE: CMOV, CX8 (cmpxchg8b), FPU (fld),
|
||||
MMX, OSFXSR (fxsave), SCE (syscall), SSE and SSE2. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_BASELINE (1U << 0)
|
||||
/* GNU_PROPERTY_X86_ISA_1_V2: GNU_PROPERTY_X86_ISA_1_BASELINE,
|
||||
CMPXCHG16B (cmpxchg16b), LAHF-SAHF (lahf), POPCNT (popcnt), SSE3,
|
||||
SSSE3, SSE4.1 and SSE4.2. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_V2 (1U << 1)
|
||||
/* GNU_PROPERTY_X86_ISA_1_V3: GNU_PROPERTY_X86_ISA_1_V2, AVX, AVX2, BMI1,
|
||||
BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_V3 (1U << 2)
|
||||
/* GNU_PROPERTY_X86_ISA_1_V4: GNU_PROPERTY_X86_ISA_1_V3, AVX512F,
|
||||
AVX512BW, AVX512CD, AVX512DQ and AVX512VL. */
|
||||
#define GNU_PROPERTY_X86_ISA_1_V4 (1U << 3)
|
||||
|
||||
/* This indicates that all executable sections are compatible with
|
||||
IBT. */
|
||||
@ -1641,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. */
|
||||
@ -1659,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. */
|
||||
|
||||
@ -1719,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. */
|
||||
@ -1887,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. */
|
||||
|
||||
@ -2871,6 +3039,9 @@ enum
|
||||
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
|
||||
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
|
||||
|
||||
/* MTE memory tag segment type. */
|
||||
#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 2)
|
||||
|
||||
/* AArch64 specific values for the Dyn d_tag field. */
|
||||
#define DT_AARCH64_BTI_PLT (DT_LOPROC + 1)
|
||||
#define DT_AARCH64_PAC_PLT (DT_LOPROC + 3)
|
||||
@ -3480,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. */
|
||||
@ -3896,6 +4072,8 @@ enum
|
||||
#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
|
||||
#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
|
||||
#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
|
||||
#define EF_RISCV_RVE 0x0008
|
||||
#define EF_RISCV_TSO 0x0010
|
||||
|
||||
/* RISC-V relocations. */
|
||||
#define R_RISCV_NONE 0
|
||||
@ -3953,8 +4131,24 @@ 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
|
||||
convention */
|
||||
|
||||
/* RISC-V specific values for the sh_type field. */
|
||||
#define SHT_RISCV_ATTRIBUTES (SHT_LOPROC + 3)
|
||||
|
||||
/* RISC-V specific values for the p_type field. */
|
||||
#define PT_RISCV_ATTRIBUTES (PT_LOPROC + 3)
|
||||
|
||||
/* RISC-V specific values for the d_tag field. */
|
||||
#define DT_RISCV_VARIANT_CC (DT_LOPROC + 1)
|
||||
|
||||
/* BPF specific declarations. */
|
||||
|
||||
@ -4034,13 +4228,158 @@ enum
|
||||
#define R_NDS32_TLS_TPOFF 102
|
||||
#define R_NDS32_TLS_DESC 119
|
||||
|
||||
/* LoongArch ELF Flags */
|
||||
#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
|
||||
#define R_LARCH_32 1
|
||||
#define R_LARCH_64 2
|
||||
#define R_LARCH_RELATIVE 3
|
||||
#define R_LARCH_COPY 4
|
||||
#define R_LARCH_JUMP_SLOT 5
|
||||
#define R_LARCH_TLS_DTPMOD32 6
|
||||
#define R_LARCH_TLS_DTPMOD64 7
|
||||
#define R_LARCH_TLS_DTPREL32 8
|
||||
#define R_LARCH_TLS_DTPREL64 9
|
||||
#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. */
|
||||
|
||||
/* used by the static linker for relocating .text. */
|
||||
#define R_LARCH_MARK_LA 20
|
||||
#define R_LARCH_MARK_PCREL 21
|
||||
#define R_LARCH_SOP_PUSH_PCREL 22
|
||||
#define R_LARCH_SOP_PUSH_ABSOLUTE 23
|
||||
#define R_LARCH_SOP_PUSH_DUP 24
|
||||
#define R_LARCH_SOP_PUSH_GPREL 25
|
||||
#define R_LARCH_SOP_PUSH_TLS_TPREL 26
|
||||
#define R_LARCH_SOP_PUSH_TLS_GOT 27
|
||||
#define R_LARCH_SOP_PUSH_TLS_GD 28
|
||||
#define R_LARCH_SOP_PUSH_PLT_PCREL 29
|
||||
#define R_LARCH_SOP_ASSERT 30
|
||||
#define R_LARCH_SOP_NOT 31
|
||||
#define R_LARCH_SOP_SUB 32
|
||||
#define R_LARCH_SOP_SL 33
|
||||
#define R_LARCH_SOP_SR 34
|
||||
#define R_LARCH_SOP_ADD 35
|
||||
#define R_LARCH_SOP_AND 36
|
||||
#define R_LARCH_SOP_IF_ELSE 37
|
||||
#define R_LARCH_SOP_POP_32_S_10_5 38
|
||||
#define R_LARCH_SOP_POP_32_U_10_12 39
|
||||
#define R_LARCH_SOP_POP_32_S_10_12 40
|
||||
#define R_LARCH_SOP_POP_32_S_10_16 41
|
||||
#define R_LARCH_SOP_POP_32_S_10_16_S2 42
|
||||
#define R_LARCH_SOP_POP_32_S_5_20 43
|
||||
#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44
|
||||
#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45
|
||||
#define R_LARCH_SOP_POP_32_U 46
|
||||
|
||||
/* used by the static linker for relocating non .text. */
|
||||
#define R_LARCH_ADD8 47
|
||||
#define R_LARCH_ADD16 48
|
||||
#define R_LARCH_ADD24 49
|
||||
#define R_LARCH_ADD32 50
|
||||
#define R_LARCH_ADD64 51
|
||||
#define R_LARCH_SUB8 52
|
||||
#define R_LARCH_SUB16 53
|
||||
#define R_LARCH_SUB24 54
|
||||
#define R_LARCH_SUB32 55
|
||||
#define R_LARCH_SUB64 56
|
||||
#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
|
||||
#define R_ARC_8 0x1
|
||||
#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
|
||||
@ -4080,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
|
||||
@ -4098,8 +4444,48 @@ 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
|
||||
#define R_OR1K_32 1
|
||||
#define R_OR1K_16 2
|
||||
#define R_OR1K_8 3
|
||||
#define R_OR1K_LO_16_IN_INSN 4
|
||||
#define R_OR1K_HI_16_IN_INSN 5
|
||||
#define R_OR1K_INSN_REL_26 6
|
||||
#define R_OR1K_GNU_VTENTRY 7
|
||||
#define R_OR1K_GNU_VTINHERIT 8
|
||||
#define R_OR1K_32_PCREL 9
|
||||
#define R_OR1K_16_PCREL 10
|
||||
#define R_OR1K_8_PCREL 11
|
||||
#define R_OR1K_GOTPC_HI16 12
|
||||
#define R_OR1K_GOTPC_LO16 13
|
||||
#define R_OR1K_GOT16 14
|
||||
#define R_OR1K_PLT26 15
|
||||
#define R_OR1K_GOTOFF_HI16 16
|
||||
#define R_OR1K_GOTOFF_LO16 17
|
||||
#define R_OR1K_COPY 18
|
||||
#define R_OR1K_GLOB_DAT 19
|
||||
#define R_OR1K_JMP_SLOT 20
|
||||
#define R_OR1K_RELATIVE 21
|
||||
#define R_OR1K_TLS_GD_HI16 22
|
||||
#define R_OR1K_TLS_GD_LO16 23
|
||||
#define R_OR1K_TLS_LDM_HI16 24
|
||||
#define R_OR1K_TLS_LDM_LO16 25
|
||||
#define R_OR1K_TLS_LDO_HI16 26
|
||||
#define R_OR1K_TLS_LDO_LO16 27
|
||||
#define R_OR1K_TLS_IE_HI16 28
|
||||
#define R_OR1K_TLS_IE_LO16 29
|
||||
#define R_OR1K_TLS_LE_HI16 30
|
||||
#define R_OR1K_TLS_LE_LO16 31
|
||||
#define R_OR1K_TLS_TPOFF 32
|
||||
#define R_OR1K_TLS_DTPOFF 33
|
||||
#define R_OR1K_TLS_DTPMOD 34
|
||||
|
||||
#endif /* elf.h */
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
@ -74,9 +73,9 @@ elfw2(LIBELFBITS,checksum) (Elf *elf)
|
||||
is the same. */
|
||||
ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident;
|
||||
same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
|
||||
&& __BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
&& BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|| (ident[EI_DATA] == ELFDATA2MSB
|
||||
&& __BYTE_ORDER == __BIG_ENDIAN));
|
||||
&& BYTE_ORDER == BIG_ENDIAN));
|
||||
|
||||
/* If we don't have native byte order, we will likely need to
|
||||
convert the data with xlate functions. We do it upfront instead
|
||||
|
||||
@ -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
|
||||
@ -34,10 +34,8 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
@ -34,9 +34,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
@ -128,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),
|
||||
@ -148,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;
|
||||
|
||||
@ -37,10 +37,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
|
||||
|
||||
|
||||
@ -32,12 +32,10 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <libelf.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "elf-knowledge.h"
|
||||
|
||||
@ -137,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. */
|
||||
@ -258,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;
|
||||
}
|
||||
@ -406,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;
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
@ -46,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;
|
||||
@ -83,8 +95,8 @@ elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
|
||||
and vice versa since the function only has to copy and/or
|
||||
change the byte order.
|
||||
*/
|
||||
if ((__BYTE_ORDER == __LITTLE_ENDIAN && encode == ELFDATA2LSB)
|
||||
|| (__BYTE_ORDER == __BIG_ENDIAN && encode == ELFDATA2MSB))
|
||||
if ((BYTE_ORDER == LITTLE_ENDIAN && encode == ELFDATA2LSB)
|
||||
|| (BYTE_ORDER == BIG_ENDIAN && encode == ELFDATA2MSB))
|
||||
{
|
||||
/* We simply have to copy since the byte order is the same. */
|
||||
if (src->d_buf != dest->d_buf)
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
@ -46,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
|
||||
|
||||
190
src/elf_begin.c
190
src/elf_begin.c
@ -1,5 +1,6 @@
|
||||
/* Create descriptor for processing file.
|
||||
Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
|
||||
Copyright (C) 2021, 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -37,12 +38,10 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
@ -63,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;
|
||||
@ -157,7 +156,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
|
||||
|
||||
if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| (((size_t) ((char *) map_address + ehdr.e32->e_shoff))
|
||||
|| (((size_t) ((char *) (map_address + ehdr.e32->e_shoff
|
||||
+ offset)))
|
||||
& (__alignof__ (Elf32_Shdr) - 1)) == 0))
|
||||
/* We can directly access the memory. */
|
||||
result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
|
||||
@ -170,9 +170,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
|
||||
if (likely (map_address != NULL))
|
||||
/* gcc will optimize the memcpy to a simple memory
|
||||
access while taking care of alignment issues. */
|
||||
memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
|
||||
+ ehdr.e32->e_shoff
|
||||
+ offset))->sh_size,
|
||||
memcpy (&size, ((char *) map_address
|
||||
+ ehdr.e32->e_shoff
|
||||
+ offset
|
||||
+ offsetof (Elf32_Shdr, sh_size)),
|
||||
sizeof (Elf32_Word));
|
||||
else
|
||||
if (unlikely ((r = pread_retry (fildes, &size,
|
||||
@ -216,7 +217,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
|
||||
Elf64_Xword size;
|
||||
if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| (((size_t) ((char *) map_address + ehdr.e64->e_shoff))
|
||||
|| (((size_t) ((char *) (map_address + ehdr.e64->e_shoff
|
||||
+ offset)))
|
||||
& (__alignof__ (Elf64_Shdr) - 1)) == 0))
|
||||
/* We can directly access the memory. */
|
||||
size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
|
||||
@ -227,9 +229,10 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes,
|
||||
if (likely (map_address != NULL))
|
||||
/* gcc will optimize the memcpy to a simple memory
|
||||
access while taking care of alignment issues. */
|
||||
memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
|
||||
+ ehdr.e64->e_shoff
|
||||
+ offset))->sh_size,
|
||||
memcpy (&size, ((char *) map_address
|
||||
+ ehdr.e64->e_shoff
|
||||
+ offset
|
||||
+ offsetof (Elf64_Shdr, sh_size)),
|
||||
sizeof (Elf64_Xword));
|
||||
else
|
||||
if (unlikely ((r = pread_retry (fildes, &size,
|
||||
@ -339,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
|
||||
{
|
||||
@ -380,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) ((char *) 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
|
||||
@ -392,8 +394,9 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
|
||||
__libelf_seterrno (ELF_E_INVALID_ELF);
|
||||
return NULL;
|
||||
}
|
||||
elf->state.elf32.shdr
|
||||
= (Elf32_Shdr *) ((char *) ehdr + e_shoff);
|
||||
|
||||
if (scncnt > 0)
|
||||
elf->state.elf32.shdr = (Elf32_Shdr *) (ehdr + e_shoff);
|
||||
|
||||
for (size_t cnt = 0; cnt < scncnt; ++cnt)
|
||||
{
|
||||
@ -409,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
|
||||
@ -436,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
|
||||
{
|
||||
@ -482,15 +473,15 @@ 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) ((char *) 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
|
||||
< scncnt * sizeof (Elf64_Shdr)))
|
||||
goto free_and_out;
|
||||
elf->state.elf64.shdr
|
||||
= (Elf64_Shdr *) ((char *) ehdr + e_shoff);
|
||||
|
||||
if (scncnt > 0)
|
||||
elf->state.elf64.shdr = (Elf64_Shdr *) (ehdr + (ptrdiff_t) e_shoff);
|
||||
|
||||
for (size_t cnt = 0; cnt < scncnt; ++cnt)
|
||||
{
|
||||
@ -506,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
|
||||
@ -533,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;
|
||||
@ -756,6 +735,11 @@ read_long_names (Elf *elf)
|
||||
*((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
|
||||
string = buf;
|
||||
}
|
||||
|
||||
/* atol expects to see at least one digit.
|
||||
It also cannot be negative (-). */
|
||||
if (!isdigit(string[0]))
|
||||
return NULL;
|
||||
len = atol (string);
|
||||
|
||||
if (memcmp (hdr->ar_name, "// ", 16) == 0)
|
||||
@ -831,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
|
||||
@ -878,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. */
|
||||
@ -963,7 +991,8 @@ __libelf_next_arhdr_wrlock (Elf *elf)
|
||||
atoll depending on the size of the types. We are also prepared
|
||||
for the case where the whole field in the `struct ar_hdr' is
|
||||
filled in which case we cannot simply use atol/l but instead have
|
||||
to create a temporary copy. */
|
||||
to create a temporary copy. Note that all fields use decimal
|
||||
encoding, except ar_mode which uses octal. */
|
||||
|
||||
#define INT_FIELD(FIELD) \
|
||||
do \
|
||||
@ -983,10 +1012,30 @@ __libelf_next_arhdr_wrlock (Elf *elf)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define OCT_FIELD(FIELD) \
|
||||
do \
|
||||
{ \
|
||||
char buf[sizeof (ar_hdr->FIELD) + 1]; \
|
||||
const char *string = ar_hdr->FIELD; \
|
||||
if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \
|
||||
{ \
|
||||
*((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \
|
||||
= '\0'; \
|
||||
string = buf; \
|
||||
} \
|
||||
if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \
|
||||
elf_ar_hdr->FIELD \
|
||||
= (__typeof (elf_ar_hdr->FIELD)) strtol (string, NULL, 8); \
|
||||
else \
|
||||
elf_ar_hdr->FIELD \
|
||||
= (__typeof (elf_ar_hdr->FIELD)) strtoll (string, NULL, 8); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
INT_FIELD (ar_date);
|
||||
INT_FIELD (ar_uid);
|
||||
INT_FIELD (ar_gid);
|
||||
INT_FIELD (ar_mode);
|
||||
OCT_FIELD (ar_mode);
|
||||
INT_FIELD (ar_size);
|
||||
|
||||
if (elf_ar_hdr->ar_size < 0)
|
||||
@ -1050,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;
|
||||
|
||||
@ -31,8 +31,6 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
|
||||
@ -44,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;
|
||||
@ -66,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:
|
||||
@ -75,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
|
||||
@ -31,16 +32,18 @@
|
||||
#endif
|
||||
|
||||
#include <libelf.h>
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.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,
|
||||
@ -56,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;
|
||||
|
||||
@ -207,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
|
||||
@ -220,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. */
|
||||
@ -262,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)
|
||||
@ -270,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;
|
||||
@ -297,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;
|
||||
@ -317,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;
|
||||
@ -362,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)
|
||||
@ -396,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)
|
||||
@ -410,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)
|
||||
@ -424,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)
|
||||
@ -438,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;
|
||||
@ -456,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);
|
||||
@ -475,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;
|
||||
@ -507,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,13 +33,22 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <search.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.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)
|
||||
{
|
||||
@ -72,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. */
|
||||
@ -103,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)
|
||||
{
|
||||
@ -113,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)
|
||||
@ -154,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
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <libintl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -32,16 +32,12 @@
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.h>
|
||||
#include <dl-hash.h>
|
||||
#include "libelfP.h"
|
||||
|
||||
@ -65,7 +61,7 @@ read_number_entries (uint64_t *nump, Elf *elf, size_t *offp, bool index64_p)
|
||||
|
||||
*offp += w;
|
||||
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
*nump = index64_p ? bswap_64 (u.ret64) : bswap_32 (u.ret32);
|
||||
else
|
||||
*nump = index64_p ? u.ret64 : u.ret32;
|
||||
@ -270,7 +266,7 @@ elf_getarsym (Elf *elf, size_t *ptr)
|
||||
if (index64_p)
|
||||
{
|
||||
uint64_t tmp = (*u64)[cnt];
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
tmp = bswap_64 (tmp);
|
||||
|
||||
arsym[cnt].as_off = tmp;
|
||||
@ -290,7 +286,7 @@ elf_getarsym (Elf *elf, size_t *ptr)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
else if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
arsym[cnt].as_off = bswap_32 ((*u32)[cnt]);
|
||||
else
|
||||
arsym[cnt].as_off = (*u32)[cnt];
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Return the next data element from the section after possibly converting it.
|
||||
Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
|
||||
Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -34,10 +35,8 @@
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
#include <system.h>
|
||||
#include "common.h"
|
||||
#include "elf-knowledge.h"
|
||||
|
||||
@ -77,7 +76,6 @@ static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
|
||||
const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||||
{
|
||||
# define TYPE_ALIGNS(Bits) \
|
||||
{ \
|
||||
[ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
|
||||
[ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
|
||||
[ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
|
||||
@ -100,13 +98,17 @@ const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||||
[ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
|
||||
[ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
|
||||
[ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
|
||||
[ELF_T_GNUHASH] = __alignof__ (Elf32_Word), \
|
||||
[ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
|
||||
[ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
|
||||
[ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */ \
|
||||
}
|
||||
[ELFCLASS32 - 1] = TYPE_ALIGNS (32),
|
||||
[ELFCLASS64 - 1] = TYPE_ALIGNS (64),
|
||||
[ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */
|
||||
[ELFCLASS32 - 1] = {
|
||||
TYPE_ALIGNS (32),
|
||||
[ELF_T_GNUHASH] = __alignof__ (Elf32_Word),
|
||||
},
|
||||
[ELFCLASS64 - 1] = {
|
||||
TYPE_ALIGNS (64),
|
||||
[ELF_T_GNUHASH] = __alignof__ (Elf64_Xword),
|
||||
},
|
||||
# undef TYPE_ALIGNS
|
||||
};
|
||||
|
||||
@ -580,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,5 +1,6 @@
|
||||
/* Return converted data from raw chunk of ELF file.
|
||||
Copyright (C) 2007, 2014, 2015 Red Hat, Inc.
|
||||
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
|
||||
@ -32,13 +33,26 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.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)
|
||||
@ -73,7 +87,30 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
int flags = 0;
|
||||
Elf_Data *result = NULL;
|
||||
|
||||
rwlock_rdlock (elf->lock);
|
||||
rwlock_wrlock (elf->lock);
|
||||
|
||||
/* Maybe we already got this chunk? */
|
||||
Elf_Data_Chunk key;
|
||||
key.offset = offset;
|
||||
key.data.d.d_size = size;
|
||||
key.data.d.d_type = type;
|
||||
Elf_Data_Chunk **found
|
||||
= eu_tsearch_nolock (&key, &elf->state.elf.rawchunk_tree, &chunk_compare);
|
||||
|
||||
if (found == NULL)
|
||||
goto nomem;
|
||||
|
||||
/* Existing entry. */
|
||||
if (*found != &key && *found != NULL)
|
||||
{
|
||||
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)
|
||||
@ -99,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;
|
||||
}
|
||||
@ -109,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;
|
||||
@ -136,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
|
||||
@ -152,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. */
|
||||
@ -171,12 +217,9 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
|
||||
chunk->data.d.d_type = type;
|
||||
chunk->data.d.d_align = align;
|
||||
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:
|
||||
|
||||
@ -35,9 +35,7 @@
|
||||
#include <errno.h>
|
||||
#include <gelf.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -32,10 +32,8 @@
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
@ -86,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))
|
||||
{
|
||||
@ -143,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);
|
||||
|
||||
@ -33,8 +33,6 @@
|
||||
|
||||
#include <libelf.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
@ -106,8 +104,10 @@ write_file (Elf *elf, int64_t size, int change_bo, size_t shnum)
|
||||
if (elf->cmd == ELF_C_RDWR_MMAP
|
||||
&& (size_t) size > elf->maximum_size)
|
||||
{
|
||||
#ifdef HAVE_MREMAP
|
||||
if (mremap (elf->map_address, elf->maximum_size,
|
||||
size, 0) == MAP_FAILED)
|
||||
#endif
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
return -1;
|
||||
|
||||
@ -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,29 +29,9 @@
|
||||
#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. */
|
||||
#define N_(Str) Str
|
||||
#define _(Str) dgettext ("elfutils", Str)
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Transformation functions for ELF data types.
|
||||
Copyright (C) 1998,1999,2000,2002,2004,2005,2006,2007,2015 Red Hat, Inc.
|
||||
Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -31,7 +32,6 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <byteswap.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -138,9 +138,14 @@ union unaligned
|
||||
int encode __attribute__ ((unused))) \
|
||||
{ ElfW2(Bits, Name) *tdest = (ElfW2(Bits, Name) *) dest; \
|
||||
ElfW2(Bits, Name) *tsrc = (ElfW2(Bits, Name) *) src; \
|
||||
size_t sz = sizeof (ElfW2(Bits, Name)); \
|
||||
size_t n; \
|
||||
for (n = len / sizeof (ElfW2(Bits, Name)); n > 0; ++tdest, ++tsrc, --n) {
|
||||
#define END(Bits, Name) } }
|
||||
for (n = len / sz; n > 0; ++tdest, ++tsrc, --n) {
|
||||
#define END(Bits, Name) \
|
||||
} \
|
||||
if (len % sz > 0) /* Cannot convert partial structures, just copy. */ \
|
||||
memmove (dest, src, len % sz); \
|
||||
}
|
||||
#define TYPE_EXTRA(Code)
|
||||
#define TYPE_XLATE(Code) Code
|
||||
#define TYPE_NAME(Type, Name) TYPE_NAME2 (Type, Name)
|
||||
@ -199,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>
|
||||
@ -39,6 +41,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <system.h>
|
||||
|
||||
/* Helper Macros to write 32 bit and 64 bit functions. */
|
||||
#define __elfw2_(Bits, Name) __elf##Bits##_##Name
|
||||
@ -61,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
|
||||
@ -70,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
|
||||
@ -213,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. */
|
||||
@ -261,11 +263,8 @@ 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;
|
||||
|
||||
|
||||
@ -307,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);
|
||||
|
||||
@ -322,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. */
|
||||
@ -341,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. */
|
||||
@ -366,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. */
|
||||
@ -392,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
|
||||
@ -513,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
|
||||
@ -572,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)
|
||||
@ -603,13 +612,16 @@ extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
|
||||
/* Align offset to 4 bytes as needed for note name and descriptor data.
|
||||
This is almost always used, except for GNU Property notes, which use
|
||||
8 byte padding... */
|
||||
#define NOTE_ALIGN4(n) (((n) + 3) & -4U)
|
||||
#define NOTE_ALIGN4(n) (((n) + 3) & -4UL)
|
||||
|
||||
/* Special note padding rule for GNU Property notes. */
|
||||
#define NOTE_ALIGN8(n) (((n) + 7) & -8U)
|
||||
#define NOTE_ALIGN8(n) (((n) + 7) & -8UL)
|
||||
|
||||
/* Convenience macro. */
|
||||
#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 */
|
||||
|
||||
@ -30,6 +30,5 @@
|
||||
#endif
|
||||
|
||||
#define crc32 attribute_hidden __libelf_crc32
|
||||
#define LIB_SYSTEM_H 1
|
||||
#include <libelf.h>
|
||||
#include "crc32.c"
|
||||
|
||||
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>
|
||||
|
||||
|
||||
|
||||
@ -35,7 +35,6 @@
|
||||
#include <gelf.h>
|
||||
#include <libelf.h>
|
||||
#include <nlist.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
|
||||
63
src/system.h
63
src/system.h
@ -1,5 +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
|
||||
@ -29,25 +31,33 @@
|
||||
#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 <sys/param.h>
|
||||
#include <endian.h>
|
||||
#include <byteswap.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#include <byteswap.h>
|
||||
#include <endian.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define LE32(n) (n)
|
||||
# define LE64(n) (n)
|
||||
# define BE32(n) bswap_32 (n)
|
||||
# define BE64(n) bswap_64 (n)
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
# define BE32(n) (n)
|
||||
# define BE64(n) (n)
|
||||
# define LE32(n) bswap_32 (n)
|
||||
@ -94,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), '|'); \
|
||||
@ -189,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 */
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/* Conversion functions for versioning information.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
|
||||
Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
@ -66,7 +67,9 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
|
||||
GElf_Verdaux *asrc;
|
||||
|
||||
/* Test for correct offset. */
|
||||
if (def_offset > len || len - def_offset < sizeof (GElf_Verdef))
|
||||
if (def_offset > len
|
||||
|| len - def_offset < sizeof (GElf_Verdef)
|
||||
|| (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
|
||||
return;
|
||||
|
||||
/* Work the tree from the first record. */
|
||||
@ -84,10 +87,16 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
|
||||
ddest->vd_aux = bswap_32 (dsrc->vd_aux);
|
||||
ddest->vd_next = bswap_32 (dsrc->vd_next);
|
||||
|
||||
if (ddest->vd_aux > len - def_offset)
|
||||
return;
|
||||
aux_offset = def_offset + ddest->vd_aux;
|
||||
}
|
||||
else
|
||||
aux_offset = def_offset + dsrc->vd_aux;
|
||||
{
|
||||
if (dsrc->vd_aux > len - def_offset)
|
||||
return;
|
||||
aux_offset = def_offset + dsrc->vd_aux;
|
||||
}
|
||||
|
||||
/* Handle all the auxiliary records belonging to this definition. */
|
||||
do
|
||||
@ -95,26 +104,38 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
|
||||
GElf_Verdaux *adest;
|
||||
|
||||
/* Test for correct offset. */
|
||||
if (aux_offset > len || len - aux_offset < sizeof (GElf_Verdaux))
|
||||
if (aux_offset > len
|
||||
|| len - aux_offset < sizeof (GElf_Verdaux)
|
||||
|| (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
|
||||
return;
|
||||
|
||||
adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
|
||||
asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
|
||||
|
||||
if (encode)
|
||||
aux_offset += asrc->vda_next;
|
||||
{
|
||||
if (asrc->vda_next > len - aux_offset)
|
||||
return;
|
||||
aux_offset += asrc->vda_next;
|
||||
}
|
||||
|
||||
adest->vda_name = bswap_32 (asrc->vda_name);
|
||||
adest->vda_next = bswap_32 (asrc->vda_next);
|
||||
|
||||
if (! encode)
|
||||
aux_offset += adest->vda_next;
|
||||
{
|
||||
if (adest->vda_next > len - aux_offset)
|
||||
return;
|
||||
aux_offset += adest->vda_next;
|
||||
}
|
||||
}
|
||||
while (asrc->vda_next != 0);
|
||||
|
||||
/* Encode now if necessary. */
|
||||
if (encode)
|
||||
{
|
||||
if (dsrc->vd_next > len - def_offset)
|
||||
return;
|
||||
def_offset += dsrc->vd_next;
|
||||
|
||||
ddest->vd_version = bswap_16 (dsrc->vd_version);
|
||||
@ -126,7 +147,11 @@ elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
|
||||
ddest->vd_next = bswap_32 (dsrc->vd_next);
|
||||
}
|
||||
else
|
||||
def_offset += ddest->vd_next;
|
||||
{
|
||||
if (ddest->vd_next > len - def_offset)
|
||||
return;
|
||||
def_offset += ddest->vd_next;
|
||||
}
|
||||
}
|
||||
while (dsrc->vd_next != 0);
|
||||
}
|
||||
@ -165,7 +190,9 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
|
||||
GElf_Vernaux *asrc;
|
||||
|
||||
/* Test for correct offset. */
|
||||
if (need_offset > len || len - need_offset < sizeof (GElf_Verneed))
|
||||
if (need_offset > len
|
||||
|| len - need_offset < sizeof (GElf_Verneed)
|
||||
|| (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
|
||||
return;
|
||||
|
||||
/* Work the tree from the first record. */
|
||||
@ -181,10 +208,16 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
|
||||
ndest->vn_aux = bswap_32 (nsrc->vn_aux);
|
||||
ndest->vn_next = bswap_32 (nsrc->vn_next);
|
||||
|
||||
if (ndest->vn_aux > len - need_offset)
|
||||
return;
|
||||
aux_offset = need_offset + ndest->vn_aux;
|
||||
}
|
||||
else
|
||||
aux_offset = need_offset + nsrc->vn_aux;
|
||||
{
|
||||
if (nsrc->vn_aux > len - need_offset)
|
||||
return;
|
||||
aux_offset = need_offset + nsrc->vn_aux;
|
||||
}
|
||||
|
||||
/* Handle all the auxiliary records belonging to this requirement. */
|
||||
do
|
||||
@ -192,14 +225,20 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
|
||||
GElf_Vernaux *adest;
|
||||
|
||||
/* Test for correct offset. */
|
||||
if (aux_offset > len || len - aux_offset < sizeof (GElf_Vernaux))
|
||||
if (aux_offset > len
|
||||
|| len - aux_offset < sizeof (GElf_Vernaux)
|
||||
|| (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
|
||||
return;
|
||||
|
||||
adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
|
||||
asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
|
||||
|
||||
if (encode)
|
||||
aux_offset += asrc->vna_next;
|
||||
{
|
||||
if (asrc->vna_next > len - aux_offset)
|
||||
return;
|
||||
aux_offset += asrc->vna_next;
|
||||
}
|
||||
|
||||
adest->vna_hash = bswap_32 (asrc->vna_hash);
|
||||
adest->vna_flags = bswap_16 (asrc->vna_flags);
|
||||
@ -208,13 +247,19 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
|
||||
adest->vna_next = bswap_32 (asrc->vna_next);
|
||||
|
||||
if (! encode)
|
||||
aux_offset += adest->vna_next;
|
||||
{
|
||||
if (adest->vna_next > len - aux_offset)
|
||||
return;
|
||||
aux_offset += adest->vna_next;
|
||||
}
|
||||
}
|
||||
while (asrc->vna_next != 0);
|
||||
|
||||
/* Encode now if necessary. */
|
||||
if (encode)
|
||||
{
|
||||
if (nsrc->vn_next > len - need_offset)
|
||||
return;
|
||||
need_offset += nsrc->vn_next;
|
||||
|
||||
ndest->vn_version = bswap_16 (nsrc->vn_version);
|
||||
@ -224,7 +269,11 @@ elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
|
||||
ndest->vn_next = bswap_32 (nsrc->vn_next);
|
||||
}
|
||||
else
|
||||
need_offset += ndest->vn_next;
|
||||
{
|
||||
if (ndest->vn_next > len - need_offset)
|
||||
return;
|
||||
need_offset += ndest->vn_next;
|
||||
}
|
||||
}
|
||||
while (nsrc->vn_next != 0);
|
||||
}
|
||||
|
||||
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