summaryrefslogtreecommitdiffstats
path: root/libelf
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2020-06-09 18:21:36 +0200
committerMark Wielaard <[email protected]>2020-06-09 18:21:36 +0200
commitc0d643e7d91fc002c9fecd83277c62a0e56ef76f (patch)
tree89b5cf6673baa2cb206fdf245f4e30fe884945ad /libelf
parent14030673602a4f331f348decd51e5f0160719f0e (diff)
parent5643e037cb7a38ed5d52f50421be706ea8014e3d (diff)
Merge tag 'elfutils-0.177' into mjw/RH-DTSdts-0.177
elfutils 0.177 release Conflicts: libebl/eblopenbackend.c Removed try_dlopen and csky. tests/run-strip-reloc.sh Removed csky tests.
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog128
-rw-r--r--libelf/common.h4
-rw-r--r--libelf/elf.h96
-rw-r--r--libelf/elf32_fsize.c12
-rw-r--r--libelf/elf32_newphdr.c3
-rw-r--r--libelf/elf32_updatefile.c99
-rw-r--r--libelf/elf32_updatenull.c44
-rw-r--r--libelf/elf32_xlatetof.c16
-rw-r--r--libelf/elf32_xlatetom.c16
-rw-r--r--libelf/elf_begin.c17
-rw-r--r--libelf/elf_compress.c33
-rw-r--r--libelf/elf_getaroff.c2
-rw-r--r--libelf/elf_getbase.c4
-rw-r--r--libelf/elf_getdata.c26
-rw-r--r--libelf/elf_getdata_rawchunk.c7
-rw-r--r--libelf/elf_newdata.c2
-rw-r--r--libelf/elf_update.c8
-rw-r--r--libelf/elf_version.c23
-rw-r--r--libelf/gelf_fsize.c13
-rw-r--r--libelf/gelf_getnote.c5
-rw-r--r--libelf/gelf_xlate.c10
-rw-r--r--libelf/libelfP.h65
-rw-r--r--libelf/nlist.c5
-rw-r--r--libelf/note_xlate.h16
24 files changed, 396 insertions, 258 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index d8e8fdc8..dde6c81d 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,131 @@
+2019-06-18 Mark Wielaard <[email protected]>
+
+ * common.h (allocate_elf): Use int64_t instead of off_t for offset.
+ * elf32_newphdr.c (newphdr): Document why Elf32/64_Word is correct.
+ * elf32_updatefile.c (fill): Use int64_t instead of off_t for pos.
+ (updatefile): Define last_offset, shdr_offset and scn_start as
+ int64_t instead of off_t.
+ * elf32_updatenull.c: Define Elf32_SizeWord and Elf64_SizeWord.
+ (updatenull_wrlock): Return int64_t instead of off_t. Define size,
+ sh_entsize, sh_align and sh_size as SizeWords. Define offset as
+ int64_t. Cast data->d_off to SizeWord instead of GElf_Word. Drop
+ size GElf_Word cast. Cast offset to SizeWord instead of GElf_Word
+ when comparing with sh_size.
+ * elf_begin.c (get_shnum): Define offset as int64_t instead of
+ off_t. Document why use GElf_Word is correct.
+ (file_read_elf): Define offset as int64_t instead of off_t.
+ (__libelf_read_mmaped_file): Likewise.
+ (read_unmmaped_file): Likewise.
+ (read_file): Likewise.
+ * elf_getaroff.c (elf_getaroff): Return int64_t.
+ * elf_getbase.c (elf_getbase): Likewise.
+ * elf_getdata_rawchunk.c (elf_getdata_rawchunk): Define offset as
+ int64_t instead of off_t.
+ * elf_update.c (write_file): Return int64_t instead of off_t,
+ define size as int64_t instead of off_t.
+ (elf_update): Likewise.
+ * libelfP.h (struct Elf): Define start_offset, sizestr_offset and
+ offset as int64_t.
+ (__libelf_read_mmaped_file): Define offset as int64_t.
+ (__elf32_updatenull_wrlock): Return int64_t.
+ (__elf64_updatenull_wrlock): Return int64_t.
+
+2019-05-12 Mark Wielaard <[email protected]>
+
+ * elf32_updatenull.c (updatenull_wrlock): Mark shdr_flags dirty if
+ either offset or size changed.
+
+2019-05-01 Mark Wielaard <[email protected]>
+
+ * gelf_getnote.c (gelf_getnote): Check n_namesz doesn't overflow
+ offset.
+
+2019-04-30 Mark Wielaard <[email protected]>
+
+ * note_xlate.h (elf_cvt_note): Indicate we only translated the note
+ header if we ran out of data by updating len, src and dest.
+
+2019-04-01 Mao Han <[email protected]>
+
+ * elf.h: Update from glibc.
+
+2019-03-07 Mark Wielaard <[email protected]>
+
+ * elf32_updatefile.c (updatemmap): Use posix_memalign instead of
+ aligned_alloc.
+
+2019-03-06 Mark Wielaard <[email protected]>
+
+ * elf32_updatefile.c (updatemmap): Free scns before returning
+ allocation failure.
+
+2019-02-24 Mark Wielaard <[email protected]>
+
+ * gelf_xlate.c (__elf_xfctstof): Remove alias.
+ * libelfP.h (__elf_xfctstof): Remove definition.
+
+2019-02-24 Mark Wielaard <[email protected]>
+
+ * elf32_fsize.c (local_strong_alias): Remove definition.
+ (msize): Remove alias.
+ * libelfP.h (__elf32_msize): Remove definition.
+ (__elf64_msize): Likewise.
+
+2019-02-21 Mark Wielaard <[email protected]>
+
+ * common.h (determine_kind): Only accept EV_CURRENT.
+ * elf32_fsize.c (fsize): Just check version is EV_CURRENT.
+ Use __libelf_type_size without version dimension.
+ * elf32_updatefile.c (updatemmap): Define fctp from __elf_xfctstom
+ without version dimension.
+ (updatefile): Likewise.
+ * elf32_updatenull.c (default_ehdr): Check e_version is EV_CURRENT.
+ (updatenull_wrlock): Check d_version is EV_CURRENT.
+ (elf32_xlatetof): Likewise. And get recsize without version
+ dimension from __elf_xfctstom.
+ (elf32_xlatetom): Likewise.
+ * elf_begin.c (elf_begin): Check __libelf_version is EV_CURRENT.
+ * elf_compress.c (__libelf_reset_rawdata): Set d_version to
+ EV_CURRENT.
+ * elf_getdata.c (shtype_map): Remove version dimension.
+ (__libelf_type_aligns): Likewise.
+ (__libelf_data_type): Use shtype_map without version dimension.
+ (convert_data): Remove unused version argument. Get fp from
+ __elf_xfctstom without version dimensions.
+ (__libelf_set_data_list_rdlock): Call convert_data without version.
+ * elf_getdata_rawchunk.c (elf_getdata_rawchunk): Call __elfcfctstom
+ conversion function without version dimensions. Set d_version to
+ EV_CURRENT.
+ * elf_newdata.c (elf_newdata): Set d_version to EV_CURRENT.
+ * elf_version.c (__libelf_version_initialized): Removed.
+ (__libelf_version): Initialized to EV_NONE.
+ (elf_version): Always return EV_CURRENT for EV_NONE version.
+ Only accept (and return) EV_CURRENT as version.
+ * gelf_fsize.c (__libelf_type_sizes): Remove version dimension.
+ (gelf_fsize): Only accept EV_CURRENT as version.
+ Use __libelf_type_sizes without version dimension.
+ * gelf_xlate.c (__elf_xftstom): Remove version dimensions.
+ * libelfP.h (__elf_xfctstom): Defined without version dimensions.
+ (__elf_xfctstof): Likewise.
+ (__libelf_type_sizes): Define without version dimension.
+ (elf_typesize): Define using __libelf_type_sizes without version
+ dimension.
+ (__libelf_version_initialized): Remove definition.
+ (__libelf_version): Add definition.
+ (LIBELF_EV_IDX): Removed define.
+ (__libelf_type_aligns): Remove version dimension.
+ * nlist.c (nlist): Call elf_version unconditionally.
+
+2019-02-19 Mark Wielaard <[email protected]>
+
+ * elf_compress.c (do_deflate_cleanup): Remove ei_data argument,
+ check cdatap is not NULL before calling free.
+ (deflate_cleanup): Add cdata as argument.
+ (__libelf_compress): Also check whether the d_size is not zero
+ before converting data. Call deflate_cleanup with an extra
+ argument depending on whether there is converted data to free.
+ Always allocate allocate at least one byte for buf_out.
+
2019-02-14 Mark Wielaard <[email protected]>
* elf_begin.c (read_long_names): Make sure ar_size is properly
diff --git a/libelf/common.h b/libelf/common.h
index 744f1bb8..b0175f60 100644
--- a/libelf/common.h
+++ b/libelf/common.h
@@ -56,7 +56,7 @@ determine_kind (void *buf, size_t len)
if (eclass > ELFCLASSNONE && eclass < ELFCLASSNUM
&& data > ELFDATANONE && data < ELFDATANUM
- && version > EV_NONE && version < EV_NUM)
+ && version == EV_CURRENT)
return ELF_K_ELF;
}
@@ -68,7 +68,7 @@ determine_kind (void *buf, size_t len)
/* Allocate an Elf descriptor and fill in the generic information. */
static inline Elf *
__attribute__ ((unused))
-allocate_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
+allocate_elf (int fildes, void *map_address, int64_t offset, size_t maxsize,
Elf_Cmd cmd, Elf *parent, Elf_Kind kind, size_t extra)
{
Elf *result = (Elf *) calloc (1, sizeof (Elf) + extra);
diff --git a/libelf/elf.h b/libelf/elf.h
index 75043bcb..01648bdb 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -1,5 +1,5 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 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
@@ -360,8 +360,9 @@ typedef struct
#define EM_RISCV 243 /* RISC-V */
#define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */
+#define EM_CSKY 252 /* C-SKY */
-#define EM_NUM 248
+#define EM_NUM 253
/* Old spellings/synonyms. */
@@ -808,6 +809,9 @@ typedef struct
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension
registers */
+#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. */
/* Legal values for the note segment descriptor types for object files. */
@@ -1214,6 +1218,9 @@ typedef struct
#define AT_L3_CACHESIZE 46
#define AT_L3_CACHEGEOMETRY 47
+#define AT_MINSIGSTKSZ 51 /* Stack needed for signal delivery
+ (AArch64). */
+
/* Note section contents. Each entry in the note section begins with
a header of a fixed form. */
@@ -3015,6 +3022,81 @@ enum
/* Keep this the last entry. */
#define R_ARM_NUM 256
+/* C-SKY */
+#define R_CKCORE_NONE 0 /* no reloc */
+#define R_CKCORE_ADDR32 1 /* direct 32 bit (S + A) */
+#define R_CKCORE_PCRELIMM8BY4 2 /* disp ((S + A - P) >> 2) & 0xff */
+#define R_CKCORE_PCRELIMM11BY2 3 /* disp ((S + A - P) >> 1) & 0x7ff */
+#define R_CKCORE_PCREL32 5 /* 32-bit rel (S + A - P) */
+#define R_CKCORE_PCRELJSR_IMM11BY2 6 /* disp ((S + A - P) >>1) & 0x7ff */
+#define R_CKCORE_RELATIVE 9 /* 32 bit adjust program base(B + A)*/
+#define R_CKCORE_COPY 10 /* 32 bit adjust by program base */
+#define R_CKCORE_GLOB_DAT 11 /* off between got and sym (S) */
+#define R_CKCORE_JUMP_SLOT 12 /* PLT entry (S) */
+#define R_CKCORE_GOTOFF 13 /* offset to GOT (S + A - GOT) */
+#define R_CKCORE_GOTPC 14 /* PC offset to GOT (GOT + A - P) */
+#define R_CKCORE_GOT32 15 /* 32 bit GOT entry (G) */
+#define R_CKCORE_PLT32 16 /* 32 bit PLT entry (G) */
+#define R_CKCORE_ADDRGOT 17 /* GOT entry in GLOB_DAT (GOT + G) */
+#define R_CKCORE_ADDRPLT 18 /* PLT entry in GLOB_DAT (GOT + G) */
+#define R_CKCORE_PCREL_IMM26BY2 19 /* ((S + A - P) >> 1) & 0x3ffffff */
+#define R_CKCORE_PCREL_IMM16BY2 20 /* disp ((S + A - P) >> 1) & 0xffff */
+#define R_CKCORE_PCREL_IMM16BY4 21 /* disp ((S + A - P) >> 2) & 0xffff */
+#define R_CKCORE_PCREL_IMM10BY2 22 /* disp ((S + A - P) >> 1) & 0x3ff */
+#define R_CKCORE_PCREL_IMM10BY4 23 /* disp ((S + A - P) >> 2) & 0x3ff */
+#define R_CKCORE_ADDR_HI16 24 /* high & low 16 bit ADDR */
+ /* ((S + A) >> 16) & 0xffff */
+#define R_CKCORE_ADDR_LO16 25 /* (S + A) & 0xffff */
+#define R_CKCORE_GOTPC_HI16 26 /* high & low 16 bit GOTPC */
+ /* ((GOT + A - P) >> 16) & 0xffff */
+#define R_CKCORE_GOTPC_LO16 27 /* (GOT + A - P) & 0xffff */
+#define R_CKCORE_GOTOFF_HI16 28 /* high & low 16 bit GOTOFF */
+ /* ((S + A - GOT) >> 16) & 0xffff */
+#define R_CKCORE_GOTOFF_LO16 29 /* (S + A - GOT) & 0xffff */
+#define R_CKCORE_GOT12 30 /* 12 bit disp GOT entry (G) */
+#define R_CKCORE_GOT_HI16 31 /* high & low 16 bit GOT */
+ /* (G >> 16) & 0xffff */
+#define R_CKCORE_GOT_LO16 32 /* (G & 0xffff) */
+#define R_CKCORE_PLT12 33 /* 12 bit disp PLT entry (G) */
+#define R_CKCORE_PLT_HI16 34 /* high & low 16 bit PLT */
+ /* (G >> 16) & 0xffff */
+#define R_CKCORE_PLT_LO16 35 /* G & 0xffff */
+#define R_CKCORE_ADDRGOT_HI16 36 /* high & low 16 bit ADDRGOT */
+ /* (GOT + G * 4) & 0xffff */
+#define R_CKCORE_ADDRGOT_LO16 37 /* (GOT + G * 4) & 0xffff */
+#define R_CKCORE_ADDRPLT_HI16 38 /* high & low 16 bit ADDRPLT */
+ /* ((GOT + G * 4) >> 16) & 0xFFFF */
+#define R_CKCORE_ADDRPLT_LO16 39 /* (GOT+G*4) & 0xffff */
+#define R_CKCORE_PCREL_JSR_IMM26BY2 40 /* disp ((S+A-P) >>1) & x3ffffff */
+#define R_CKCORE_TOFFSET_LO16 41 /* (S+A-BTEXT) & 0xffff */
+#define R_CKCORE_DOFFSET_LO16 42 /* (S+A-BTEXT) & 0xffff */
+#define R_CKCORE_PCREL_IMM18BY2 43 /* disp ((S+A-P) >>1) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18 44 /* disp (S+A-BDATA) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18BY2 45 /* disp ((S+A-BDATA)>>1) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18BY4 46 /* disp ((S+A-BDATA)>>2) & 0x3ffff */
+#define R_CKCORE_GOT_IMM18BY4 48 /* disp (G >> 2) */
+#define R_CKCORE_PLT_IMM18BY4 49 /* disp (G >> 2) */
+#define R_CKCORE_PCREL_IMM7BY4 50 /* disp ((S+A-P) >>2) & 0x7f */
+#define R_CKCORE_TLS_LE32 51 /* 32 bit offset to TLS block */
+#define R_CKCORE_TLS_IE32 52
+#define R_CKCORE_TLS_GD32 53
+#define R_CKCORE_TLS_LDM32 54
+#define R_CKCORE_TLS_LDO32 55
+#define R_CKCORE_TLS_DTPMOD32 56
+#define R_CKCORE_TLS_DTPOFF32 57
+#define R_CKCORE_TLS_TPOFF32 58
+
+/* C-SKY elf header definition. */
+#define EF_CSKY_ABIMASK 0XF0000000
+#define EF_CSKY_OTHER 0X0FFF0000
+#define EF_CSKY_PROCESSOR 0X0000FFFF
+
+#define EF_CSKY_ABIV1 0X10000000
+#define EF_CSKY_ABIV2 0X20000000
+
+/* C-SKY attributes section. */
+#define SHT_CSKY_ATTRIBUTES (SHT_LOPROC + 1)
+
/* IA-64 specific declarations. */
/* Processor specific flags for the Ehdr e_flags field. */
@@ -3915,6 +3997,16 @@ enum
#define R_METAG_TLS_LE_HI16 60
#define R_METAG_TLS_LE_LO16 61
+/* NDS32 relocations. */
+#define R_NDS32_NONE 0
+#define R_NDS32_32_RELA 20
+#define R_NDS32_COPY 39
+#define R_NDS32_GLOB_DAT 40
+#define R_NDS32_JMP_SLOT 41
+#define R_NDS32_RELATIVE 42
+#define R_NDS32_TLS_TPOFF 102
+#define R_NDS32_TLS_DESC 119
+
__END_DECLS
#endif /* elf.h */
diff --git a/libelf/elf32_fsize.c b/libelf/elf32_fsize.c
index fddae91e..139f4a91 100644
--- a/libelf/elf32_fsize.c
+++ b/libelf/elf32_fsize.c
@@ -44,7 +44,7 @@ elfw2(LIBELFBITS, fsize) (Elf_Type type, size_t count, unsigned int version)
{
/* We do not have differences between file and memory sizes. Better
not since otherwise `mmap' would not work. */
- if (unlikely (version == EV_NONE) || unlikely (version >= EV_NUM))
+ if (unlikely (version != EV_CURRENT))
{
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
return 0;
@@ -56,13 +56,5 @@ elfw2(LIBELFBITS, fsize) (Elf_Type type, size_t count, unsigned int version)
return 0;
}
-#if EV_NUM != 2
- return (count
- * __libelf_type_sizes[version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
-#else
- return (count
- * __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
-#endif
+ return (count * __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
}
-#define local_strong_alias(n1, n2) strong_alias (n1, n2)
-local_strong_alias (elfw2(LIBELFBITS, fsize), __elfw2(LIBELFBITS, msize))
diff --git a/libelf/elf32_newphdr.c b/libelf/elf32_newphdr.c
index 4aa72137..7dd78ca9 100644
--- a/libelf/elf32_newphdr.c
+++ b/libelf/elf32_newphdr.c
@@ -56,6 +56,9 @@ elfw2(LIBELFBITS,newphdr) (Elf *elf, size_t count)
return NULL;
}
+ /* This check is correct, it is for sh_info, which is either
+ Elf32_Word or Elf64_Word, both being 32 bits. But count is size_t
+ so might not fit on 32bit ELF files. */
if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
{
__libelf_seterrno (ELF_E_INVALID_OPERAND);
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index 284bacc9..f67e6261 100644
--- a/libelf/elf32_updatefile.c
+++ b/libelf/elf32_updatefile.c
@@ -143,13 +143,8 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
if (unlikely (change_bo))
{
/* Today there is only one version of the ELF header. */
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
/* Do the real work. */
(*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
@@ -189,13 +184,8 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
if (unlikely (change_bo))
{
/* Today there is only one version of the ELF header. */
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
/* Do the real work. */
(*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
@@ -238,12 +228,8 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
+ ehdr->e_shoff);
char *const shdr_end = shdr_start + shnum * ehdr->e_shentsize;
-#if EV_NUM != 2
- xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
-#else
-# undef shdr_fctp
-# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
-#endif
+#undef shdr_fctp
+#define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
/* Get all sections into the array and sort them. */
@@ -358,13 +344,8 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
&& dl->data.d.d_size != 0
&& dl->data.d.d_type != ELF_T_BYTE))
{
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
size_t align;
align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
@@ -379,15 +360,30 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
else
{
/* We have to do the conversion on properly
- aligned memory first. */
+ aligned memory first. align is a power of 2,
+ but posix_memalign only works for alignments
+ which are a multiple of sizeof (void *).
+ So use normal malloc for smaller alignments. */
size_t size = dl->data.d.d_size;
- char *converted = aligned_alloc (align, size);
+ void *converted;
+ if (align < sizeof (void *))
+ converted = malloc (size);
+ else
+ {
+ int res;
+ res = posix_memalign (&converted, align, size);
+ if (res != 0)
+ converted = NULL;
+ }
+
if (converted == NULL)
{
+ free (scns);
__libelf_seterrno (ELF_E_NOMEM);
return 1;
}
- (*fctp) (converted, dl->data.d.d_buf, size, 1);
+
+ (*fctp) (converted, dl->data.d.d_buf, size, 1);
/* And then write it to the mmapped file. */
memcpy (last_position, converted, size);
@@ -502,7 +498,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
/* Helper function to write out fill bytes. */
static int
-fill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
+fill (int fd, int64_t pos, size_t len, char *fillbuf, size_t *filledp)
{
size_t filled = *filledp;
size_t fill_len = MIN (len, FILLBUFSIZE);
@@ -559,13 +555,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
if (unlikely (change_bo))
{
/* Today there is only one version of the ELF header. */
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
/* Write the converted ELF header in a temporary buffer. */
(*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
@@ -618,13 +609,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
if (unlikely (change_bo))
{
/* Today there is only one version of the ELF header. */
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
/* Allocate sufficient memory. */
tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
@@ -665,7 +651,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
/* From now on we have to keep track of the last position to eventually
fill the gaps with the prescribed fill byte. */
- off_t last_offset;
+ int64_t last_offset;
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
else
@@ -678,13 +664,9 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
+ sizeof (ElfW2(LIBELFBITS,Shdr)))))
return 1;
- off_t shdr_offset = elf->start_offset + ehdr->e_shoff;
-#if EV_NUM != 2
- xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
-#else
-# undef shdr_fctp
-# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
-#endif
+ int64_t shdr_offset = elf->start_offset + ehdr->e_shoff;
+#undef shdr_fctp
+#define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
ElfW2(LIBELFBITS,Shdr) *shdr_data;
ElfW2(LIBELFBITS,Shdr) *shdr_data_mem = NULL;
@@ -730,7 +712,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
if (shdr->sh_type == SHT_NOBITS)
goto next;
- off_t scn_start = elf->start_offset + shdr->sh_offset;
+ int64_t scn_start = elf->start_offset + shdr->sh_offset;
Elf_Data_List *dl = &scn->data_list;
bool scn_changed = false;
@@ -769,13 +751,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
if (unlikely (change_bo))
{
-#if EV_NUM != 2
- xfct_t fctp;
- fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
-#else
-# undef fctp
-# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
-#endif
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
buf = tmpbuf;
if (dl->data.d.d_size > MAX_TMPBUF)
diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
index 3e9ef61b..5f3cdbf6 100644
--- a/libelf/elf32_updatenull.c
+++ b/libelf/elf32_updatenull.c
@@ -45,6 +45,10 @@
# define LIBELFBITS 32
#endif
+/* Some fields contain 32/64 sizes. We cannot use Elf32/64_Word for those,
+ since those are both 32bits. Elf32/64_Xword is always 64bits. */
+#define Elf32_SizeWord Elf32_Word
+#define Elf64_SizeWord Elf64_Xword
static int
@@ -89,7 +93,7 @@ ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
ehdr->e_version = EV_CURRENT;
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
}
- else if (unlikely (ehdr->e_version >= EV_NUM))
+ else if (unlikely (ehdr->e_version != EV_CURRENT))
{
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
return 1;
@@ -122,7 +126,7 @@ ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
}
-off_t
+int64_t
internal_function
__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
{
@@ -137,7 +141,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
return -1;
/* At least the ELF header is there. */
- off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
+ ElfW2(LIBELFBITS,SizeWord) size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
/* Set the program header position. */
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
@@ -152,7 +156,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
{
/* The user is supposed to fill out e_phoff. Use it and
e_phnum to determine the maximum extend. */
- size = MAX ((size_t) size,
+ size = MAX (size,
ehdr->e_phoff
+ elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
}
@@ -205,11 +209,11 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
{
Elf_Scn *scn = &list->data[cnt];
ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
- off_t offset = 0;
+ int64_t offset = 0;
assert (shdr != NULL);
- ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
- ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
+ ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize;
+ ElfW2(LIBELFBITS,SizeWord) sh_align = shdr->sh_addralign ?: 1;
if (unlikely (! powerof2 (sh_align)))
{
__libelf_seterrno (ELF_E_INVALID_ALIGN);
@@ -280,8 +284,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
&& scn->rawdata.d.d_buf != NULL)
data = &scn->rawdata.d;
- if (unlikely (data->d_version == EV_NONE)
- || unlikely (data->d_version >= EV_NUM))
+ if (unlikely (data->d_version != EV_CURRENT))
{
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
return -1;
@@ -300,8 +303,8 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
/* The user specified the offset and the size.
All we have to do is check whether this block
fits in the size specified for the section. */
- if (unlikely ((GElf_Word) (data->d_off
- + data->d_size)
+ if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
+ (data->d_off + data->d_size)
> shdr->sh_size))
{
__libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
@@ -330,7 +333,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
if (elf->flags & ELF_F_LAYOUT)
{
- size = MAX ((GElf_Word) size,
+ size = MAX (size,
(shdr->sh_type != SHT_NOBITS
? shdr->sh_offset + shdr->sh_size : 0));
@@ -354,8 +357,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
size = (size + sh_align - 1) & ~(sh_align - 1);
int offset_changed = 0;
- update_if_changed (shdr->sh_offset, (GElf_Word) size,
- offset_changed);
+ update_if_changed (shdr->sh_offset, size, offset_changed);
changed |= offset_changed;
if (offset_changed && scn->data_list_rear == NULL)
@@ -367,12 +369,16 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
}
/* See whether the section size is correct. */
- update_if_changed (shdr->sh_size, (GElf_Word) offset,
- changed);
+ int size_changed = 0;
+ update_if_changed (shdr->sh_size,
+ (ElfW2(LIBELFBITS,SizeWord)) offset,
+ size_changed);
+ changed |= size_changed;
if (shdr->sh_type != SHT_NOBITS)
size += offset;
+ scn->shdr_flags |= (offset_changed | size_changed);
scn->flags |= changed;
}
@@ -382,7 +388,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
&& (elf->flags & ELF_F_PERMISSIVE) == 0)
{
/* For compressed sections check the uncompressed size. */
- ElfW2(LIBELFBITS,Word) sh_size;
+ ElfW2(LIBELFBITS,SizeWord) sh_size;
if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
sh_size = shdr->sh_size;
else
@@ -416,7 +422,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
/* The user is supposed to fill out e_shoff. Use it and
e_shnum (or sh_size of the dummy, first section header)
to determine the maximum extend. */
- size = MAX ((GElf_Word) size,
+ size = MAX (size,
(ehdr->e_shoff
+ (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
}
@@ -430,7 +436,7 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
- update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
+ update_if_changed (ehdr->e_shoff, size, elf->flags);
/* Account for the section header size. */
size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
diff --git a/libelf/elf32_xlatetof.c b/libelf/elf32_xlatetof.c
index ac4eaf40..082d833f 100644
--- a/libelf/elf32_xlatetof.c
+++ b/libelf/elf32_xlatetof.c
@@ -50,11 +50,7 @@ elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
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. */
-#if EV_NUM != 2
- size_t recsize = __libelf_type_sizes[src->d_version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
-#else
- size_t recsize = __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
-#endif
+ size_t recsize = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
if (src->d_size % recsize != 0)
{
@@ -97,15 +93,7 @@ elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
else
{
xfct_t fctp;
-
- /* Get a pointer to the transformation functions. The `#ifdef' is
- a small optimization since we don't anticipate another ELF
- version and so would waste "precious" code. */
-#if EV_NUM != 2
- fctp = __elf_xfctstom[dest->d_version - 1][src->d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
-#else
- fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
-#endif
+ fctp = __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
/* Do the real work. */
(*fctp) (dest->d_buf, src->d_buf, src->d_size, 1);
diff --git a/libelf/elf32_xlatetom.c b/libelf/elf32_xlatetom.c
index 3b94cac7..cb0bb8d5 100644
--- a/libelf/elf32_xlatetom.c
+++ b/libelf/elf32_xlatetom.c
@@ -50,11 +50,7 @@ elfw2(LIBELFBITS, xlatetom) (Elf_Data *dest, const Elf_Data *src,
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. */
-#if EV_NUM != 2
- size_t recsize = __libelf_type_sizes[src->d_version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
-#else
- size_t recsize = __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
-#endif
+ size_t recsize = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
/* We shouldn't require integer number of records when processing
@@ -102,15 +98,7 @@ elfw2(LIBELFBITS, xlatetom) (Elf_Data *dest, const Elf_Data *src,
else
{
xfct_t fctp;
-
- /* Get a pointer to the transformation functions. The `#ifdef' is
- a small optimization since we don't anticipate another ELF
- version and so would waste "precious" code. */
-#if EV_NUM != 2
- fctp = __elf_xfctstom[src->d_version - 1][dest->d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
-#else
- fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
-#endif
+ fctp = __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
/* Do the real work. */
(*fctp) (dest->d_buf, src->d_buf, src->d_size, 0);
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index fde14c61..8107a103 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -71,8 +71,8 @@ file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
static size_t
-get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
- size_t maxsize)
+get_shnum (void *map_address, unsigned char *e_ident, int fildes,
+ int64_t offset, size_t maxsize)
{
size_t result;
union
@@ -243,6 +243,9 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
CONVERT (size);
}
+ /* Although sh_size is an Elf64_Xword and can contain a 64bit
+ value, we only expect an 32bit value max. GElf_Word is
+ 32bit unsigned. */
if (size > ~((GElf_Word) 0))
{
/* Invalid value, it is too large. */
@@ -266,7 +269,7 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
/* Create descriptor for ELF file in memory. */
static Elf *
file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
- off_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
+ int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
{
/* Verify the binary is of the class we can handle. */
if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
@@ -531,7 +534,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
Elf *
internal_function
-__libelf_read_mmaped_file (int fildes, void *map_address, off_t offset,
+__libelf_read_mmaped_file (int fildes, void *map_address, int64_t offset,
size_t maxsize, Elf_Cmd cmd, Elf *parent)
{
/* We have to find out what kind of file this is. We handle ELF
@@ -564,7 +567,7 @@ __libelf_read_mmaped_file (int fildes, void *map_address, off_t offset,
static Elf *
-read_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
+read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
Elf *parent)
{
/* We have to find out what kind of file this is. We handle ELF
@@ -626,7 +629,7 @@ read_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
/* Open a file for reading. If possible we will try to mmap() the file. */
static struct Elf *
-read_file (int fildes, off_t offset, size_t maxsize,
+read_file (int fildes, int64_t offset, size_t maxsize,
Elf_Cmd cmd, Elf *parent)
{
void *map_address = NULL;
@@ -1108,7 +1111,7 @@ elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
{
Elf *retval;
- if (unlikely (! __libelf_version_initialized))
+ if (unlikely (__libelf_version != EV_CURRENT))
{
/* Version wasn't set so far. */
__libelf_seterrno (ELF_E_NO_VERSION);
diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index be9eeaba..244467b5 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -44,17 +44,17 @@
/* Cleanup and return result. Don't leak memory. */
static void *
do_deflate_cleanup (void *result, z_stream *z, void *out_buf,
- int ei_data, Elf_Data *cdatap)
+ Elf_Data *cdatap)
{
deflateEnd (z);
free (out_buf);
- if (ei_data != MY_ELFDATA)
+ if (cdatap != NULL)
free (cdatap->d_buf);
return result;
}
-#define deflate_cleanup(result) \
- do_deflate_cleanup(result, &z, out_buf, ei_data, &cdata)
+#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
@@ -127,7 +127,8 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
{
/* Convert to raw if different endianess. */
cdata = *data;
- if (ei_data != MY_ELFDATA)
+ 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. */
@@ -135,10 +136,10 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
if (cdata.d_buf == NULL)
{
__libelf_seterrno (ELF_E_NOMEM);
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, NULL);
}
if (gelf_xlatetof (scn->elf, &cdata, data, ei_data) == NULL)
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, &cdata);
}
z.avail_in = cdata.d_size;
@@ -164,7 +165,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
if (zrc == Z_STREAM_ERROR)
{
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, convert ? &cdata : NULL);
}
used += (out_size - used) - z.avail_out;
@@ -172,7 +173,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
compression forced and we are using more compressed data
than original data. */
if (!force && flush == Z_FINISH && used >= *orig_size)
- return deflate_cleanup ((void *) -1);
+ return deflate_cleanup ((void *) -1, convert ? &cdata : NULL);
if (z.avail_out == 0)
{
@@ -180,7 +181,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
if (bigger == NULL)
{
__libelf_seterrno (ELF_E_NOMEM);
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, convert ? &cdata : NULL);
}
out_buf = bigger;
out_size += block;
@@ -188,7 +189,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
}
while (z.avail_out == 0); /* Need more output buffer. */
- if (ei_data != MY_ELFDATA)
+ if (convert)
{
free (cdata.d_buf);
cdata.d_buf = NULL;
@@ -200,7 +201,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
if (zrc != Z_OK)
{
__libelf_seterrno (ELF_E_COMPRESS_ERROR);
- return deflate_cleanup (NULL);
+ return deflate_cleanup (NULL, NULL);
}
*new_size = used;
@@ -220,7 +221,11 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t size_out)
return NULL;
}
- void *buf_out = malloc (size_out);
+ /* Malloc might return NULL when requestion 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);
@@ -308,7 +313,7 @@ __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size, size_t align,
{
/* This is the new raw data, replace and possibly free old data. */
scn->rawdata.d.d_off = 0;
- scn->rawdata.d.d_version = __libelf_version;
+ scn->rawdata.d.d_version = EV_CURRENT;
scn->rawdata.d.d_buf = buf;
scn->rawdata.d.d_size = size;
scn->rawdata.d.d_align = align;
diff --git a/libelf/elf_getaroff.c b/libelf/elf_getaroff.c
index 5b59203f..5c102ad6 100644
--- a/libelf/elf_getaroff.c
+++ b/libelf/elf_getaroff.c
@@ -38,7 +38,7 @@
#include "libelfP.h"
-off_t
+int64_t
elf_getaroff (Elf *elf)
{
/* Be gratious, the specs demand it. */
diff --git a/libelf/elf_getbase.c b/libelf/elf_getbase.c
index 8ec5f87e..4890d336 100644
--- a/libelf/elf_getbase.c
+++ b/libelf/elf_getbase.c
@@ -37,8 +37,8 @@
#include "libelfP.h"
-off_t
+int64_t
elf_getbase (Elf *elf)
{
- return elf == NULL ? (off_t) -1 : elf->start_offset;
+ return elf == NULL ? (int64_t) -1 : elf->start_offset;
}
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 639a798e..40fe1694 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -50,10 +50,8 @@
: 0))
/* Associate section types with libelf types. */
-static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
+static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
{
- [EV_CURRENT - 1] =
- {
[SHT_SYMTAB] = ELF_T_SYM,
[SHT_RELA] = ELF_T_RELA,
[SHT_HASH] = ELF_T_WORD,
@@ -73,11 +71,10 @@ static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
[TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
[TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
[TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
- }
};
/* Associate libelf types with their internal alignment requirements. */
-const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] =
+const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
{
# define TYPE_ALIGNS(Bits) \
{ \
@@ -108,11 +105,8 @@ const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM]
[ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
[ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */ \
}
- [EV_CURRENT - 1] =
- {
[ELFCLASS32 - 1] = TYPE_ALIGNS (32),
[ELFCLASS64 - 1] = TYPE_ALIGNS (64),
- }
# undef TYPE_ALIGNS
};
@@ -131,7 +125,7 @@ __libelf_data_type (Elf *elf, int sh_type, GElf_Xword align)
}
else
{
- Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (sh_type)];
+ Elf_Type t = shtype_map[TYPEIDX (sh_type)];
/* Special case for GNU Property notes. */
if (t == ELF_T_NHDR && align == 8)
t = ELF_T_NHDR8;
@@ -141,7 +135,7 @@ __libelf_data_type (Elf *elf, int sh_type, GElf_Xword align)
/* Convert the data in the current section. */
static void
-convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
+convert_data (Elf_Scn *scn, int eclass,
int data, size_t size, Elf_Type type)
{
const size_t align = __libelf_type_align (eclass, type);
@@ -195,11 +189,7 @@ convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
}
/* Get the conversion function. */
-#if EV_NUM != 2
- fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
-#else
- fp = __elf_xfctstom[0][0][eclass - 1][type];
-#endif
+ fp = __elf_xfctstom[eclass - 1][type];
fp (scn->data_base, rawdata_source, size, 0);
@@ -285,14 +275,14 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn)
}
else
{
- Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)];
+ Elf_Type t = shtype_map[TYPEIDX (type)];
if (t == ELF_T_NHDR && align == 8)
t = ELF_T_NHDR8;
if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
|| (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
entsize = 1;
else
- entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t];
+ entsize = __libelf_type_sizes[elf->class - 1][t];
}
/* We assume it is an array of bytes if it is none of the structured
@@ -444,7 +434,7 @@ __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
}
/* Convert according to the version and the type. */
- convert_data (scn, __libelf_version, elf->class,
+ convert_data (scn, elf->class,
(elf->class == ELFCLASS32
|| (offsetof (struct Elf, state.elf32.ehdr)
== offsetof (struct Elf, state.elf64.ehdr))
diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c
index d0c0b75f..1072f7de 100644
--- a/libelf/elf_getdata_rawchunk.c
+++ b/libelf/elf_getdata_rawchunk.c
@@ -41,7 +41,7 @@
#include "common.h"
Elf_Data *
-elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type)
+elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
{
if (unlikely (elf == NULL))
return NULL;
@@ -151,8 +151,7 @@ elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type)
}
/* Call the conversion function. */
- (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type])
- (buffer, rawchunk, size, 0);
+ (*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0);
}
/* Allocate the dummy container to point at this buffer. */
@@ -171,7 +170,7 @@ elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type)
chunk->data.d.d_size = size;
chunk->data.d.d_type = type;
chunk->data.d.d_align = align;
- chunk->data.d.d_version = __libelf_version;
+ chunk->data.d.d_version = EV_CURRENT;
rwlock_unlock (elf->lock);
rwlock_wrlock (elf->lock);
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
index f6609a80..896f22cd 100644
--- a/libelf/elf_newdata.c
+++ b/libelf/elf_newdata.c
@@ -117,7 +117,7 @@ elf_newdata (Elf_Scn *scn)
}
/* Set the predefined values. */
- result->data.d.d_version = __libelf_version;
+ result->data.d.d_version = EV_CURRENT;
result->data.s = scn;
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index 36997c2b..9b8867ce 100644
--- a/libelf/elf_update.c
+++ b/libelf/elf_update.c
@@ -40,8 +40,8 @@
#include "libelfP.h"
-static off_t
-write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
+static int64_t
+write_file (Elf *elf, int64_t size, int change_bo, size_t shnum)
{
int class = elf->class;
@@ -164,11 +164,11 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
}
-off_t
+int64_t
elf_update (Elf *elf, Elf_Cmd cmd)
{
size_t shnum;
- off_t size;
+ int64_t size;
int change_bo = 0;
if (cmd != ELF_C_NULL
diff --git a/libelf/elf_version.c b/libelf/elf_version.c
index 7c336ff9..6ec534ab 100644
--- a/libelf/elf_version.c
+++ b/libelf/elf_version.c
@@ -34,32 +34,25 @@
#include <libelfP.h>
-/* Is the version initialized? */
-int __libelf_version_initialized;
-
-/* Currently selected version. */
-unsigned int __libelf_version = EV_CURRENT;
-
+/* 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;
unsigned int
elf_version (unsigned int version)
{
if (version == EV_NONE)
- return __libelf_version;
+ return EV_CURRENT;
- if (likely (version < EV_NUM))
+ if (likely (version == EV_CURRENT))
{
/* Phew, we know this version. */
- unsigned int last_version = __libelf_version;
-
- /* Store the new version. */
- __libelf_version = version;
/* Signal that the version is now initialized. */
- __libelf_version_initialized = 1;
+ __libelf_version = EV_CURRENT;
- /* And return the last version. */
- return last_version;
+ /* And return the last (or initial) version. */
+ return EV_CURRENT;
}
/* We cannot handle this version. */
diff --git a/libelf/gelf_fsize.c b/libelf/gelf_fsize.c
index d04ec5d5..493d7916 100644
--- a/libelf/gelf_fsize.c
+++ b/libelf/gelf_fsize.c
@@ -38,10 +38,8 @@
/* These are the sizes for all the known types. */
-const size_t __libelf_type_sizes[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] =
+const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM] =
{
- /* We have no entry for EV_NONE since we have to set an error. */
- [EV_CURRENT - 1] = {
[ELFCLASS32 - 1] = {
#define TYPE_SIZES(LIBELFBITS) \
[ELF_T_ADDR] = ELFW2(LIBELFBITS, FSZ_ADDR), \
@@ -77,7 +75,6 @@ const size_t __libelf_type_sizes[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] =
[ELFCLASS64 - 1] = {
TYPE_SIZES (64)
}
- }
};
@@ -89,7 +86,7 @@ gelf_fsize (Elf *elf, Elf_Type type, size_t count, unsigned int version)
if (elf == NULL)
return 0;
- if (version == EV_NONE || version >= EV_NUM)
+ if (version != EV_CURRENT)
{
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
return 0;
@@ -101,10 +98,6 @@ gelf_fsize (Elf *elf, Elf_Type type, size_t count, unsigned int version)
return 0;
}
-#if EV_NUM != 2
- return count * __libelf_type_sizes[version - 1][elf->class - 1][type];
-#else
- return count * __libelf_type_sizes[0][elf->class - 1][type];
-#endif
+ return count * __libelf_type_sizes[elf->class - 1][type];
}
INTDEF(gelf_fsize)
diff --git a/libelf/gelf_getnote.c b/libelf/gelf_getnote.c
index 6d33b355..0f7b9d68 100644
--- a/libelf/gelf_getnote.c
+++ b/libelf/gelf_getnote.c
@@ -80,11 +80,12 @@ gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
the offset, after adding the namesz, and include padding
in descsz to get to the end. */
*name_offset = offset;
- offset += n->n_namesz;
- if (offset > data->d_size)
+ if (n->n_namesz > data->d_size
+ || offset > data->d_size - n->n_namesz)
offset = 0;
else
{
+ offset += n->n_namesz;
/* Include padding. Check below for overflow. */
GElf_Word descsz = (data->d_type == ELF_T_NHDR8
? NOTE_ALIGN8 (n->n_descsz)
diff --git a/libelf/gelf_xlate.c b/libelf/gelf_xlate.c
index b5d6ef3d..b9e7fd65 100644
--- a/libelf/gelf_xlate.c
+++ b/libelf/gelf_xlate.c
@@ -170,10 +170,8 @@ union unaligned
/* Now the externally visible table with the function pointers. */
-const xfct_t __elf_xfctstom[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] =
+const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM] =
{
- [EV_CURRENT - 1] = {
- [EV_CURRENT - 1] = {
[ELFCLASS32 - 1] = {
#define define_xfcts(Bits) \
[ELF_T_BYTE] = elf_cvt_Byte, \
@@ -209,10 +207,4 @@ const xfct_t __elf_xfctstom[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM]
define_xfcts (64),
[ELF_T_GNUHASH] = elf_cvt_gnuhash
}
- }
- }
};
-/* For now we only handle the case where the memory representation is the
- same as the file representation. Should this change we have to define
- separate functions. For now reuse them. */
-strong_alias (__elf_xfctstom, __elf_xfctstof)
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 9f3e8e9d..b55d5c48 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -296,7 +296,7 @@ struct Elf
int fildes;
/* Offset in the archive this file starts or zero. */
- off_t start_offset;
+ int64_t start_offset;
/* Size of the file in the archive or the entire file size, or ~0
for an (yet) unknown size. */
@@ -350,7 +350,7 @@ struct Elf
int ehdr_flags; /* Flags (dirty) for ELF header. */
int phdr_flags; /* Flags (dirty|malloc) for program header. */
int shdr_malloced; /* Nonzero if shdr array was allocated. */
- off_t sizestr_offset; /* Offset of the size string in the parent
+ int64_t sizestr_offset; /* Offset of the size string in the parent
if this is an archive member. */
Elf32_Ehdr ehdr_mem; /* Memory used for ELF header when not
mmaped. */
@@ -375,7 +375,7 @@ struct Elf
int ehdr_flags; /* Flags (dirty) for ELF header. */
int phdr_flags; /* Flags (dirty|malloc) for program header. */
int shdr_malloced; /* Nonzero if shdr array was allocated. */
- off_t sizestr_offset; /* Offset of the size string in the parent
+ int64_t sizestr_offset; /* Offset of the size string in the parent
if this is an archive member. */
Elf64_Ehdr ehdr_mem; /* Memory used for ELF header when not
mmaped. */
@@ -392,7 +392,7 @@ struct Elf
char *long_names; /* If no index is available but long names
are used this elements points to the data.*/
size_t long_names_len; /* Length of the long name table. */
- off_t offset; /* Offset in file we are currently at.
+ 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'. */
@@ -411,43 +411,30 @@ struct Elf
typedef void (*xfct_t) (void *, const void *, size_t, int);
/* The table with the function pointers. */
-extern const xfct_t __elf_xfctstom[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
-extern const xfct_t __elf_xfctstof[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
+extern const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM]
+ attribute_hidden;
/* Array with sizes of the external types indexed by ELF version, binary
class, and type. */
-extern const size_t __libelf_type_sizes[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
+extern const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM]
+ attribute_hidden;
/* We often have to access the size for a type in the current version. */
-#if EV_NUM != 2
-# define elf_typesize(class,type,n) \
- elfw2(class,fsize) (type, n, __libelf_version)
-#else
# define elf_typesize(class,type,n) \
- (__libelf_type_sizes[EV_CURRENT - 1][ELFW(ELFCLASS,class) - 1][type] * n)
-#endif
-
-/* Currently selected version of the ELF specification. */
-extern unsigned int __libelf_version attribute_hidden;
+ (__libelf_type_sizes[ELFW(ELFCLASS,class) - 1][type] * n)
/* The byte value used for filling gaps. */
extern int __libelf_fill_byte attribute_hidden;
-/* Nonzero if the version was set. */
-extern int __libelf_version_initialized attribute_hidden;
-
-/* Index for __libelf_type_sizes et al. */
-#if EV_NUM == 2
-# define LIBELF_EV_IDX 0
-#else
-# define LIBELF_EV_IDX (__libelf_version - 1)
-#endif
+/* EV_CURRENT if the version was set, EV_NONE otherwise. */
+extern unsigned int __libelf_version attribute_hidden;
-/* Array with alignment requirements of the internal types indexed by ELF
- version, binary class, and type. */
-extern const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden;
+/* Array with alignment requirements of the internal types indexed by
+ binary class, and type. */
+extern const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM]
+ attribute_hidden;
# define __libelf_type_align(class, type) \
- (__libelf_type_aligns[LIBELF_EV_IDX][class - 1][type] ?: 1)
+ (__libelf_type_aligns[class - 1][type] ?: 1)
/* Given an Elf handle and a section type returns the Elf_Data d_type.
Should not be called when SHF_COMPRESSED is set, the d_type should
@@ -455,20 +442,10 @@ extern const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_
extern Elf_Type __libelf_data_type (Elf *elf, int sh_type, GElf_Xword align)
internal_function;
-/* The libelf API does not have such a function but it is still useful.
- Get the memory size for the given type.
-
- These functions cannot be marked internal since they are aliases
- of the export elfXX_fsize functions.*/
-extern size_t __elf32_msize (Elf_Type __type, size_t __count,
- unsigned int __version) __const_attribute__;
-extern size_t __elf64_msize (Elf_Type __type, size_t __count,
- unsigned int __version) __const_attribute__;
-
/* Create Elf descriptor from memory image. */
extern Elf *__libelf_read_mmaped_file (int fildes, void *map_address,
- off_t offset, size_t maxsize,
+ int64_t offset, size_t maxsize,
Elf_Cmd cmd, Elf *parent)
internal_function;
@@ -490,10 +467,10 @@ extern int __libelf_set_rawdata_wrlock (Elf_Scn *scn) internal_function;
/* Helper functions for elf_update. */
-extern off_t __elf32_updatenull_wrlock (Elf *elf, int *change_bop,
- size_t shnum) internal_function;
-extern off_t __elf64_updatenull_wrlock (Elf *elf, int *change_bop,
- size_t shnum) internal_function;
+extern int64_t __elf32_updatenull_wrlock (Elf *elf, int *change_bop,
+ size_t shnum) internal_function;
+extern int64_t __elf64_updatenull_wrlock (Elf *elf, int *change_bop,
+ size_t shnum) internal_function;
extern int __elf32_updatemmap (Elf *elf, int change_bo, size_t shnum)
internal_function;
diff --git a/libelf/nlist.c b/libelf/nlist.c
index c7b32fdb..8593c1de 100644
--- a/libelf/nlist.c
+++ b/libelf/nlist.c
@@ -80,9 +80,8 @@ nlist (const char *filename, struct nlist *nl)
/* For compatibility reasons (`nlist' existed before ELF and libelf)
we don't expect the caller to set the ELF version. Do this here
- if it hasn't happened yet. */
- if (__libelf_version_initialized == 0)
- INTUSE(elf_version) (EV_CURRENT);
+ as if it hasn't happened yet. */
+ INTUSE(elf_version) (EV_CURRENT);
/* Now get an ELF descriptor. */
elf = INTUSE(elf_begin) (fd, ELF_C_READ_MMAP, NULL);
diff --git a/libelf/note_xlate.h b/libelf/note_xlate.h
index bc9950ff..7e2784b0 100644
--- a/libelf/note_xlate.h
+++ b/libelf/note_xlate.h
@@ -47,13 +47,25 @@ elf_cvt_note (void *dest, const void *src, size_t len, int encode,
note_len += n->n_namesz;
note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len);
if (note_len > len || note_len < sizeof *n)
- break;
+ {
+ /* Header was translated, nothing else. */
+ len -= sizeof *n;
+ src += sizeof *n;
+ dest += sizeof *n;
+ break;
+ }
/* data as a whole needs to be aligned. */
note_len += n->n_descsz;
note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len);
if (note_len > len || note_len < sizeof *n)
- break;
+ {
+ /* Header was translated, nothing else. */
+ len -= sizeof *n;
+ src += sizeof *n;
+ dest += sizeof *n;
+ break;
+ }
/* Copy or skip the note data. */
size_t note_data_len = note_len - sizeof *n;