diff options
author | Mark Wielaard <[email protected]> | 2020-06-09 18:21:36 +0200 |
---|---|---|
committer | Mark Wielaard <[email protected]> | 2020-06-09 18:21:36 +0200 |
commit | c0d643e7d91fc002c9fecd83277c62a0e56ef76f (patch) | |
tree | 89b5cf6673baa2cb206fdf245f4e30fe884945ad /libelf | |
parent | 14030673602a4f331f348decd51e5f0160719f0e (diff) | |
parent | 5643e037cb7a38ed5d52f50421be706ea8014e3d (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/ChangeLog | 128 | ||||
-rw-r--r-- | libelf/common.h | 4 | ||||
-rw-r--r-- | libelf/elf.h | 96 | ||||
-rw-r--r-- | libelf/elf32_fsize.c | 12 | ||||
-rw-r--r-- | libelf/elf32_newphdr.c | 3 | ||||
-rw-r--r-- | libelf/elf32_updatefile.c | 99 | ||||
-rw-r--r-- | libelf/elf32_updatenull.c | 44 | ||||
-rw-r--r-- | libelf/elf32_xlatetof.c | 16 | ||||
-rw-r--r-- | libelf/elf32_xlatetom.c | 16 | ||||
-rw-r--r-- | libelf/elf_begin.c | 17 | ||||
-rw-r--r-- | libelf/elf_compress.c | 33 | ||||
-rw-r--r-- | libelf/elf_getaroff.c | 2 | ||||
-rw-r--r-- | libelf/elf_getbase.c | 4 | ||||
-rw-r--r-- | libelf/elf_getdata.c | 26 | ||||
-rw-r--r-- | libelf/elf_getdata_rawchunk.c | 7 | ||||
-rw-r--r-- | libelf/elf_newdata.c | 2 | ||||
-rw-r--r-- | libelf/elf_update.c | 8 | ||||
-rw-r--r-- | libelf/elf_version.c | 23 | ||||
-rw-r--r-- | libelf/gelf_fsize.c | 13 | ||||
-rw-r--r-- | libelf/gelf_getnote.c | 5 | ||||
-rw-r--r-- | libelf/gelf_xlate.c | 10 | ||||
-rw-r--r-- | libelf/libelfP.h | 65 | ||||
-rw-r--r-- | libelf/nlist.c | 5 | ||||
-rw-r--r-- | libelf/note_xlate.h | 16 |
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; |