Index: head/lib/libelf/Makefile =================================================================== --- head/lib/libelf/Makefile (revision 165534) +++ head/lib/libelf/Makefile (revision 165535) @@ -1,160 +1,163 @@ # $FreeBSD$ LIB= elf SRCS= elf_begin.c \ elf_cntl.c \ elf_end.c elf_errmsg.c elf_errno.c \ elf_data.c \ elf_fill.c \ elf_flag.c \ elf_getarhdr.c \ elf_getarsym.c \ elf_getbase.c \ elf_getident.c \ elf_hash.c \ elf_kind.c \ elf_memory.c \ elf_next.c \ elf_rand.c \ elf_rawfile.c \ + elf_phnum.c \ elf_shnum.c \ elf_shstrndx.c \ elf_scn.c \ elf_strptr.c \ elf_update.c \ elf_version.c \ gelf_cap.c \ gelf_checksum.c \ gelf_dyn.c \ gelf_ehdr.c \ gelf_getclass.c \ gelf_fsize.c \ gelf_move.c \ gelf_phdr.c \ gelf_rel.c \ gelf_rela.c \ gelf_shdr.c \ gelf_sym.c \ gelf_syminfo.c \ gelf_symshndx.c \ gelf_xlate.c \ libelf.c \ libelf_align.c \ libelf_allocate.c \ libelf_ar.c \ libelf_checksum.c \ libelf_data.c \ libelf_ehdr.c \ + libelf_extended.c \ libelf_phdr.c \ libelf_shdr.c \ libelf_xlate.c \ ${GENSRCS} INCS= libelf.h gelf.h GENSRCS= libelf_fsize.c libelf_msize.c libelf_convert.c CLEANFILES= ${GENSRCS} CFLAGS+= -I. -I${.CURDIR} SHLIB_MAJOR= 1 WARNS?= 6 MAN= elf.3 \ elf_begin.3 \ elf_cntl.3 \ elf_end.3 elf_errmsg.3 \ elf_fill.3 \ elf_flagdata.3 \ elf_getarhdr.3 \ elf_getarsym.3 \ elf_getbase.3 \ elf_getdata.3 \ elf_getident.3 \ elf_getscn.3 \ + elf_getphnum.3 \ elf_getshnum.3 \ elf_getshstrndx.3 \ elf_hash.3 \ elf_kind.3 \ elf_memory.3 \ elf_next.3 \ elf_rawfile.3 \ elf_rand.3 \ elf_strptr.3 \ elf_update.3 \ elf_version.3 \ gelf.3 \ gelf_checksum.3 \ gelf_fsize.3 \ gelf_getcap.3 \ gelf_getclass.3 \ gelf_getdyn.3 \ gelf_getehdr.3 \ gelf_getmove.3 \ gelf_getphdr.3 \ gelf_getrel.3 \ gelf_getrela.3 \ gelf_getshdr.3 \ gelf_getsym.3 \ gelf_getsyminfo.3 \ gelf_getsymshndx.3 \ gelf_newehdr.3 \ gelf_newphdr.3 \ gelf_update_ehdr.3 \ gelf_xlatetof.3 MLINKS+= \ elf_errmsg.3 elf_errno.3 \ elf_flagdata.3 elf_flagehdr.3 \ elf_flagdata.3 elf_flagelf.3 \ elf_flagdata.3 elf_flagphdr.3 \ elf_flagdata.3 elf_flagscn.3 \ elf_flagdata.3 elf_flagshdr.3 \ elf_getdata.3 elf_newdata.3 \ elf_getdata.3 elf_rawdata.3 \ elf_getscn.3 elf_ndxscn.3 \ elf_getscn.3 elf_newscn.3 \ elf_getscn.3 elf_nextscn.3 \ elf_getshstrndx.3 elf_setshstrndx.3 \ gelf_getcap.3 gelf_update_cap.3 \ gelf_getdyn.3 gelf_update_dyn.3 \ gelf_getmove.3 gelf_update_move.3 \ gelf_getrel.3 gelf_update_rel.3 \ gelf_getrela.3 gelf_update_rela.3 \ gelf_getsym.3 gelf_update_sym.3 \ gelf_getsyminfo.3 gelf_update_syminfo.3 \ gelf_getsymshndx.3 gelf_update_symshndx.3 \ gelf_update_ehdr.3 gelf_update_phdr.3 \ gelf_update_ehdr.3 gelf_update_shdr.3 \ gelf_xlatetof.3 gelf_xlatetom.3 .for E in 32 64 MLINKS+= \ gelf_checksum.3 elf${E}_checksum.3 \ gelf_fsize.3 elf${E}_fsize.3 \ gelf_getehdr.3 elf${E}_getehdr.3 \ gelf_getphdr.3 elf${E}_getphdr.3 \ gelf_getshdr.3 elf${E}_getshdr.3 \ gelf_newehdr.3 elf${E}_newehdr.3 \ gelf_newphdr.3 elf${E}_newphdr.3 \ gelf_xlatetof.3 elf${E}_xlatetof.3 \ gelf_xlatetof.3 elf${E}_xlatetom.3 .endfor VERSION_MAP= ${.CURDIR}/Version.map LIBELF_TEST_HOOKS?= 1 .if defined(LIBELF_TEST_HOOKS) && (${LIBELF_TEST_HOOKS} > 0) CFLAGS+= -DLIBELF_TEST_HOOKS=1 .endif libelf_convert.c: elf_types.m4 libelf_convert.m4 libelf_fsize.c: elf_types.m4 libelf_fsize.m4 libelf_msize.c: elf_types.m4 libelf_msize.m4 .include # Keep the .SUFFIXES line after the include of bsd.lib.mk .SUFFIXES: .m4 .c .m4.c: m4 -D SRCDIR=${.CURDIR} ${.IMPSRC} > ${.TARGET} Index: head/lib/libelf/Version.map =================================================================== --- head/lib/libelf/Version.map (revision 165534) +++ head/lib/libelf/Version.map (revision 165535) @@ -1,101 +1,102 @@ # # $FreeBSD$ # FBSD_1.0 { global: elf32_checksum; elf32_fsize; elf32_getehdr; elf32_getphdr; elf32_getshdr; elf32_newehdr; elf32_newphdr; elf32_xlatetof; elf32_xlatetom; elf64_checksum; elf64_fsize; elf64_getehdr; elf64_getphdr; elf64_getshdr; elf64_newehdr; elf64_newphdr; elf64_xlatetof; elf64_xlatetom; elf_begin; elf_cntl; elf_end; elf_errmsg; elf_errno; elf_fill; elf_flagdata; elf_flagehdr; elf_flagelf; elf_flagphdr; elf_flagscn; elf_flagshdr; elf_getarhdr; elf_getarsym; elf_getbase; elf_getdata; elf_getident; elf_getscn; + elf_getphnum; elf_getshnum; elf_getshstrndx; elf_hash; elf_kind; elf_memory; elf_ndxscn; elf_newdata; elf_newscn; elf_next; elf_nextscn; elf_rand; elf_rawdata; elf_rawfile; elf_setshstrndx; elf_strptr; elf_update; elf_version; gelf_checksum; gelf_fsize; gelf_getcap; gelf_getclass; gelf_getdyn; gelf_getehdr; gelf_getmove; gelf_getphdr; gelf_getrel; gelf_getrela; gelf_getshdr; gelf_getsym; gelf_getsyminfo; gelf_getsymshndx; gelf_newehdr; gelf_newphdr; gelf_update_cap; gelf_update_dyn; gelf_update_ehdr; gelf_update_move; gelf_update_phdr; gelf_update_rel; gelf_update_rela; gelf_update_shdr; gelf_update_sym; gelf_update_syminfo; gelf_update_symshndx; gelf_xlatetof; gelf_xlatetom; local: *; }; # # Private symbols, mostly test hooks # FBSDprivate { global: _libelf_set_error; _libelf_get_max_error; _libelf_get_no_error_message; _libelf_get_unknown_error_message; }; Index: head/lib/libelf/_libelf.h =================================================================== --- head/lib/libelf/_libelf.h (revision 165534) +++ head/lib/libelf/_libelf.h (revision 165535) @@ -1,191 +1,193 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __LIBELF_H_ #define __LIBELF_H_ #include #ifndef NULL #define NULL ((void *) 0) #endif /* * Library-private data structures. */ #define LIBELF_MSG_SIZE 256 struct _libelf_globals { int libelf_arch; unsigned int libelf_byteorder; int libelf_class; int libelf_error; int libelf_fillchar; unsigned int libelf_version; char libelf_msg[LIBELF_MSG_SIZE]; }; extern struct _libelf_globals _libelf; #define LIBELF_PRIVATE(N) (_libelf.libelf_##N) #define LIBELF_ELF_ERROR_MASK 0xFF #define LIBELF_OS_ERROR_SHIFT 8 #define LIBELF_SET_ERROR(E, O) do { \ LIBELF_PRIVATE(error) = ((ELF_E_##E & LIBELF_ELF_ERROR_MASK)| \ ((O) << LIBELF_OS_ERROR_SHIFT)); \ } while (0) #define LIBELF_ADJUST_AR_SIZE(S) (((S) + 1U) & ~1U) /* * Flags for library internal use. These use the upper 16 bits of a * flags field. */ #define LIBELF_F_MALLOCED 0x010000 /* whether data was malloc'ed */ #define LIBELF_F_MMAP 0x020000 /* whether e_rawfile was mmap'ed */ +#define LIBELF_F_SHDRS_LOADED 0x040000 /* whether all shdrs were read in */ struct _Elf { int e_activations; /* activation count */ Elf_Arhdr *e_arhdr; /* header for archive members */ unsigned int e_byteorder; /* ELFDATA* */ int e_class; /* ELFCLASS* */ Elf_Cmd e_cmd; /* ELF_C_* used at creation time */ int e_fd; /* associated file descriptor */ unsigned int e_flags; /* ELF_F_*, LIBELF_F_* flags */ Elf_Kind e_kind; /* ELF_K_* */ Elf *e_parent; /* non-NULL for archive members */ char *e_rawfile; /* uninterpreted bytes */ size_t e_rawsize; /* size of uninterpreted bytes */ unsigned int e_version; /* file version */ union { struct { /* ar(1) archives */ off_t e_next; /* set by elf_rand()/elf_next() */ int e_nchildren; char *e_rawstrtab; /* file name strings */ size_t e_rawstrtabsz; char *e_rawsymtab; /* symbol table */ size_t e_rawsymtabsz; Elf_Arsym *e_symtab; size_t e_symtabsz; } e_ar; struct { /* regular ELF files */ union { Elf32_Ehdr *e_ehdr32; Elf64_Ehdr *e_ehdr64; } e_ehdr; union { Elf32_Phdr *e_phdr32; Elf64_Phdr *e_phdr64; } e_phdr; STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */ + size_t e_nphdr; /* number of Phdr entries */ + size_t e_nscn; /* number of sections */ + size_t e_strndx; /* string table section index */ } e_elf; } e_u; }; struct _Elf_Scn { union { Elf32_Shdr s_shdr32; Elf64_Shdr s_shdr64; } s_shdr; STAILQ_HEAD(, _Elf_Data) s_data; /* list of Elf_Data descriptors */ STAILQ_HEAD(, _Elf_Data) s_rawdata; /* raw data for this section */ STAILQ_ENTRY(_Elf_Scn) s_next; struct _Elf *s_elf; /* parent ELF descriptor */ unsigned int s_flags; /* flags for the section as a whole */ size_t s_ndx; /* index# for this section */ uint64_t s_offset; /* managed by elf_update() */ uint64_t s_rawoff; /* original offset in the file */ uint64_t s_size; /* managed by elf_update() */ }; enum { ELF_TOFILE, ELF_TOMEMORY }; #define LIBELF_COPY_U32(DST,SRC,NAME) do { \ if ((SRC)->NAME > UINT_MAX) { \ LIBELF_SET_ERROR(RANGE, 0); \ return (0); \ } \ (DST)->NAME = (SRC)->NAME; \ } while (0) #define LIBELF_COPY_S32(DST,SRC,NAME) do { \ if ((SRC)->NAME > INT_MAX || \ (SRC)->NAME < INT_MIN) { \ LIBELF_SET_ERROR(RANGE, 0); \ return (0); \ } \ (DST)->NAME = (SRC)->NAME; \ } while (0) /* * Prototypes */ Elf_Data *_libelf_allocate_data(Elf_Scn *_s); Elf *_libelf_allocate_elf(void); Elf_Scn *_libelf_allocate_scn(Elf *_e, size_t _ndx); Elf_Arhdr *_libelf_ar_gethdr(Elf *_e); Elf *_libelf_ar_open(Elf *_e); Elf *_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar); Elf_Arsym *_libelf_ar_process_symtab(Elf *_ar, size_t *_dst); unsigned long _libelf_checksum(Elf *_e, int _elfclass); void *_libelf_ehdr(Elf *_e, int _elfclass, int _allocate); int _libelf_falign(Elf_Type _t, int _elfclass); size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version, size_t count); void (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass)) (char *_dst, char *_src, size_t _cnt, int _byteswap); void *_libelf_getphdr(Elf *_e, int _elfclass); void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass); -int _libelf_getshnum(Elf *_e, void *_eh, int _elfclass, size_t *_shnum); -int _libelf_getshstrndx(Elf *_e, void *_eh, int _elfclass, - size_t *_shstrndx); void _libelf_init_elf(Elf *_e, Elf_Kind _kind); int _libelf_malign(Elf_Type _t, int _elfclass); size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version); void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count); Elf_Data *_libelf_release_data(Elf_Data *_d); Elf *_libelf_release_elf(Elf *_e); Elf_Scn *_libelf_release_scn(Elf_Scn *_s); +int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum); int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum); int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass, size_t _shstrndx); Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s, unsigned int _encoding, int _elfclass, int _direction); int _libelf_xlate_shtype(uint32_t _sht); #endif /* __LIBELF_H_ */ Index: head/lib/libelf/elf_getphnum.3 =================================================================== --- head/lib/libelf/elf_getphnum.3 (nonexistent) +++ head/lib/libelf/elf_getphnum.3 (revision 165535) @@ -0,0 +1,87 @@ +.\" Copyright (c) 2006 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $FreeBSD$ +.\" +.Dd December 16, 2006 +.Os +.Dt ELF_GETPHNUM 3 +.Sh NAME +.Nm elf_getphnum +.Nd return the number of program headers in an ELF file +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_getphnum "Elf *elf" "size_t *phnum" +.Sh DESCRIPTION +Function +.Fn elf_getphnum +retrieves the number of ELF program headers associated with descriptor +.Ar elf +and stores it into the location pointed to by argument +.Ar phnum . +.Pp +This routine allows applications to uniformly process both normal ELF +objects and ELF objects that use extended numbering. +.Pp +.Sh RETURN VALUES +Function +.Fn elf_getphnum +returns a non-zero value if successful, or zero in case of an +error. +.Sh ERRORS +Function +.Fn elf_getphnum +can fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +A NULL value was passed in for argument +.Ar elf . +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not for an ELF file. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +lacks an ELF Executable Header. +.It Bq Er ELF_E_HEADER +The ELF Executable Header associated with argument +.Ar elf +was corrupt. +.It Bq Er ELF_E_SECTION +The section header at index +.Dv SHN_UNDEF +was corrupt. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf32_getehdr 3 , +.Xr elf64_getehdr 3 , +.Xr elf_getident 3 , +.Xr elf_getshnum 3 , +.Xr elf_getshstrndx 3 , +.Xr gelf 3 , +.Xr gelf_getehdr 3 Property changes on: head/lib/libelf/elf_getphnum.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libelf/elf_phnum.c =================================================================== --- head/lib/libelf/elf_phnum.c (nonexistent) +++ head/lib/libelf/elf_phnum.c (revision 165535) @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "_libelf.h" + +int +elf_getphnum(Elf *e, size_t *phnum) +{ + void *eh; + int ec; + + if (e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *phnum = e->e_u.e_elf.e_nphdr; + + return (1); +} Property changes on: head/lib/libelf/elf_phnum.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libelf/elf_scn.c =================================================================== --- head/lib/libelf/elf_scn.c (revision 165534) +++ head/lib/libelf/elf_scn.c (revision 165535) @@ -1,244 +1,228 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "_libelf.h" /* * Load an ELF section table and create a list of Elf_Scn structures. */ static int _libelf_load_scn(Elf *e, void *ehdr) { int ec, swapbytes; size_t fsz, i, shnum; uint64_t shoff; - uint32_t shtype; char *src; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; Elf_Scn *scn; void (*xlator)(char *_d, char *_s, size_t _c, int _swap); assert(e != NULL); assert(ehdr != NULL); + assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0); #define CHECK_EHDR(E,EH) do { \ if (fsz != (EH)->e_shentsize || \ shoff + fsz * shnum > e->e_rawsize) { \ LIBELF_SET_ERROR(HEADER, 0); \ return (0); \ } \ } while (0) - fsz = gelf_fsize(e, ELF_T_SHDR, (size_t) 1, e->e_version); + ec = e->e_class; + fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); assert(fsz > 0); - ec = e->e_class; + shnum = e->e_u.e_elf.e_nscn; + if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; - shnum = eh32->e_shnum; shoff = (uint64_t) eh32->e_shoff; CHECK_EHDR(e, eh32); } else { eh64 = (Elf64_Ehdr *) ehdr; - shnum = eh64->e_shnum; shoff = eh64->e_shoff; CHECK_EHDR(e, eh64); } xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder); src = e->e_rawfile + shoff; - i = 0; - if (shnum == (size_t) 0 && shoff != 0LL) { - /* Extended section numbering */ - if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL) - return (0); + /* + * If the file is using extended numbering then section #0 + * would have already been read in. + */ - (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes); + i = 0; + if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { + assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) == + STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next)); - if (ec == ELFCLASS32) { - shtype = scn->s_shdr.s_shdr32.sh_type; - shnum = scn->s_shdr.s_shdr32.sh_size; - } else { - shtype = scn->s_shdr.s_shdr64.sh_type; - shnum = scn->s_shdr.s_shdr64.sh_size; - } - - if (shtype != SHT_NULL) { - LIBELF_SET_ERROR(SECTION, 0); - return (0); - } - - scn->s_size = 0LL; - scn->s_offset = scn->s_rawoff = 0LL; - - i++; + i = 1; src += fsz; } for (; i < shnum; i++, src += fsz) { if ((scn = _libelf_allocate_scn(e, i)) == NULL) return (0); (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes); if (ec == ELFCLASS32) { scn->s_offset = scn->s_rawoff = scn->s_shdr.s_shdr32.sh_offset; scn->s_size = scn->s_shdr.s_shdr32.sh_size; } else { scn->s_offset = scn->s_rawoff = scn->s_shdr.s_shdr64.sh_offset; scn->s_size = scn->s_shdr.s_shdr64.sh_size; } } + + e->e_flags |= LIBELF_F_SHDRS_LOADED; + return (1); } Elf_Scn * elf_getscn(Elf *e, size_t index) { int ec; void *ehdr; Elf_Scn *s; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); - if (e->e_cmd != ELF_C_WRITE && STAILQ_EMPTY(&e->e_u.e_elf.e_scn) && + if (e->e_cmd != ELF_C_WRITE && + (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && _libelf_load_scn(e, ehdr) == 0) return (NULL); STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) if (s->s_ndx == index) return (s); LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } size_t elf_ndxscn(Elf_Scn *s) { if (s == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (SHN_UNDEF); } return (s->s_ndx); } Elf_Scn * elf_newscn(Elf *e) { int ec; void *ehdr; - size_t shnum; Elf_Scn *scn; if (e == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); /* * The application may be asking for a new section descriptor * on an ELF object opened with ELF_C_RDWR or ELF_C_READ. We * need to bring in the existing section information before * appending a new one to the list. * * Per the ELF(3) API, an application is allowed to open a * file using ELF_C_READ, mess with its internal structure and * use elf_update(...,ELF_C_NULL) to compute its new layout. */ - if (e->e_cmd != ELF_C_WRITE && STAILQ_EMPTY(&e->e_u.e_elf.e_scn) && + if (e->e_cmd != ELF_C_WRITE && + (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && _libelf_load_scn(e, ehdr) == 0) return (NULL); - if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0) - return (NULL); - if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { - assert(shnum == 0); + assert(e->e_u.e_elf.e_nscn == 0); if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == NULL) return (NULL); - shnum++; + e->e_u.e_elf.e_nscn++; } - assert(shnum > 0); + assert(e->e_u.e_elf.e_nscn > 0); - if ((scn = _libelf_allocate_scn(e, shnum)) == NULL) + if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL) return (NULL); - shnum++; - - if (_libelf_setshnum(e, ehdr, ec, shnum) == 0) - return (NULL); + e->e_u.e_elf.e_nscn++; (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); return (scn); } Elf_Scn * elf_nextscn(Elf *e, Elf_Scn *s) { if (e == NULL || (e->e_kind != ELF_K_ELF) || (s && s->s_elf != e)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } return (s == NULL ? elf_getscn(e, (size_t) 1) : STAILQ_NEXT(s, s_next)); } Index: head/lib/libelf/elf_shnum.c =================================================================== --- head/lib/libelf/elf_shnum.c (revision 165534) +++ head/lib/libelf/elf_shnum.c (revision 165535) @@ -1,123 +1,53 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include "_libelf.h" int -_libelf_getshnum(Elf *e, void *eh, int ec, size_t *shnum) -{ - Elf64_Off off; - Elf_Scn *scn; - void *sh; - size_t n; - - if (ec == ELFCLASS32) { - n = ((Elf32_Ehdr *) eh)->e_shnum; - off = (Elf64_Off) ((Elf32_Ehdr *) eh)->e_shoff; - } else { - n = ((Elf64_Ehdr *) eh)->e_shnum; - off = ((Elf64_Ehdr *) eh)->e_shoff; - } - - if (n != 0) { - *shnum = n; - return (1); - } - - if (off == 0L) { - *shnum = (size_t) 0; - return (1); - } - - /* - * If 'e_shnum' is zero and 'e_shoff' is non-zero, the file is - * using extended section numbering, and the true section - * number is kept in the 'sh_size' field of the section header - * at offset SHN_UNDEF. - */ - if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL) - return (0); - if ((sh = _libelf_getshdr(scn, ec)) == NULL) - return (0); - - if (ec == ELFCLASS32) - *shnum = ((Elf32_Shdr *) sh)->sh_size; - else - *shnum = ((Elf64_Shdr *) sh)->sh_size; - - return (1); -} - -int -_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum) -{ - Elf_Scn *scn; - void *sh; - - if (shnum < SHN_LORESERVE) { - if (ec == ELFCLASS32) - ((Elf32_Ehdr *) eh)->e_shnum = shnum; - else - ((Elf64_Ehdr *) eh)->e_shnum = shnum; - return (1); - } - - if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL) - return (0); - if ((sh = _libelf_getshdr(scn, ec)) == NULL) - return (0); - - if (ec == ELFCLASS32) - ((Elf32_Shdr *) sh)->sh_size = shnum; - else - ((Elf64_Shdr *) sh)->sh_size = shnum; - - (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); - - return (1); -} - -int elf_getshnum(Elf *e, size_t *shnum) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || - ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || - ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) { + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } - return (_libelf_getshnum(e, eh, ec, shnum)); + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *shnum = e->e_u.e_elf.e_nscn; + + return (1); } Index: head/lib/libelf/elf_shstrndx.c =================================================================== --- head/lib/libelf/elf_shstrndx.c (revision 165534) +++ head/lib/libelf/elf_shstrndx.c (revision 165535) @@ -1,127 +1,69 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include "_libelf.h" -/* - * Helpers to get/set the e_shstrndx field of the ELF header. - */ - int -_libelf_getshstrndx(Elf *e, void *eh, int ec, size_t *strndx) -{ - Elf_Scn *scn; - void *sh; - size_t n; - - n = (ec == ELFCLASS32) ? ((Elf32_Ehdr *) eh)->e_shstrndx : - ((Elf64_Ehdr *) eh)->e_shstrndx; - - if (n < SHN_LORESERVE) { - *strndx = n; - return (1); - } - - if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL) - return (0); - if ((sh = _libelf_getshdr(scn, ec)) == NULL) - return (0); - - if (ec == ELFCLASS32) - *strndx = ((Elf32_Shdr *) sh)->sh_link; - else - *strndx = ((Elf64_Shdr *) sh)->sh_link; - - return (1); -} - -int -_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t strndx) -{ - Elf_Scn *scn; - void *sh; - - if (strndx < SHN_LORESERVE) { - if (ec == ELFCLASS32) - ((Elf32_Ehdr *) eh)->e_shstrndx = strndx; - else - ((Elf64_Ehdr *) eh)->e_shstrndx = strndx; - return (1); - } - - if ((scn = elf_getscn(e, (size_t) SHN_UNDEF)) == NULL) - return (0); - if ((sh = _libelf_getshdr(scn, ec)) == NULL) - return (0); - - if (ec == ELFCLASS32) { - ((Elf32_Ehdr *) eh)->e_shstrndx = SHN_XINDEX; - ((Elf32_Shdr *) sh)->sh_link = strndx; - } else { - ((Elf64_Ehdr *) eh)->e_shstrndx = SHN_XINDEX; - ((Elf64_Shdr *) sh)->sh_link = strndx; - } - - return (1); -} - -int elf_getshstrndx(Elf *e, size_t *strndx) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || - ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || - ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) { + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } - return (_libelf_getshstrndx(e, eh, ec, strndx)); + if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + *strndx = e->e_u.e_elf.e_strndx; + + return (1); } int elf_setshstrndx(Elf *e, size_t strndx) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } return (_libelf_setshstrndx(e, eh, ec, strndx)); } Index: head/lib/libelf/elf_update.c =================================================================== --- head/lib/libelf/elf_update.c (revision 165534) +++ head/lib/libelf/elf_update.c (revision 165535) @@ -1,880 +1,884 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "_libelf.h" /* * Update the internal data structures associated with an ELF object. * Returns the size in bytes the ELF object would occupy in its file * representation. * * After a successful call to this function, the following structures * are updated: * * - The ELF header is updated. * - All sections are sorted in order of ascending addresses and their * section header table entries updated. An error is signalled * if an overlap was detected among sections. * - All data descriptors associated with a section are sorted in order * of ascending addresses. Overlaps, if detected, are signalled as * errors. Other sanity checks for alignments, section types etc. are * made. * * After a resync_elf() successfully returns, the ELF descriptor is * ready for being handed over to _libelf_write_elf(). * * File alignments: * PHDR - Addr * SHDR - Addr * * XXX: how do we handle 'flags'. */ /* * Compute the extents of a section, by looking at the. */ static int _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) { int ec; Elf_Data *d, *td; unsigned int elftype; uint32_t sh_type; uint64_t d_align; uint64_t sh_align, sh_entsize, sh_offset, sh_size; uint64_t scn_size, scn_alignment; /* * We need to recompute library private data structures if one * or more of the following is true: * - The underlying Shdr structure has been marked `dirty'. Significant * fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'. * - The Elf_Data structures part of this section have been marked * `dirty'. Affected members include `d_align', `d_offset', `d_type', * and `d_size'. * - The section as a whole is `dirty', e.g., it has been allocated * using elf_newscn(), or if a new Elf_Data structure was added using * elf_newdata(). * * Each of these conditions would result in the ELF_F_DIRTY bit being * set on the section descriptor's `s_flags' field. */ ec = e->e_class; if (ec == ELFCLASS32) { sh_type = s->s_shdr.s_shdr32.sh_type; sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize; sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; } else { sh_type = s->s_shdr.s_shdr64.sh_type; sh_align = s->s_shdr.s_shdr64.sh_addralign; sh_entsize = s->s_shdr.s_shdr64.sh_entsize; sh_offset = s->s_shdr.s_shdr64.sh_offset; sh_size = s->s_shdr.s_shdr64.sh_size; } if (sh_type == SHT_NULL || sh_type == SHT_NOBITS) return (1); if ((s->s_flags & ELF_F_DIRTY) == 0) { if ((size_t) *rc < sh_offset + sh_size) *rc = sh_offset + sh_size; return (1); } elftype = _libelf_xlate_shtype(sh_type); if (elftype > ELF_T_LAST) { LIBELF_SET_ERROR(SECTION, 0); return (0); } /* * Compute the extent of the data descriptors associated with * this section. */ scn_alignment = 0; if (sh_align == 0) sh_align = _libelf_falign(elftype, ec); /* Compute the section alignment. */ STAILQ_FOREACH(d, &s->s_data, d_next) { if (d->d_type != elftype) { LIBELF_SET_ERROR(DATA, 0); return (0); } if (d->d_version != e->e_version) { LIBELF_SET_ERROR(VERSION, 0); return (0); } if ((d_align = d->d_align) % sh_align) { LIBELF_SET_ERROR(LAYOUT, 0); return (0); } if (d_align == 0 || (d_align & (d_align - 1))) { LIBELF_SET_ERROR(DATA, 0); return (0); } if (d_align > scn_alignment) scn_alignment = d_align; } scn_size = 0L; STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { if (e->e_flags & ELF_F_LAYOUT) { if ((uint64_t) d->d_off + d->d_size > scn_size) scn_size = d->d_off + d->d_size; } else { scn_size = roundup2(scn_size, scn_alignment); d->d_off = scn_size; scn_size += d->d_size; } } /* * If the application is requesting full control over the layout * of the section, check its values for sanity. */ if (e->e_flags & ELF_F_LAYOUT) { if (scn_alignment > sh_align || sh_offset % sh_align || sh_size < scn_size) { LIBELF_SET_ERROR(LAYOUT, 0); return (0); } } else { /* * Otherwise compute the values in the section header. */ if (scn_alignment > sh_align) sh_align = scn_alignment; /* * If the section entry size is zero, try and fill in an * appropriate entry size. Per the elf(5) manual page * sections without fixed-size entries should have their * 'sh_entsize' field set to zero. */ if (sh_entsize == 0 && (sh_entsize = _libelf_fsize(elftype, ec, e->e_version, (size_t) 1)) == 1) sh_entsize = 0; sh_size = scn_size; sh_offset = roundup(*rc, sh_align); if (ec == ELFCLASS32) { s->s_shdr.s_shdr32.sh_addralign = (uint32_t) sh_align; s->s_shdr.s_shdr32.sh_entsize = (uint32_t) sh_entsize; s->s_shdr.s_shdr32.sh_offset = (uint32_t) sh_offset; s->s_shdr.s_shdr32.sh_size = (uint32_t) sh_size; } else { s->s_shdr.s_shdr64.sh_addralign = sh_align; s->s_shdr.s_shdr64.sh_entsize = sh_entsize; s->s_shdr.s_shdr64.sh_offset = sh_offset; s->s_shdr.s_shdr64.sh_size = sh_size; } } if ((size_t) *rc < sh_offset + sh_size) *rc = sh_offset + sh_size; s->s_size = sh_size; s->s_offset = sh_offset; return (1); } /* * Insert a section in ascending order in the list */ static int _libelf_insert_section(Elf *e, Elf_Scn *s) { Elf_Scn *t, *prevt; uint64_t smax, smin, tmax, tmin; smin = s->s_offset; smax = smin + s->s_size; prevt = NULL; STAILQ_FOREACH(t, &e->e_u.e_elf.e_scn, s_next) { tmin = t->s_offset; tmax = tmin + t->s_size; /* check if there is an overlap */ if (tmax < smin) { prevt = t; continue; } else if (smax < tmin) break; else { LIBELF_SET_ERROR(LAYOUT, 0); return (0); } } if (prevt) STAILQ_INSERT_AFTER(&e->e_u.e_elf.e_scn, prevt, s, s_next); else STAILQ_INSERT_HEAD(&e->e_u.e_elf.e_scn, s, s_next); return (1); } static off_t _libelf_resync_sections(Elf *e, off_t rc) { int ec; off_t nrc; size_t sh_type; Elf_Scn *s, *ts; ec = e->e_class; /* * Make a pass through sections, computing the extent of each * section. Order in increasing order of addresses. */ nrc = rc; STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) if (_libelf_compute_section_extents(e, s, &nrc) == 0) return ((off_t) -1); STAILQ_FOREACH_SAFE(s, &e->e_u.e_elf.e_scn, s_next, ts) { if (ec == ELFCLASS32) sh_type = s->s_shdr.s_shdr32.sh_type; else sh_type = s->s_shdr.s_shdr64.sh_type; /* XXX Do we need the 'size' field of an SHT_NOBITS section */ if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) continue; if (s->s_offset < (uint64_t) rc) { if (s->s_offset + s->s_size < (uint64_t) rc) { /* * Try insert this section in the * correct place in the list, * detecting overlaps if any. */ STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); if (_libelf_insert_section(e, s) == 0) return ((off_t) -1); } else { LIBELF_SET_ERROR(LAYOUT, 0); return ((off_t) -1); } } else rc = s->s_offset + s->s_size; } assert(nrc == rc); return (rc); } static off_t _libelf_resync_elf(Elf *e) { int ec, eh_class, eh_type; unsigned int eh_byteorder, eh_version; size_t align, fsz; size_t phnum, shnum; off_t rc, phoff, shoff; void *ehdr; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; rc = 0; ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); /* * Prepare the EHDR. */ if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return ((off_t) -1); eh32 = ehdr; eh64 = ehdr; if (ec == ELFCLASS32) { eh_byteorder = eh32->e_ident[EI_DATA]; eh_class = eh32->e_ident[EI_CLASS]; - phnum = eh32->e_phnum; phoff = (uint64_t) eh32->e_phoff; shoff = (uint64_t) eh32->e_shoff; eh_type = eh32->e_type; eh_version = eh32->e_version; } else { eh_byteorder = eh64->e_ident[EI_DATA]; eh_class = eh64->e_ident[EI_CLASS]; - phnum = eh64->e_phnum; phoff = eh64->e_phoff; shoff = eh64->e_shoff; eh_type = eh64->e_type; eh_version = eh64->e_version; } if (eh_version == EV_NONE) eh_version = EV_CURRENT; if (eh_version != e->e_version) { /* always EV_CURRENT */ LIBELF_SET_ERROR(VERSION, 0); return ((off_t) -1); } if (eh_class != e->e_class) { LIBELF_SET_ERROR(CLASS, 0); return ((off_t) -1); } if (e->e_cmd != ELF_C_WRITE && eh_byteorder != e->e_byteorder) { LIBELF_SET_ERROR(HEADER, 0); return ((off_t) -1); } - if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0) - return ((off_t) -1); + shnum = e->e_u.e_elf.e_nscn; + phnum = e->e_u.e_elf.e_nphdr; e->e_byteorder = eh_byteorder; #define INITIALIZE_EHDR(E,EC,V) do { \ (E)->e_ident[EI_MAG0] = ELFMAG0; \ (E)->e_ident[EI_MAG1] = ELFMAG1; \ (E)->e_ident[EI_MAG2] = ELFMAG2; \ (E)->e_ident[EI_MAG3] = ELFMAG3; \ (E)->e_ident[EI_CLASS] = (EC); \ (E)->e_ident[EI_VERSION] = (V); \ (E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V), \ (size_t) 1); \ (E)->e_phentsize = _libelf_fsize(ELF_T_PHDR, (EC), (V), \ (size_t) 1); \ (E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V), \ (size_t) 1); \ } while (0) if (ec == ELFCLASS32) INITIALIZE_EHDR(eh32, ec, eh_version); else INITIALIZE_EHDR(eh64, ec, eh_version); (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1); /* * Compute the layout the program header table, if one is * present. The program header table needs to be aligned to a * `natural' boundary. */ if (phnum) { fsz = _libelf_fsize(ELF_T_PHDR, ec, eh_version, phnum); align = _libelf_falign(ELF_T_PHDR, ec); if (e->e_flags & ELF_F_LAYOUT) { /* * Check offsets for sanity. */ if (rc > phoff) { LIBELF_SET_ERROR(HEADER, 0); return ((off_t) -1); } if (phoff % align) { LIBELF_SET_ERROR(LAYOUT, 0); return ((off_t) -1); } } else phoff = roundup(rc, align); rc = phoff + fsz; } else phoff = 0; /* * Compute the layout of the sections associated with the * file. */ if ((rc = _libelf_resync_sections(e, rc)) < 0) return ((off_t) -1); /* * Compute the space taken up by the section header table, if * one is needed. */ if (shnum) { fsz = _libelf_fsize(ELF_T_SHDR, ec, eh_version, (size_t) 1); align = _libelf_falign(ELF_T_SHDR, ec); if (e->e_flags & ELF_F_LAYOUT) { if (rc > shoff) { LIBELF_SET_ERROR(HEADER, 0); return ((off_t) -1); } if (shoff % align) { LIBELF_SET_ERROR(LAYOUT, 0); return ((off_t) -1); } } else shoff = roundup(rc, align); rc = shoff + fsz * shnum; } else shoff = 0; /* + * Set the fields of the Executable Header that could potentially use + * extended numbering. + */ + _libelf_setphnum(e, ehdr, ec, phnum); + _libelf_setshnum(e, ehdr, ec, shnum); + + /* * Update the `e_phoff' and `e_shoff' fields if the library is * doing the layout. */ if ((e->e_flags & ELF_F_LAYOUT) == 0) { if (ec == ELFCLASS32) { eh32->e_phoff = (uint32_t) phoff; eh32->e_shoff = (uint32_t) shoff; } else { eh64->e_phoff = (uint64_t) phoff; eh64->e_shoff = (uint64_t) shoff; } } return (rc); } /* * Write out the contents of a section. */ static off_t _libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc) { int ec; size_t fsz, msz, nobjects; uint32_t sh_type; uint64_t sh_off; int elftype; Elf_Data *d, dst; if ((ec = e->e_class) == ELFCLASS32) sh_type = s->s_shdr.s_shdr32.sh_type; else sh_type = s->s_shdr.s_shdr64.sh_type; /* * Ignore sections that do not allocate space in the file. */ if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) return (rc); elftype = _libelf_xlate_shtype(sh_type); assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST); msz = _libelf_msize(elftype, ec, e->e_version); sh_off = s->s_offset; assert(sh_off % _libelf_falign(elftype, ec) == 0); /* * If the section has a `rawdata' descriptor, and the section * contents have not been modified, use its contents directly. * The `s_rawoff' member contains the offset into the original * file, while `s_offset' contains its new location in the * destination. */ if (STAILQ_EMPTY(&s->s_data)) { if ((d = elf_rawdata(s, NULL)) == NULL) return ((off_t) -1); STAILQ_FOREACH(d, &s->s_rawdata, d_next) { if ((uint64_t) rc < sh_off + d->d_off) (void) memset(nf + rc, LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc); rc = sh_off + d->d_off; assert(d->d_buf != NULL); assert(d->d_type == ELF_T_BYTE); assert(d->d_version == e->e_version); (void) memcpy(nf + rc, e->e_rawfile + s->s_rawoff + d->d_off, d->d_size); rc += d->d_size; } return (rc); } /* * Iterate over the set of data descriptors for this section. * The prior call to _libelf_resync_elf() would have setup the * descriptors for this step. */ dst.d_version = e->e_version; STAILQ_FOREACH(d, &s->s_data, d_next) { if ((uint64_t) rc < sh_off + d->d_off) (void) memset(nf + rc, LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc); rc = sh_off + d->d_off; assert(d->d_buf != NULL); assert(d->d_type == (Elf_Type) elftype); assert(d->d_version == e->e_version); assert(d->d_size % msz == 0); nobjects = d->d_size / msz; fsz = _libelf_fsize(elftype, ec, e->e_version, nobjects); dst.d_buf = nf + rc; dst.d_size = fsz; if (_libelf_xlate(&dst, d, e->e_byteorder, ec, ELF_TOFILE) == NULL) return ((off_t) -1); rc += fsz; } return ((off_t) rc); } /* * Write out the file image. * * The original file could have been mapped in with an ELF_C_RDWR * command and the application could have added new content or * re-arranged its sections before calling elf_update(). Consequently * its not safe to work `in place' on the original file. So we * malloc() the required space for the updated ELF object and build * the object there and write it out to the underlying file at the * end. Note that the application may have opened the underlying file * in ELF_C_RDWR and only retrieved/modified a few sections. We take * care to avoid translating file sections unnecessarily. * * Gaps in the coverage of the file by the file's sections will be * filled with the fill character set by elf_fill(3). */ static off_t _libelf_write_elf(Elf *e, off_t newsize) { int ec; off_t rc; size_t fsz, msz, phnum, shnum; uint64_t phoff, shoff; void *ehdr; char *newfile; Elf_Data dst, src; Elf_Scn *scn, *tscn; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; assert(e->e_kind == ELF_K_ELF); assert(e->e_cmd != ELF_C_READ); assert(e->e_fd >= 0); if ((newfile = malloc((size_t) newsize)) == NULL) { LIBELF_SET_ERROR(RESOURCE, errno); return ((off_t) -1); } ec = e->e_class; ehdr = _libelf_ehdr(e, ec, 0); assert(ehdr != NULL); + phnum = e->e_u.e_elf.e_nphdr; + if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; - phnum = eh32->e_phnum; phoff = (uint64_t) eh32->e_phoff; shnum = eh32->e_shnum; shoff = (uint64_t) eh32->e_shoff; - } else { eh64 = (Elf64_Ehdr *) ehdr; - phnum = eh64->e_phnum; phoff = eh64->e_phoff; shnum = eh64->e_shnum; shoff = eh64->e_shoff; } fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version); (void) memset(&dst, 0, sizeof(dst)); (void) memset(&src, 0, sizeof(src)); src.d_buf = ehdr; src.d_size = msz; src.d_type = ELF_T_EHDR; src.d_version = dst.d_version = e->e_version; rc = 0; dst.d_buf = newfile + rc; dst.d_size = fsz; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == NULL) goto error; rc += fsz; /* * Write the program header table if present. */ if (phnum != 0 && phoff != 0) { assert((unsigned) rc <= phoff); fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum); assert(phoff % _libelf_falign(ELF_T_PHDR, ec) == 0); assert(fsz > 0); src.d_version = dst.d_version = e->e_version; src.d_type = ELF_T_PHDR; if (ec == ELFCLASS32) src.d_buf = e->e_u.e_elf.e_phdr.e_phdr32; else src.d_buf = e->e_u.e_elf.e_phdr.e_phdr64; src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec, e->e_version); dst.d_size = fsz; if ((uint64_t) rc < phoff) (void) memset(newfile + rc, LIBELF_PRIVATE(fillchar), phoff - rc); dst.d_buf = newfile + rc; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) == NULL) goto error; rc = phoff + fsz; } /* * Write out individual sections. */ STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) if ((rc = _libelf_write_scn(e, newfile, scn, rc)) < 0) goto error; /* * Write out the section header table, if required. */ if (shnum != 0 && shoff != 0) { assert((unsigned) rc <= shoff); if ((uint64_t) rc < shoff) (void) memset(newfile + rc, LIBELF_PRIVATE(fillchar), shoff - rc); rc = shoff; assert(rc % _libelf_falign(ELF_T_SHDR, ec) == 0); src.d_type = ELF_T_SHDR; src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version); src.d_version = dst.d_version = e->e_version; fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) { if (ec == ELFCLASS32) src.d_buf = &scn->s_shdr.s_shdr32; else src.d_buf = &scn->s_shdr.s_shdr64; dst.d_size = fsz; dst.d_buf = newfile + rc; if (_libelf_xlate(&dst, &src, e->e_byteorder, ec, ELF_TOFILE) != &dst) goto error; rc += fsz; } } /* */ assert(rc == newsize); /* * Write out the constructed contents and remap the file in * read-only. */ if (e->e_rawfile && munmap(e->e_rawfile, e->e_rawsize) < 0) { LIBELF_SET_ERROR(IO, errno); goto error; } if (write(e->e_fd, newfile, (size_t) newsize) != newsize || lseek(e->e_fd, (off_t) 0, SEEK_SET) < 0) { LIBELF_SET_ERROR(IO, errno); goto error; } if (e->e_cmd != ELF_C_WRITE) { if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) { LIBELF_SET_ERROR(IO, errno); goto error; } e->e_rawsize = newsize; } /* * Reset flags, remove existing section descriptors and * {E,P}HDR pointers so that a subsequent elf_get{e,p}hdr() * and elf_getscn() will function correctly. */ e->e_flags &= ~ELF_F_DIRTY; STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) _libelf_release_scn(scn); if (ec == ELFCLASS32) { free(e->e_u.e_elf.e_ehdr.e_ehdr32); if (e->e_u.e_elf.e_phdr.e_phdr32) free(e->e_u.e_elf.e_phdr.e_phdr32); e->e_u.e_elf.e_ehdr.e_ehdr32 = NULL; e->e_u.e_elf.e_phdr.e_phdr32 = NULL; } else { free(e->e_u.e_elf.e_ehdr.e_ehdr64); if (e->e_u.e_elf.e_phdr.e_phdr64) free(e->e_u.e_elf.e_phdr.e_phdr64); e->e_u.e_elf.e_ehdr.e_ehdr64 = NULL; e->e_u.e_elf.e_phdr.e_phdr64 = NULL; } return (rc); error: if (newfile) free(newfile); return ((off_t) -1); } off_t elf_update(Elf *e, Elf_Cmd c) { int ec; off_t rc; rc = (off_t) -1; if (e == NULL || e->e_kind != ELF_K_ELF || (c != ELF_C_NULL && c != ELF_C_WRITE)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (rc); } if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { LIBELF_SET_ERROR(CLASS, 0); return (rc); } if (e->e_version == EV_NONE) e->e_version = EV_CURRENT; if (c == ELF_C_WRITE && e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (rc); } if ((rc = _libelf_resync_elf(e)) < 0) return (rc); if (c == ELF_C_NULL) return (rc); if (e->e_cmd == ELF_C_READ) { /* * This descriptor was opened in read-only mode or by * elf_memory(). */ if (e->e_fd) LIBELF_SET_ERROR(MODE, 0); else LIBELF_SET_ERROR(ARGUMENT, 0); return ((off_t) -1); } if (e->e_fd < 0) { LIBELF_SET_ERROR(SEQUENCE, 0); return ((off_t) -1); } return (_libelf_write_elf(e, rc)); } Index: head/lib/libelf/libelf_checksum.c =================================================================== --- head/lib/libelf/libelf_checksum.c (revision 165534) +++ head/lib/libelf/libelf_checksum.c (revision 165535) @@ -1,99 +1,99 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include "_libelf.h" static unsigned long _libelf_sum(unsigned long c, const unsigned char *s, size_t size) { if (s == NULL || size == 0) return (c); while (size--) c += *s++; return (c); } unsigned long _libelf_checksum(Elf *e, int elfclass) { size_t shn; Elf_Scn *scn; Elf_Data *d; unsigned long checksum; GElf_Ehdr eh; GElf_Shdr shdr; if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0L); } if (e->e_class != elfclass) { LIBELF_SET_ERROR(CLASS, 0); return (0L); } if (gelf_getehdr(e, &eh) == NULL) return (0); /* * Iterate over all sections in the ELF file, computing the * checksum along the way. * * The first section is always SHN_UNDEF and can be skipped. * Non-allocatable sections are skipped, as are sections that * could be affected by utilities such as strip(1). */ checksum = 0; - for (shn = 1; shn < eh.e_shnum; shn++) { + for (shn = 1; shn < e->e_u.e_elf.e_nscn; shn++) { if ((scn = elf_getscn(e, shn)) == NULL) return (0); if (gelf_getshdr(scn, &shdr) == NULL) return (0); if ((shdr.sh_flags & SHF_ALLOC) == 0 || shdr.sh_type == SHT_DYNAMIC || shdr.sh_type == SHT_DYNSYM) continue; d = NULL; while ((d = elf_rawdata(scn, d)) != NULL) checksum = _libelf_sum(checksum, (unsigned char *) d->d_buf, d->d_size); } /* * Return a 16-bit checksum compatible with Solaris. */ return (((checksum >> 16) & 0xFFFFUL) + (checksum & 0xFFFFUL)); } Index: head/lib/libelf/libelf_ehdr.c =================================================================== --- head/lib/libelf/libelf_ehdr.c (revision 165534) +++ head/lib/libelf/libelf_ehdr.c (revision 165535) @@ -1,125 +1,204 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "_libelf.h" +/* + * Retrieve counts for sections, phdrs and the section string table index + * from section header #0 of the ELF object. + */ +static int +_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum, + uint16_t strndx) +{ + Elf_Scn *scn; + size_t fsz; + void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + uint32_t shtype; + + assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + + fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1); + assert(fsz > 0); + + if (e->e_rawsize < shoff + fsz) { /* raw file too small */ + LIBELF_SET_ERROR(HEADER, 0); + return (0); + } + + if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL) + return (0); + + xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); + (*xlator)((char *) &scn->s_shdr, e->e_rawfile + shoff, (size_t) 1, + e->e_byteorder != LIBELF_PRIVATE(byteorder)); + +#define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \ + scn->s_shdr.s_shdr64.M) + + if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) { + LIBELF_SET_ERROR(SECTION, 0); + return (0); + } + + e->e_u.e_elf.e_nscn = GET_SHDR_MEMBER(sh_size); + e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum : + GET_SHDR_MEMBER(sh_info); + e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx : + GET_SHDR_MEMBER(sh_link); +#undef GET_SHDR_MEMBER + + return (1); +} + #define EHDR_INIT(E,SZ) do { \ Elf##SZ##_Ehdr *eh = (E); \ eh->e_ident[EI_MAG0] = ELFMAG0; \ eh->e_ident[EI_MAG1] = ELFMAG1; \ eh->e_ident[EI_MAG2] = ELFMAG2; \ eh->e_ident[EI_MAG3] = ELFMAG3; \ eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \ eh->e_ident[EI_DATA] = ELFDATANONE; \ eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version); \ eh->e_machine = EM_NONE; \ eh->e_type = ELF_K_NONE; \ eh->e_version = LIBELF_PRIVATE(version); \ } while (0) void * _libelf_ehdr(Elf *e, int ec, int allocate) { - size_t fsz, msz; void *ehdr; + size_t fsz, msz; + uint16_t phnum, shnum, strndx; + uint64_t shoff; void (*xlator)(char *_d, char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (e == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (e->e_class != ELFCLASSNONE && e->e_class != ec) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } if (e->e_version != EV_CURRENT) { LIBELF_SET_ERROR(VERSION, 0); return (NULL); } if (e->e_class == ELFCLASSNONE) e->e_class = ec; if (ec == ELFCLASS32) ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32; else ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64; if (ehdr != NULL) /* already have a translated ehdr */ return (ehdr); - fsz = gelf_fsize(e, ELF_T_EHDR, (size_t) 1, e->e_version); - + fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); assert(fsz > 0); if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) { LIBELF_SET_ERROR(HEADER, 0); return (NULL); } msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); assert(msz > 0); if ((ehdr = calloc((size_t) 1, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) { e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr; EHDR_INIT(ehdr,32); } else { e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr; EHDR_INIT(ehdr,64); } if (allocate) e->e_flags |= ELF_F_DIRTY; if (e->e_cmd == ELF_C_WRITE) return (ehdr); xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); (*xlator)(ehdr, e->e_rawfile, (size_t) 1, e->e_byteorder != LIBELF_PRIVATE(byteorder)); + + /* + * If extended numbering is being used, read the correct + * number of sections and program header entries. + */ + if (ec == ELFCLASS32) { + phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; + shnum = ((Elf32_Ehdr *) ehdr)->e_shnum; + shoff = ((Elf32_Ehdr *) ehdr)->e_shoff; + strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx; + } else { + phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; + shnum = ((Elf64_Ehdr *) ehdr)->e_shnum; + shoff = ((Elf64_Ehdr *) ehdr)->e_shoff; + strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx; + } + + if (shnum >= SHN_LORESERVE || + (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM || + strndx == SHN_XINDEX))) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */ + e->e_u.e_elf.e_nphdr = phnum; + e->e_u.e_elf.e_nscn = shnum; + e->e_u.e_elf.e_strndx = strndx; + } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0) + return (NULL); return (ehdr); } Index: head/lib/libelf/libelf_extended.c =================================================================== --- head/lib/libelf/libelf_extended.c (nonexistent) +++ head/lib/libelf/libelf_extended.c (revision 165535) @@ -0,0 +1,136 @@ +/*- + * Copyright (c) 2006 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "_libelf.h" + +/* + * Retrieve section #0, allocating a new section if needed. + */ +static Elf_Scn * +_libelf_getscn0(Elf *e) +{ + Elf_Scn *s; + + if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL) + return (s); + + return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF)); +} + +int +_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum) +{ + Elf_Scn *scn; + + if (shnum >= SHN_LORESERVE) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_size = shnum; + else + scn->s_shdr.s_shdr64.sh_size = shnum; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + shnum = 0; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_shnum = shnum; + else + ((Elf64_Ehdr *) eh)->e_shnum = shnum; + + + return (1); +} + +int +_libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx) +{ + Elf_Scn *scn; + + if (shstrndx >= SHN_LORESERVE) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_link = shstrndx; + else + scn->s_shdr.s_shdr64.sh_link = shstrndx; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + shstrndx = SHN_XINDEX; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx; + else + ((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx; + + return (1); +} + +int +_libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum) +{ + Elf_Scn *scn; + + if (phnum >= PN_XNUM) { + if ((scn = _libelf_getscn0(e)) == NULL) + return (0); + + assert(scn->s_ndx == SHN_UNDEF); + + if (ec == ELFCLASS32) + scn->s_shdr.s_shdr32.sh_info = phnum; + else + scn->s_shdr.s_shdr64.sh_info = phnum; + + (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); + + phnum = PN_XNUM; + } + + if (ec == ELFCLASS32) + ((Elf32_Ehdr *) eh)->e_phnum = phnum; + else + ((Elf64_Ehdr *) eh)->e_phnum = phnum; + + return (1); +} + Property changes on: head/lib/libelf/libelf_extended.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libelf/libelf_phdr.c =================================================================== --- head/lib/libelf/libelf_phdr.c (revision 165534) +++ head/lib/libelf/libelf_phdr.c (revision 165535) @@ -1,165 +1,157 @@ /*- * Copyright (c) 2006 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "_libelf.h" void * _libelf_getphdr(Elf *e, int ec) { size_t phnum, phentsize; size_t fsz, msz; uint64_t phoff; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; void *ehdr, *phdr; void (*xlator)(char *_d, char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((phdr = (ec == ELFCLASS32 ? (void *) e->e_u.e_elf.e_phdr.e_phdr32 : (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) return (phdr); /* * Check the PHDR related fields in the EHDR for sanity. */ if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); + phnum = e->e_u.e_elf.e_nphdr; + if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; - phnum = eh32->e_phnum; phentsize = eh32->e_phentsize; phoff = (uint64_t) eh32->e_phoff; } else { eh64 = (Elf64_Ehdr *) ehdr; - phnum = eh64->e_phnum; phentsize = eh64->e_phentsize; phoff = (uint64_t) eh64->e_phoff; } fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); assert(fsz > 0); if ((uint64_t) e->e_rawsize < (phoff + fsz)) { LIBELF_SET_ERROR(HEADER, 0); return (NULL); } msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); assert(msz > 0); if ((phdr = calloc(phnum, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) e->e_u.e_elf.e_phdr.e_phdr32 = phdr; else e->e_u.e_elf.e_phdr.e_phdr64 = phdr; xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); (*xlator)(phdr, e->e_rawfile + phoff, phnum, e->e_byteorder != LIBELF_PRIVATE(byteorder)); return (phdr); } void * _libelf_newphdr(Elf *e, int ec, size_t count) { - void *ehdr, *nphdr, *ophdr; - Elf32_Ehdr *eh32; - Elf64_Ehdr *eh64; + void *ehdr, *newphdr, *oldphdr; size_t msz; if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { LIBELF_SET_ERROR(SEQUENCE, 0); return (NULL); } assert(e->e_class == ec); assert(ec == ELFCLASS32 || ec == ELFCLASS64); assert(e->e_version == EV_CURRENT); msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); assert(msz > 0); - nphdr = NULL; - if (count > 0 && (nphdr = calloc(count, msz)) == NULL) { + newphdr = NULL; + if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) { - if ((ophdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) - free(ophdr); - e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) nphdr; + if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) + free(oldphdr); + e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; } else { - if ((ophdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) - free(ophdr); - e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) nphdr; + if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) + free(oldphdr); + e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; } - if (ec == ELFCLASS32) { - eh32 = (Elf32_Ehdr *) ehdr; - eh32->e_phnum = count; - } else { - eh64 = (Elf64_Ehdr *) ehdr; - eh64->e_phnum = count; - } + e->e_u.e_elf.e_nphdr = count; elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); - return (nphdr); + return (newphdr); }