diff options
Diffstat (limited to 'lib')
102 files changed, 14195 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile index 35328f5..665cd98 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -24,7 +24,7 @@ # # Otherwise, the SUBDIR list should be in alphabetical order. -SUBDIR= ${_csu} libbsm libcom_err libcrypt libkvm msun libmd libncurses \ +SUBDIR= ${_csu} libbsm libcom_err libcrypt libelf libkvm msun libmd libncurses \ libnetgraph libradius librpcsvc libsbuf libtacplus libutil \ ${_libypclnt} libalias libarchive ${_libatm} \ libbegemot ${_libbluetooth} libbsnmp libbz2 libc \ diff --git a/lib/libelf/Makefile b/lib/libelf/Makefile new file mode 100644 index 0000000..655e85f --- /dev/null +++ b/lib/libelf/Makefile @@ -0,0 +1,166 @@ +# $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_shnum.c \ + elf_shstrndx.c \ + elf_scn.c \ + elf_strptr.c \ + elf_update.c \ + elf_version.c \ + gelf_checksum.c \ + gelf_fsize.c \ + gelf_getclass.c \ + gelf_dyn.c \ + gelf_ehdr.c \ + gelf_phdr.c \ + gelf_rel.c \ + gelf_rela.c \ + gelf_shdr.c \ + gelf_sym.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_phdr.c \ + libelf_shdr.c \ + libelf_xlate.c +INCS= libelf.h gelf.h + +DPSRCS+= libelf_fsize.c libelf_msize.c libelf_convert.c +CLEANFILES+= libelf_fsize.c libelf_msize.c libelf_convert.c +CFLAGS+= -I${.OBJDIR} -I${.CURDIR} + +OBJS+= libelf_convert.o libelf_fsize.o libelf_msize.o + +OSRELDATE!= sysctl -n kern.osreldate + +SHLIB_MAJOR= 1 + +.if ${OSRELDATE} > 700009 +SRCS+= gelf_cap.c \ + gelf_move.c \ + gelf_syminfo.c +.endif + +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_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 <bsd.lib.mk> + +# Keep the .suffixes line after the include of bsd.lib.mk +.SUFFIXES: .m4 .c +.m4.c: + m4 -D SRCDIR=${.CURDIR} -D OSRELDATE=${OSRELDATE} ${.IMPSRC} > ${.TARGET} diff --git a/lib/libelf/Version.map b/lib/libelf/Version.map new file mode 100644 index 0000000..e8cc819 --- /dev/null +++ b/lib/libelf/Version.map @@ -0,0 +1,101 @@ +# +# $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_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; +}; diff --git a/lib/libelf/_libelf.h b/lib/libelf/_libelf.h new file mode 100644 index 0000000..02e7cf5 --- /dev/null +++ b/lib/libelf/_libelf.h @@ -0,0 +1,191 @@ +/*- + * 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 <sys/queue.h> + +#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 */ + +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 */ + } 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_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_ */ diff --git a/lib/libelf/elf.3 b/lib/libelf/elf.3 new file mode 100644 index 0000000..9d2c380 --- /dev/null +++ b/lib/libelf/elf.3 @@ -0,0 +1,482 @@ +.\" 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 September 1, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf +.Nd API for manipulating ELF objects +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Sh DESCRIPTION +The +.Lb libelf +library provides functions that allow an application to read and +manipulate ELF object files, and to read +.Xr ar 1 +archives. +The library allows the manipulation of ELF objects in a byte ordering +and word-size independent way, allowing an application to read and +create ELF objects for 32 and 64 bit architectures and for little- +and big-endian machines. +The library is capable of processing ELF objects that use extended +section numbering. +.Pp +This manual page serves to provide an overview of the functionality in +the ELF library. +Further information may found in the manual pages for individual +.Xr ELF 3 +functions that comprise the library. +.Ss ELF Concepts +As described in +.Xr elf 5 , +ELF files contain several data structures that are laid out in a +specific way. +ELF files begin with an +.Dq Executable Header , +and may contain an optional +.Dq Program Header Table , +and optional data in the form of ELF +.Dq sections . +A +.Dq Section Header Table +describes the content of the data in these sections. +.Pp +ELF objects have an associated +.Dq "ELF class" +which denotes the natural machine word size for the architecture +the object is associated with. +Objects for 32 bit architectures have an ELF class of +.Dv ELFCLASS32 . +Objects for 64 bit architectures have an ELF class of +.Dv ELFCLASS64 . +.Pp +ELF objects also have an associated +.Dq endianness +which denotes the endianness of the machine architecture associated +with the object. +This may be +.Dv ELFDATA2LSB +for little-endian architectures and +.Dv ELFDATA2MSB +for big-endian architectures. +.Pp +ELF objects are also associated with an API version number. +This version number determines the layout of the individual components +of an ELF file and the semantics associated with these. +.Ss Data Representation And Translation +The +.Xr ELF 3 +library distinguishes between +.Dq native +representations of ELF data structures and their +.Dq file +representations. +.Pp +An application would work with ELF data in its +.Dq native +representation, i.e., using the native byteorder and alignment mandated +by the processor the application is running on. +The +.Dq file +representation of the same data could use a different byte ordering +and follow different constraints on object alignment than these native +constraints. +.Pp +Accordingly, the +.Xr ELF 3 +library offers translation facilities +.Xr ( elf32_xlatetof 3 , +.Xr elf32_xlatetom 3 , +.Xr elf64_xlatetof 3 +and +.Xr elf64_xlatetom 3 ) +to and from these +representations and also provides higher-level APIs that retrieve and store +data from the ELF object in a transparent manner. +.Ss Library Working Version +Conceptually, there are three version numbers associated with an +application using the ELF library to manipulate ELF objects: +.Bl -bullet -compact -offset indent +.It +The ELF version that the application was compiled against. +This version determines the ABI expected by the application. +.It +The ELF version of the ELF object being manipulated by the +application through the ELF library. +.It +The ELF version (or set of versions) supported by the ELF library itself. +.El +.Pp +In order to facilitate working with ELF objects of differing versions, +the ELF library requires the application to call the +.Fn elf_version +function before invoking many of its operations, in order to inform +the library of the application's desired working version. +.Pp +In the current implementation, all three versions have to be +.Dv EV_CURRENT . +.Ss Namespace use +The ELF library uses the following prefixes: +.Bl -tag -width "ELF_F_*" +.It elf_* +Used for class-independent functions. +.It elf32_* +Used for functions working with 32 bit ELF objects. +.It elf64_* +Used for functions working with 64 bit ELF objects. +.It Elf_* +Used for class-independent data types. +.It ELF_C_* +Used for command values used in a few functions. +These symbols are defined as members of the +.Vt Elf_Cmd +enumeration. +.It ELF_E_* +Used for error numbers. +.It ELF_F_* +Used for flags. +.It ELF_K_* +These constants define the kind of file associated with an ELF +descriptor. +See +.Xr elf_kind 3 . +The symbols are defined by the +.Vt Elf_Kind +enumeration. +.It ELF_T_* +These values are defined by the +.Vt Elf_Type +enumeration, and denote the types of ELF data structures +that can be present in an ELF object. +.El +.Ss Descriptors +Applications communicate with the library using descriptors. +These are: +.Bl -tag -width ".Vt Elf_Data" +.It Vt Elf +An +.Vt Elf +descriptor represents an ELF object or an +.Xr ar 1 +archive. +It is allocated using one of the +.Fn elf_begin +or +.Fn elf_memory +functions. +An +.Vt Elf +descriptor can be used to read and write data to an ELF file. +An +.Vt Elf +descriptor can be associated with zero or more +.Vt Elf_Scn +section descriptors. +.Pp +Given an ELF descriptor, the application may retrieve the ELF +object's class-dependent +.Dq "Executable Header" +structures using the +.Fn elf32_getehdr +or +.Fn elf64_getehdr +functions. +A new Ehdr structure may be allocated using the +.Fn elf64_newehdr +or +.Fn elf64_newehdr +functions. +.Pp +The +.Dq "Program Header Table" +associated with an ELF descriptor may be allocated using the +.Fn elf32_getphdr +or +.Fn elf64_getphdr +functions. +A new program header table may be allocated or an existing table +resized using the +.Fn elf32_newphdr +or +.Fn elf64_newphdr +functions. +.Pp +The +.Vt Elf +structure is opaque and has no members visible to the +application. +.\" TODO describe the Elf_Arhdr and Elf_Arsym structures. +.It Vt Elf_Data +An +.Vt Elf_Data +data structure describes an individual chunk of a ELF file as +represented in memory. +It has the following application visible members: +.Bl -tag -width ".Vt unsigned int d_version" -compact +.It Vt "uint64_t d_align" +The in-file alignment of the data buffer within its containing ELF section. +This value must be a power of two. +.It Vt "uint64_t d_off" +The offset with the containing section where this descriptors data +would be placed. +This field will be computed by the library unless the application +requests full control of the ELF object's layout. +.It Vt "uint64_t d_size" +The number of bytes of data in this descriptor. +.It Vt "void *d_buf" +A pointer to data in memory. +.It Vt "Elf_Type d_type" +The ELF type (see below) of the data in this descriptor. +.It Vt "unsigned int d_version" +The operating version for the data in this buffer. +.El +.Pp +.Vt Elf_Data +descriptors are usually associated with +.Vt Elf_Scn +descriptors. +Existing data descriptors associated with an ELF section may be +structures are retrieved using the +.Fn elf_getdata +function. +The +.Fn elf_newdata +function may be used to attach new data descriptors to an ELF section. +.It Vt Elf_Scn +.Vt Elf_Scn +descriptors represent a section in an ELF object. +.Pp +They are retrieved using the +.Fn elf_getscn +function. +An application may iterate through the existing sections of an ELF +object using the +.Fn elf_nextscn +function. +New sections may be allocated using the +.Fn elf_newscn +function. +.Pp +The +.Vt Elf_Scn +descriptor is opaque and contains no application modifiable fields. +.El +.Ss Functional Grouping +This section contains a brief overview of the available functionality +in the ELF library. +Each function listed here is described further in its own manual page. +.Bl -tag -width indent +.It "Archive Access" +.Bl -tag -compact +.It Fn elf_getarsym +Retrieve the archive symbol table. +.It Fn elf_getarhdr +Retrieve the archive header for an object. +.It Fn elf_getbase +Retrieve the offset of a member inside an archive. +.It Fn elf_next +Iterate through an +.Xr ar 1 +archive. +.It Fn elf_rand +Random access inside an +.Xr ar 1 +archive. +.El +.It "Data Structures" +.Bl -tag -compact +.It Fn elf_getdata +Retrieve translated data for an ELF section. +.It Fn elf_getscn +Retrieve the section descriptor for a named section. +.It Fn elf_ndxscn +Retrieve the index for a section. +.It Fn elf_newdata +Add a new +.Vt Elf_Data +descriptor to an ELF section. +.It Fn elf_newscn +Add a new section descriptor to an ELF descriptor. +.It Fn elf_nextscn +Iterate through the sections in an ELF object. +.It Fn elf_rawdata +Retrieve untranslated data for an ELF sectino. +.It Fn elf_rawfile +Return a pointer to the untranslated file contents for an ELF object. +.It Fn elf32_getehdr , Fn elf64_getehdr +Retrieve the Executable Header in an ELF object. +.It Fn elf32_getphdr , Fn elf64_getphdr +Retrieve the Program Header Table in an ELF object. +.It Fn elf32_getshdr , Fn elf64_getshdr +Retrieve the ELF section header associated with an +.Vt Elf_Scn +descriptor. +.It Fn elf32_newehdr , Fn elf64_newehdr +Allocate an Executable Header in an ELF object. +.It Fn elf32_newphdr , Fn elf64_newphdr +Allocate or resize the Program Header Table in an ELF object. +.El +.It "Data Translation" +.Bl -tag -compact +.It Fn elf32_xlatetof , Fn elf64_xlatetof +Translate an ELF data structure from its native representation to its +file representation. +.It Fn elf32_xlatetom , Fn elf64_xlatetom +Translate an ELF data structure from its file representation to a +native representation. +.El +.It "Error Reporting" +.Bl -tag -compact +.It Fn elf_errno +Retrieve the current error. +.It Fn elf_errmsg +Retrieve a human readable description of the current error. +.El +.It "Initialization" +.Bl -tag -compact +.It Fn elf_begin +Opens an +.Xr ar 1 +archive or ELF object given a file descriptor. +.It Fn elf_end +Close an ELF descriptor and release all its resources. +.It Fn elf_memory +Opens an +.Xr ar 1 +archive or ELF object present in a memory arena. +.It Fn elf_version +Sets the operating version. +.El +.It "IO Control" +.Bl -tag -width ".Fn elf_setshstrndx" -compact +.It Fn elf_cntl +Manage the association between and ELF descriptor and its underlying file. +.It Fn elf_flagdata +Mark an +.Vt Elf_Data +descriptor as dirty. +.It Fn elf_flagehdr +Mark the ELF Executable Header in an ELF descriptor as dirty. +.It Fn elf_flagphdr +Mark the ELF Program Header Table in an ELF descriptor as dirty. +.It Fn elf_flagscn +Mark an +.Vt Elf_Scn +descriptor as dirty. +.It Fn elf_flagshdr +Mark an ELF Section Header as dirty. +.It Fn elf_setshstrndx +Set the index of the section name string table for the ELF object. +.It Fn elf_update +Recompute ELF object layout and optionally write the modified object +back to the underlying file. +.El +.It "Queries" +.Bl -tag -width ".Fn elf_getshstrndx" -compact +.It Fn elf32_checksum , Fn elf64_checkum +Compute checksum of an ELF object. +.It Fn elf_getident +Retrieve the identification bytes for an ELF object. +.It Fn elf_getshnum +Retrieve the number of sections in an ELF object. +.It Fn elf_getshstrndx +Retrieve the section index of the section name string table in +an ELF object. +.It Fn elf_hash +Compute the ELF hash value of a string. +.It Fn elf_kind +Query the kind of object associated with an ELF descriptor. +.It Fn elf32_fsize , Fn elf64_fsize +Return the size of the file representation of an ELF type. +.El +.El +.Ss Controlling ELF Object Layout +In the usual mode of operation, library will compute section +offsets and alignments based on the contents of an ELF descriptor's +sections without need for further intervention by the +application. +.Pp +However, if the application wishes to take complete charge of the +layout of the ELF file, it may set the +.Dv ELF_F_LAYOUT +flag on an ELF descriptor using +.Xr elf_flagelf 3 , +following which the library will use the data offsets and alignments +specified by the application when laying out the file. +.Pp +Gaps in between sections will be filled with the fill character +set by function +.Fn elf_fill . +.Ss Error Handling +In case an error is encountered, these library functions set an +internal error number and signal the presence of the error by +returning an special return value. The application can check the +current error number by calling +.Xr elf_errno 3 . +A human readable description of the recorded error is available by +calling +.Xr elf_errmsg 3 . +.Ss Memory Management Rules +The library keeps track of all +.Vt Elf_Scn +and +.Vt Elf_Data +descriptors associated with an ELF descriptor and recovers them +when the descriptor is closed using +.Xr elf_end 3 . +Thus the application must not call +.Xr free 3 +on data structures allocated by the ELF library. +.Pp +Conversely the library will not +free data that it has not allocated. +As an example, an application may call +.Xr elf_newdata 3 +to allocate a new +.Vt Elf_Data +descriptor and can set the +.Va d_off +member of the descriptor to point to a region of memory allocated +using +.Xr malloc 3 . +It is the applications responsibility to free this arena, though the +library will reclaim the space used by the +.Vt Elf_Data +descriptor itself. +.Sh SEE ALSO +.Xr gelf 3 , +.Xr elf 5 +.Sh HISTORY +The original ELF(3) API was developed for Unix System V. +The current implementation of the ELF(3) API appeared in +.Fx 7.0 . +.Sh AUTHORS +The ELF library was written by +.An "Joseph Koshy" +.Aq jkoshy@FreeBSD.org . diff --git a/lib/libelf/elf_begin.3 b/lib/libelf/elf_begin.3 new file mode 100644 index 0000000..355366f --- /dev/null +++ b/lib/libelf/elf_begin.3 @@ -0,0 +1,281 @@ +.\" 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 June 21, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_begin +.Nd open an ELF file or ar(1) archive +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf *" +.Fn elf_begin "int fd" "Elf_Cmd cmd" "Elf *elf" +.Sh DESCRIPTION +Function +.Fn elf_begin +is used to open ELF files and +.Xr ar 1 +archives for further processing by other APIs in the +.Xr elf 3 +library. +It is also used to access individual ELF members of an +.Xr ar 1 +archive in combination with the +.Xr elf_next 3 +and +.Xr elf_rand 3 +APIs. +.Pp +Argument +.Ar fd +is an open file descriptor returned from an +.Xr open 2 +system call. +Function +.Fn elf_begin +uses argument +.Ar fd +for reading or writing depending on the value of argument +.Ar cmd . +Argument +.Ar elf +is primarily used for iterating through archives. +.Pp +The argument +.Ar cmd +can have the following values: +.Bl -tag -width "ELF_C_WRITE" +.It ELF_C_NULL +Causes +.Fn elf_begin +to return NULL. +Arguments +.Ar fd +and +.Ar elf +are ignored, and no additional error is signalled. +.It ELF_C_READ +This value is to be when the application wishes to examine (but not +modify) the contents of the file specified by argument +.Ar fd . +It can be used for both +.Xr ar 1 +archives and for regular ELF files. +.Pp +Argument +.Ar fd +should have been opened for reading. +If argument +.Ar elf +is NULL, the library will allocate a new ELF descriptor for +the file being processed. +If argument +.Ar elf +is not NULL, and references a regular ELF file previously opened with +.Fn elf_begin , +then the activation count for +.Ar elf +is incremented. +If argument +.Ar elf +is not NULL, and references a descriptor for an +.Xr ar 1 +archive opened earlier with +.Fn elf_begin , +a descriptor for an element in the archive is returned as +described in the section +.Sx "Processing ar(1) archives" +below. +.It Dv ELF_C_RDWR +The command is used to prepare an ELF file for reading and writing. +It is not supported for archives. +.Pp +Argument +.Ar fd +should have been opened for reading and writing. +If argument +.Ar elf +is NULL, the library will allocate a new ELF descriptor for +the file being processed. +If the argument +.Ar elf +is non-null, it should point to a descriptor previously +allocated with +.Fn elf_begin +with the same values for arguments +.Ar fd +and +.Ar cmd ; +in this case the library will increment the activation count for descriptor +.Ar elf +and return the same descriptor. +Changes to the in-memory image of the ELF file are written back to +disk using the +.Xr elf_update 3 +function. +.Pp +This command is not valid for +.Xr ar 1 +archives. +.It Dv ELF_C_WRITE +This command is used when the application wishes to create a new ELF +file. +Argument +.Ar fd +should have been opened for writing. +Argument +.Ar elf +is ignored, and the previous contents of file referenced by +argument +.Ar fd +are overwritten. +.El +.Ss Processing ar(1) archives +An +.Xr ar 1 +archive may be opened in read mode (with argument +.Ar cmd +set to +.Dv ELF_C_READ ) +using +.Fn elf_begin . +The returned ELF descriptor can be passed into to +subsequent calls to +.Fn elf_begin +to access individual members of the archive. +.Pp +Random access within an opened archive is possible using +the +.Xr elf_next 3 +and +.Xr elf_rand 3 +functions. +.Pp +The symbol table of the archive may be retrieved +using +.Xr elf_getarsym 3 . +.Sh RETURN VALUES +The function returns a pointer to a ELF descriptor if successful, or NULL +if an error occurred. +.Sh EXAMPLES +To iterate through the members of an +.Xr ar 1 +archive, use: +.Bd -literal -offset indent +Elf_Cmd c; +Elf *ar_e, *elf_e; +\&... +c = ELF_C_READ; +if ((ar_e = elf_begin(fd, c, (Elf *) 0)) == 0) { + \&... handle error in opening the archive ... +} +while ((elf_e = elf_begin(fd, c, ar_e)) != 0) { + \&... process member referenced by elf_e here ... + c = elf_next(elf_e); + elf_end(elf_e); +} +.Ed +.Pp +To create a new ELF file, use: +.Bd -literal -offset indent +int fd; +Elf *e; +\&... +if ((fd = open("filename", O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) { + \&... handle the error from open(2) ... +} +if ((e = elf_begin(fd, ELF_C_WRITE, (Elf *) 0)) == 0) { + \&... handle the error from elf_begin() ... +} +\&... create the ELF image using other elf(3) APIs ... +elf_update(e, ELF_C_WRITE); +elf_end(e); +.Ed +.Sh ERRORS +Function +.Fn elf_begin +can fail with the following errors: +.Pp +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +An unrecognized value was specified in argument +.Ar cmd . +.It Bq Er ELF_E_ARGUMENT +A non-null value for argument +.Ar elf +was specified when +.Ar cmd +was set to +.Dv ELF_C_RDWR . +.It Bq Er ELF_E_ARGUMENT +The value of argument +.Ar fd +differs from the one the ELF descriptor +.Ar elf +was created with. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar cmd +differs from the value specified when ELF descriptor +.Ar elf +was created. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an +.Xr ar 1 +archive. +.It Bq Er ELF_E_ARGUMENT +An +.Xr ar 1 +archive was opened with with +.Ar cmd +set to +.Dv ELF_C_RDWR . +.It Bq Er ELF_E_IO +Function +.Fn elf_begin +was unable to truncate a file opened for writing using +.Dv ELF_C_WRITE . +.It Bq Er ELF_E_RESOURCE +An out of memory condition was encountered. +.It Bq Er ELF_E_SEQUENCE +Function +.Fn elf_begin +was called before a working version was established with +.Xr elf_version 3 . +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_end 3 , +.Xr elf_error 3 , +.Xr elf_memory 3 , +.Xr elf_next 3 , +.Xr elf_rand 3 , +.Xr elf_update 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_begin.c b/lib/libelf/elf_begin.c new file mode 100644 index 0000000..d59042c --- /dev/null +++ b/lib/libelf/elf_begin.c @@ -0,0 +1,156 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include <ar.h> +#include <ctype.h> +#include <libelf.h> + +#include "_libelf.h" + +static Elf * +_libelf_open_object(int fd, Elf_Cmd c) +{ + Elf *e; + void *m; + struct stat sb; + + /* + * 'Raw' files are always mapped with 'PROT_READ'. At + * elf_update(3) time for files opened with ELF_C_RDWR the + * mapping is unmapped, file data is written to using write(2) + * and then the raw data is immediately mapped back in. + */ + if (fstat(fd, &sb) < 0) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + m = NULL; + if ((m = mmap(NULL, (size_t) sb.st_size, PROT_READ, MAP_PRIVATE, fd, + (off_t) 0)) == MAP_FAILED) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + if ((e = elf_memory(m, (size_t) sb.st_size)) == NULL) { + (void) munmap(m, (size_t) sb.st_size); + return (NULL); + } + + e->e_flags |= LIBELF_F_MMAP; + e->e_fd = fd; + e->e_cmd = c; + + if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) { + (void) elf_end(e); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + return (e); +} + +Elf * +elf_begin(int fd, Elf_Cmd c, Elf *a) +{ + Elf *e; + + e = NULL; + + if (LIBELF_PRIVATE(version) == EV_NONE) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + switch (c) { + case ELF_C_NULL: + return (NULL); + + case ELF_C_WRITE: + + if (a != NULL) { /* not allowed for ar(1) archives. */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + /* + * Check writeability of `fd' immediately and fail if + * not writeable. + */ + if (ftruncate(fd, (off_t) 0) < 0) { + LIBELF_SET_ERROR(IO, errno); + return (NULL); + } + + if ((e = _libelf_allocate_elf()) != NULL) { + _libelf_init_elf(e, ELF_K_ELF); + e->e_byteorder = LIBELF_PRIVATE(byteorder); + e->e_fd = fd; + e->e_cmd = c; + } + return (e); + + case ELF_C_RDWR: + if (a != NULL) { /* not allowed for ar(1) archives. */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + /*FALLTHROUGH*/ + case ELF_C_READ: + /* + * Descriptor `a' could be for a regular ELF file, or + * for an ar(1) archive. + */ + if (a && (a->e_fd != fd || c != a->e_cmd)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + break; + + default: + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + + } + + if (a == NULL) + e = _libelf_open_object(fd, c); + else if (a->e_kind == ELF_K_AR) + e = _libelf_ar_open_member(fd, c, a); + else + (e = a)->e_activations++; + + return (e); +} diff --git a/lib/libelf/elf_cntl.3 b/lib/libelf/elf_cntl.3 new file mode 100644 index 0000000..4853c1c --- /dev/null +++ b/lib/libelf/elf_cntl.3 @@ -0,0 +1,111 @@ +.\" 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 August 9, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_cntl +.Nd control an elf file descriptor +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_cntl "Elf *elf" "Elf_Cmd cmd" +.Sh DESCRIPTION +Function +.Fn elf_cntl +controls the ELF library's subsequent use of the file descriptor +used to create ELF descriptor +.Ar elf . +.Pp +Argument +.Ar cmd +informs the library of the action to be taken: +.Bl -tag -width "ELF_C_FDDONE" +.It Dv ELF_C_FDDONE +This value instructs the ELF library not to perform any further +I/O on the file descriptor associated with argument +.Ar elf . +For ELF descriptors opened with mode +.Ar ELF_C_WRITE +or +.Ar ELF_C_RDWR +subsequent +.Fn elf_update +operations on the descriptor will fail. +.It Dv ELF_C_FDREAD +This value instructs the ELF library to read in all necessary +data associated with ELF descriptor +.Ar elf +into memory so that the underlying file descriptor can be +safely closed with command +.Dv ELF_C_FDDONE . +.El +.Pp +Argument +.Ar elf +must be an ELF descriptor associated with a file system object +(e.g., an +.Xr ar 1 +archive, an ELF file, or other data file). +.Sh IMPLEMENTATION NOTES +Due to use of +.Xr mmap 2 +internally, this function is a no-op for for ELF objects opened in +.Dv ELF_C_READ +mode. +.Sh RETURN VALUES +Function +.Fn elf_cntl +returns 0 on success, or -1 if an error was detected. +.Sh ERRORS +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARCHIVE +Argument +.Ar elf +is a descriptor for an archive member. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar cmd +was not recognized. +.It Bq Er ELF_E_MODE +An +.Dv ELF_C_FDREAD +operation was requested on an ELF descriptor opened +for writing. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_end 3 , +.Xr elf_next 3 , +.Xr elf_update 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_cntl.c b/lib/libelf/elf_cntl.c new file mode 100644 index 0000000..9fbd5c7 --- /dev/null +++ b/lib/libelf/elf_cntl.c @@ -0,0 +1,59 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +int +elf_cntl(Elf *e, Elf_Cmd c) +{ + if (e == NULL || + (c != ELF_C_FDDONE && c != ELF_C_FDREAD)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (-1); + } + + if (e->e_parent) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (-1); + } + + if (c == ELF_C_FDREAD) { + if (e->e_cmd == ELF_C_WRITE) { + LIBELF_SET_ERROR(MODE, 0); + return (-1); + } + else + return (0); + } + + e->e_fd = -1; + return 0; +} diff --git a/lib/libelf/elf_data.c b/lib/libelf/elf_data.c new file mode 100644 index 0000000..481fb3d --- /dev/null +++ b/lib/libelf/elf_data.c @@ -0,0 +1,224 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <libelf.h> +#include <stdlib.h> + +#include "_libelf.h" + + +Elf_Data * +elf_getdata(Elf_Scn *s, Elf_Data *d) +{ + Elf *e; + char *dst; + size_t fsz, msz, count; + int elfclass, elftype; + unsigned int sh_type; + uint64_t sh_align, sh_offset, sh_size; + void (*xlate)(char *_d, char *_s, size_t _c, int _swap); + + if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF || + (d != NULL && s != d->d_scn)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) + return (d); + + if (d != NULL) + return (STAILQ_NEXT(d, d_next)); + + if (e->e_rawfile == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + elfclass = e->e_class; + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + + if (elfclass == ELFCLASS32) { + sh_type = s->s_shdr.s_shdr32.sh_type; + sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; + sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; + } else { + sh_type = s->s_shdr.s_shdr64.sh_type; + sh_offset = s->s_shdr.s_shdr64.sh_offset; + sh_size = s->s_shdr.s_shdr64.sh_size; + sh_align = s->s_shdr.s_shdr64.sh_addralign; + } + + if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || + elftype > ELF_T_LAST || + sh_offset + sh_size > (uint64_t) e->e_rawsize) { + LIBELF_SET_ERROR(SECTION, 0); + return (NULL); + } + + if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(elftype, + (size_t) 1, e->e_version)) == 0) { + LIBELF_SET_ERROR(UNIMPL, 0); + return (NULL); + } + + + if (sh_size % fsz) { + LIBELF_SET_ERROR(SECTION, 0); + return (NULL); + } + + count = sh_size / fsz; + + msz = _libelf_msize(elftype, elfclass, e->e_version); + + assert(msz > 0); + + if ((dst = malloc(msz*count)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + if ((d = _libelf_allocate_data(s)) == NULL) + return (NULL); + + d->d_buf = dst; + d->d_off = 0; + d->d_align = sh_align; + d->d_size = msz * count; + d->d_type = elftype; + d->d_version = e->e_version; + + d->d_flags |= LIBELF_F_MALLOCED; + STAILQ_INSERT_TAIL(&s->s_data, d, d_next); + + xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); + (*xlate)(d->d_buf, e->e_rawfile + sh_offset, count, e->e_byteorder != + LIBELF_PRIVATE(byteorder)); + + return (d); +} + +Elf_Data * +elf_newdata(Elf_Scn *s) +{ + Elf *e; + Elf_Data *d; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + /* + * elf_newdata() has to append a data descriptor, so + * bring in existing section data if not already present. + */ + if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) + if (elf_getdata(s, NULL) == NULL) + return (NULL); + + if ((d = malloc(sizeof(Elf_Data))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return (NULL); + } + + STAILQ_INSERT_TAIL(&s->s_data, d, d_next); + d->d_flags = 0; + d->d_scn = s; + + d->d_align = 1; + d->d_buf = NULL; + d->d_off = (uint64_t) ~0; + d->d_size = 0; + d->d_type = ELF_T_BYTE; + d->d_version = LIBELF_PRIVATE(version); + + (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); + + return (d); +} + +/* + * Retrieve a data descriptor for raw (untranslated) data for section + * `s'. + */ + +Elf_Data * +elf_rawdata(Elf_Scn *s, Elf_Data *d) +{ + Elf *e; + int elf_class; + uint64_t sh_align, sh_offset, sh_size; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF || e->e_rawfile == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) + return (d); + + if (d != NULL) + return (STAILQ_NEXT(d, d_next)); + + elf_class = e->e_class; + + assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); + + if (elf_class == ELFCLASS32) { + sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; + sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; + } else { + sh_offset = s->s_shdr.s_shdr32.sh_offset; + sh_size = s->s_shdr.s_shdr32.sh_size; + sh_align = s->s_shdr.s_shdr32.sh_addralign; + } + + if ((d = _libelf_allocate_data(s)) == NULL) + return (NULL); + + d->d_buf = e->e_rawfile + sh_offset; + d->d_off = 0; + d->d_align = sh_align; + d->d_size = sh_size; + d->d_type = ELF_T_BYTE; + d->d_version = e->e_version; + + STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); + + return (d); +} diff --git a/lib/libelf/elf_end.3 b/lib/libelf/elf_end.3 new file mode 100644 index 0000000..67afed4 --- /dev/null +++ b/lib/libelf/elf_end.3 @@ -0,0 +1,76 @@ +.\" 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 June 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_end +.Nd release an ELF descriptor +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_end "Elf *elf" +.Sh DESCRIPTION +Function +.Fn elf_end +is used to release the resources associated with an ELF descriptor +pointed to by argument +.Ar elf . +This descriptor must have been allocated by a previous call to +.Xr elf_begin 3 +or +.Xr elf_memory 3 . +For programming convenience, a NULL value is permitted for argument +.Ar elf . +.Pp +A call to +.Fn elf_end +decrements the activation count for descriptor +.Ar elf +by one. +The resources associated with the descriptor are only released +with its activation count goes to zero. +.Pp +Once function +.Fn elf_end +returns zero, the ELF descriptor +.Ar elf +will no longer be valid and should not be used further. +.Sh RETURN VALUES +Function +.Fn elf_end +returns the current value of the ELF descriptor +.Ar elf Ap s +activation count, or zero if argument +.Ar elf +was NULL. +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_memory 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_end.c b/lib/libelf/elf_end.c new file mode 100644 index 0000000..affb135 --- /dev/null +++ b/lib/libelf/elf_end.c @@ -0,0 +1,88 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/mman.h> + +#include <assert.h> +#include <libelf.h> +#include <stdlib.h> + +#include "_libelf.h" + +int +elf_end(Elf *e) +{ + Elf *sv; + Elf_Scn *scn, *tscn; + + if (e == NULL || e->e_activations == 0) + return (0); + + if (--e->e_activations > 0) + return (e->e_activations); + + assert(e->e_activations == 0); + + while (e && e->e_activations == 0) { + switch (e->e_kind) { + case ELF_K_AR: + /* + * If we still have open child descriptors, we + * need to defer reclaiming resources till all + * the child descriptors for the archive are + * closed. + */ + if (e->e_u.e_ar.e_nchildren > 0) + return (0); + break; + case ELF_K_ELF: + /* + * Reclaim all section descriptors. + */ + STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) + scn = _libelf_release_scn(scn); + break; + case ELF_K_NUM: + assert(0); + default: + break; + } + + if (e->e_flags & LIBELF_F_MMAP) + (void) munmap(e->e_rawfile, e->e_rawsize); + + sv = e; + if ((e = e->e_parent) != NULL) + e->e_u.e_ar.e_nchildren--; + sv = _libelf_release_elf(sv); + } + + return (0); +} + diff --git a/lib/libelf/elf_errmsg.3 b/lib/libelf/elf_errmsg.3 new file mode 100644 index 0000000..2b21e26 --- /dev/null +++ b/lib/libelf/elf_errmsg.3 @@ -0,0 +1,107 @@ +.\" 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 June 11, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_errmsg , +.Nm elf_errno +.Nd ELF library error message handling +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_errno "void" +.Ft "const char *" +.Fn elf_errmsg "int error" +.Sh DESCRIPTION +When an error occurs during an ELF library API call, the library +encodes the error using an error number and stores the error number +internally for retrieval by the application at a later point of time. +Error numbers may contain an OS supplied error code in addition to +an ELF API specific error code. +An error number value of zero indicates no error. +.Pp +Function +.Fn elf_errno +is used to retrieve the last error recorded by the ELF library. +Invoking this function has the side-effect of resetting the +ELF library's recorded error number to zero. +.Pp +The function +.Fn elf_errmsg +returns a null-terminated string with a human readable +description of the error specified in argument +.Ar error . +A zero value for argument +.Ar error +retrieves the most recent error encountered by the ELF +library. +An argument value of -1 behaves identically, except that +it guarantees a non-NULL return from +.Fn elf_errmsg . +.Sh RETURN VALUES +Function +.Fn elf_errno +returns a non-zero value encoding the last error encountered +by the ELF library, or zero if no error was encountered. +.Pp +Function +.Fn elf_errmsg +returns a pointer to library local storage for non-zero values +of argument +.Ar error . +With a zero argument, the function will return a NULL pointer if no +error had been encountered by the library, or will return a pointer to +library local storage containing an appropriate message otherwise. +.Sh EXAMPLES +Clearing the ELF library's recorded error number can be accomplished +by invoking +.Fn elf_errno +and discarding its return value. +.Bd -literal -offset indent +/* clear error */ +(void) elf_errno(); +.Ed +.Pp +Retrieving a human-readable description of the current error number +can be done with the following snippet: +.Bd -literal -offset indent +int err; +const char *errmsg; +\&... +err = elf_errno(); +if (err != 0) + errmsg = elf_errmsg(err); +.Ed +.Sh SEE ALSO +.Xr elf 3 , +.Xr gelf 3 +.Sh BUGS +Function +.Fn elf_errmsg +is not localized. diff --git a/lib/libelf/elf_errmsg.c b/lib/libelf/elf_errmsg.c new file mode 100644 index 0000000..394c63b --- /dev/null +++ b/lib/libelf/elf_errmsg.c @@ -0,0 +1,100 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + +/* + * Retrieve a human readable translation for an error message. + */ + +const char *_libelf_errors[] = { +#define DEFINE_ERROR(N,S) [ELF_E_##N] = S + DEFINE_ERROR(NONE, "No Error"), + DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"), + DEFINE_ERROR(ARGUMENT, "Invalid argument"), + DEFINE_ERROR(CLASS, "ELF class mismatch"), + DEFINE_ERROR(DATA, "Invalid data buffer descriptor"), + DEFINE_ERROR(HEADER, "Missing or malformed ELF header"), + DEFINE_ERROR(IO, "I/O error"), + DEFINE_ERROR(LAYOUT, "Layout constraint violation"), + DEFINE_ERROR(MODE, "Incorrect ELF descriptor mode"), + DEFINE_ERROR(RANGE, "Value out of range of target"), + DEFINE_ERROR(RESOURCE, "Resource exhaustion"), + DEFINE_ERROR(SECTION, "Invalid section descriptor"), + DEFINE_ERROR(SEQUENCE, "API calls out of sequence"), + DEFINE_ERROR(UNIMPL, "Unimplemented feature"), + DEFINE_ERROR(VERSION, "Unknown ELF API version"), + DEFINE_ERROR(NUM, "Unknown error") +#undef DEFINE_ERROR +}; + +const char * +elf_errmsg(int error) +{ + int oserr; + + if (error == 0 && (error = LIBELF_PRIVATE(error)) == 0) + return NULL; + else if (error == -1) + error = LIBELF_PRIVATE(error); + + oserr = error >> LIBELF_OS_ERROR_SHIFT; + error &= LIBELF_ELF_ERROR_MASK; + + if (error < 0 || error >= ELF_E_NUM) + return _libelf_errors[ELF_E_NUM]; + if (oserr) { + strlcpy(LIBELF_PRIVATE(msg), _libelf_errors[error], + sizeof(LIBELF_PRIVATE(msg))); + strlcat(LIBELF_PRIVATE(msg), ":", sizeof(LIBELF_PRIVATE(msg))); + strlcat(LIBELF_PRIVATE(msg), strerror(oserr), + sizeof(LIBELF_PRIVATE(msg))); + return (const char *)&LIBELF_PRIVATE(msg); + } + return _libelf_errors[error]; +} + +#if defined(LIBELF_TEST_HOOKS) + +const char * +_libelf_get_unknown_error_message(void) +{ + return _libelf_errors[ELF_E_NUM]; +} + +const char * +_libelf_get_no_error_message(void) +{ + return _libelf_errors[0]; +} + +#endif /* LIBELF_TEST_HOOKS */ diff --git a/lib/libelf/elf_errno.c b/lib/libelf/elf_errno.c new file mode 100644 index 0000000..44feae3 --- /dev/null +++ b/lib/libelf/elf_errno.c @@ -0,0 +1,58 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +int +elf_errno(void) +{ + int old; + + old = LIBELF_PRIVATE(error); + LIBELF_PRIVATE(error) = 0; + return (old & LIBELF_ELF_ERROR_MASK); +} + +#if defined(LIBELF_TEST_HOOKS) + +int +_libelf_get_max_error(void) +{ + return ELF_E_NUM; +} + +void +_libelf_set_error(int error) +{ + LIBELF_PRIVATE(error) = error; +} + +#endif /* LIBELF_TEST_HOOKS */ diff --git a/lib/libelf/elf_fill.3 b/lib/libelf/elf_fill.3 new file mode 100644 index 0000000..88d0286 --- /dev/null +++ b/lib/libelf/elf_fill.3 @@ -0,0 +1,52 @@ +.\" 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 June 11, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_fill +.Nd set fill byte for inter-section padding +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft void +.Fn elf_fill "int fill" +.Sh DESCRIPTION +Function +.Fn elf_fill +allows an application to specify a fill value for the padding inserted +between two sections of an ELF file to meet section alignment +constraints. +By default the ELF library uses zero bytes for padding. +.Pp +The ELF library will only pad bytes if the +.Dv ELF_F_LAYOUT +flag is not set for the ELF file. +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagelf 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/elf_fill.c b/lib/libelf/elf_fill.c new file mode 100644 index 0000000..3dae25d --- /dev/null +++ b/lib/libelf/elf_fill.c @@ -0,0 +1,38 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +void +elf_fill(int fill) +{ + LIBELF_PRIVATE(fillchar) = fill; +} diff --git a/lib/libelf/elf_flag.c b/lib/libelf/elf_flag.c new file mode 100644 index 0000000..a8e948e --- /dev/null +++ b/lib/libelf/elf_flag.c @@ -0,0 +1,164 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +unsigned int +elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags) +{ + Elf *e; + Elf_Scn *scn; + unsigned int r; + + if (d == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL || e->e_kind != ELF_K_ELF || + (flags & ~ELF_F_DIRTY) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = scn->s_flags |= flags; + else + r = scn->s_flags &= ~flags; + + return (r); +} + +unsigned int +elf_flagehdr(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int ec; + void *ehdr; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) + ehdr = e->e_u.e_elf.e_ehdr.e_ehdr32; + else + ehdr = e->e_u.e_elf.e_ehdr.e_ehdr64; + + if (ehdr == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (0); + } + + return (elf_flagelf(e, c, flags)); +} + +unsigned int +elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int r; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || + (flags & ~(ELF_F_DIRTY|ELF_F_LAYOUT)) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = e->e_flags |= flags; + else + r = e->e_flags &= ~flags; + return (r); +} + +unsigned int +elf_flagphdr(Elf *e, Elf_Cmd c, unsigned int flags) +{ + int ec; + void *phdr; + + if (e == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) + phdr = e->e_u.e_elf.e_phdr.e_phdr32; + else + phdr = e->e_u.e_elf.e_phdr.e_phdr64; + + if (phdr == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (0); + } + + return (elf_flagelf(e, c, flags)); +} + +unsigned int +elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags) +{ + int r; + + if (s == NULL) + return (0); + + if ((c != ELF_C_SET && c != ELF_C_CLR) || + (flags & ~ELF_F_DIRTY) != 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (c == ELF_C_SET) + r = s->s_flags |= flags; + else + r = s->s_flags &= ~flags; + return (r); +} + +unsigned int +elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags) +{ + return (elf_flagscn(s, c, flags)); +} diff --git a/lib/libelf/elf_flagdata.3 b/lib/libelf/elf_flagdata.3 new file mode 100644 index 0000000..b80d902 --- /dev/null +++ b/lib/libelf/elf_flagdata.3 @@ -0,0 +1,159 @@ +.\" 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 August 10, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_flagdata , +.Nm elf_flagehdr , +.Nm elf_flagelf , +.Nm elf_flagphdr , +.Nm elf_flagscn , +.Nm elf_flagshdr +.Nd manipulate flags associated with ELF(3) data structures +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "unsigned int" +.Fn elf_flagdata "Elf_Data *data" "Elf_Cmd cmd" "unsigned int flags" +.Ft "unsigned int" +.Fn elf_flagehdr "Elf *elf" "Elf_Cmd cmd" "unsigned int flags" +.Ft "unsigned int" +.Fn elf_flagelf "Elf *elf" "Elf_Cmd cmd" "unsigned int flags" +.Ft "unsigned int" +.Fn elf_flagphdr "Elf *elf" "Elf_Cmd cmd" "unsigned int flags" +.Ft "unsigned int" +.Fn elf_flagscn "Elf_Scn *scn" "Elf_Cmd cmd" "unsigned int flags" +.Ft "unsigned int" +.Fn elf_flagshdr "Elf_Scn *scn" "Elf_Cmd cmd" "unsigned int flags" +.Sh DESCRIPTION +These functions are used to query, set or reset flag bits on data +structures associated with an ELF file. +.Pp +Arguments +.Ar data , +.Ar elf +and +.Ar scn +denote the data structures whose status bits need to be changed. +These values are allowed to be NULL to simplify error handling in +application code. +.Pp +Argument +.Ar cmd +may have the following values: +.Bl -tag -width ELF_C_SET +.It Dv ELF_C_CLR +The argument +.Ar flags +specifies the bits to be cleared. +.It Dv ELF_C_SET +The argument +.Ar flags +specifies the bits to be set. +.El +.Pp +The argument +.Ar flags +is allowed to have the following bits set: +.Bl -tag -width ELF_F_LAYOUT +.It Dv ELF_F_DIRTY +Mark the associated data structure as needing to be written back +to the underlying file. +A subsequent call to +.Xr elf_update 3 +will resynchronize the library's internal data structures. +.It Dv ELF_F_LAYOUT +This flag is only valid with the +.Fn elf_flagelf +API. +It informs the library that the application will take +responsibility for the layout of the file and that the library is +not to insert any padding in between sections. +.El +.Pp +Marking a given data structure as +.Dq dirty +affects all of its contained elements. +Thus marking an ELF descriptor +.Ar elf +with +.Fn elf_flagelf "elf" "ELF_C_SET" "ELF_F_DIRTY" +means that the entire contents of the descriptor are +.Dq dirty . +.Pp +Using a value of zero for argument +.Ar flags +will return the current set of flags for the data structure being +queried. +.Sh RETURN VALUES +These functions return the updated bits is successful, and zero if +an error is detected. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +An unsupported value was used for the +.Ar cmd +argument. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar flags +had unsupported flag bits set. +.It Bq Er ELF_E_ARGUMENT +The argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_SEQUENCE +Function +.Fn elf_flagehdr +was called without an executable header being allocated. +.It Bq Er ELF_E_SEQUENCE +Function +.Fn elf_flagphdr +was called without a program header being allocated. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_newdata 3 , +.Xr elf_update 3 , +.Xr elf32_newehdr 3 , +.Xr elf32_newphdr 3 , +.Xr elf32_newshdr 3 , +.Xr elf64_newehdr 3 , +.Xr elf64_newphdr 3 , +.Xr elf64_newshdr 3 , +.Xr gelf 3 , +.Xr gelf_newehdr 3 , +.Xr gelf_newphdr 3 , +.Xr gelf_newshdr 3 , +.Xr gelf_update_dyn 3 , +.Xr gelf_update_move 3 , +.Xr gelf_update_rel 3 , +.Xr gelf_update_rela 3 , +.Xr gelf_update_sym 3 , +.Xr gelf_update_syminfo 3 diff --git a/lib/libelf/elf_getarhdr.3 b/lib/libelf/elf_getarhdr.3 new file mode 100644 index 0000000..879fb31 --- /dev/null +++ b/lib/libelf/elf_getarhdr.3 @@ -0,0 +1,97 @@ +.\" 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 August 15, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getarhdr +.Nd retrieve ar(1) header for an archive member +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf_Arhdr *" +.Fn elf_getarhdr "Elf *elf" +.Sh DESCRIPTION +The +.Fn elf_getarhdr +function returns a pointer to an archive member header for +a descriptor +.Ar elf . +This descriptor must have been returned by a prior call to +.Xr elf_begin 3 , +and must be a descriptor for a member inside an +.Xr ar 1 +archive. +.Pp +Structure +.Vt Elf_Arhdr +includes the following members: +.Bl -tag -width indent +.It Vt "char *" Va ar_name +A pointer to a null terminated string with the archive +member's name inside the archive. +.It Vt "char *" Va ar_rawname +A pointer to a null terminated string that representing the +name in the archive symbol table, including the formatting characters +used by +.Xr ar 1 . +.It Vt time_t Va ar_date +The timestamp associated with the member. +.It Vt uid_t Va ar_uid +The uid of the creator of the member. +.It Vt gid_t Va ar_gid +The gid of the creator of the member. +.It Vt mode_t Va ar_mode +The file mode of the member. +.It Vt size_t Va ar_size +The size of the member in bytes. +.El +.Sh RETURN VALUES +This function returns a valid pointer to an +.Vt Elf_Arhdr +structure if successful, or NULL if an error is encountered. +.Sh ERRORS +Function +.Fn elf_getarhdr +may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for a member of an +.Xr ar 1 +archive. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_getarsym 3 , +.Xr elf_memory 3
\ No newline at end of file diff --git a/lib/libelf/elf_getarhdr.c b/lib/libelf/elf_getarhdr.c new file mode 100644 index 0000000..31b1f34 --- /dev/null +++ b/lib/libelf/elf_getarhdr.c @@ -0,0 +1,48 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +Elf_Arhdr * +elf_getarhdr(Elf *e) +{ + Elf_Arhdr *arh; + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((arh = e->e_arhdr) != NULL) + return (arh); + + return (_libelf_ar_gethdr(e)); +} diff --git a/lib/libelf/elf_getarsym.3 b/lib/libelf/elf_getarsym.3 new file mode 100644 index 0000000..d7d27f8 --- /dev/null +++ b/lib/libelf/elf_getarsym.3 @@ -0,0 +1,130 @@ +.\" 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 August 15, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getarsym +.Nd retrieve the symbol table of an archive +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf_Arsym *" +.Fn elf_getarsym "Elf *elf" "size_t *ptr" +.Sh DESCRIPTION +The function +.Fn elf_getarsym +retrieves the symbol table for an +.Xr ar 1 +archive, if one is available. +.Pp +Argument +.Ar elf +should be a descriptor for an +.Xr ar 1 +archive opened using +.Fn elf_begin +or +.Fn elf_memory . +.Pp +If the archive +.Ar elf +contains a symbol table with n entries, this function returns a +pointer to an array of n+1 +.Vt Elf_Arsym +structures. +An +.Vt Elf_Arsym +structure has the following elements: +.Bl -tag -width indent -compact +.It Vt "char *" Va as_name +This structure member is a pointer to a null-terminated symbol name. +.It Vt "off_t" Va as_off +This structure member contains the byte offset from the beginning of the archive to +the header for the archive member. +This value is suitable for use with +.Xr elf_rand 3 . +.It Vt "unsigned long" Va as_hash +This structure member contains a portable hash value for the symbol +name, as computed by +.Xr elf_hash 3 . +.El +.Pp +The last entry of the returned array will have a NULL value for member +.Va as_name , +a zero value for member +.Va as_off +and an illegal value of ~0UL for +.Va as_hash . +.Pp +If argument +.Ar ptr +is non-null, the +.Fn elf_getarsym +function will store the number of table entries returned (including the +sentinel entry at the end) into the location it points to. +.Sh RETURN VALUES +Function +.Fn elf_getarsym +returns a pointer to an array of +.Vt Elf_Arsym +structures if successful, or a NULL +pointer if an error was encountered. +.Pp +If argument +.Ar ptr +is non-null and there was no error, the library will store the +number of archive symbol entries returned into the location it +points to. +If argument +.Ar ptr +is non-null and an error was encountered, the library will +set the location pointed to by it to zero. +.Sh ERRORS +Function +.Fn elf_getarsym +may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an +.Xr ar 1 +archive. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_getarhdr 3 , +.Xr elf_hash 3 , +.Xr elf_memory 3 , +.Xr elf_next 3 , +.Xr elf_rand 3 diff --git a/lib/libelf/elf_getarsym.c b/lib/libelf/elf_getarsym.c new file mode 100644 index 0000000..df85c05 --- /dev/null +++ b/lib/libelf/elf_getarsym.c @@ -0,0 +1,56 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +Elf_Arsym * +elf_getarsym(Elf *ar, size_t *ptr) +{ + size_t n; + Elf_Arsym *symtab; + + n = 0; + symtab = NULL; + + if (ar == NULL || ar->e_kind != ELF_K_AR) + LIBELF_SET_ERROR(ARGUMENT, 0); + else if ((symtab = ar->e_u.e_ar.e_symtab) != NULL) + n = ar->e_u.e_ar.e_symtabsz; + else if (ar->e_u.e_ar.e_rawsymtab) + symtab = _libelf_ar_process_symtab(ar, &n); + else + LIBELF_SET_ERROR(ARCHIVE, 0); + + if (ptr) + *ptr = n; + return (symtab); +} + diff --git a/lib/libelf/elf_getbase.3 b/lib/libelf/elf_getbase.3 new file mode 100644 index 0000000..dfb88fc --- /dev/null +++ b/lib/libelf/elf_getbase.3 @@ -0,0 +1,67 @@ +.\" 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 June 11, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getbase +.Nd get the base offset for an object file +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft off_t +.Fn elf_getbase "Elf *elf" +.Sh DESCRIPTION +Function +.Fn elf_getbase +returns the file offset in the containing archive of the first byte of +the file referenced by ELF descriptor +.Ar elf . +.Sh RETURN VALUES +Function +.Fn elf_getbase +returns a valid file offset into the containing archive if successful. +It returns -1 if argument +.Ar elf +is NULL or is not a member of an +archive. +.Sh ERRORS +Function +.Fn elf_getbase +may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +is not an ELF descriptor for an archive member. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getarhdr 3 , +.Xr elf_getident 3 , +.Xr elf_rawfile 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/elf_getbase.c b/lib/libelf/elf_getbase.c new file mode 100644 index 0000000..d32fa6c --- /dev/null +++ b/lib/libelf/elf_getbase.c @@ -0,0 +1,45 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +off_t +elf_getbase(Elf *e) +{ + if (e == NULL || + e->e_parent == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (off_t) -1; + } + + return ((off_t) ((uintptr_t) e->e_rawfile - + (uintptr_t) e->e_parent->e_rawfile)); +} diff --git a/lib/libelf/elf_getdata.3 b/lib/libelf/elf_getdata.3 new file mode 100644 index 0000000..19bd3d9 --- /dev/null +++ b/lib/libelf/elf_getdata.3 @@ -0,0 +1,172 @@ +.\" 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 August 26, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getdata , +.Nm elf_newdata , +.Nm elf_rawdata +.Nd iterate through or allocate section data +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf_Data *" +.Fn elf_getdata "Elf_Scn *scn" "Elf_Data *data" +.Ft "Elf_Data *" +.Fn elf_newdata "Elf_Scn *scn" +.Ft "Elf_Data *" +.Fn elf_rawdata "Elf_Scn *scn" "Elf_Data *data" +.Sh DESCRIPTION +These functions are used to access and manipulate data descriptors +associated with section descriptors. +Data descriptors used by the ELF library are described in +.Xr elf 3 . +.Pp +Function +.Fn elf_getdata +will return the next data descriptor associated with section descriptor +.Ar scn . +The returned data descriptor will be setup to contain translated data. +Argument +.Ar data +may be NULL, in which case the function returns the first data descriptor +associated with section +.Ar scn . +If argument +.Ar data +is not NULL, it must be a pointer to a data descriptor associated with +section descriptor +.Ar scn , +and function +.Fn elf_getdata +will return a pointer to the next data descriptor for the section, +or NULL when the end of the section's descriptor list is reached. +.Pp +Function +.Fn elf_newdata +will allocate a new data descriptor and append it to the list of data +descriptors associated with section descriptor +.Ar scn . +The new data descriptor will be initialized as follows: +.Bl -tag -width "d_version" -compact -offset indent +.It Va d_align +Set to 1. +.It Va d_buf +Initialized to NULL. +.It Va d_off +Set to (off_t) -1. +This field is under application control if the +.Dv ELF_F_LAYOUT +flag was set on the ELF descriptor. +.It Va d_size +Set to zero. +.It Va d_type +Initialized to +.Dv ELF_T_BYTE . +.It Va d_version +Set to the current working version of the library, as set by +.Xr elf_version 3 . +.El +The application must set these values as appropriate before +calling +.Xr elf_update 3 . +Section +.Ar scn +must be associated with an ELF file opened for writing. +If the application has not requested full control of layout by +setting the +.Dv ELF_F_LAYOUT +flag on descriptor +.Ar elf , +then the data referenced by the returned descriptor will be positioned +after the existing content of the section, honoring the file alignment +specified in member +.Va d_align . +On successful completion of a call to +.Fn elf_newdata , +the ELF library will mark the section +.Ar scn +as +.Dq dirty . +.Pp +Function +.Fn elf_rawdata +is used to step through the data descriptors associated with +section +.Ar scn . +In contrast to function +.Fn elf_getdata , +this function returns untranslated data. +If argument +.Ar data +is NULL, the first data descriptor associated with section +.Ar scn +is returned. +If argument +.Ar data +is not NULL, is must be a data descriptor associated with +section +.Ar scn , +and function +.Fn elf_rawdata +will return the next data descriptor in the list, or NULL +if no further descriptors are present. +Function +.Fn elf_rawdata +always returns +.Vt Elf_Data +structures of type +.Dv ELF_T_BYTE . +.Sh RETURN VALUES +These functions return a valid pointer to a data descriptor if successful, or +NULL if an error occurs. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar scn +was NULL. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with section descriptor +.Ar scn . +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagdata 3 , +.Xr elf_flagscn 3 , +.Xr elf_getscn 3 , +.Xr elf_getshdr 3 , +.Xr elf_newscn 3 , +.Xr elf_update 3 , +.Xr elf_version 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_getident.3 b/lib/libelf/elf_getident.3 new file mode 100644 index 0000000..49e1fc4 --- /dev/null +++ b/lib/libelf/elf_getident.3 @@ -0,0 +1,83 @@ +.\" 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 July 3, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getident +.Nd return the initial bytes of a file +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft char * +.Fn elf_getident "Elf *elf" "size_t *sz" +.Sh DESCRIPTION +Function +.Fn elf_getident +returns a pointer to the initial bytes of the file for descriptor +.Ar elf . +.Pp +If argument +.Ar sz +is non-null, the size of the identification area returned is written +to the location pointed to by +.Ar sz . +This location is set to zero on errors. +.Sh RETURN VALUES +Function +.Fn elf_getident +will return a non-NULL pointer to the initial bytes of the file if +successful, or NULL if an error condition is detected. +.Sh ERRORS +Function +.Fn elf_getident +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_SEQUENCE +ELF descriptor +.Ar elf +was opened for writing and function +.Fn elf_getident +was called before a call to +.Xr elf_update 3 . +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getarhdr 3 , +.Xr elf_getbase 3 , +.Xr elf_getflags 3 , +.Xr elf_kind 3 , +.Xr elf_rawfile 3 , +.Xr elf_update 3 , +.Xr elf32_getehdr , +.Xr elf64_getehdr , +.Xr gelf 3 , +.Xr gelf_getclass 3 , +.Xr gelf_getehdr 3 diff --git a/lib/libelf/elf_getident.c b/lib/libelf/elf_getident.c new file mode 100644 index 0000000..1b5ae13 --- /dev/null +++ b/lib/libelf/elf_getident.c @@ -0,0 +1,67 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <assert.h> +#include <libelf.h> + +#include "_libelf.h" + +char * +elf_getident(Elf *e, size_t *sz) +{ + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + goto error; + } + + if (e->e_cmd == ELF_C_WRITE && e->e_rawfile == NULL) { + LIBELF_SET_ERROR(SEQUENCE, 0); + goto error; + } + + assert(e->e_kind != ELF_K_AR || e->e_cmd == ELF_C_READ); + + if (sz) { + if (e->e_kind == ELF_K_AR) + *sz = SARMAG; + else if (e->e_kind == ELF_K_ELF) + *sz = EI_NIDENT; + else + *sz = e->e_rawsize; + } + + return (e->e_rawfile); + + error: + if (sz) + *sz = 0; + return (NULL); +} diff --git a/lib/libelf/elf_getscn.3 b/lib/libelf/elf_getscn.3 new file mode 100644 index 0000000..5b4bd748 --- /dev/null +++ b/lib/libelf/elf_getscn.3 @@ -0,0 +1,151 @@ +.\" 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 August 26, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getscn , +.Nm elf_ndxscn , +.Nm elf_newscn , +.Nm elf_nextscn +.Nd get/allocate section information for an ELF object +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf_Scn *" +.Fn elf_getscn "Elf *elf" "size_t index" +.Ft size_t +.Fn elf_ndxscn "Elf_Scn *scn" +.Ft "Elf_Scn *" +.Fn elf_newscn "Elf *elf" +.Ft "Elf_Scn *" +.Fn elf_nextscn "Elf *elf" "Elf_Scn *scn" +.Sh DESCRIPTION +These functions are used to iterate through the sections associated +with an ELF descriptor. +.Pp +Function +.Fn elf_getscn +will return a section descriptor for the section at index +.Ar index +in the object denoted by ELF descriptor +.Ar elf . +An error will be signalled if the specified section does not +exist. +.Pp +Function +.Fn elf_ndxscn +returns the section table index associated with section descriptor +.Ar scn . +.Pp +Function +.Fn elf_newscn +creates a new section and appends it to the list of sections +associated with descriptor +.Ar elf . +The library will automatically increment the +.Va e_shnum +field of the ELF header associated with descriptor +.Ar elf , +and will set the +.Dv ELF_F_DIRTY +bit for the new section. +For ELF descriptors opened for writing, the ELF library will +automatically create an empty section at index zero +.Dv ( SHN_UNDEF ) +on the first call to +.Fn elf_newscn . +.Pp +Function +.Fn elf_nextscn +takes a section descriptor +.Ar scn +and returns a pointer to the section descriptor at the next higher +index. +Argument +.Ar scn +is allowed to be NULL, in which case this function will return a +pointer to the section descriptor at index 1. +If no further sections are present, function +.Fn elf_nextscn +will return a NULL pointer. +.Sh RETURN VALUES +Functions +.Fn elf_getscn , +.Fn elf_newscn +and +.Fn elf_nextscn +return a valid pointer to a section descriptor if successful, or +NULL if an error occurs. +.Pp +Function +.Fn elf_ndxscn +returns a valid section table index if successful, or +.Dv SHN_UNDEF +if an error occurs. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar elf +or +.Ar scn +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar index +exceeded the current number of sections in the ELF object. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF file. +.It Bq Er ELF_E_ARGUMENT +Section descriptor +.Ar scn +was not associated with ELF descriptor +.Ar elf . +.It Bq Er ELF_E_CLASS +Descriptor +.Ar elf +was of an unknown ELF class. +.It Bq Er ELF_E_SECTION +Argument +.Ar elf +specified extended section numbering in the ELF header with the section header at +index +.Dv SHN_UNDEF +not being of type +.Dv SHT_NULL . +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagdata 3 , +.Xr elf_flagscn 3 , +.Xr elf_getdata 3 , +.Xr elf_getshdr 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_getshnum.3 b/lib/libelf/elf_getshnum.3 new file mode 100644 index 0000000..0dbaca6 --- /dev/null +++ b/lib/libelf/elf_getshnum.3 @@ -0,0 +1,78 @@ +.\" 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 October 31, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getshnum +.Nd return the number of sections in an ELF file +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_getshnum "Elf *elf" "size_t *shnum" +.Sh DESCRIPTION +Function +.Fn elf_getshnum +retrieves the number of ELF sections associated with descriptor +.Ar elf +and stores it into the location pointed to by argument +.Ar sz . +.Pp +This routine allows applications to uniformly process both normal ELF +objects, and ELF objects that use extended section numbering. +.Pp +.Sh RETURN VALUES +Function +.Fn elf_getshnum +returns a non-zero value if successful, or zero in case of an +error. +.Sh ERRORS +Function +.Fn elf_getshnum +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. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getident 3 , +.Xr elf_getshstrndx 3 , +.Xr elf32_getehdr , +.Xr elf64_getehdr , +.Xr gelf 3 , +.Xr gelf_getehdr 3 diff --git a/lib/libelf/elf_getshstrndx.3 b/lib/libelf/elf_getshstrndx.3 new file mode 100644 index 0000000..c7a008b --- /dev/null +++ b/lib/libelf/elf_getshstrndx.3 @@ -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 October 31, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_getshstrndx , +.Nm elf_setshstrndx +.Nd retrieve/update the index of the section name string table +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft int +.Fn elf_getshstrndx "Elf *elf" "size_t *ndxptr" +.Ft int +.Fn elf_setshstrndx "Elf *elf" "size_t ndx" +.Sh DESCRIPTION +Function +.Fn elf_getshstrndx +retrieves the section index of the string table containing section +names from descriptor +.Ar elf +and stores it into the location pointed to by argument +.Ar ndxptr . +.Pp +Function +.Fn elf_setshstrndx +sets the index of the section name string table to argument +.Ar ndx . +.Pp +These routines allow applications to process both normal ELF +objects and ELF objects that use extended section numbering uniformly. +.Pp +.Sh RETURN VALUES +These functions return a non-zero value if successful, or zero in case +of an error. +.Sh ERRORS +These functions 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_ARGUMENT +Argument +.Ar ndx +contained a value in the reserved range of section indices. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getident 3 , +.Xr elf_getshnum 3 , +.Xr elf32_getehdr , +.Xr elf64_getehdr , +.Xr gelf 3 , +.Xr gelf_getehdr 3 diff --git a/lib/libelf/elf_hash.3 b/lib/libelf/elf_hash.3 new file mode 100644 index 0000000..c309b71 --- /dev/null +++ b/lib/libelf/elf_hash.3 @@ -0,0 +1,57 @@ +.\" 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 August 15, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_hash +.Nd compute a hash value for a string +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "unsigned long" +.Fn elf_hash "const char *name" +.Sh DESCRIPTION +Function +.Fn elf_hash +computes a portable hash value for the null terminated string +pointed to by argument +.Ar name . +.Pp +The hash value returned is will be identical across +machines of different architectures. +This allows hash tables to be built on one machine and +correctly used on another of a different architecture. +The hash value returned is also guaranteed +.Em not +to be the bit pattern of all ones (~0UL). +.Sh IMPLEMENTATION NOTES +The library internally uses unsigned 32 bit arithmetic to compute +the hash value. +.Sh SEE ALSO +.Xr elf 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/elf_hash.c b/lib/libelf/elf_hash.c new file mode 100644 index 0000000..6091450 --- /dev/null +++ b/lib/libelf/elf_hash.c @@ -0,0 +1,54 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +/* + * This elf_hash function is defined by the System V ABI. It must be + * kept compatible with "src/libexec/rtld-elf/rtld.c". + */ + +unsigned long +elf_hash(const char *name) +{ + unsigned long h, t; + const unsigned char *s; + + s = (const unsigned char *) name; + h = t = 0; + + for (; *s != '\0'; h = h & ~t) { + h = (h << 4) + *s++; + t = h & 0xF0000000UL; + if (t) + h ^= t >> 24; + } + + return (h); +} diff --git a/lib/libelf/elf_kind.3 b/lib/libelf/elf_kind.3 new file mode 100644 index 0000000..8008bc2 --- /dev/null +++ b/lib/libelf/elf_kind.3 @@ -0,0 +1,71 @@ +.\" 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 June 1, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_kind +.Nd determine ELF file type +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft Elf_Kind +.Fn elf_kind "Elf *elf" +.Sh DESCRIPTION +The +.Fn elf_kind +function identifies the kind of file associated with its argument +.Ar elf . +The argument +.Ar elf +is allowed to be NULL. +.Sh RETURN VALUES +The +.Fn elf_kind +function returns one of the following values: +.Bl -tag -width indent +.It Dv ELF_K_AR +The file associated with argument +.Ar elf +is an archive. +.It Dv ELF_K_ELF +The file associated with argument +.Ar elf +is an ELF file. +.It Dv ELF_K_NONE +The argument +.Ar elf +was NULL, or the ELF library could not determine the type of the file +associated with argument +.Ar elf , +or an error occurred when processing. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getident 3 , +.Xr elf_begin 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/elf_kind.c b/lib/libelf/elf_kind.c new file mode 100644 index 0000000..88888da --- /dev/null +++ b/lib/libelf/elf_kind.c @@ -0,0 +1,43 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +Elf_Kind +elf_kind(Elf *e) +{ + if (e == NULL) + return (ELF_K_NONE); + if (e->e_kind == ELF_K_AR || + e->e_kind == ELF_K_ELF) + return (e->e_kind); + return (ELF_K_NONE); +} diff --git a/lib/libelf/elf_memory.3 b/lib/libelf/elf_memory.3 new file mode 100644 index 0000000..d75ca2f --- /dev/null +++ b/lib/libelf/elf_memory.3 @@ -0,0 +1,122 @@ +.\" 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 June 28, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_memory +.Nd process an ELF or ar(1) archive mapped into memory +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf *" +.Fn elf_memory "char *image" "size_t size" +.Sh DESCRIPTION +Function +.Fn elf_memory +is used to process an ELF file or +.Xr ar 1 +archive whose image is present in memory. +.Pp +Argument +.Ar image +points to the start of the memory image of the file or archive. +Argument +.Ar size +contains the size in bytes of the memory image. +.Pp +The ELF descriptor is created for reading (i.e., analogous to the +use of +.Xr elf_begin 3 +with a command argument value of +.Dv ELF_C_READ Ns ). +.Sh RETURN VALUES +Function +.Fn elf_memory +returns a pointer to a new ELF descriptor if successful, or NULL if an +error occurred. +.Pp +The return value may be queried for the file type using +.Xr elf_kind 3 . +.Sh EXAMPLES +To read parse an elf file, use: +.Bd -literal -offset indent +int fd; +void *p; +struct stat sb; +Elf *e; +\&... +if ((fd = open("./elf-file", O_RDONLY)) < 0 || + fstat(fd, &sb) < 0 || + (p = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t) 0)) == + MAP_FAILED) { + ... handle system error ... +} + +if ((e = elf_memory(p, sb.st_size)) == NULL) { + ... handle elf(3) error ... +} +\&... use ELF descriptor "e" here ... +.Ed +.Sh ERRORS +Function +.Fn elf_memory +can fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +A NULL value was used for argument +.Ar image +or the value of argument +.Ar sz +was zero. +.It Bq Er ELF_E_HEADER +The header of the ELF object contained an unsupported value in its +.Va e_ident[EI_CLASS] +field. +.It Bq Er ELF_E_HEADER +The header of the ELF object contained an unsupported value in its +.Va e_ident[EI_DATA] +field. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.It Bq Er ELF_E_SEQUENCE +Function +.Fn elf_memory +was called before a working version was set using +.Xr elf_version 3 . +.It Bq Er ELF_E_VERSION +The argument +.Ar image +corresponds to an ELF file with an unsupported version. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_end 3 , +.Xr elf_error 3 , +.Xr elf_kind 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_memory.c b/lib/libelf/elf_memory.c new file mode 100644 index 0000000..f42378e --- /dev/null +++ b/lib/libelf/elf_memory.c @@ -0,0 +1,91 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + +Elf * +elf_memory(char *image, size_t sz) +{ + Elf *e; + + if (LIBELF_PRIVATE(version) == EV_NONE) { + LIBELF_SET_ERROR(SEQUENCE, 0); + return (NULL); + } + + if (image == NULL || sz == 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((e = _libelf_allocate_elf()) == NULL) + return (NULL); + + e->e_cmd = ELF_C_READ; + e->e_rawfile = image; + e->e_rawsize = sz; + +#undef LIBELF_IS_ELF +#define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \ + (P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 && \ + (P)[EI_MAG3] == ELFMAG3) + + if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) { + _libelf_init_elf(e, ELF_K_ELF); + e->e_class = image[EI_CLASS]; + e->e_byteorder = image[EI_DATA]; + e->e_version = image[EI_VERSION]; + + if (e->e_version > EV_CURRENT) { + e = _libelf_release_elf(e); + LIBELF_SET_ERROR(VERSION, 0); + return (NULL); + } + + if ((e->e_byteorder != ELFDATA2LSB && e->e_byteorder != + ELFDATA2MSB) || (e->e_class != ELFCLASS32 && e->e_class != + ELFCLASS64)) { + e = _libelf_release_elf(e); + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } + + } else if (sz >= SARMAG && + strncmp(image, ARMAG, (size_t) SARMAG) == 0) { + _libelf_init_elf(e, ELF_K_AR); + e = _libelf_ar_open(e); + } else + _libelf_init_elf(e, ELF_K_NONE); + + return (e); +} diff --git a/lib/libelf/elf_next.3 b/lib/libelf/elf_next.3 new file mode 100644 index 0000000..771a1e4 --- /dev/null +++ b/lib/libelf/elf_next.3 @@ -0,0 +1,96 @@ +.\" 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 June 17, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_next +.Nd provide sequential access to the next archive member +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft Elf_Cmd +.Fn elf_next "Elf *elf" +.Sh DESCRIPTION +The +.Fn elf_next +function causes the ELF archive descriptor corresponding to argument +.Ar elf +to be adjusted to provide access to the next member in +the archive on a subsequent call to +.Fn elf_begin . +.Pp +The return value of +.Fn elf_next +is suitable for use in a loop invoking +.Fn elf_begin . +.Sh RETURN VALUES +If successful, function +.Fn elf_next +returns the value +.Dv ELF_C_READ . +Otherwise, if argument +.Ar elf +was not associated with an archive, or if it was +.Dv NULL , +or if any other error occurred, the value +.Dv ELF_C_NULL +is returned. +.Sh EXAMPLES +To process all the members of an archive use: +.Bd -literal -offset indent +Elf_Cmd cmd; +Elf *archive, *e; +\&... +cmd = ELF_C_READ; +archive = elf_begin(fd, cmd, NULL); +while ((e = elf_begin(fd, cmd, archive)) != (Elf *) 0) +{ + ... process `e' here ... + + cmd = elf_next(e); + elf_end(e); +} +elf_end(archive); +.Ed +.Sh ERRORS +Function +.Fn elf_next +may fail with the following error: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not associated with a containing +.Xr ar 1 +archive. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_end 3 , +.Xr elf_rand 3 diff --git a/lib/libelf/elf_next.c b/lib/libelf/elf_next.c new file mode 100644 index 0000000..1e1627c --- /dev/null +++ b/lib/libelf/elf_next.c @@ -0,0 +1,61 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <assert.h> +#include <libelf.h> + +#include "_libelf.h" + +Elf_Cmd +elf_next(Elf *e) +{ + off_t next; + Elf *parent; + + if (e == NULL) + return (ELF_C_NULL); + + if ((parent = e->e_parent) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (ELF_C_NULL); + } + + assert (parent->e_kind == ELF_K_AR); + assert (parent->e_cmd == ELF_C_READ); + assert((uintptr_t) e->e_rawfile % 2 == 0); + assert(e->e_rawfile > parent->e_rawfile); + + next = e->e_rawfile - parent->e_rawfile + e->e_rawsize; + next = (next + 1) & ~1; /* round up to an even boundary */ + + parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ? (off_t) 0 : next; + + return (ELF_C_READ); +} diff --git a/lib/libelf/elf_rand.3 b/lib/libelf/elf_rand.3 new file mode 100644 index 0000000..982cc8d --- /dev/null +++ b/lib/libelf/elf_rand.3 @@ -0,0 +1,118 @@ +.\" 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 June 17, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_rand +.Nd provide sequential access to the next archive member +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft Elf_Cmd +.Fn elf_rand "Elf *archive" "off_t offset" +.Sh DESCRIPTION +The +.Fn elf_rand +function causes the ELF descriptor +.Ar archive +to be adjusted so that the next call to +.Xr elf_begin 3 +will provide access to the archive member at byte offset +.Ar offset +in the archive. +Argument +.Ar offset +is the byte offset from the start of the archive to the beginning of +the archive header for the desired member. +.Pp +Archive member offsets may be retrieved using the +.Xr elf_getarsym 3 +function. +.Sh RETURN VALUES +Function +.Fn elf_rand +returns +.Ar offset +if successful or zero in case of an error. +.Sh EXAMPLES +To process all the members of an archive use: +.Bd -literal -offset indent +off_t off; +Elf *archive, *e; +\&... +cmd = ELF_C_READ; +archive = elf_begin(fd, cmd, NULL); +while ((e = elf_begin(fd, cmd, archive)) != (Elf *) 0) +{ + ... process `e' here ... + elf_end(e); + + off = ...new value...; + if (elf_rand(archive, off) != off) { + ... process error ... + } +} +elf_end(archive); +.Ed +.Pp +To rewind an archive, use: +.Bd -literal -offset indent +Elf *archive; +\&... +if (elf_rand(archive, SARMAG) != SARMAG) { + ... error ... +} +.Ed +.Sh ERRORS +Function +.Fn elf_rand +may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar archive +was null. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar archive +was not a descriptor for an +.Xr ar 1 +archive. +.It Bq Er ELF_E_ARCHIVE +Argument +.Ar offset +did not correspond to the start of an archive member header. +.El +.Sh SEE ALSO +.Xr ar 1 , +.Xr elf 3 , +.Xr elf_begin 3 , +.Xr elf_end 3 , +.Xr elf_getarsym 3 , +.Xr elf_next 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_rand.c b/lib/libelf/elf_rand.c new file mode 100644 index 0000000..0b79c5c --- /dev/null +++ b/lib/libelf/elf_rand.c @@ -0,0 +1,58 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <libelf.h> + +#include "_libelf.h" + +off_t +elf_rand(Elf *ar, off_t offset) +{ + struct ar_hdr *arh; + + if (ar == NULL || ar->e_kind != ELF_K_AR || + (offset & 1) || offset < SARMAG || + offset + sizeof(struct ar_hdr) >= ar->e_rawsize) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return 0; + } + + arh = (struct ar_hdr *) (ar->e_rawfile + offset); + + /* a too simple sanity check */ + if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') { + LIBELF_SET_ERROR(ARCHIVE, 0); + return 0; + } + + ar->e_u.e_ar.e_next = offset; + + return (offset); +} diff --git a/lib/libelf/elf_rawfile.3 b/lib/libelf/elf_rawfile.3 new file mode 100644 index 0000000..c6dcd68 --- /dev/null +++ b/lib/libelf/elf_rawfile.3 @@ -0,0 +1,76 @@ +.\" 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 July 3, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_rawfile +.Nd return uninterpreted contents of an ELF file +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft char * +.Fn elf_rawfile "Elf *elf" "size_t *sz" +.Sh DESCRIPTION +Function +.Fn elf_rawfile +returns the uninterpreted contents of the file referenced by ELF descriptor +.Ar elf . +.Pp +If argument +.Ar sz +is non-null, the function stores the file's size in bytes +in the location to which it points. +A value of zero is written to this location if an error is +encountered. +.Sh RETURN VALUES +Function +.Fn elf_rawfile +returns a valid pointer if successful or NULL if an error occurs. +.Sh ERRORS +Function +.Fn elf_rawfile +may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_SEQUENCE +Argument +.Ar elf +was opened for writing and function +.Fn elf_rawfile +was invoked before +.Xr elf_update 3 . +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getident 3 , +.Xr elf_kind 3 , +.Xr elf_update 3 diff --git a/lib/libelf/elf_rawfile.c b/lib/libelf/elf_rawfile.c new file mode 100644 index 0000000..5143ad7 --- /dev/null +++ b/lib/libelf/elf_rawfile.c @@ -0,0 +1,52 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +char * +elf_rawfile(Elf *e, size_t *sz) +{ + char *ptr; + size_t size; + + size = e ? e->e_rawsize : 0; + ptr = NULL; + + if (e == NULL) + LIBELF_SET_ERROR(ARGUMENT, 0); + else if ((ptr = e->e_rawfile) == NULL && e->e_cmd == ELF_C_WRITE) + LIBELF_SET_ERROR(SEQUENCE, 0); + + if (sz) + *sz = size; + + return (ptr); +} diff --git a/lib/libelf/elf_scn.c b/lib/libelf/elf_scn.c new file mode 100644 index 0000000..fa1527f --- /dev/null +++ b/lib/libelf/elf_scn.c @@ -0,0 +1,244 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <gelf.h> +#include <libelf.h> +#include <stdlib.h> + +#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); + +#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); + assert(fsz > 0); + + ec = e->e_class; + 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); + + (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes); + + 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++; + 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; + } + } + 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) && + _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) && + _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); + if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == + NULL) + return (NULL); + shnum++; + } + + assert(shnum > 0); + + if ((scn = _libelf_allocate_scn(e, shnum)) == NULL) + return (NULL); + + shnum++; + + if (_libelf_setshnum(e, ehdr, ec, shnum) == 0) + return (NULL); + + (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)); +} diff --git a/lib/libelf/elf_shnum.c b/lib/libelf/elf_shnum.c new file mode 100644 index 0000000..8a53eed --- /dev/null +++ b/lib/libelf/elf_shnum.c @@ -0,0 +1,123 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <libelf.h> + +#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)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + return (_libelf_getshnum(e, eh, ec, shnum)); +} diff --git a/lib/libelf/elf_shstrndx.c b/lib/libelf/elf_shstrndx.c new file mode 100644 index 0000000..cae25c3 --- /dev/null +++ b/lib/libelf/elf_shstrndx.c @@ -0,0 +1,127 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <libelf.h> + +#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)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + return (_libelf_getshstrndx(e, eh, ec, strndx)); +} + +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)); +} diff --git a/lib/libelf/elf_strptr.3 b/lib/libelf/elf_strptr.3 new file mode 100644 index 0000000..7f6e281 --- /dev/null +++ b/lib/libelf/elf_strptr.3 @@ -0,0 +1,112 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_strptr +.Nd retrieve a string pointer in a string table +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "char *" +.Fn elf_strptr "Elf *elf" "size_t scndx" "size_t stroffset" +.Sh DESCRIPTION +Function +.Fn elf_strptr +allows an application to convert a string table offset to a string +pointer, correctly translating the offset in the presence +of multiple +.Vt Elf_Data +descriptors covering the contents of the section. +.Pp +Argument +.Ar elf +is a descriptor for an ELF object. +Argument +.Ar scndx +is the section index for an ELF string table. +Argument +.Ar stroffset +is the index of the desired string in the string +table. +.Sh RETURN VALUES +Function +.Fn elf_strptr +returns a valid pointer on success or NULL in case an error was +encountered. +.Sh ERRORS +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar scndx +was not the section index for a string table. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar stroffset +exceeeded the size of the string table. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar stroffset +index an unallocated region of the string table. +.It Bq Er ELF_E_DATA +Offset +.Ar stroffset +indexed a region that was not covered by any Elf_Data +descriptor. +.Iq Bq Er ELF_E_DATA +An erroneous +.Vt Elf_Data +descriptor was part of the section specified by argument +.Ar scndx . +.It Bq Er ELF_E_HEADER +ELF descriptor +.Ar elf +contained an invalid section header. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.It Bq Er ELF_E_SECTION +Section +.Ar scndx +contained a malformed section header. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_rawdata 3 , +.Xr elf32_getshdr 3 , +.Xr elf64_getshdr 3 , +.Xr gelf 3 , +.Xr gelf_getshdr 3 diff --git a/lib/libelf/elf_strptr.c b/lib/libelf/elf_strptr.c new file mode 100644 index 0000000..04cc624 --- /dev/null +++ b/lib/libelf/elf_strptr.c @@ -0,0 +1,133 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +/* + * Convert an ELF section#,offset pair to a string pointer. + */ + +char * +elf_strptr(Elf *e, size_t scndx, size_t offset) +{ + Elf_Scn *s; + Elf_Data *d; + size_t alignment, count; + GElf_Shdr shdr; + + if (e == NULL || e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((s = elf_getscn(e, scndx)) == NULL || + gelf_getshdr(s, &shdr) == NULL) + return (NULL); + + if (shdr.sh_type != SHT_STRTAB || + offset >= shdr.sh_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + d = NULL; + if (e->e_flags & ELF_F_LAYOUT) { + + /* + * The application is taking responsibility for the + * ELF object's layout, so we can directly translate + * an offset to a `char *' address using the `d_off' + * members of Elf_Data descriptors. + */ + while ((d = elf_getdata(s, d)) != NULL) { + + if (d->d_buf == 0 || d->d_size == 0) + continue; + + if (d->d_type != ELF_T_BYTE) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if (offset >= d->d_off && + offset < d->d_off + d->d_size) + return ((char *) d->d_buf + offset - d->d_off); + } + } else { + /* + * Otherwise, the `d_off' members are not useable and + * we need to compute offsets ourselves, taking into + * account 'holes' in coverage of the section introduced + * by alignment requirements. + */ + count = (size_t) 0; /* cumulative count of bytes seen */ + while ((d = elf_getdata(s, d)) != NULL && count <= offset) { + + if (d->d_buf == NULL || d->d_size == 0) + continue; + + if (d->d_type != ELF_T_BYTE) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((alignment = d->d_align) > 1) { + if ((alignment & (alignment - 1)) != 0) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + count = roundup2(count, alignment); + } + + if (offset < count) { + /* offset starts in the 'hole' */ + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (offset < count + d->d_size) { + if (d->d_buf != NULL) + return ((char *) d->d_buf + + offset - count); + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + count += d->d_size; + } + } + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} diff --git a/lib/libelf/elf_types.m4 b/lib/libelf/elf_types.m4 new file mode 100644 index 0000000..b317184 --- /dev/null +++ b/lib/libelf/elf_types.m4 @@ -0,0 +1,304 @@ +/*- + * 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$ + */ + +/* + * ELF types, defined in the "enum Elf_Type" API. + */ + +define(`ELF_TYPE_LIST', + ``ADDR, Addr', + `BYTE, Byte', + `CAP, Cap', + `DYN, Dyn', + `EHDR, Ehdr', + `HALF, Half', + `LWORD, Lword', + `MOVE, Move', + `MOVEP, MoveP', + `NOTE, Note', + `OFF, Off', + `PHDR, Phdr', + `REL, Rel', + `RELA, Rela', + `SHDR, Shdr', + `SWORD, Sword', + `SXWORD, Sxword', + `SYMINFO, Syminfo', + `SYM, Sym', + `VDEF, Verdef', + `VNEED, Verneed', + `WORD, Word', + `XWORD, Xword', + `NUM, _'') + +/* + * DEFINE_STRUCT(NAME,MEMBERLIST...) + * + * Map a type name to its members. + * + * Each member-list element comprises of pairs of (field name, type), + * in the sequence used in the file representation of `NAME'. + * + * Each member list element comprises a pair containing a field name + * and a basic type. Basic types include IDENT, HALF, WORD, LWORD, + * ADDR{32,64}, OFF{32,64}, SWORD, XWORD, SXWORD. + * + * The last element of a member list is the null element: `_,_'. + */ + +define(`DEFINE_STRUCT',`define(`$1_DEF',shift($@))dnl') + +DEFINE_STRUCT(`Elf32_Cap', + ``c_tag, WORD', + `c_un.c_val, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Cap', + ``c_tag, XWORD', + `c_un.c_val, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Dyn', + ``d_tag, SWORD', + `d_un.d_ptr, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Dyn', + ``d_tag, SXWORD', + `d_un.d_ptr, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Ehdr', + ``e_ident, IDENT', + `e_type, HALF', + `e_machine, HALF', + `e_version, WORD', + `e_entry, ADDR', + `e_phoff, OFF', + `e_shoff, OFF', + `e_flags, WORD', + `e_ehsize, HALF', + `e_phentsize, HALF', + `e_phnum, HALF', + `e_shentsize, HALF', + `e_shnum, HALF', + `e_shstrndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Ehdr', + ``e_ident, IDENT', + `e_type, HALF', + `e_machine, HALF', + `e_version, WORD', + `e_entry, ADDR', + `e_phoff, OFF', + `e_shoff, OFF', + `e_flags, WORD', + `e_ehsize, HALF', + `e_phentsize, HALF', + `e_phnum, HALF', + `e_shentsize, HALF', + `e_shnum, HALF', + `e_shstrndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Move', + ``m_value, LWORD', + `m_info, WORD', + `m_poffset, WORD', + `m_repeat, HALF', + `m_stride, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Move', + ``m_value, LWORD', + `m_info, XWORD', + `m_poffset, XWORD', + `m_repeat, HALF', + `m_stride, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Phdr', + ``p_type, WORD', + `p_offset, OFF', + `p_vaddr, ADDR', + `p_paddr, ADDR', + `p_filesz, WORD', + `p_memsz, WORD', + `p_flags, WORD', + `p_align, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Phdr', + ``p_type, WORD', + `p_flags, WORD', + `p_offset, OFF', + `p_vaddr, ADDR', + `p_paddr, ADDR', + `p_filesz, XWORD', + `p_memsz, XWORD', + `p_align, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Rel', + ``r_offset, ADDR', + `r_info, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Rel', + ``r_offset, ADDR', + `r_info, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Rela', + ``r_offset, ADDR', + `r_info, WORD', + `r_addend, SWORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Rela', + ``r_offset, ADDR', + `r_info, XWORD', + `r_addend, SXWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Shdr', + ``sh_name, WORD', + `sh_type, WORD', + `sh_flags, WORD', + `sh_addr, ADDR', + `sh_offset, OFF', + `sh_size, WORD', + `sh_link, WORD', + `sh_info, WORD', + `sh_addralign, WORD', + `sh_entsize, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Shdr', + ``sh_name, WORD', + `sh_type, WORD', + `sh_flags, XWORD', + `sh_addr, ADDR', + `sh_offset, OFF', + `sh_size, XWORD', + `sh_link, WORD', + `sh_info, WORD', + `sh_addralign, XWORD', + `sh_entsize, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Sym', + ``st_name, WORD', + `st_value, ADDR', + `st_size, WORD', + `st_info, BYTE', + `st_other, BYTE', + `st_shndx, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Sym', + ``st_name, WORD', + `st_info, BYTE', + `st_other, BYTE', + `st_shndx, HALF', + `st_value, ADDR', + `st_size, XWORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Syminfo', + ``si_boundto, HALF', + `si_flags, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf64_Syminfo', + ``si_boundto, HALF', + `si_flags, HALF', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verdaux', + ``vda_name, WORD', + `vda_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verdaux', + ``vda_name, WORD', + `vda_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verdef', + ``vd_version, HALF', + `vd_flags, HALF', + `vd_ndx, HALF', + `vd_cnt, HALF', + `vd_hash, WORD', + `vd_aux, WORD', + `vd_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verdef', + ``vd_version, HALF', + `vd_flags, HALF', + `vd_ndx, HALF', + `vd_cnt, HALF', + `vd_hash, WORD', + `vd_aux, WORD', + `vd_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Verneed', + ``vn_version, HALF', + `vn_cnt, HALF', + `vn_file, WORD', + `vn_aux, WORD', + `vn_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Verneed', + ``vn_version, HALF', + `vn_cnt, HALF', + `vn_file, WORD', + `vn_aux, WORD', + `vn_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf32_Vernaux', + ``vna_hash, WORD', + `vna_flags, HALF', + `vna_other, HALF', + `vna_name, WORD', + `vna_next, WORD', + `_,_'') + +DEFINE_STRUCT(`Elf64_Vernaux', + ``vna_hash, WORD', + `vna_flags, HALF', + `vna_other, HALF', + `vna_name, WORD', + `vna_next, WORD', + `_,_'') diff --git a/lib/libelf/elf_update.3 b/lib/libelf/elf_update.3 new file mode 100644 index 0000000..c5c0b5e --- /dev/null +++ b/lib/libelf/elf_update.3 @@ -0,0 +1,277 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_update +.Nd update an ELF descriptor +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft off_t +.Fn elf_update "Elf *elf" "Elf_Cmd cmd" +.Sh DESCRIPTION +Function +.Fn elf_update +causes the library to recalculate the structure of an ELF +object and optionally write out the image of the object +to file. +.Pp +Argument +.Ar elf +is a descriptor to an ELF object. +Argument +.Ar cmd +can take on the following values: +.Bl -tag -width "ELF_C_WRITE" +.It Dv ELF_C_NULL +The library will recalculate structural information flagging +modified structures with the +.Dv ELF_F_DIRTY +flag, but will not write back data to the underlying file image. +.It Dv ELF_C_WRITE +The library will recalculate structural information and will +also write the new image to the underlying file. +.El +.Ss File Layout +If the +.Dv ELF_F_LAYOUT +flag has been set on the ELF descriptor, the application assumes full +responsibility for the layout of the ELF object. +If this bit is not set, the ELF library will compute the layout of the +file from its associated section descriptors. +.Pp +It is the application's responsibility to manage the the following +structure members in the ELF file: +.Bl -tag -width indent +.It "Executable Header" +The ELF executable header is described in +.Xr elf 5 . +The following members of the ELF executable header are the application's +responsibility: +.Pp +.Bl -tag -width "e_ident[EI_OSABI]" -compact +.It Va e_entry +Set to the desired entry address for executables. +.It Va e_flags +Set to the desired processor specific flags. +.It Va "e_ident[EI_DATA]" +Must be set to one of +.Dv ELFDATA2LSB +or +.Dv ELFDATA2MSB . +.It Va "e_ident[EI_OSABI]" +Set to the OS ABI desired. +For +.Fx +executables, this field should be set to +.Dv ELFOSABI_FREEBSD . +.It Va e_machine +Set to the desired machine architecture, one of the +.Dv EM_* +values in +.In sys/elf_common.h . +.It Va e_phoff +If the application is managing the object's layout, it must +set this field to the file offset of the ELF program header table. +.It Va e_shoff +If the application is managing the object's layout, it must +set this field to the file offset of the ELF section header table. +.It Va e_shstrndx +Set to the index of the string table containing +section names. +.It Va e_type +Set to the type of the ELF object, one of the +.Dv ET_* +values in +.In sys/elf_common.h . +.It Va e_version +Set to the desired version of the ELF object. +.El +.It "Program Header" +All fields of the entries in the program header table are +under application control. +.It "Section Header" +The ELF section header is described in +.Xr elf 5 . +The following members of the ELF section header are the +application's responsibility: +.Pp +.Bl -tag -width "sh_addralign" -compact +.It Va sh_addr +Set to the physical memory address where the section should reside. +.It Va sh_addralign +If the application is managing the file layout, it must set this +field to the desired alignment for the section's contents. +This value must be a power of two. +.It Va sh_entsize +Set to the size of each entry, for sections containing fixed size +elements, or set to zero for sections without fixed size elements. +For section contents of types known to the library, the application +may leave this field as zero. +.It Va sh_flags +Set to the desired section flags. +.It Va sh_info +Set as described in +.Xr elf 5 . +.It Va sh_link +Set as described in +.Xr elf 5 . +.It Va sh_name +Set to the index of the section's name in the string table containing +section names. +.It Va sh_offset +If the application is managing the file layout, it must set this +field to the file offset of the section's contents. +.It Va sh_size +If the application is managing the file layout, it must set this +field to the file size of the section's contents. +.It Va sh_type +Set to the type of the section. +.El +.El +.Pp +Gaps in the coverage of the file's contents will be set to the fill value +specified by +.Xr elf_fill 3 . +.Pp +If the application has requested full control over the file's layout by +setting the +.Dv ELF_F_LAYOUT +flag on the ELF descriptor, it should ensure that there are no +gaps in the coverage of the file's contents. +.Pp +All pointers to +.Vt Elf_Scn +and +.Vt Elf_Data +descriptors associated with descriptor +.Ar elf +should be considered as invalid after a call to +.Fn elf_update . +.Sh RETURN VALUES +Function +.Fn elf_update +returns the total size of the file image if successful, or -1 if an +error occurred. +.Sh ERRORS +This function may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was null. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar cmd +was not recognized. +.It Bq Er ELF_E_ARGUMENT +The argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_CLASS +The +.Va e_ident[EI_CLASS] +field of the executable header of argument +.Ar elf +did not match the class of the file. +.It Bq Er ELF_E_DATA +An +.Vt Elf_Data +descriptor contained in argument +.Ar elf +specified a type incompatible with its containing section. +.It Bq Er ELF_E_HEADER +The ELF header in argument +.Ar elf +requested a different byte order from the byte order already +associated with the file. +.It Bq Er ELF_E_IO +An I/O error was encountered. +.It Bq Er ELF_E_LAYOUT +An +.Vt Elf_Data +descriptor contained in argument +.Ar elf +specified an alignment incompatible with its containing section. +.It Bq Er ELF_E_LAYOUT +Argument +.Ar elf +contained section descriptors that overlapped in extent. +.It Bq Er ELF_E_LAYOUT +Argument +.Ar elf +contained section descriptors that were incorrectly aligned or were +too small for their data. +.It Bq Er ELF_E_MODE +An +.Dv ELF_C_WRITE +operation was requested with an ELF descriptor that was not opened for +writing or updating. +.It Bq Er ELF_E_SECTION +Argument +.Ar elf +contained a section with an unrecognized type. +.It Bq Er ELF_E_SEQUENCE +An +.Dv ELF_C_WRITE +operation was requested after a prior call to +.Fn elf_cntl elf ELF_C_FDDONE +disassociated the ELF descriptor +.Ar elf +from its underlying file. +.It Bq Er ELF_E_VERSION +Argument +.Ar elf +had an unsupported version or contained an +.Vt Elf_Data +descriptor with an unsupported version. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_cntl 3 , +.Xr elf_fill 3 , +.Xr elf_flagehdr 3 , +.Xr elf_flagelf 3 , +.Xr elf_getscn 3 , +.Xr elf_getdata 3 , +.Xr elf_newscn 3 , +.Xr elf_newdata 3 , +.Xr elf_rawdata 3 , +.Xr elf32_getehdr 3 , +.Xr elf32_getphdr 3 , +.Xr elf32_newehdr 3 , +.Xr elf32_newphdr 3 , +.Xr elf64_getehdr 3 , +.Xr elf64_getphdr 3 , +.Xr elf64_newehdr 3 , +.Xr elf64_newphdr 3 , +.Xr gelf 3 , +.Xr gelf_newehdr 3 , +.Xr gelf_newphdr 3 , +.Xr elf 5 diff --git a/lib/libelf/elf_update.c b/lib/libelf/elf_update.c new file mode 100644 index 0000000..c0203f9 --- /dev/null +++ b/lib/libelf/elf_update.c @@ -0,0 +1,880 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/mman.h> +#include <sys/param.h> + +#include <assert.h> +#include <errno.h> +#include <gelf.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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); + + 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; + + /* + * 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); + + 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)); +} diff --git a/lib/libelf/elf_version.3 b/lib/libelf/elf_version.3 new file mode 100644 index 0000000..cfe56f4 --- /dev/null +++ b/lib/libelf/elf_version.3 @@ -0,0 +1,95 @@ +.\" 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 June 1, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf_version +.Nd retrieve or set ELF library operating version +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft unsigned int +.Fn elf_version "unsigned int version" +.Sh DESCRIPTION +The +.Fn elf_version +function is used to query the current operating version of the ELF +library, and to inform the ELF library about the application's desired +operating version. +.Pp +If the argument +.Ar version +is +.Dv EV_NONE , +the +.Fn elf_version +function returns the currently configured operating version for the +ELF library. +.Pp +If the argument +.Ar version +is not +.Dv EV_NONE , +and if argument +.Ar version +is supported by the ELF library, function +.Fn elf_version +sets the library's operating version to +.Ar version , +and returns the previous value of the operating version. +If argument +.Ar version +cannot be supported, then the +.Fn elf_version +function returns +.Dv EV_NONE . +.Sh RETURN VALUES +The +.Fn elf_version +function returns the currently configured ELF library version, or +.Dv EV_NONE +if an unsupported version is requested. +.Sh EXAMPLES +An application program would inform the ELF library about its desired +operating version and check for an error using the following code +snippet: +.Bd -literal -offset indent +if (elf_version(EV_CURRENT) == EV_NONE) + err(EX_SOFTWARE, "ELF library too old"); +.Ed +.Sh ERRORS +Function +.Fn elf_version +may fail with the following error: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er "ELF_E_VERSION" +An unsupported library version number was requested. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr gelf 3 diff --git a/lib/libelf/elf_version.c b/lib/libelf/elf_version.c new file mode 100644 index 0000000..7f66d42 --- /dev/null +++ b/lib/libelf/elf_version.c @@ -0,0 +1,51 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> + +#include "_libelf.h" + +unsigned int +elf_version(unsigned int v) +{ + unsigned int old; + + if ((old = LIBELF_PRIVATE(version)) == EV_NONE) + old = EV_CURRENT; + + if (v == EV_NONE) + return old; + if (v > EV_CURRENT) { + LIBELF_SET_ERROR(VERSION, 0); + return EV_NONE; + } + + LIBELF_PRIVATE(version) = v; + return (old); +} diff --git a/lib/libelf/gelf.3 b/lib/libelf/gelf.3 new file mode 100644 index 0000000..4ab5ff2 --- /dev/null +++ b/lib/libelf/gelf.3 @@ -0,0 +1,201 @@ +.\" 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 September 1, 2006 +.Os +.Dt GELF 3 +.Sh NAME +.Nm GElf +.Nd class-independent API for ELF manipulation +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Sh DESCRIPTION +This manual page describes a class independent API for manipulating +ELF objects. +This API allows an application to operate on ELF descriptors without +needing to the know the ELF class of the descriptor. +.Pp +The GElf API may be used alongside the ELF API without restriction. +.Ss GElf Data Structures +The GElf API defines the following class-independent data structures: +.Bl -tag -width GElf_Sxword +.It Vt GElf_Addr +A representation of ELF addresses. +.It Vt GElf_Dyn +A class-independent representation of ELF +.Sy .dynamic +section entries. +.It Vt GElf_Ehdr +A class-independent representation of an ELF Executable Header. +.It Vt GElf_Half +An unsigned 16 bit quantity. +.It Vt GElf_Off +A class-independent representation of a ELF offset. +.It Vt GElf_Phdr +A class-independent representation of an ELF Program Header Table +entry. +.It Vt GElf_Rel +A class-independent representation of an ELF relocation entry. +.It Vt GElf_Rela +A class-independent representation of an ELF relocation entry with +addend. +.It Vt GElf_Shdr +A class-independent representation of an ELF Section Header Table +entry. +.It Vt GElf_Sword +A signed 32 bit quantity. +.It Vt GElf_Sxword +A signed 64 bit quantity. +.It Vt GElf_Sym +A class-independent representation of an ELF symbol table entry. +.It Vt GElf_Word +An unsigned 32 bit quantity. +.It Vt GElf_Xword +An unsigned 64 bit quantity. +.El +.Pp +These data structures are sized to be compatible with the +corresponding 64 bit ELF structures, and have the same internal +structure as their 64 bit class-dependent counterparts. +Class-dependent ELF structures are described in +.Xr elf 5 . +.Ss GElf Programming Model +GElf functions always return a +.Em copy +of the underlying (class-dependent) ELF data structure. +The programming model with GElf is as follows: +.Bl -enum +.It +An application will retrieve data from an ELF descriptor using a +.Fn gelf_get_* +function. +This will copy out data into a private +.Vt GElf_* +data structure. +.It +The application will work with its private copy of the GElf +structure. +.It +Once done, the application copies the new values back to the +underlying ELF data structure using the +.Fn gelf_update_* +functions. +.It +The application will then use the +.Fn elf_flag* +APIs to indicate to the ELF library that an ELF data structure is dirty. +.El +.Pp +When updating an underlying 32 bit ELF data structure, the GElf +routines will signal an error if a GElf value is out of range +for the underlying ELF data type. +.Ss Namespace use +The GElf interface uses the following symbols: +.Bl -tag +.It GElf_* +Class-independent data types. +.It gelf_* +For functions defined in the API set. +.El +.Ss GElf Programming APIs +This section provides an overview of the GElf programming APIs. +Further information is provided in the manual page of each function +listed here. +.Bl -tag +.It "Allocating ELF Data Structures" +.Bl -tag -compact +.It Fn gelf_newehdr +Allocate a new ELF Executable Header. +.It Fn gelf_newphdr +Allocate a new ELF Program Header Table. +.El +.It "Data Translation" +.Bl -tag -compact +.It Fn gelf_xlatetof +Translate the native representation of an ELF data structure to its +file representation. +.It Fn gelf_xlatetom +Translate from the file representation of an ELF data structure to a +native representation. +.El +.It "Retrieving ELF Data" +.Bl -tag -compact +.It Fn gelf_getdyn +Retrieve an ELF +.Sy .dynamic +table entry. +.It Fn gelf_getehdr +Retrieve an ELF Executable Header from the underlying ELF descriptor. +.It Fn gelf_getphdr +Retrieve an ELF Program Header Table entry from the underlying ELF descriptor. +.It Fn gelf_getrel +Retrieve an ELF relocation entry. +.It Fn gelf_getrela +Retrieve an ELF relocation entry with addend. +.It Fn gelf_getshdr +Retrieve an ELF Section Header Table entry from the underlying ELF descriptor. +.It Fn gelf_getsym +Retrieve an ELF symbol table entry. +.El +.It Queries +.Bl -tag -compact +.It Fn gelf_checksum +Retrieves the ELF checksum for an ELF descriptor. +.It Fn gelf_fsize +Retrieves the size of the file representation of an ELF type. +.It Fn gelf_getclass +Retrieves the ELF class of an ELF descriptor. +.El +.It "Updating ELF Data" +.Bl -tag -compact -width ".Fn gelf_update_shdr" +.It Fn gelf_update_dyn +Copy back an ELF +.Sy .dynamic +Table entry. +.It Fn gelf_update_phdr +Copy back an ELF Program Header Table entry. +.It Fn gelf_update_rel +Copy back an ELF relocation entry. +.It Fn gelf_update_rela +Copy back an ELF relocation with addend entry. +.It Fn gelf_update_shdr +Copy back an ELF Section Header Table entry. +.It Fn gelf_update_sym +Copy back an ELF symbol table entry. +.El +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf 5 +.Sh HISTORY +The GELF(3) API first appeared in System V Release 4. +This implementation of the API first appeared in +.Fx 7.0 . +.Sh AUTHORS +The GElf API was implemented by +.An "Joseph Koshy" +.Aq jkoshy@FreeBSD.org . diff --git a/lib/libelf/gelf.h b/lib/libelf/gelf.h new file mode 100644 index 0000000..8a05958 --- /dev/null +++ b/lib/libelf/gelf.h @@ -0,0 +1,97 @@ +/*- + * 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 _GELF_H_ +#define _GELF_H_ + +#include <sys/cdefs.h> + +#include <libelf.h> +#include <osreldate.h> + +typedef Elf64_Addr GElf_Addr; /* Addresses */ +typedef Elf64_Half GElf_Half; /* Half words (16 bit) */ +typedef Elf64_Off GElf_Off; /* Offsets */ +typedef Elf64_Sword GElf_Sword; /* Signed words (32 bit) */ +typedef Elf64_Sxword GElf_Sxword; /* Signed long words (64 bit) */ +typedef Elf64_Word GElf_Word; /* Unsigned words (32 bit) */ +typedef Elf64_Xword GElf_Xword; /* Unsigned long words (64 bit) */ + +typedef Elf64_Dyn GElf_Dyn; /* ".dynamic" section entries */ +typedef Elf64_Ehdr GElf_Ehdr; /* ELF header */ +typedef Elf64_Phdr GElf_Phdr; /* Program header */ +typedef Elf64_Shdr GElf_Shdr; /* Section header */ +typedef Elf64_Sym GElf_Sym; /* Symbol table entries */ +typedef Elf64_Rel GElf_Rel; /* Relocation entries */ +typedef Elf64_Rela GElf_Rela; /* Relocation entries with addend */ + +#if __FreeBSD_version > 700009 +typedef Elf64_Cap GElf_Cap; /* SW/HW capabilities */ +typedef Elf64_Move GElf_Move; /* Move entries */ +typedef Elf64_Syminfo GElf_Syminfo; /* Symbol information */ +#endif + +__BEGIN_DECLS +long gelf_checksum(Elf *_elf); +size_t gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count, + unsigned int _version); +int gelf_getclass(Elf *_elf); +GElf_Dyn *gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst); +GElf_Ehdr *gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst); +GElf_Phdr *gelf_getphdr(Elf *_elf, int _index, GElf_Phdr *_dst); +GElf_Rel *gelf_getrel(Elf_Data *_src, int _index, GElf_Rel *_dst); +GElf_Rela *gelf_getrela(Elf_Data *_src, int _index, GElf_Rela *_dst); +GElf_Shdr *gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst); +GElf_Sym *gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst); +GElf_Sym *gelf_getsymshndx(Elf_Data *_src, Elf_Data *_shindexsrc, + int _index, GElf_Sym *_dst, Elf32_Word *_shindexdst); +void * gelf_newehdr(Elf *_elf, int _class); +void * gelf_newphdr(Elf *_elf, size_t _phnum); +int gelf_update_dyn(Elf_Data *_dst, int _index, GElf_Dyn *_src); +int gelf_update_ehdr(Elf *_elf, GElf_Ehdr *_src); +int gelf_update_phdr(Elf *_elf, int _index, GElf_Phdr *_src); +int gelf_update_rel(Elf_Data *_dst, int _index, GElf_Rel *_src); +int gelf_update_rela(Elf_Data *_dst, int _index, GElf_Rela *_src); +int gelf_update_shdr(Elf_Scn *_dst, GElf_Shdr *_src); +int gelf_update_sym(Elf_Data *_dst, int _index, GElf_Sym *_src); +int gelf_update_symshndx(Elf_Data *_symdst, Elf_Data *_shindexdst, + int _index, GElf_Sym *_symsrc, Elf32_Word _shindexsrc); +Elf_Data *gelf_xlatetof(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); +Elf_Data *gelf_xlatetom(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); + +#if __FreeBSD_version > 700009 +GElf_Cap *gelf_getcap(Elf_Data *_data, int _index, GElf_Cap *_cap); +GElf_Move *gelf_getmove(Elf_Data *_src, int _index, GElf_Move *_dst); +GElf_Syminfo *gelf_getsyminfo(Elf_Data *_src, int _index, GElf_Syminfo *_dst); +int gelf_update_cap(Elf_Data *_dst, int _index, GElf_Cap *_src); +int gelf_update_move(Elf_Data *_dst, int _index, GElf_Move *_src); +int gelf_update_syminfo(Elf_Data *_dst, int _index, GElf_Syminfo *_src); +#endif +__END_DECLS + +#endif /* _GELF_H_ */ diff --git a/lib/libelf/gelf_cap.c b/lib/libelf/gelf_cap.c new file mode 100644 index 0000000..6e1a9d9 --- /dev/null +++ b/lib/libelf/gelf_cap.c @@ -0,0 +1,145 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Cap * +gelf_getcap(Elf_Data *d, int ndx, GElf_Cap *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Cap *cap32; + Elf64_Cap *cap64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + + cap32 = (Elf32_Cap *) d->d_buf + ndx; + + dst->c_tag = cap32->c_tag; + dst->c_un.c_val = (Elf64_Xword) cap32->c_un.c_val; + + } else { + + cap64 = (Elf64_Cap *) d->d_buf + ndx; + + *dst = *cap64; + } + + return (dst); +} + +int +gelf_update_cap(Elf_Data *d, int ndx, GElf_Cap *gc) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Cap *cap32; + Elf64_Cap *cap64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || gc == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + cap32 = (Elf32_Cap *) d->d_buf + ndx; + + LIBELF_COPY_U32(cap32, gc, c_tag); + LIBELF_COPY_U32(cap32, gc, c_un.c_val); + } else { + cap64 = (Elf64_Cap *) d->d_buf + ndx; + + *cap64 = *gc; + } + + return (1); +} diff --git a/lib/libelf/gelf_checksum.3 b/lib/libelf/gelf_checksum.3 new file mode 100644 index 0000000..9fc500c --- /dev/null +++ b/lib/libelf/gelf_checksum.3 @@ -0,0 +1,115 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_checksum , +.Nm elf64_checksum , +.Nm gelf_checksum +.Nd return the checksum of an ELF object +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft long +.Fn elf32_checksum "Elf *elf" +.Ft long +.Fn elf64_checksum "Elf *elf" +.In gelf.h +.Ft long +.Fn gelf_checksum "Elf *elf" +.Sh DESCRIPTION +These functions return a simple checksum of the ELF object described +by their argument +.Ar elf . +The checksum is computed in way that allows its value to remain +unchanged in presence of modifications to the ELF object by utilities +like +.Xr strip 1 . +.Pp +Function +.Fn elf32_checksum +returns a checksum for an ELF descriptor +.Ar elf +of class +.Dv ELFCLASS32 . +.Pp +Function +.Fn elf64_checksum +returns a checksum for an ELF descriptor +.Ar elf +of class +.Dv ELFCLASS64 . +.Pp +Function +.Fn gelf_checksum +provides a class-independent way retrieving the checksum +for ELF object +.Ar elf . +.Sh RETURN VALUES +These functions return the checksum of the ELF object, or zero in case +an error was encountered. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF file. +.It Bq Er ELF_E_ARGUMENT +The ELF descriptor +.Ar elf +was not opened for reading or updating. +.It Bq Er ELF_E_CLASS +For functions +.Fn elf32_checksum +and +.Fn elf64_checksum , +ELF descriptor +.Ar elf +did not match the class of the called function. +.It Bq Er ELF_E_HEADER +The ELF object specified by argument +.Ar elf +had a malformed executable header. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected during processing. +.It Bq Er ELF_E_SECTION +The ELF object specified by argument +.Ar elf +contained a section with a malformed section header. +.It Bq Er ELF_E_VERSION +The ELF object was of an unsupported version. +.El +.Sh SEE ALSO +.Xr strip 1 , +.Xr elf 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/gelf_checksum.c b/lib/libelf/gelf_checksum.c new file mode 100644 index 0000000..64eb6c3 --- /dev/null +++ b/lib/libelf/gelf_checksum.c @@ -0,0 +1,57 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> +#include <libelf.h> + +#include "_libelf.h" + +long +elf32_checksum(Elf *e) +{ + return (_libelf_checksum(e, ELFCLASS32)); +} + +long +elf64_checksum(Elf *e) +{ + return (_libelf_checksum(e, ELFCLASS64)); +} + +long +gelf_checksum(Elf *e) +{ + int ec; + if (e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0L); + } + return (_libelf_checksum(e, ec)); +} diff --git a/lib/libelf/gelf_dyn.c b/lib/libelf/gelf_dyn.c new file mode 100644 index 0000000..329fe93 --- /dev/null +++ b/lib/libelf/gelf_dyn.c @@ -0,0 +1,144 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Dyn * +gelf_getdyn(Elf_Data *d, int ndx, GElf_Dyn *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Dyn *dyn32; + Elf64_Dyn *dyn64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + dyn32 = (Elf32_Dyn *) d->d_buf + ndx; + + dst->d_tag = dyn32->d_tag; + dst->d_un.d_val = (Elf64_Xword) dyn32->d_un.d_val; + + } else { + + dyn64 = (Elf64_Dyn *) d->d_buf + ndx; + + *dst = *dyn64; + } + + return (dst); +} + +int +gelf_update_dyn(Elf_Data *d, int ndx, GElf_Dyn *ds) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Dyn *dyn32; + Elf64_Dyn *dyn64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || ds == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + dyn32 = (Elf32_Dyn *) d->d_buf + ndx; + + LIBELF_COPY_S32(dyn32, ds, d_tag); + LIBELF_COPY_U32(dyn32, ds, d_un.d_val); + } else { + dyn64 = (Elf64_Dyn *) d->d_buf + ndx; + + *dyn64 = *ds; + } + + return (1); +} diff --git a/lib/libelf/gelf_ehdr.c b/lib/libelf/gelf_ehdr.c new file mode 100644 index 0000000..4d7698a --- /dev/null +++ b/lib/libelf/gelf_ehdr.c @@ -0,0 +1,167 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + +Elf32_Ehdr * +elf32_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 0)); +} + +Elf64_Ehdr * +elf64_getehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 0)); +} + +GElf_Ehdr * +gelf_getehdr(Elf *e, GElf_Ehdr *d) +{ + int ec; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (d == NULL || e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL) + return (NULL); + + (void) memcpy(d->e_ident, eh32->e_ident, sizeof(eh32->e_ident)); + d->e_type = eh32->e_type; + d->e_machine = eh32->e_machine; + d->e_version = eh32->e_version; + d->e_entry = eh32->e_entry; + d->e_phoff = eh32->e_phoff; + d->e_shoff = eh32->e_shoff; + d->e_flags = eh32->e_flags; + d->e_ehsize = eh32->e_ehsize; + d->e_phentsize = eh32->e_phentsize; + d->e_phnum = eh32->e_phnum; + d->e_shentsize = eh32->e_shentsize; + d->e_shnum = eh32->e_shnum; + d->e_shstrndx = eh32->e_shstrndx; + + return (d); + } + + assert(ec == ELFCLASS64); + + if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL) + return (NULL); + *d = *eh64; + + return (d); +} + +Elf32_Ehdr * +elf32_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS32, 1)); +} + +Elf64_Ehdr * +elf64_newehdr(Elf *e) +{ + return (_libelf_ehdr(e, ELFCLASS64, 1)); +} + +void * +gelf_newehdr(Elf *e, int ec) +{ + if (e != NULL && + (ec == ELFCLASS32 || ec == ELFCLASS64)) + return (_libelf_ehdr(e, ec, 1)); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +int +gelf_update_ehdr(Elf *e, GElf_Ehdr *s) +{ + int ec; + void *ehdr; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + + if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + if (ec == ELFCLASS64) { + eh64 = (Elf64_Ehdr *) ehdr; + *eh64 = *s; + return (1); + } + + eh32 = (Elf32_Ehdr *) ehdr; + + (void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident)); + + eh32->e_type = s->e_type; + eh32->e_machine = s->e_machine; + eh32->e_version = s->e_version; + LIBELF_COPY_U32(eh32, s, e_entry); + LIBELF_COPY_U32(eh32, s, e_phoff); + LIBELF_COPY_U32(eh32, s, e_shoff); + eh32->e_flags = s->e_flags; + eh32->e_ehsize = s->e_ehsize; + eh32->e_phentsize = s->e_phentsize; + eh32->e_phnum = s->e_phnum; + eh32->e_shentsize = s->e_shentsize; + eh32->e_shnum = s->e_shnum; + eh32->e_shstrndx = s->e_shstrndx; + + (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/lib/libelf/gelf_fsize.3 b/lib/libelf/gelf_fsize.3 new file mode 100644 index 0000000..681e338 --- /dev/null +++ b/lib/libelf/gelf_fsize.3 @@ -0,0 +1,93 @@ +.\" 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 July 3, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_fsize , +.Nm elf32_fsize , +.Nm elf64_fsize +.Nd return the size of a file type +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft size_t +.Fn elf32_fsize "Elf_Type type" "size_t count" "unsigned int version" +.Ft size_t +.Fn elf64_fsize "Elf_Type type" "size_t count" "unsigned int version" +.In gelf.h +.Fn gelf_fsize "Elf *elf" "Elf_Type type" "size_t count" "unsigned int version" +.Sh DESCRIPTION +These functions return the size in bytes of the file representation of +.Ar count +numbers of objects of ELF type +.Ar type . +.Pp +Functions +.Fn elf32_fsize +and +.Fn elf64_fsize +return sizes for files of class +.Dv ELFCLASS32 +and +.Dv ELFCLASS64 +respectively. +Function +.Fn gelf_fsize +returns the size for the class of ELF descriptor +.Ar elf . +.Sh RETURN VALUES +These functions return a non-zero value in case of success, or zero in +case of an error. +.Sh ERRORS +These functions may fail with: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL in a call to +.Fn gelf_fsize . +.It Bq Er ELF_E_ARGUMENT +ELF descriptor +.Ar elf +had an unknown ELF class. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar type +contained an illegal value. +.It Bq Er ELF_E_UNIMPL +Support for ELF type +.Ar type +has not been implemented. +.It Bq Er ELF_E_VERSION +Argument +.Ar version +is not a supported version. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr gelf 3
\ No newline at end of file diff --git a/lib/libelf/gelf_fsize.c b/lib/libelf/gelf_fsize.c new file mode 100644 index 0000000..0137c11 --- /dev/null +++ b/lib/libelf/gelf_fsize.c @@ -0,0 +1,61 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> +#include <libelf.h> + +#include "_libelf.h" + +size_t +elf32_fsize(Elf_Type t, size_t c, unsigned int v) +{ + return (_libelf_fsize(t, ELFCLASS32, v, c)); +} + +size_t +elf64_fsize(Elf_Type t, size_t c, unsigned int v) +{ + return (_libelf_fsize(t, ELFCLASS64, v, c)); +} + +size_t +gelf_fsize(Elf *e, Elf_Type t, size_t c, unsigned int v) +{ + + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_class == ELFCLASS32 || e->e_class == ELFCLASS64) + return (_libelf_fsize(t, e->e_class, v, c)); + + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); +} diff --git a/lib/libelf/gelf_getcap.3 b/lib/libelf/gelf_getcap.3 new file mode 100644 index 0000000..41ecd5e --- /dev/null +++ b/lib/libelf/gelf_getcap.3 @@ -0,0 +1,121 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getcap , +.Nm gelf_update_cap +.Nd read and update ELF capability information +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Cap *" +.Fn gelf_getcap "Elf_Data *data" "int ndx" "GElf_Cap *cap" +.Ft int +.Fn gelf_update_cap "Elf_Data *data" "int ndx" "GElf_Cap *cap" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Cap +or +.Vt Elf64_Cap +information. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SUNW_cap . +Argument +.Ar ndx +is the index of the entry being retrieved or updated. +The class-independent +.Vt GElf_Cap +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getcap +retrieves the class-dependent entry at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar cap +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_cap +converts the class-independent entry pointed to +by argument +.Ar cap +to class-dependent form, and writes it to the entry at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_cap +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getcap +returns the value of argument +.Ar cap +if successful, or NULL in case of an error. +Function +.Fn gelf_update_cap +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar cap +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of entries in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section of type +.Dv SHT_SUNW_cap . +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getclass.3 b/lib/libelf/gelf_getclass.3 new file mode 100644 index 0000000..9ca4baf --- /dev/null +++ b/lib/libelf/gelf_getclass.3 @@ -0,0 +1,61 @@ +.\" 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 July 3, 2006 +.Os +.Dt GELF 3 +.Sh NAME +.Nm gelf_getclass +.Nd retrieve the class of an ELF descriptor +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft int +.Fn gelf_getclass "Elf *elf" +.Sh DESCRIPTION +Function +.Fn gelf_getclass +returns the ELF class of the descriptor supplied in argument +.Ar elf . +.Sh RETURN VALUES +Function +.Fn gelf_getclass +will return one of +.Dv ELFCLASS32 +or +.Dv ELFCLASS64 +if the argument +.Ar elf +is a descriptor for an ELF file. +The value +.Dv ELFCLASSNONE +is returned if argument +.Ar elf +was null, or if it was not a descriptor for an ELF file. +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_kind 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getclass.c b/lib/libelf/gelf_getclass.c new file mode 100644 index 0000000..badd8ff --- /dev/null +++ b/lib/libelf/gelf_getclass.c @@ -0,0 +1,38 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> + +#include "_libelf.h" + +int +gelf_getclass(Elf *e) +{ + return (e != NULL ? e->e_class : ELFCLASSNONE); +} diff --git a/lib/libelf/gelf_getdyn.3 b/lib/libelf/gelf_getdyn.3 new file mode 100644 index 0000000..492319e --- /dev/null +++ b/lib/libelf/gelf_getdyn.3 @@ -0,0 +1,123 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getdyn , +.Nm gelf_update_dyn +.Nd read and update ELF dynamic entries +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Dyn *" +.Fn gelf_getdyn "Elf_Data *data" "int ndx" "GElf_Dyn *dyn" +.Ft int +.Fn gelf_update_dyn "Elf_Data *data" "int ndx" "GElf_Dyn *dyn" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Dyn +or +.Vt Elf64_Dyn +information in the +.Sy dynamic +table of an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_DYNAMIC . +Argument +.Ar ndx +is the index of the entry being retrieved or updated. +The class-independent +.Vt GElf_Dyn +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getdyn +retrieves the class-dependent entry at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar dyn +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_dyn +converts the class-independent entry pointed to +by argument +.Ar dyn +to class-dependent form, and writes it to the entry at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_dyn +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getdyn +returns the value of argument +.Ar dyn +if successful, or NULL in case of an error. +Function +.Fn gelf_update_dyn +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar dyn +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of entries in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section of type +.Dv SHT_DYNAMIC . +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getehdr.3 b/lib/libelf/gelf_getehdr.3 new file mode 100644 index 0000000..efac1215 --- /dev/null +++ b/lib/libelf/gelf_getehdr.3 @@ -0,0 +1,119 @@ +.\" 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 July 6, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_getehdr , +.Nm elf64_getehdr , +.Nm gelf_getehdr +.Nd retrieve the object file header +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Ehdr *" +.Fn elf32_getehdr "Elf *elf" +.Ft "Elf64_Ehdr *" +.Fn elf64_getehdr "Elf *elf" +.In gelf.h +.Ft "Gelf_Ehdr *" +.Fn gelf_getehdr "Elf *elf" "Gelf_Ehdr *dst" +.Sh DESCRIPTION +These functions retrieve the ELF object file +header from the ELF descriptor +.Ar elf +and return a translated header descriptor to their callers. +.Pp +Functions +.Fn elf32_getehdr +and +.Fn elf64_getehdr +return a pointer to the appropriate class-specific header descriptor +if it exists in the file referenced by descriptor +.Ar elf . +These functions return +.Dv NULL +if an ELF header was not found in file +.Ar elf . +.Pp +Function +.Fn gelf_getehdr +stores a translated copy of the header for ELF file +.Ar elf +into the descriptor pointed to by argument +.Ar dst . +It returns argument +.Ar dst +if successful or +.Dv NULL +in case of failure. +.Sh RETURN VALUES +These functions return a pointer to a translated header descriptor +if successful, or NULL on failure. +.Sh ERRORS +These functions can fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +The argument +.Ar elf +was null. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF file. +.It Bq Er ELF_E_ARGUMENT +The elf class of descriptor +.Ar elf +was not recognized. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar dst +was null. +.It Bq Er ELF_E_CLASS +The ELF class of descriptor +.Ar elf +did not match that of the API function being called. +.It Bq Er ELF_E_HEADER +ELF descriptor +.Ar elf +does not have an associated header. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected during execution. +.It Bq Er ELF_E_VERSION +The ELF descriptor +.Ar elf +had an unsupported ELF version number. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getident 3 , +.Xr elf_flagehdr 3 , +.Xr elf32_newehdr 3 , +.Xr elf64_newehdr 3 , +.Xr gelf 3 , +.Xr gelf_newehdr 3 , +.Xr elf 5 diff --git a/lib/libelf/gelf_getmove.3 b/lib/libelf/gelf_getmove.3 new file mode 100644 index 0000000..2ce5fcf --- /dev/null +++ b/lib/libelf/gelf_getmove.3 @@ -0,0 +1,120 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getmove , +.Nm gelf_update_move +.Nd read and update Elf Move information +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Move *" +.Fn gelf_getmove "Elf_Data *data" "int ndx" "GElf_Move *move" +.Ft int +.Fn gelf_update_move "Elf_Data *data" "int ndx" "GElf_Move *move" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Move +and +.Vt Elf64_Move +structures in an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SUNW_move . +Argument +.Ar ndx +is the index of the move record being retrieved or updated. +The class-independent +.Vt GElf_Move +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getmove +retrieves class-dependent move record at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar move +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_move +converts the class-independent move information pointed to +by argument +.Ar move +to class-dependent form, and writes it to the move record at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_move +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getmove +returns the value of argument +.Ar move +if successful, or NULL in case of an error. +Function +.Fn gelf_update_move +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar move +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of records in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section containing move information. +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getphdr.3 b/lib/libelf/gelf_getphdr.3 new file mode 100644 index 0000000..9914460 --- /dev/null +++ b/lib/libelf/gelf_getphdr.3 @@ -0,0 +1,137 @@ +.\" 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 August 25, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_getphdr , +.Nm elf64_getphdr , +.Nm gelf_getphdr +.Nd retrieve an ELF program header table +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Phdr *" +.Fn elf32_getphdr "Elf *elf" +.Ft "Elf64_Phdr *" +.Fn elf64_getphdr "Elf *elf" +.In gelf.h +.Ft "GElf_Phdr *" +.Fn gelf_getphdr "Elf *elf" "int index" "GElf_Phdr *dst" +.Sh DESCRIPTION +These functions retrieve and translate ELF program header information +from an ELF descriptor, if this information exists. +.Pp +Functions +.Fn elf32_getphdr +and +.Fn elf64_getphdr +return a pointer to an array of translated +.Vt Elf32_Phdr +and +.Vt Elf64_Phdr +descriptors respectively. +These descriptors are described in +.Xr elf 5 . +The number of entries in this array is specified by the +.Va e_phnum +field of the executable header for ELF descriptor +.Ar elf . +.Pp +Function +.Fn gelf_getphdr +will retrieve the program header table entry at index +.Ar index +from ELF descriptor +.Ar elf. +The translated program header table entry will be written to the +address pointed to be argument +.Ar dst . +.Pp +Applications may inform the library of modifications to a program header table entry +by using the +.Xr elf_flagphdr 3 +API. +Applications using the +.Xr gelf 3 +interface need to use the +.Xr gelf_update_phdr 3 +API to copy modifications to a program header entry back to the underlying +ELF descriptor. +.Sh RETURN VALUES +The functions a valid pointer if successful, or NULL in case an error +was encountered. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar dst +was NULL. +.It Bq Er ELF_E_ARGUMENT +Index +.Ar index +was out of range. +.It Bq Er ELF_E_CLASS +The class of ELF descriptor +.Ar elf +did not match the expected class of the function being called. +.It Bq Er ELF_E_HEADER +ELF descriptor +.Ar elf +did not possess an executable header. +.It Bq Er ELF_E_HEADER +ELF descriptor +.Ar elf +had a corrupt executable header. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.It Bq Er ELF_VERSION +ELF descriptor +.Ar elf +was of an unsupported version. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagphdr 3 , +.Xr elf32_getehdr 3 , +.Xr elf32_newphdr 3 , +.Xr elf64_getehdr 3 , +.Xr elf64_newphdr 3 , +.Xr gelf 3 , +.Xr gelf_getehdr 3 , +.Xr gelf_newphdr 3 , +.Xr gelf_update_phdr 3 , +.Xr elf 5 diff --git a/lib/libelf/gelf_getrel.3 b/lib/libelf/gelf_getrel.3 new file mode 100644 index 0000000..be85931 --- /dev/null +++ b/lib/libelf/gelf_getrel.3 @@ -0,0 +1,121 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getrel , +.Nm gelf_update_rel +.Nd read and update ELF relocation entries +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Rel *" +.Fn gelf_getrel "Elf_Data *data" "int ndx" "GElf_Rel *rel" +.Ft int +.Fn gelf_update_rel "Elf_Data *data" "int ndx" "GElf_Rel *rel" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Rel +or +.Vt Elf64_Rel +structures in an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_REL . +Argument +.Ar ndx +is the index of the entry being retrieved or updated. +The class-independent +.Vt GElf_Rel +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getrel +retrieves the class-dependent entry at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar rel +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_rel +converts the class-independent entry pointed to +by argument +.Ar rel +to class-dependent form, and writes it to the entry at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_rel +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getrel +returns the value of argument +.Ar rel +if successful, or NULL in case of an error. +Function +.Fn gelf_update_rel +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar rel +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of entries in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section of type +.Dv SHT_REL . +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getrela.3 b/lib/libelf/gelf_getrela.3 new file mode 100644 index 0000000..cef1e1a --- /dev/null +++ b/lib/libelf/gelf_getrela.3 @@ -0,0 +1,121 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getrela , +.Nm gelf_update_rela +.Nd read and update ELF relocation entries with addends +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Rela *" +.Fn gelf_getrela "Elf_Data *data" "int ndx" "GElf_Rela *rela" +.Ft int +.Fn gelf_update_rela "Elf_Data *data" "int ndx" "GElf_Rela *rela" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Rela +or +.Vt Elf64_Rela +structures in an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_RELA . +Argument +.Ar ndx +is the index of the entry being retrieved or updated. +The class-independent +.Vt GElf_Rela +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getrela +retrieves the class-dependent entry at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar rela +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_rela +converts the class-independent entry pointed to +by argument +.Ar rela +to class-dependent form, and writes it to the entry at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_rela +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getrela +returns the value of argument +.Ar rela +if successful, or NULL in case of an error. +Function +.Fn gelf_update_rela +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar rela +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of entries in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section of type +.Dv SHT_RELA . +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 diff --git a/lib/libelf/gelf_getshdr.3 b/lib/libelf/gelf_getshdr.3 new file mode 100644 index 0000000..77016f5 --- /dev/null +++ b/lib/libelf/gelf_getshdr.3 @@ -0,0 +1,115 @@ +.\" 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 August 27, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_getshdr , +.Nm elf64_getshdr , +.Nm gelf_getshdr +.Nd retrieve the class-dependent section header +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Shdr *" +.Fn elf32_getshdr "Elf_Scn *scn" +.Ft "Elf64_Shdr *" +.Fn elf64_getshdr "Elf_Scn *scn" +.In gelf.h +.Ft "GElf_Shdr *" +.Fn gelf_getshdr "Elf_Scn *scn" "GElf_Shdr *shdr" +.Sh DESCRIPTION +These functions return a pointer to the ELF Section Header data +structure associated with section descriptor +.Ar scn . +.Pp +Function +.Fn elf32_getshdr +retrieves a pointer to an +.Vt Elf32_Shdr +structure. +Section descriptor +.Ar scn +must be associated with an ELF descriptor of class +.Dv ELFCLASS32 . +.Pp +Function +.Fn elf64_getshdr +retrieves a pointer to an +.Vt Elf64_Shdr +structure. +Section descriptor +.Ar scn +must be associated with an ELF descriptor of class +.Dv ELFCLASS64 . +.Pp +Function +.Fn gelf_getshdr +copies the values in the section header associated with argument +.Ar scn +to the structure pointed to be argument +.Ar dst . +The +.Vt GElf_Shdr +data structure is described in +.Xr gelf 3 . +.Sh RETURN VALUES +Functions +.Fn elf32_getshdr +and +.Fn elf64_getshdr +return a valid pointer to the appropriate section header on success +or NULL if an error was encountered. +.Pp +Function +.Fn gelf_getshdr +returns argument +.Ar dst +if successful, or NULL if an error was encountered. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar scn +or +.Ar shdr +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar scn +was not associated a descriptor for an ELF object. +.It Bq Er ELF_E_CLASS +The ELF class associated with the section descriptor +.Ar scn +did not match the class expected by the API. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 , +.Xr gelf_update_shdr 3 diff --git a/lib/libelf/gelf_getsym.3 b/lib/libelf/gelf_getsym.3 new file mode 100644 index 0000000..38e4dfa --- /dev/null +++ b/lib/libelf/gelf_getsym.3 @@ -0,0 +1,125 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getsym , +.Nm gelf_update_sym +.Nd read and update symbol information +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Sym *" +.Fn gelf_getsym "Elf_Data *data" "int ndx" "GElf_Sym *sym" +.Ft int +.Fn gelf_update_sym "Elf_Data *data" "int ndx" "GElf_Sym *sym" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Sym +and +.Vt Elf64_Sym +structures in an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SYMTAB , +.Dv SHT_DYNSYM +or +.Dv SHT_GNU_versym . +Argument +.Ar ndx +is the index of the symbol being retrieved or updated. +The class-independent +.Vt GElf_Sym +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getsym +retrieves class-dependent symbol information at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar sym +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_sym +converts the class-independent symbol information pointed to +by argument +.Ar sym +to class-dependent form, and writes it to the symbol entry at index +.Ar ndx +in the data buffer described by argument +.Ar data . +Function +.Fn gelf_update_sym +signals an error if any of the values in the class-independent +representation exceeds the representable limits of the target +type. +.Sh RETURN VALUES +Function +.Fn gelf_getsym +returns the value of argument +.Ar sym +if successful, or NULL in case of an error. +Function +.Fn gelf_update_sym +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar sym +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of symbols in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section containing symbol information. +.It Bq Er ELF_E_RANGE +A value was not representable in the target type. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 , +.Xr gelf_getsyminfo 3 , +.Xr gelf_update_syminfo 3 diff --git a/lib/libelf/gelf_getsyminfo.3 b/lib/libelf/gelf_getsyminfo.3 new file mode 100644 index 0000000..b77dce5 --- /dev/null +++ b/lib/libelf/gelf_getsyminfo.3 @@ -0,0 +1,115 @@ +.\" 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 August 29, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getsyminfo , +.Nm gelf_update_syminfo +.Nd read and update symbol information +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Syminfo *" +.Fn gelf_getsyminfo "Elf_Data *data" "int ndx" "GElf_Syminfo *syminfo" +.Ft int +.Fn gelf_update_syminfo "Elf_Data *data" "int ndx" "GElf_Syminfo *syminfo" +.Sh DESCRIPTION +These convenience functions are used to retrieve and update class-dependent +.Vt Elf32_Syminfo +and +.Vt Elf64_Syminfo +records in an ELF object. +.Pp +Argument +.Ar data +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SUNW_syminfo . +Argument +.Ar ndx +is the index of the record being retrieved or updated. +The class-independent +.Vt GElf_Syminfo +structure is described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getsyminfo +retrieves class-dependent record at index +.Ar ndx +in data buffer +.Ar data +and copies it to the destination pointed to by argument +.Ar syminfo +after translation to class-independent form. +.Pp +Function +.Fn gelf_update_syminfo +converts the class-independent record pointed to +by argument +.Ar syminfo +to class-dependent form, and writes it to the record at index +.Ar ndx +in the data buffer described by argument +.Ar data . +.Sh RETURN VALUES +Function +.Fn gelf_getsyminfo +returns the value of argument +.Ar syminfo +if successful, or NULL in case of an error. +Function +.Fn gelf_update_syminfo +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar data +or +.Ar syminfo +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero or larger than the number of symbols in the data +descriptor. +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar data +was not associated with a section containing symbol information. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 , +.Xr gelf_getsym 3 , +.Xr gelf_update_sym 3 diff --git a/lib/libelf/gelf_getsymshndx.3 b/lib/libelf/gelf_getsymshndx.3 new file mode 100644 index 0000000..2aa82d9 --- /dev/null +++ b/lib/libelf/gelf_getsymshndx.3 @@ -0,0 +1,162 @@ +.\" 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 November 5, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_getsymshndx , +.Nm gelf_update_symshndx +.Nd read and update symbol information using extended section indices +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft "GElf_Sym *" +.Fo gelf_getsyminfo +.Fa "Elf_Data *symdata" +.Fa "Elf_Data *xndxdata" +.Fa "int ndx" +.Fa "GElf_Sym *sym" +.Fa "Elf32_Word *xndxptr" +.Fc +.Ft int +.Fo gelf_update_syminfo +.Fa "Elf_Data *symdata" +.Fa "Elf_Data *xndxdata" +.Fa "int ndx" +.Fa "GElf_Sym *sym" +.Fa "Elf32_Word xndx" +.Fc +.Sh DESCRIPTION +These functions are analogous to +.Fn gelf_getsym +and +.Fn gelf_update_sym +respectively, but are capable of handling symbol tables using extended +section numbering. +.Pp +Argument +.Ar symdata +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SYMTAB . +Argument +.Ar xndxdata +is an +.Vt Elf_Data +descriptor associated with a section of type +.Dv SHT_SYMTAB_SHNDX . +Argument +.Ar ndx +is the index of the symbol table entry being retrieved or updated. +Argument +.Ar sym +is a pointer to a class-independent +.Vt GElf_Sym +structure. +.Vt GElf_Sym +structures are described in detail in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_getsymshndx +retrieves symbol information at index +.Ar ndx +from the data descriptor specified by argument +.Ar symdata +and stores in class-independent form in argument +.Ar sym . +In addition it retrieves the extended section index for the +symbol from data buffer +.Ar xndxdata +and stores it into the location pointed to by argument +.Ar xndxptr . +.Pp +Function +.Fn gelf_update_symshndx +updates the underlying symbol table entry in data +descriptor +.Ar symdata +with the information in argument +.Ar sym . +In addition it sets the extended section index in +data buffer +.Ar xndxdata +to the value of argument +.Ar xndx . +.Sh RETURN VALUES +Function +.Fn gelf_getsymshndx +returns the value of argument +.Ar sym +if successful, or NULL in case of an error. +.Pp +Function +.Fn gelf_update_symshndx +returns a non-zero value if successful, or zero in case of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar symdata , +.Ar xndxdata , +.Ar xndxptr +or +.Ar sym +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +was less than zero, or too large for either of descriptors +.Ar symdata +or +.Ar xndxdata . +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar symdata +was not associated with a section of type +.Dv SHT_SYMTAB . +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar xndxdata +was not associated with a section of type +.Dv SHT_SYMTAB_SHNDX . +.It Bq Er ELF_E_ARGUMENT +Data descriptor +.Ar symdata +and +.Ar xndxdata +were associated with different ELF objects. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr elf_getscn 3 , +.Xr gelf 3 , +.Xr gelf_getsym 3 , +.Xr gelf_update_sym 3 diff --git a/lib/libelf/gelf_move.c b/lib/libelf/gelf_move.c new file mode 100644 index 0000000..96d0aae --- /dev/null +++ b/lib/libelf/gelf_move.c @@ -0,0 +1,151 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Move * +gelf_getmove(Elf_Data *d, int ndx, GElf_Move *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Move *move32; + Elf64_Move *move64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + + move32 = (Elf32_Move *) d->d_buf + ndx; + + dst->m_value = move32->m_value; + dst->m_info = (Elf64_Xword) move32->m_info; + dst->m_poffset = (Elf64_Xword) move32->m_poffset; + dst->m_repeat = move32->m_repeat; + dst->m_stride = move32->m_stride; + } else { + + move64 = (Elf64_Move *) d->d_buf + ndx; + + *dst = *move64; + } + + return (dst); +} + +int +gelf_update_move(Elf_Data *d, int ndx, GElf_Move *gm) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Move *move32; + Elf64_Move *move64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || gm == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + move32 = (Elf32_Move *) d->d_buf + ndx; + + move32->m_value = gm->m_value; + LIBELF_COPY_U32(move32, gm, m_info); + LIBELF_COPY_U32(move32, gm, m_poffset); + move32->m_repeat = gm->m_repeat; + move32->m_stride = gm->m_stride; + + } else { + move64 = (Elf64_Move *) d->d_buf + ndx; + + *move64 = *gm; + } + + return (1); +} diff --git a/lib/libelf/gelf_newehdr.3 b/lib/libelf/gelf_newehdr.3 new file mode 100644 index 0000000..0b08f0a --- /dev/null +++ b/lib/libelf/gelf_newehdr.3 @@ -0,0 +1,181 @@ +.\" 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 July 6, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_newehdr , +.Nm elf64_newehdr , +.Nm gelf_newehdr +.Nd retrieve or allocate the object file header +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Ehdr *" +.Fn elf32_newehdr "Elf *elf" +.Ft "Elf64_Ehdr *" +.Fn elf64_newehdr "Elf *elf" +.In gelf.h +.Ft "void *" +.Fn gelf_newehdr "Elf *elf" "int elfclass" +.Sh DESCRIPTION +These functions retrieve the ELF header from the ELF descriptor +.Ar elf , +allocating a new header if needed. +File data structures are translated to their in-memory representations +as described in +.Xr elf 3 . +.Pp +Function +.Fn elf32_newehdr +returns a pointer to a 32 bit +.Vt Elf32_Ehdr +structure. +Function +.Fn elf64_newehdr +returns a pointer to a 64 bit +.Vt Elf64_Ehdr structure. +.Pp +When argument +.Ar elfclass +has value +.Dv ELFCLASS32 , +function +.Fn gelf_newehdr +returns the value returned by +.Fn elf32_newehdr "elf" . +When argument +.Ar elfclass +has value +.Dv ELFCLASS64 +it returns the value returned by +.Fn elf64_newehdr "elf" . +.Pp +If a fresh header structure is allocated, the members of the +structure are initialized as follows: +.Bl -tag -width indent +.It Va "e_ident[EI_MAG0..EI_MAG3]" +Identification bytes at offsets +.Dv EI_MAG0 , +.Dv EI_MAG1 , +.Dv EI_MAG2 +and +.Dv EI_MAG3 +are set to the ELF signature. +.It Va "e_ident[EI_CLASS]" +The identification byte at offset +.Dv EI_CLASS +is set to the ELF class associated with the function being called +or to argument +.Ar elfclass +for function +.Fn gelf_newehdr . +.It Va "e_ident[EI_DATA]" +The identification byte at offset +.Dv EI_DATA +is set to +.Dv ELFDATANONE . +.It Va "e_ident[EI_VERSION]" +The identification byte at offset +.Dv EI_VERSION +is set to the ELF library's operating version set by a prior call to +.Xr elf_version 3 . +.It Va e_machine +is set to +.Dv EM_NONE . +.It Va e_type +is set to +.Dv ELF_K_NONE . +.It Va e_version +is set to the ELF library's operating version set by a prior call to +.Xr elf_version 3 . +.El +.Pp +Other members of the header are set to zero. +The application is responsible for changing these values +as needed before calling +.Fn elf_update . +.Pp +If successful, these three functions set the +.Dv ELF_F_DIRTY +bit on ELF descriptor +.Ar elf . +.Sh RETURN VALUES +These functions return a pointer to a translated header descriptor +if successful, or NULL on failure. +.Sh ERRORS +These functions can fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +The argument +.Ar elf +was null. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elfclass +had an unsupported value. +.It Bq Er ELF_E_ARGUMENT +The class of the ELF descriptor +.Ar elf +did not match that of the requested operation. +.It Bq Er ELF_E_ARGUMENT +For function +.Fn gelf_newehdr , +the class of argument +.Ar elf +was not +.Dv ELFCLASSNONE +and did not match the argument +.Ar elfclass . +.It Bq Er ELF_E_CLASS +The ELF class of descriptor +.Ar elf +did not match that of the API function being called. +.It Bq Er ELF_E_HEADER +A malformed ELF header was detected. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected during execution. +.It Bq Er ELF_E_VERSION +The ELF descriptor +.Ar elf +had an unsupported ELF version number. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagdata 3 , +.Xr elf_getident 3 , +.Xr elf_update 3 , +.Xr elf32_getehdr 3 , +.Xr elf64_getehdr 3 , +.Xr elf_version 3 , +.Xr gelf 3 , +.Xr gelf_getehdr 3 , +.Xr elf 5 diff --git a/lib/libelf/gelf_newphdr.3 b/lib/libelf/gelf_newphdr.3 new file mode 100644 index 0000000..cff31ba --- /dev/null +++ b/lib/libelf/gelf_newphdr.3 @@ -0,0 +1,138 @@ +.\" 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 August 25, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_newphdr , +.Nm elf64_newphdr , +.Nm gelf_newphdr +.Nd allocate an ELF program header table +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf32_Phdr *" +.Fn elf32_newphdr "Elf *elf" "size_t count" +.Ft "Elf64_Phdr *" +.Fn elf64_newphdr "Elf *elf" "size_t count" +.In gelf.h +.Ft "void *" +.Fn gelf_newphdr "Elf *elf" "size_t count" +.Sh DESCRIPTION +These functions allocate an ELF Program Header table +for an ELF descriptor. +.Vt Elf32_Phdr +and +.Vt Elf64_Phdr +descriptors are described further in +.Xr elf 5 . +.Pp +Functions +.Fn elf32_newphdr +and +.Fn elf64_newphdr +allocate a table of +.Ar count +.Vt Elf32_Phdr +and +.Vt Elf64_Phdr +descriptors respectively, +discarding any existing program header table +already present in the ELF descriptor +.Ar elf . +A value of zero for argument +.Ar count +may be used to delete an existing program header table +from an ELF descriptor. +.Pp +Function +.Fn gelf_newphdr +will return a table of +.Vt Elf32_Phdr +or +.Vt Elf64_Phdr +with +.Ar count +elements depending on the ELF class of ELF descriptor +.Ar elf . +.Pp +The functions set the +.Va e_phnum +field of the executable header for ELF descriptor +.Ar elf +to +.Ar count , +and also set the +.Dv ELF_F_DIRTY +bit on the program header table. +All members of the returned array of Phdr structures +will be initialized to zero. +.Pp +After a successful call to these functions, the pointer returned +by a prior call to +.Fn elf32_getphdr +or +.Fn elf64_getphdr +on the same descriptor +.Ar elf +will no longer be valid. +.Sh RETURN VALUES +The functions a valid pointer if successful, or NULL in case an error +was encountered. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_CLASS +ELF descriptor +.Ar elf +was of an unrecognized class. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.It Bq Er ELF_E_SEQUENCE +An executable header was not allocated for ELF descriptor +.Ar elf +before using these APIs. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagphdr 3 , +.Xr elf32_getphdr 3 , +.Xr elf32_newehdr 3 , +.Xr elf64_getphdr 3 , +.Xr elf64_newehdr 3 , +.Xr gelf 3 , +.Xr gelf_getphdr 3 , +.Xr gelf_newehdr 3 , +.Xr elf 5 diff --git a/lib/libelf/gelf_phdr.c b/lib/libelf/gelf_phdr.c new file mode 100644 index 0000000..6d82d7f --- /dev/null +++ b/lib/libelf/gelf_phdr.c @@ -0,0 +1,178 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <gelf.h> +#include <libelf.h> + +#include "_libelf.h" + +Elf32_Phdr * +elf32_getphdr(Elf *e) +{ + return (_libelf_getphdr(e, ELFCLASS32)); +} + +Elf64_Phdr * +elf64_getphdr(Elf *e) +{ + return (_libelf_getphdr(e, ELFCLASS64)); +} + +GElf_Phdr * +gelf_getphdr(Elf *e, int index, GElf_Phdr *d) +{ + int ec; + Elf32_Ehdr *eh32; + Elf64_Ehdr *eh64; + Elf32_Phdr *ep32; + Elf64_Phdr *ep64; + + if (d == NULL || e == NULL || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || + (e->e_kind != ELF_K_ELF) || index < 0) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL || + ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL)) + return (NULL); + + if (index >= eh32->e_phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ep32 += index; + + d->p_type = ep32->p_type; + d->p_offset = ep32->p_offset; + d->p_vaddr = (Elf64_Addr) ep32->p_vaddr; + d->p_paddr = (Elf64_Addr) ep32->p_paddr; + d->p_filesz = (Elf64_Xword) ep32->p_filesz; + d->p_memsz = (Elf64_Xword) ep32->p_memsz; + d->p_flags = ep32->p_flags; + d->p_align = (Elf64_Xword) ep32->p_align; + + } else { + if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL || + (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL) + return (NULL); + + if (index >= eh64->e_phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ep64 += index; + + *d = *ep64; + } + + return (d); +} + +Elf32_Phdr * +elf32_newphdr(Elf *e, size_t count) +{ + return (_libelf_newphdr(e, ELFCLASS32, count)); +} + +Elf64_Phdr * +elf64_newphdr(Elf *e, size_t count) +{ + return (_libelf_newphdr(e, ELFCLASS64, count)); +} + +void * +gelf_newphdr(Elf *e, size_t count) +{ + if (e == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + return (_libelf_newphdr(e, e->e_class, count)); +} + +int +gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s) +{ + int ec, phnum; + void *ehdr; + Elf32_Phdr *ph32; + Elf64_Phdr *ph64; + + if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) + return (0); + + if (ec == ELFCLASS32) + phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; + else + phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; + + if (ndx < 0 || ndx > phnum) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS64) { + ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx; + *ph64 = *s; + return (1); + } + + ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx; + + ph32->p_type = s->p_type; + ph32->p_flags = s->p_flags; + LIBELF_COPY_U32(ph32, s, p_offset); + LIBELF_COPY_U32(ph32, s, p_vaddr); + LIBELF_COPY_U32(ph32, s, p_paddr); + LIBELF_COPY_U32(ph32, s, p_filesz); + LIBELF_COPY_U32(ph32, s, p_memsz); + LIBELF_COPY_U32(ph32, s, p_align); + + (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/lib/libelf/gelf_rel.c b/lib/libelf/gelf_rel.c new file mode 100644 index 0000000..e9cf948 --- /dev/null +++ b/lib/libelf/gelf_rel.c @@ -0,0 +1,144 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Rel * +gelf_getrel(Elf_Data *d, int ndx, GElf_Rel *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rel *rel32; + Elf64_Rel *rel64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + rel32 = (Elf32_Rel *) d->d_buf + ndx; + + dst->r_offset = (Elf64_Addr) rel32->r_offset; + dst->r_info = (Elf64_Xword) rel32->r_info; + + } else { + + rel64 = (Elf64_Rel *) d->d_buf + ndx; + + *dst = *rel64; + } + + return (dst); +} + +int +gelf_update_rel(Elf_Data *d, int ndx, GElf_Rel *dr) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rel *rel32; + Elf64_Rel *rel64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dr == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + rel32 = (Elf32_Rel *) d->d_buf + ndx; + + LIBELF_COPY_U32(rel32, dr, r_offset); + LIBELF_COPY_U32(rel32, dr, r_info); + } else { + rel64 = (Elf64_Rel *) d->d_buf + ndx; + + *rel64 = *dr; + } + + return (1); +} diff --git a/lib/libelf/gelf_rela.c b/lib/libelf/gelf_rela.c new file mode 100644 index 0000000..1549a53 --- /dev/null +++ b/lib/libelf/gelf_rela.c @@ -0,0 +1,146 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Rela * +gelf_getrela(Elf_Data *d, int ndx, GElf_Rela *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rela *rela32; + Elf64_Rela *rela64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + rela32 = (Elf32_Rela *) d->d_buf + ndx; + + dst->r_offset = (Elf64_Addr) rela32->r_offset; + dst->r_info = (Elf64_Xword) rela32->r_info; + dst->r_addend = (Elf64_Sxword) rela32->r_addend; + + } else { + + rela64 = (Elf64_Rela *) d->d_buf + ndx; + + *dst = *rela64; + } + + return (dst); +} + +int +gelf_update_rela(Elf_Data *d, int ndx, GElf_Rela *dr) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Rela *rela32; + Elf64_Rela *rela64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dr == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + rela32 = (Elf32_Rela *) d->d_buf + ndx; + + LIBELF_COPY_U32(rela32, dr, r_offset); + LIBELF_COPY_U32(rela32, dr, r_info); + LIBELF_COPY_S32(rela32, dr, r_addend); + } else { + rela64 = (Elf64_Rela *) d->d_buf + ndx; + + *rela64 = *dr; + } + + return (1); +} diff --git a/lib/libelf/gelf_shdr.c b/lib/libelf/gelf_shdr.c new file mode 100644 index 0000000..efe98b8 --- /dev/null +++ b/lib/libelf/gelf_shdr.c @@ -0,0 +1,131 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> +#include <libelf.h> + +#include "_libelf.h" + +Elf32_Shdr * +elf32_getshdr(Elf_Scn *s) +{ + return (_libelf_getshdr(s, ELFCLASS32)); +} + +Elf64_Shdr * +elf64_getshdr(Elf_Scn *s) +{ + return (_libelf_getshdr(s, ELFCLASS64)); +} + +GElf_Shdr * +gelf_getshdr(Elf_Scn *s, GElf_Shdr *d) +{ + int ec; + void *sh; + Elf32_Shdr *sh32; + Elf64_Shdr *sh64; + + if (d == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL) + return (NULL); + + ec = s->s_elf->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) { + sh32 = (Elf32_Shdr *) sh; + + d->sh_name = sh32->sh_name; + d->sh_type = sh32->sh_type; + d->sh_flags = (Elf64_Xword) sh32->sh_flags; + d->sh_addr = (Elf64_Addr) sh32->sh_addr; + d->sh_offset = (Elf64_Off) sh32->sh_offset; + d->sh_size = (Elf64_Xword) sh32->sh_size; + d->sh_link = sh32->sh_link; + d->sh_info = sh32->sh_info; + d->sh_addralign = (Elf64_Xword) sh32->sh_addralign; + d->sh_entsize = (Elf64_Xword) sh32->sh_entsize; + } else { + sh64 = (Elf64_Shdr *) sh; + *d = *sh64; + } + + return (d); +} + +int +gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s) +{ + int ec; + Elf *e; + Elf32_Shdr *sh32; + + + if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL || + e->e_kind != ELF_K_ELF || + ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (e->e_cmd == ELF_C_READ) { + LIBELF_SET_ERROR(MODE, 0); + return (0); + } + + if (ec == ELFCLASS64) { + scn->s_shdr.s_shdr64 = *s; + return (1); + } + + sh32 = &scn->s_shdr.s_shdr32; + + sh32->sh_name = s->sh_name; + sh32->sh_type = s->sh_type; + LIBELF_COPY_U32(sh32, s, sh_flags); + LIBELF_COPY_U32(sh32, s, sh_addr); + LIBELF_COPY_U32(sh32, s, sh_offset); + LIBELF_COPY_U32(sh32, s, sh_size); + sh32->sh_link = s->sh_link; + sh32->sh_info = s->sh_info; + LIBELF_COPY_U32(sh32, s, sh_addralign); + LIBELF_COPY_U32(sh32, s, sh_entsize); + + (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); + + return (1); +} diff --git a/lib/libelf/gelf_sym.c b/lib/libelf/gelf_sym.c new file mode 100644 index 0000000..ef969ef --- /dev/null +++ b/lib/libelf/gelf_sym.c @@ -0,0 +1,154 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Sym * +gelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Sym *sym32; + Elf64_Sym *sym64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + + sym32 = (Elf32_Sym *) d->d_buf + ndx; + + dst->st_name = sym32->st_name; + dst->st_value = (Elf64_Addr) sym32->st_value; + dst->st_size = (Elf64_Xword) sym32->st_size; + dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info), + ELF32_ST_TYPE(sym32->st_info)); + dst->st_other = sym32->st_other; + dst->st_shndx = sym32->st_shndx; + } else { + + sym64 = (Elf64_Sym *) d->d_buf + ndx; + + *dst = *sym64; + } + + return (dst); +} + +int +gelf_update_sym(Elf_Data *d, int ndx, GElf_Sym *gs) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Sym *sym32; + Elf64_Sym *sym64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || gs == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + sym32 = (Elf32_Sym *) d->d_buf + ndx; + + sym32->st_name = gs->st_name; + sym32->st_info = gs->st_info; + sym32->st_other = gs->st_other; + sym32->st_shndx = gs->st_shndx; + + LIBELF_COPY_U32(sym32, gs, st_value); + LIBELF_COPY_U32(sym32, gs, st_size); + } else { + sym64 = (Elf64_Sym *) d->d_buf + ndx; + + *sym64 = *gs; + } + + return (1); +} diff --git a/lib/libelf/gelf_syminfo.c b/lib/libelf/gelf_syminfo.c new file mode 100644 index 0000000..4d0adfe --- /dev/null +++ b/lib/libelf/gelf_syminfo.c @@ -0,0 +1,146 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Syminfo * +gelf_getsyminfo(Elf_Data *d, int ndx, GElf_Syminfo *dst) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Syminfo *syminfo32; + Elf64_Syminfo *syminfo64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || dst == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASS32) { + + syminfo32 = (Elf32_Syminfo *) d->d_buf + ndx; + + dst->si_boundto = syminfo32->si_boundto; + dst->si_flags = syminfo32->si_flags; + + } else { + + syminfo64 = (Elf64_Syminfo *) d->d_buf + ndx; + + *dst = *syminfo64; + } + + return (dst); +} + +int +gelf_update_syminfo(Elf_Data *d, int ndx, GElf_Syminfo *gs) +{ + int ec; + Elf *e; + Elf_Scn *scn; + Elf32_Syminfo *syminfo32; + Elf64_Syminfo *syminfo64; + size_t msz; + uint32_t sh_type; + + if (d == NULL || ndx < 0 || gs == NULL || + (scn = d->d_scn) == NULL || + (e = scn->s_elf) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= d->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + if (ec == ELFCLASS32) { + syminfo32 = (Elf32_Syminfo *) d->d_buf + ndx; + + syminfo32->si_boundto = gs->si_boundto; + syminfo32->si_flags = gs->si_flags; + + } else { + syminfo64 = (Elf64_Syminfo *) d->d_buf + ndx; + + *syminfo64 = *gs; + } + + return (1); +} diff --git a/lib/libelf/gelf_symshndx.c b/lib/libelf/gelf_symshndx.c new file mode 100644 index 0000000..b8f2103 --- /dev/null +++ b/lib/libelf/gelf_symshndx.c @@ -0,0 +1,129 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/limits.h> + +#include <assert.h> +#include <gelf.h> + +#include "_libelf.h" + +GElf_Sym * +gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, + Elf32_Word *shindex) +{ + int ec; + Elf *e; + Elf_Scn *scn; + size_t msz; + uint32_t sh_type; + + if (gelf_getsym(d, ndx, dst) == 0) + return (NULL); + + if (id == NULL || (scn = id->d_scn) == NULL || + (e = scn->s_elf) == NULL || (e != d->d_scn->s_elf) || + shindex == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || + id->d_type != ELF_T_WORD) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + + assert(msz > 0); + + if (msz * ndx >= id->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + *shindex = ((Elf32_Word *) id->d_buf)[ndx]; + + return (dst); +} + +int +gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs, + Elf32_Word xindex) +{ + int ec; + Elf *e; + Elf_Scn *scn; + size_t msz; + uint32_t sh_type; + + if (gelf_update_sym(d, ndx, gs) == 0) + return (0); + + if (id == NULL || (scn = id->d_scn) == NULL || + (e = scn->s_elf) == NULL || (e != d->d_scn->s_elf)) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + ec = e->e_class; + assert(ec == ELFCLASS32 || ec == ELFCLASS64); + + if (ec == ELFCLASS32) + sh_type = scn->s_shdr.s_shdr32.sh_type; + else + sh_type = scn->s_shdr.s_shdr64.sh_type; + + if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || + d->d_type != ELF_T_WORD) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + assert(msz > 0); + + if (msz * ndx >= id->d_size) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (0); + } + + *(((Elf32_Word *) id->d_buf) + ndx) = xindex; + + return (1); +} diff --git a/lib/libelf/gelf_update_ehdr.3 b/lib/libelf/gelf_update_ehdr.3 new file mode 100644 index 0000000..9bc7fc2 --- /dev/null +++ b/lib/libelf/gelf_update_ehdr.3 @@ -0,0 +1,123 @@ +.\" 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 August 27, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm gelf_update_ehdr , +.Nm gelf_update_phdr , +.Nm gelf_update_shdr +.Nd update underlying ELF data structures +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In gelf.h +.Ft int +.Fn gelf_update_ehdr "Elf *elf" "GElf_Ehdr *ehdr" +.Ft int +.Fn gelf_update_phdr "Elf *elf" "int ndx" "GElf_Phdr *phdr" +.Ft int +.Fn gelf_update_shdr "Elf_Scn *scn" "GElf_Shdr *shdr" +.Sh DESCRIPTION +These functions are used to update ELF data structures on the underlying +ELF descriptor. +Class-dependent data structures in the underlying ELF descriptor +are updated using the data in the class-independent GElf descriptors +and the underlying ELF data structures are marked +.Dq dirty . +The conversion process signals an error if the values being copied +to the target ELF data structure would exceed representation +limits. +GElf descriptors are described in +.Xr gelf 3 . +.Pp +Function +.Fn gelf_update_ehdr +updates the ELF Executable Header with the values in the +class-independent executable header +.Ar ehdr . +.Pp +Function +.Fn gelf_update_phdr +updates the ELF Program Header structure at index +.Ar ndx +with the values in the class-independent program header +.Ar phdr . +.Pp +Function +.Fn gelf_update_shdr +updates the ELF Section Header structure associated with section +descriptor +.Ar scn +with the values in argument +.Ar shdr . +.Sh RETURN VALUES +These functions return a non-zero integer on success, or zero in case +of an error. +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar elf , +.Ar ehdr , +.Ar phdr , +.Ar scn , +or +.Ar shdr +were NULL. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +was not a descriptor for an ELF object. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar elf +had an unsupported ELF class. +.It Bq Er ELF_E_ARGUMENT +Argument +.Ar ndx +exceeded the number of entries in the program header table. +.It Bq Er ELF_E_ARGUMENT +Section descriptor +.Ar scn +was not associated with an ELF descriptor. +.It Bq Er ELF_E_MODE +ELF descriptor +.Ar elf +was not opened for writing or updating. +.It Bq Er ELF_E_RESOURCE +An out of memory condition was detected. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_flagelf 3 , +.Xr elf_flagphdr 3 , +.Xr elf_flagshdr 3 , +.Xr gelf 3 , +.Xr gelf_getehdr 3 , +.Xr gelf_getphdr 3 , +.Xr gelf_getshdr 3 diff --git a/lib/libelf/gelf_xlate.c b/lib/libelf/gelf_xlate.c new file mode 100644 index 0000000..d161984 --- /dev/null +++ b/lib/libelf/gelf_xlate.c @@ -0,0 +1,79 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + + +Elf_Data * +elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOFILE); +} + +Elf_Data * +elf64_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOFILE); +} + +Elf_Data * +elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOMEMORY); +} + +Elf_Data * +elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOMEMORY); +} + +Elf_Data * +gelf_xlatetom(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + if (e != NULL) + return (_libelf_xlate(dst, src, encoding, e->e_class, + ELF_TOMEMORY)); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} + +Elf_Data * +gelf_xlatetof(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) +{ + if (e != NULL) + return (_libelf_xlate(dst, src, encoding, e->e_class, + ELF_TOFILE)); + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); +} diff --git a/lib/libelf/gelf_xlatetof.3 b/lib/libelf/gelf_xlatetof.3 new file mode 100644 index 0000000..37ef890 --- /dev/null +++ b/lib/libelf/gelf_xlatetof.3 @@ -0,0 +1,253 @@ +.\" 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 July 24, 2006 +.Os +.Dt ELF 3 +.Sh NAME +.Nm elf32_xlate , +.Nm elf64_xlate , +.Nm gelf_xlate +.Nd translate data between files and memory +.Sh LIBRARY +.Lb libelf +.Sh SYNOPSIS +.In libelf.h +.Ft "Elf_Data *" +.Fn elf32_xlatetof "Elf_Data *dst" "Elf_Data *src" "unsigned int encode" +.Ft "Elf_Data *" +.Fn elf32_xlatetom "Elf_Data *dst" "Elf_Data *src" "unsigned int encode" +.Ft "Elf_Data *" +.Fn elf64_xlatetof "Elf_Data *dst" "Elf_Data *src" "unsigned int encode" +.Ft "Elf_Data *" +.Fn elf64_xlatetom "Elf_Data *dst" "Elf_Data *src" "unsigned int encode" +.In gelf.h +.Ft "Elf_Data *" +.Fo gelf_xlatetof +.Fa "Elf *elf" +.Fa "Elf_Data *dst" +.Fa "Elf_Data *src" +.Fa "unsigned int encode" +.Fc +.Ft "Elf_Data *" +.Fo gelf_xlatetom +.Fa "Elf *elf" +.Fa "Elf_Data *dst" +.Fa "Elf_Data *src" +.Fa "unsigned int encode" +.Fc +.Sh DESCRIPTION +These functions translate between the file and memory representations +of ELF data structures. +The in-memory representation of an ELF data structure would confirm to +the byte ordering and data alignment restrictions dictated by the host +processor. +A file representation of the same data structure could use a non-native byte +ordering and in addition may be laid out differently with the file. +.Pp +Functions +.Fn elf32_xlatetom , +.Fn elf64_xlatetom , +and +.Fn gelf_xlatetom +translate data from file representations to native, in-memory representations. +Functions +.Fn elf32_xlatetof , +.Fn elf64_xlatetof , +and +.Fn gelf_xlatetof +translate data from in-memory representations to file representations. +.Pp +Argument +.Ar src +denotes an +.Vt Elf_Data +descriptor describing the source to be translated. +The following elements of the descriptor need to be set before +invoking these functions: +.Bl -hang -offset indent +.It Va d_buf +Set to a valid pointer value denoting the beginning of the data area +to be translated. +.It Va d_size +Set to the total size in bytes of the source data area to be +translated. +.It Va d_type +Set to the type of the source data being translated. +This value is one of the values defined in the +.Vt Elf_Type +enumeration. +The +.Vt Elf_Type +enumeration is described in +.Xr elf 3 . +.It Va d_version +Set to the version number of the ELF data structures being +translated. +Currently only version +.Dv EV_CURRENT +is supported. +.El +.Pp +Argument +.Ar dst +describes the destination buffer. +The following elements of the +.Vt Elf_Data +descriptor need to be set before invoking these functions: +.Bl -hang -offset indent +.It Va d_buf +Set to a valid pointer value that denotes the start of the destination +buffer that will hold translated data. +This value may be the same as that of the source buffer, in which case +an in-place conversion will be attempted. +.It Va d_size +Set to the size of the destination buffer in bytes. +This value will be modified if the function call succeeds. +.It Va d_version +Set to the desired version number of the destination. +Currently only version +.Dv EV_CURRENT +is supported. +.El +.Pp +These translations routines allow the source and destination buffers +to coincide, in which case an in-place translation will be done +if the destination is large enough to hold the translated data. +Other kinds of overlap between the source and destination buffers +are not permitted. +.Pp +On successful completion of the translation request the following +fields of the +.Ar dst +descriptor would be modified: +.Bl -hang -offset indent +.It Va d_size +Set to the size in bytes of the translated data. +.It Va d_type +Set to the +.Va d_type +value of the source data descriptor. +.El +.Pp +Argument +.Ar encode +specifies the encoding in which the file objects are represented. +It must be one of: +.Bl -hang -offset indent +.It Dv ELFDATANONE +File objects use the library's native byte ordering. +.It Dv ELFDATA2LSB +File objects use a little-endian ordering. +.It Dv ELFDATA2MSB +File objects use a big-endian ordering. +.El +.Pp +The functions +.Fn gelf_xlatetof +and +.Fn gelf_xlatetom +select the appropriate 32 or 64 bit translations based on the class of argument +.Ar elf . +.Sh RETURN VALUES +These functions return argument +.Ar dst +if successful, or NULL in case of an error. +.Sh EXAMPLES +TODO +.Sh ERRORS +These functions may fail with the following errors: +.Bl -tag -width "[ELF_E_RESOURCE]" +.It Bq Er ELF_E_ARGUMENT +One of arguments +.Ar src , +.Ar dst +or +.Ar elf +was NULL. +.It Bq Er ELF_E_ARGUMENT +Arguments +.Ar src +and +.Ar dst +were equal. +.It Bq Er ELF_E_ARGUMENT +The desired encoding parameter was not one of +.Dv ELFDATANONE , +.Dv ELFDATA2LSB +or +.Dv ELFDATA2MSB . +.It Bq Er ELF_E_ARGUMENT +The +.Ar d_type +field of argument +.Ar src +specified an unsupported type. +.It Bq Er ELF_E_DATA +The +.Ar src +argument had a zero +.Va d_size +field. +.It Bq Er ELF_E_DATA +The +.Ar src +argument specified a buffer size that was not an integral multiple of +its underlying type. +.It Bq Er ELF_E_DATA +The +.Ar dst +argument specified a buffer size that was too small. +.It Bq Er ELF_E_DATA +Argument +.Ar dst +specified a destination buffer that overlaps with the source +buffer. +.It Bq Er ELF_E_DATA +The destination buffer for a conversion to memory had an alignment +inappropriate for the underlying ELF type. +.It Bq Er ELF_E_DATA +The source buffer for a conversion to file had an alignment +inappropriate for the underlying ELF type. +.It Bq Er ELF_E_UNIMPL +The version numbers for arguments +.Ar dst +and +.Ar src +were not identical. +.It Bq Er ELF_E_UNIMPL +The argument +.Ar src +requested conversion for a type which is not currently +supported. +.It Bq Er ELF_E_VERSION +Argument +.Ar src +specified an unsupported version number. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_getdata 3 , +.Xr gelf 3 diff --git a/lib/libelf/libelf.c b/lib/libelf/libelf.c new file mode 100644 index 0000000..837556e --- /dev/null +++ b/lib/libelf/libelf.c @@ -0,0 +1,61 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <machine/elf.h> +#include <machine/endian.h> + +#include <libelf.h> + +#include "_libelf.h" + +struct _libelf_globals _libelf = { + .libelf_arch = ELF_ARCH, + .libelf_byteorder = ELF_TARG_DATA, + .libelf_class = ELF_TARG_CLASS, + .libelf_error = 0, + .libelf_fillchar = 0, + .libelf_version = EV_NONE +}; + + +#if defined(LIBELF_TEST_HOOKS) +int +_libelf_get_elf_class(Elf *elf) +{ + return elf->e_class; +} + +void +_libelf_set_elf_class(Elf *elf, int c) +{ + elf->e_class = c; +} +#endif /* LIBELF_TEST_HOOKS */ diff --git a/lib/libelf/libelf.h b/lib/libelf/libelf.h new file mode 100644 index 0000000..ceb0350 --- /dev/null +++ b/lib/libelf/libelf.h @@ -0,0 +1,251 @@ +/*- + * 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 <sys/types.h> +#include <sys/elf32.h> +#include <sys/elf64.h> +#include <sys/queue.h> + +/* Library private data structures */ +typedef struct _Elf Elf; +typedef struct _Elf_Scn Elf_Scn; + +/* File types */ +typedef enum { + ELF_K_NONE = 0, + ELF_K_AR, /* `ar' archives */ + ELF_K_COFF, /* COFF files (unsupported) */ + ELF_K_ELF, /* ELF files */ + ELF_K_NUM +} Elf_Kind; + +#define ELF_K_FIRST ELF_K_NONE +#define ELF_K_LAST ELF_K_NUM + +/* Data types */ +typedef enum { + ELF_T_ADDR, + ELF_T_BYTE, + ELF_T_CAP, + ELF_T_DYN, + ELF_T_EHDR, + ELF_T_HALF, + ELF_T_LWORD, + ELF_T_MOVE, + ELF_T_MOVEP, + ELF_T_NOTE, + ELF_T_OFF, + ELF_T_PHDR, + ELF_T_REL, + ELF_T_RELA, + ELF_T_SHDR, + ELF_T_SWORD, + ELF_T_SXWORD, + ELF_T_SYMINFO, + ELF_T_SYM, + ELF_T_VDEF, + ELF_T_VNEED, + ELF_T_WORD, + ELF_T_XWORD, + ELF_T_NUM +} Elf_Type; + +#define ELF_T_FIRST ELF_T_ADDR +#define ELF_T_LAST ELF_T_XWORD + +/* Commands */ +typedef enum { + ELF_C_NULL = 0, + ELF_C_CLR, + ELF_C_FDDONE, + ELF_C_FDREAD, + ELF_C_RDWR, + ELF_C_READ, + ELF_C_SET, + ELF_C_WRITE, + ELF_C_NUM +} Elf_Cmd; + +#define ELF_C_FIRST ELF_C_NULL +#define ELF_C_LAST ELF_C_NUM + +/* + * An `Elf_Data' structure describes data in an + * ELF section. + */ +typedef struct _Elf_Data { + /* + * `Public' members that are part of the ELF(3) API. + */ + uint64_t d_align; + void *d_buf; + uint64_t d_off; + uint64_t d_size; + Elf_Type d_type; + unsigned int d_version; + + /* + * Members that are not part of the public API. + */ + Elf_Scn *d_scn; /* containing section */ + unsigned int d_flags; + STAILQ_ENTRY(_Elf_Data) d_next; +} Elf_Data; + +/* + * An `Elf_Arhdr' structure describes an archive + * header. + */ +typedef struct { + time_t ar_date; + char *ar_name; /* archive member name */ + gid_t ar_gid; + mode_t ar_mode; + char *ar_rawname; /* 'raw' member name */ + size_t ar_size; + uid_t ar_uid; +} Elf_Arhdr; + +/* + * An `Elf_Arsym' describes an entry in the archive + * symbol table. + */ +typedef struct { + off_t as_off; /* byte offset to member's header */ + unsigned long as_hash; /* elf_hash() value for name */ + char *as_name; /* null terminated symbol name */ +} Elf_Arsym; + +/* + * Error numbers. + */ + +enum Elf_Error { + ELF_E_NONE, /* No error */ + ELF_E_ARCHIVE, /* Malformed ar(1) archive */ + ELF_E_ARGUMENT, /* Invalid argument */ + ELF_E_CLASS, /* Mismatched ELF class */ + ELF_E_DATA, /* Invalid data descriptor */ + ELF_E_HEADER, /* Missing or malformed ELF header */ + ELF_E_IO, /* I/O error */ + ELF_E_LAYOUT, /* Layout constraint violation */ + ELF_E_MODE, /* Wrong mode for ELF descriptor */ + ELF_E_RANGE, /* Value out of range */ + ELF_E_RESOURCE, /* Resource exhaustion */ + ELF_E_SECTION, /* Invalid section descriptor */ + ELF_E_SEQUENCE, /* API calls out of sequence */ + ELF_E_UNIMPL, /* Feature is unimplemented */ + ELF_E_VERSION, /* Unknown API version */ + ELF_E_NUM /* Max error number */ +}; + +/* + * Flags defined by the API. + */ + +#define ELF_F_LAYOUT 0x001U /* application will layout the file */ +#define ELF_F_DIRTY 0x002U /* a section or ELF file is dirty */ + +__BEGIN_DECLS +Elf *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf); +int elf_cntl(Elf *_elf, Elf_Cmd _cmd); +int elf_end(Elf *_elf); +const char *elf_errmsg(int _error); +int elf_errno(void); +void elf_fill(int _fill); +unsigned int elf_flagdata(Elf_Data *_data, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagehdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagelf(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagphdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagscn(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); +unsigned int elf_flagshdr(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); +Elf_Arhdr *elf_getarhdr(Elf *_elf); +Elf_Arsym *elf_getarsym(Elf *_elf, size_t *_ptr); +off_t elf_getbase(Elf *_elf); +Elf_Data *elf_getdata(Elf_Scn *, Elf_Data *); +char *elf_getident(Elf *_elf, size_t *_ptr); +int elf_getphnum(Elf *_elf, size_t *_dst); +Elf_Scn *elf_getscn(Elf *_elf, size_t _index); +int elf_getshnum(Elf *_elf, size_t *_dst); +int elf_getshstrndx(Elf *_elf, size_t *_dst); +unsigned long elf_hash(const char *_name); +Elf_Kind elf_kind(Elf *_elf); +Elf *elf_memory(char *_image, size_t _size); +size_t elf_ndxscn(Elf_Scn *_scn); +Elf_Data *elf_newdata(Elf_Scn *_scn); +Elf_Scn *elf_newscn(Elf *_elf); +Elf_Scn *elf_nextscn(Elf *_elf, Elf_Scn *_scn); +Elf_Cmd elf_next(Elf *_elf); +off_t elf_rand(Elf *_elf, off_t _off); +Elf_Data *elf_rawdata(Elf_Scn *_scn, Elf_Data *_data); +char *elf_rawfile(Elf *_elf, size_t *_size); +int elf_setshstrndx(Elf *_elf, size_t _shnum); +char *elf_strptr(Elf *_elf, size_t _section, size_t _offset); +off_t elf_update(Elf *_elf, Elf_Cmd _cmd); +unsigned int elf_version(unsigned int _version); + +long elf32_checksum(Elf *_elf); +size_t elf32_fsize(Elf_Type _type, size_t _count, + unsigned int _version); +Elf32_Ehdr *elf32_getehdr(Elf *_elf); +Elf32_Phdr *elf32_getphdr(Elf *_elf); +Elf32_Shdr *elf32_getshdr(Elf_Scn *_scn); +Elf32_Ehdr *elf32_newehdr(Elf *_elf); +Elf32_Phdr *elf32_newphdr(Elf *_elf, size_t _count); +Elf_Data *elf32_xlatetof(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); +Elf_Data *elf32_xlatetom(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); + +long elf64_checksum(Elf *_elf); +size_t elf64_fsize(Elf_Type _type, size_t _count, + unsigned int _version); +Elf64_Ehdr *elf64_getehdr(Elf *_elf); +Elf64_Phdr *elf64_getphdr(Elf *_elf); +Elf64_Shdr *elf64_getshdr(Elf_Scn *_scn); +Elf64_Ehdr *elf64_newehdr(Elf *_elf); +Elf64_Phdr *elf64_newphdr(Elf *_elf, size_t _count); +Elf_Data *elf64_xlatetof(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); +Elf_Data *elf64_xlatetom(Elf_Data *_dst, const Elf_Data *_src, + unsigned int _enc); + +#if defined(LIBELF_TEST_HOOKS) +int _libelf_get_elf_class(Elf *_elf); +int _libelf_get_max_error(void); +const char *_libelf_get_no_error_message(void); +const char *_libelf_get_unknown_error_message(void); +void _libelf_set_elf_class(Elf *_elf, int _class); +void _libelf_set_error(int _error); +#endif /* LIBELF_TEST_HOOKS */ +__END_DECLS + +#endif /* _LIBELF_H_ */ diff --git a/lib/libelf/libelf_align.c b/lib/libelf/libelf_align.c new file mode 100644 index 0000000..4d37255 --- /dev/null +++ b/lib/libelf/libelf_align.c @@ -0,0 +1,154 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> + +#include <machine/elf.h> +#include <machine/endian.h> + +#include <libelf.h> +#include <osreldate.h> + +#include "_libelf.h" + +struct align { + int a32; + int a64; +}; + +#ifdef __GNUC__ +#define MALIGN(N) { \ + .a32 = __alignof__(Elf32_##N), \ + .a64 = __alignof__(Elf64_##N) \ + } +#define MALIGN64(V) { \ + .a32 = 0, \ + .a64 = __alignof__(Elf64_##V) \ + } +#else +#error Need the __alignof__ builtin. +#endif +#define UNSUPPORTED() { \ + .a32 = 0, \ + .a64 = 0 \ + } + +static struct align malign[ELF_T_NUM] = { + [ELF_T_ADDR] = MALIGN(Addr), + [ELF_T_BYTE] = { .a32 = 1, .a64 = 1 }, +#if __FreeBSD_version >= 700009 + [ELF_T_CAP] = MALIGN(Cap), +#endif + [ELF_T_DYN] = MALIGN(Dyn), + [ELF_T_EHDR] = MALIGN(Ehdr), + [ELF_T_HALF] = MALIGN(Half), +#if __FreeBSD_version >= 700009 + [ELF_T_LWORD] = MALIGN(Lword), + [ELF_T_MOVE] = MALIGN(Move), +#endif + [ELF_T_MOVEP] = UNSUPPORTED(), +#if __FreeBSD_version >= 700009 + [ELF_T_NOTE] = MALIGN(Nhdr), +#endif + [ELF_T_OFF] = MALIGN(Off), + [ELF_T_PHDR] = MALIGN(Phdr), + [ELF_T_REL] = MALIGN(Rel), + [ELF_T_RELA] = MALIGN(Rela), + [ELF_T_SHDR] = MALIGN(Shdr), + [ELF_T_SWORD] = MALIGN(Sword), + [ELF_T_SXWORD] = MALIGN64(Sxword), + [ELF_T_SYM] = MALIGN(Sym), +#if __FreeBSD_version >= 700009 + [ELF_T_SYMINFO] = MALIGN(Syminfo), +#endif +#if __FreeBSD_version >= 700009 + [ELF_T_VDEF] = MALIGN(Verdef), + [ELF_T_VNEED] = MALIGN(Verneed), +#endif + [ELF_T_WORD] = MALIGN(Word), + [ELF_T_XWORD] = MALIGN64(Xword) +}; + +int +_libelf_malign(Elf_Type t, int elfclass) +{ + if (t >= ELF_T_NUM || (int) t < 0) + return (0); + + return (elfclass == ELFCLASS32 ? malign[t].a32 : + malign[t].a64); +} + +#define FALIGN(A32,A64) { .a32 = (A32), .a64 = (A64) } + +static struct align falign[ELF_T_NUM] = { + [ELF_T_ADDR] = FALIGN(4,8), + [ELF_T_BYTE] = FALIGN(1,1), +#if __FreeBSD_version >= 700009 + [ELF_T_CAP] = FALIGN(4,8), +#endif + [ELF_T_DYN] = FALIGN(4,8), + [ELF_T_EHDR] = FALIGN(4,8), + [ELF_T_HALF] = FALIGN(2,2), +#if __FreeBSD_version >= 700009 + [ELF_T_LWORD] = FALIGN(8,8), + [ELF_T_MOVE] = FALIGN(8,8), +#endif + [ELF_T_MOVEP] = UNSUPPORTED(), +#if __FreeBSD_version >= 700009 + [ELF_T_NOTE] = FALIGN(4,4), +#endif + [ELF_T_OFF] = FALIGN(4,8), + [ELF_T_PHDR] = FALIGN(4,8), + [ELF_T_REL] = FALIGN(4,8), + [ELF_T_RELA] = FALIGN(4,8), + [ELF_T_SHDR] = FALIGN(4,8), + [ELF_T_SWORD] = FALIGN(4,4), + [ELF_T_SXWORD] = FALIGN(0,8), + [ELF_T_SYM] = FALIGN(4,8), +#if __FreeBSD_version >= 700009 + [ELF_T_SYMINFO] = FALIGN(2,2), +#endif +#if __FreeBSD_version >= 700009 + [ELF_T_VDEF] = FALIGN(4,4), + [ELF_T_VNEED] = FALIGN(4,4), +#endif + [ELF_T_WORD] = FALIGN(4,4), + [ELF_T_XWORD] = FALIGN(0,8) +}; + +int +_libelf_falign(Elf_Type t, int elfclass) +{ + if (t >= ELF_T_NUM || (int) t < 0) + return (0); + + return (elfclass == ELFCLASS32 ? falign[t].a32 : + falign[t].a64); +} diff --git a/lib/libelf/libelf_allocate.c b/lib/libelf/libelf_allocate.c new file mode 100644 index 0000000..834e0dd --- /dev/null +++ b/lib/libelf/libelf_allocate.c @@ -0,0 +1,209 @@ +/*- + * 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. + */ + +/* + * Internal APIs + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/errno.h> + +#include <assert.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> + +#include "_libelf.h" + +Elf * +_libelf_allocate_elf(void) +{ + Elf *e; + + if ((e = malloc(sizeof(*e))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return NULL; + } + + e->e_activations = 1; + e->e_arhdr = NULL; + e->e_byteorder = ELFDATANONE; + e->e_class = ELFCLASSNONE; + e->e_cmd = ELF_C_NULL; + e->e_fd = -1; + e->e_flags = 0; + e->e_kind = ELF_K_NONE; + e->e_parent = NULL; + e->e_rawfile = NULL; + e->e_rawsize = 0; + e->e_version = LIBELF_PRIVATE(version); + + (void) memset(&e->e_u, 0, sizeof(e->e_u)); + + return (e); +} + +void +_libelf_init_elf(Elf *e, Elf_Kind kind) +{ + assert(e != NULL); + assert(e->e_kind == ELF_K_NONE); + + e->e_kind = kind; + + switch (kind) { + case ELF_K_ELF: + STAILQ_INIT(&e->e_u.e_elf.e_scn); + break; + default: + break; + } +} + +#define FREE(P) do { \ + if (P) \ + free(P); \ + } while (0) + + +Elf * +_libelf_release_elf(Elf *e) +{ + switch (e->e_kind) { + case ELF_K_AR: + FREE(e->e_u.e_ar.e_symtab); + break; + + case ELF_K_ELF: + switch (e->e_class) { + case ELFCLASS32: + FREE(e->e_u.e_elf.e_ehdr.e_ehdr32); + FREE(e->e_u.e_elf.e_phdr.e_phdr32); + break; + case ELFCLASS64: + FREE(e->e_u.e_elf.e_ehdr.e_ehdr64); + FREE(e->e_u.e_elf.e_phdr.e_phdr64); + break; + } + + assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + + if (e->e_arhdr) { + FREE(e->e_arhdr->ar_name); + FREE(e->e_arhdr->ar_rawname); + free(e->e_arhdr); + } + + break; + + default: + break; + } + + free(e); + + return (NULL); +} + +Elf_Data * +_libelf_allocate_data(Elf_Scn *s) +{ + Elf_Data *d; + + if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + d->d_scn = s; + + return (d); +} + +Elf_Data * +_libelf_release_data(Elf_Data *d) +{ + + if (d->d_flags & LIBELF_F_MALLOCED) + free(d->d_buf); + + free(d); + + return (NULL); +} + +Elf_Scn * +_libelf_allocate_scn(Elf *e, size_t ndx) +{ + Elf_Scn *s; + + if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, errno); + return (NULL); + } + + s->s_elf = e; + s->s_ndx = ndx; + + STAILQ_INIT(&s->s_data); + STAILQ_INIT(&s->s_rawdata); + + STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); + + return (s); +} + +Elf_Scn * +_libelf_release_scn(Elf_Scn *s) +{ + Elf *e; + Elf_Data *d, *td; + + assert(s != NULL); + + STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { + STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next); + d = _libelf_release_data(d); + } + + STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { + assert((d->d_flags & LIBELF_F_MALLOCED) == 0); + STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next); + d = _libelf_release_data(d); + } + + e = s->s_elf; + + assert(e != NULL); + + STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); + + free(s); + + return (NULL); +} diff --git a/lib/libelf/libelf_ar.c b/lib/libelf/libelf_ar.c new file mode 100644 index 0000000..e8cfc7f --- /dev/null +++ b/lib/libelf/libelf_ar.c @@ -0,0 +1,463 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ar.h> +#include <assert.h> +#include <ctype.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> + +#include "_libelf.h" + +#define LIBELF_NALLOC_SIZE 16 + +/* + * `ar' archive handling. + * + * `ar' archives start with signature `ARMAG'. Each archive member is + * preceded by a header containing meta-data for the member. This + * header is described in <ar.h> (struct ar_hdr). The header always + * starts on an even address. File data is padded with "\n" + * characters to keep this invariant. + * + * Special considerations for `ar' archives: + * + * The `ar' header only has space for a 16 character file name. File + * names are terminated with a '/', so this effectively leaves 15 + * characters for the actual file name. In order to accomodate longer + * file names, names may be stored in a separate 'string table' and + * referenced indirectly by a member header. The string table itself + * appears as an archive member with name "// ". An indirect file name + * in an `ar' header matches the pattern "/[0-9]*". The digits form a + * decimal number that corresponds to a byte offset into the string + * table where the actual file name of the object starts. Strings in + * the string table are padded to start on even addresses. + * + * Archives may also have a symbol table (see ranlib(1)), mapping + * program symbols to object files inside the archive. A symbol table + * uses a file name of "/ " in its archive header. The symbol table + * is structured as: + * - a 4-byte count of entries stored as a binary value, MSB first + * - 'n' 4-byte offsets, stored as binary values, MSB first + * - 'n' NUL-terminated strings, for ELF symbol names, stored unpadded. + * + * If the symbol table and string table are is present in an archive + * they must be the very first objects and in that order. + */ + +/* + * Convert a string bounded by `start' and `start+sz' (exclusive) to a + * number in the specified base. + */ +static int +_libelf_ar_get_number(char *s, size_t sz, int base, size_t *ret) +{ + int c, v; + size_t r; + char *e; + + assert(base <= 10); + + e = s + sz; + + /* skip leading blanks */ + for (;s < e && (c = *s) == ' '; s++) + ; + + r = 0L; + for (;s < e; s++) { + if ((c = *s) == ' ') + break; + if (c < '0' || c > '9') + return (0); + v = c - '0'; + if (v >= base) /* illegal digit */ + break; + r *= base; + r += v; + } + + *ret = r; + + return (1); +} + +/* + * Retrieve a string from a name field. If `rawname' is set, leave + * ar(1) control characters in. + */ +static char * +_libelf_ar_get_string(char *buf, size_t bufsize, int rawname) +{ + char *q, *r; + + q = buf + bufsize; + + /* Skip trailing blanks. */ + for (q = buf + bufsize - 1; q > buf && *q == ' '; --q) + ; + + if (rawname == 0 && *q == '/') + q--; + + if (q <= buf) + return (NULL); + + if ((r = malloc(q - buf + 2)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + (void) strlcpy(r, buf, q - buf + 2); + + return (r); +} + +/* + * Retrieve the full name of the archive member. + */ +static char * +_libelf_ar_get_name(char *buf, size_t bufsize, Elf *e) +{ + char *q, *r, *s; + size_t len; + size_t offset; + + assert(e->e_kind == ELF_K_AR); + + if (buf[0] == '/') { + /* + * The value in field ar_name is a decimal offset into + * the archive string table where the actual name + * resides. + */ + if (_libelf_ar_get_number(buf + 1, bufsize - 1, 10, &offset) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + if (offset > e->e_u.e_ar.e_rawstrtabsz) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + s = q = e->e_u.e_ar.e_rawstrtab + offset; + r = e->e_u.e_ar.e_rawstrtab + e->e_u.e_ar.e_rawstrtabsz; + + for (s = q; s < r && *s != '/'; s++) + ; + len = s - q + 1; /* space for the trailing NUL */ + + if ((s = malloc(len)) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + (void) strlcpy(s, q, len); + + return (s); + } + + /* + * Normal 'name' + */ + return (_libelf_ar_get_string(buf, bufsize, 0)); +} + + +Elf_Arhdr * +_libelf_ar_gethdr(Elf *e) +{ + Elf *parent; + struct ar_hdr *arh; + Elf_Arhdr *eh; + size_t n; + + if ((parent = e->e_parent) == NULL) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + arh = (struct ar_hdr *) ((uintptr_t) e->e_rawfile - sizeof(struct ar_hdr)); + + assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG); + assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile + parent->e_rawsize - + sizeof(struct ar_hdr)); + + if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + e->e_arhdr = eh; + eh->ar_name = eh->ar_rawname = NULL; + + if ((eh->ar_name = _libelf_ar_get_name(arh->ar_name, sizeof(arh->ar_name), + parent)) == NULL) + goto error; + + if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10, &n) == 0) + goto error; + eh->ar_uid = (uid_t) n; + + if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10, &n) == 0) + goto error; + eh->ar_gid = (gid_t) n; + + if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8, &n) == 0) + goto error; + eh->ar_mode = (mode_t) n; + + if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &n) == 0) + goto error; + eh->ar_size = n; + + if ((eh->ar_rawname = _libelf_ar_get_string(arh->ar_name, + sizeof(arh->ar_name), 1)) == NULL) + goto error; + + return (eh); + + error: + if (eh) { + if (eh->ar_name) + free(eh->ar_name); + if (eh->ar_rawname) + free(eh->ar_rawname); + free(eh); + } + e->e_arhdr = NULL; + + return (NULL); +} + +Elf * +_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf) +{ + Elf *e; + off_t next; + struct ar_hdr *arh; + size_t sz; + + assert(elf->e_kind == ELF_K_AR); + + next = elf->e_u.e_ar.e_next; + + /* + * `next' is only set to zero by elf_next() when the last + * member of an archive is processed. + */ + if (next == (off_t) 0) + return (NULL); + + assert((next & 1) == 0); + + arh = (struct ar_hdr *) (elf->e_rawfile + next); + + if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &sz) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + assert(sz > 0); + + arh++; /* skip over archive member header */ + + if ((e = elf_memory((char *) arh, sz)) == NULL) + return (NULL); + + e->e_fd = fd; + e->e_cmd = c; + + elf->e_u.e_ar.e_nchildren++; + e->e_parent = elf; + + return (e); +} + +Elf * +_libelf_ar_open(Elf *e) +{ + int i; + char *s, *end; + size_t sz; + struct ar_hdr arh; + + e->e_kind = ELF_K_AR; + e->e_u.e_ar.e_nchildren = 0; + e->e_u.e_ar.e_next = (off_t) -1; + + /* + * Look for special members. + */ + + s = e->e_rawfile + SARMAG; + end = e->e_rawfile + e->e_rawsize; + + assert(e->e_rawsize > 0); + + /* + * Look for magic names "/ " and "// " in the first two entries + * of the archive. + */ + for (i = 0; i < 2; i++) { + + if (s + sizeof(arh) > end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + (void) memcpy(&arh, s, sizeof(arh)); + + if (arh.ar_fmag[0] != '`' || arh.ar_fmag[1] != '\n') { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + if (arh.ar_name[0] != '/') /* not a special symbol */ + break; + + if (_libelf_ar_get_number(arh.ar_size, sizeof(arh.ar_size), 10, &sz) == 0) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + assert(sz > 0); + + s += sizeof(arh); + + if (arh.ar_name[1] == ' ') { /* "/ " => symbol table */ + + e->e_u.e_ar.e_rawsymtab = s; + e->e_u.e_ar.e_rawsymtabsz = sz; + + } else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') { + + /* "// " => string table for long file names */ + e->e_u.e_ar.e_rawstrtab = s; + e->e_u.e_ar.e_rawstrtabsz = sz; + } + + sz = LIBELF_ADJUST_AR_SIZE(sz); + + s += sz; + } + + e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile); + + return (e); +} + +/* + * An ar(1) symbol table has the following layout: + * + * The first 4 bytes are a binary count of the number of entries in the + * symbol table, stored MSB-first. + * + * Then there are 'n' 4-byte binary offsets, also stored MSB first. + * + * Following this, there are 'n' null-terminated strings. + */ + +#define GET_WORD(P, V) do { \ + (V) = 0; \ + (V) = (P)[0]; (V) <<= 8; \ + (V) += (P)[1]; (V) <<= 8; \ + (V) += (P)[2]; (V) <<= 8; \ + (V) += (P)[3]; \ + } while (0) + +#define INTSZ 4 + +Elf_Arsym * +_libelf_ar_process_symtab(Elf *e, size_t *count) +{ + size_t n, nentries, off; + Elf_Arsym *symtab, *sym; + unsigned char *p, *s, *end; + + assert(e != NULL); + assert(count != NULL); + + if (e->e_u.e_ar.e_rawsymtabsz < INTSZ) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + p = (unsigned char *) e->e_u.e_ar.e_rawsymtab; + end = p + e->e_u.e_ar.e_rawsymtabsz; + + GET_WORD(p, nentries); + p += INTSZ; + + if (nentries == 0 || p + nentries * INTSZ >= end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + return (NULL); + } + + /* Allocate space for a nentries + a sentinel. */ + if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries+1))) == NULL) { + LIBELF_SET_ERROR(RESOURCE, 0); + return (NULL); + } + + s = p + (nentries * INTSZ); /* start of the string table. */ + + for (n = nentries, sym = symtab; n > 0; n--) { + off = 0; + + GET_WORD(p, off); + + sym->as_off = off; + sym->as_hash = elf_hash(s); + sym->as_name = s; + + p += INTSZ; + sym++; + + for (; s < end && *s++ != '\0';) /* skip to next string */ + ; + if (s > end) { + LIBELF_SET_ERROR(ARCHIVE, 0); + free(symtab); + return (NULL); + } + } + + /* Fill up the sentinel entry. */ + sym->as_name = NULL; + sym->as_hash = ~0UL; + sym->as_off = (off_t) 0; + + *count = e->e_u.e_ar.e_symtabsz = nentries + 1; + e->e_u.e_ar.e_symtab = symtab; + + return (symtab); +} diff --git a/lib/libelf/libelf_checksum.c b/lib/libelf/libelf_checksum.c new file mode 100644 index 0000000..3210412 --- /dev/null +++ b/lib/libelf/libelf_checksum.c @@ -0,0 +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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> + +#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++) { + 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)); +} diff --git a/lib/libelf/libelf_convert.m4 b/lib/libelf/libelf_convert.m4 new file mode 100644 index 0000000..0eb0b70 --- /dev/null +++ b/lib/libelf/libelf_convert.m4 @@ -0,0 +1,668 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/elf32.h> +#include <sys/elf64.h> + +#include <assert.h> +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + +/* WARNING: GENERATED FROM __file__. */ + +/* + * Macros to swap various integral quantities. + */ + +#define SWAP_HALF(X) do { \ + uint16_t _x = (uint16_t) (X); \ + uint16_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_WORD(X) do { \ + uint32_t _x = (uint32_t) (X); \ + uint32_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_ADDR32(X) SWAP_WORD(X) +#define SWAP_OFF32(X) SWAP_WORD(X) +#define SWAP_SWORD(X) SWAP_WORD(X) +#define SWAP_WORD64(X) do { \ + uint64_t _x = (uint64_t) (X); \ + uint64_t _t = _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ + (X) = _t; \ + } while (0) +#define SWAP_ADDR64(X) SWAP_WORD64(X) +#define SWAP_LWORD(X) SWAP_WORD64(X) +#define SWAP_OFF64(X) SWAP_WORD64(X) +#define SWAP_SXWORD(X) SWAP_WORD64(X) +#define SWAP_XWORD(X) SWAP_WORD64(X) + +/* + * Write out various integral values. The destination pointer could + * be unaligned. Values are written out in native byte order. The + * destination pointer is incremented after the write. + */ +#define WRITE_BYTE(P,X) do { \ + unsigned char *const _p = (unsigned char *) (P); \ + _p[0] = (unsigned char) (X); \ + (P) = _p + 1; \ + } while (0) +#define WRITE_HALF(P,X) do { \ + uint16_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + (P) = _p + 2; \ + } while (0) +#define WRITE_WORD(P,X) do { \ + uint32_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + _p[2] = _q[2]; \ + _p[3] = _q[3]; \ + (P) = _p + 4; \ + } while (0) +#define WRITE_ADDR32(P,X) WRITE_WORD(P,X) +#define WRITE_OFF32(P,X) WRITE_WORD(P,X) +#define WRITE_SWORD(P,X) WRITE_WORD(P,X) +#define WRITE_WORD64(P,X) do { \ + uint64_t _t = (X); \ + unsigned char *const _p = (unsigned char *) (P); \ + unsigned const char *const _q = (unsigned char *) &_t; \ + _p[0] = _q[0]; \ + _p[1] = _q[1]; \ + _p[2] = _q[2]; \ + _p[3] = _q[3]; \ + _p[4] = _q[4]; \ + _p[5] = _q[5]; \ + _p[6] = _q[6]; \ + _p[7] = _q[7]; \ + (P) = _p + 8; \ + } while (0) +#define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) +#define WRITE_LWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_OFF64(P,X) WRITE_WORD64(P,X) +#define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_XWORD(P,X) WRITE_WORD64(P,X) +#define WRITE_IDENT(P,X) do { \ + (void) memcpy((P), (X), sizeof((X))); \ + (P) = (P) + EI_NIDENT; \ + } while (0) + +/* + * Read in various integral values. The source pointer could be + * unaligned. Values are read in in native byte order. The source + * pointer is incremented appropriately. + */ + +#define READ_BYTE(P,X) do { \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + (X) = _p[0]; \ + (P) = (P) + 1; \ + } while (0) +#define READ_HALF(P,X) do { \ + uint16_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + (P) = (P) + 2; \ + (X) = _t; \ + } while (0) +#define READ_WORD(P,X) do { \ + uint32_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + _q[2] = _p[2]; \ + _q[3] = _p[3]; \ + (P) = (P) + 4; \ + (X) = _t; \ + } while (0) +#define READ_ADDR32(P,X) READ_WORD(P,X) +#define READ_OFF32(P,X) READ_WORD(P,X) +#define READ_SWORD(P,X) READ_WORD(P,X) +#define READ_WORD64(P,X) do { \ + uint64_t _t; \ + unsigned char *const _q = (unsigned char *) &_t; \ + const unsigned char *const _p = \ + (const unsigned char *) (P); \ + _q[0] = _p[0]; \ + _q[1] = _p[1]; \ + _q[2] = _p[2]; \ + _q[3] = _p[3]; \ + _q[4] = _p[4]; \ + _q[5] = _p[5]; \ + _q[6] = _p[6]; \ + _q[7] = _p[7]; \ + (P) = (P) + 8; \ + (X) = _t; \ + } while (0) +#define READ_ADDR64(P,X) READ_WORD64(P,X) +#define READ_LWORD(P,X) READ_WORD64(P,X) +#define READ_OFF64(P,X) READ_WORD64(P,X) +#define READ_SXWORD(P,X) READ_WORD64(P,X) +#define READ_XWORD(P,X) READ_WORD64(P,X) +#define READ_IDENT(P,X) do { \ + (void) memcpy((X), (P), sizeof((X))); \ + (P) = (P) + EI_NIDENT; \ + } while (0) + +#define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) + +divert(-1) + +/* + * Generate conversion routines for converting between in-memory and + * file representations of Elf data structures. + * + * `In-memory' representations of an Elf data structure use natural + * alignments and native byte ordering. This allows arithmetic and + * casting to work as expected. On the other hand the `file' + * representation of an ELF data structure could be packed tighter + * than its `in-memory' representation, and could be of a differing + * byte order. An additional complication is that `ar' only pads data + * to even addresses and so ELF archive member data being read from + * inside an `ar' archive could end up at misaligned memory addresses. + * + * Consequently, casting the `char *' pointers that point to memory + * representations (i.e., source pointers for the *_tof() functions + * and the destination pointers for the *_tom() functions), is safe, + * as these pointers should be correctly aligned for the memory type + * already. However, pointers to file representations have to be + * treated as being potentially unaligned and no casting can be done. + */ + +include(SRCDIR`/elf_types.m4') + +/* + * `IGNORE'_* flags turn off generation of template code. + */ + +define(`IGNORE', + `define(IGNORE_$1`'32, 1) + define(IGNORE_$1`'64, 1)') + +IGNORE(MOVEP) +IGNORE(NOTE) + +ifelse(eval(OSRELDATE < 700009),1, + `IGNORE(CAP) + IGNORE(MOVE) + IGNORE(SYMINFO) + IGNORE(VDEF) + IGNORE(VNEED) + define(`IGNORE_LWORD', 1)', + `') + +define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ +define(IGNORE_NOTE, 1) +define(IGNORE_SXWORD32, 1) +define(IGNORE_XWORD32, 1) + +/* + * `BASE'_XXX flags cause class agnostic template functions + * to be generated. + */ + +define(`BASE_BYTE', 1) +define(`BASE_HALF', 1) +define(`BASE_NOTE', 1) +define(`BASE_WORD', 1) +define(`BASE_LWORD', 1) +define(`BASE_SWORD', 1) +define(`BASE_XWORD', 1) +define(`BASE_SXWORD', 1) + +/* + * `SIZEDEP'_XXX flags cause 32/64 bit variants to be generated + * for each primitive type. + */ + +define(`SIZEDEP_ADDR', 1) +define(`SIZEDEP_OFF', 1) + +/* + * `Primitive' ELF types are those that are an alias for an integral + * type. They have no internal structure. These can be copied using + * a `memcpy()', and byteswapped in straightforward way. + * + * Macro use: + * `$1': Name of the ELF type. + * `$2': C structure name suffix + * `$3': ELF class specifier for symbols, one of [`', `32', `64'] + * `$4': ELF class specifier for types, one of [`32', `64'] + */ +define(`MAKEPRIM_TO_F',` +static void +libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap) +{ + Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; + size_t c; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count * sizeof(*s)); + return; + } + + for (c = 0; c < count; c++) { + t = *s++; + SWAP_$1$3(t); + WRITE_$1$3(dst,t); + } +} +') + +define(`MAKEPRIM_TO_M',` +static void +libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap) +{ + Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; + size_t c; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count * sizeof(*d)); + return; + } + + for (c = 0; c < count; c++) { + READ_$1$3(src,t); + SWAP_$1$3(t); + *d++ = t; + } +} +') + +define(`SWAP_FIELD', + `ifdef(`IGNORE_'$2,`', + `ifelse(BASE_$2,1, + `SWAP_$2(t.$1); + ', + `ifelse($2,BYTE,`', + `ifelse($2,IDENT,`', + `SWAP_$2'SZ()`(t.$1); + ')')')')') +define(`SWAP_MEMBERS', + `ifelse($#,1,`/**/', + `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') + +define(`SWAP_STRUCT', + `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ + SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +define(`WRITE_FIELD', + `ifelse(BASE_$2,1, + `WRITE_$2(dst,t.$1); + ', + `ifelse($2,IDENT, + `WRITE_$2(dst,t.$1); + ', + `WRITE_$2'SZ()`(dst,t.$1); + ')')') +define(`WRITE_MEMBERS', + `ifelse($#,1,`/**/', + `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') + +define(`WRITE_STRUCT', + `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ + WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +define(`READ_FIELD', + `ifelse(BASE_$2,1, + `READ_$2(s,t.$1); + ', + `ifelse($2,IDENT, + `READ_$2(s,t.$1); + ', + `READ_$2'SZ()`(s,t.$1); + ')')') + +define(`READ_MEMBERS', + `ifelse($#,1,`/**/', + `READ_FIELD($1)READ_MEMBERS(shift($@))')') + +define(`READ_STRUCT', + `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ + READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') + +/* + * Converters for non-integral ELF data structures. + * + * When converting data to file representation, the source pointer + * will be naturally aligned for a data structure's in-memory + * representation. When converting data to memory, the destination + * pointer will be similarly aligned. + * + * For in-place conversions, when converting to file representations, + * the source buffer is large enough to hold `file' data. When + * converting from file to memory, we need to be careful to work + * `backwards', to avoid overwriting unconverted data. + * + * Macro use: + * `$1': Name of the ELF type. + * `$2': C structure name suffix. + * `$3': ELF class specifier, one of [`', `32', `64'] + */ + +define(`MAKE_TO_F', + `ifdef(`IGNORE_'$1$3,`',` +static void +libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap) +{ + Elf$3_$2 t, *s; + size_t c; + + s = (Elf$3_$2 *) (uintptr_t) src; + for (c = 0; c < count; c++) { + t = *s++; + if (byteswap) { + SWAP_STRUCT($2,$3) + } + WRITE_STRUCT($2,$3) + } +} +')') + +define(`MAKE_TO_M', + `ifdef(`IGNORE_'$1$3,`',` +static void +libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap) +{ + Elf$3_$2 t, *d; + unsigned char *s,*s0; + size_t fsz; + + fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); + d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); + s0 = (unsigned char *) src + (count - 1) * fsz; + + while (count--) { + s = s0; + READ_STRUCT($2,$3) + if (byteswap) { + SWAP_STRUCT($2,$3) + } + *d-- = t; s0 -= fsz; + } +} +')') + +/* + * Make type convertor functions from the type definition + * of the ELF type: + * - if the type is a base (i.e., `primitive') type: + * - if it is marked as to be ignored (i.e., `IGNORE_'TYPE) + * is defined, we skip the code generation step. + * - if the type is declared as `SIZEDEP', then 32 and 64 bit + * variants of the conversion functions are generated. + * - otherwise a 32 bit variant is generated. + * - if the type is a structure type, we generate 32 and 64 bit + * variants of the conversion functions. + */ + +define(`MAKE_TYPE_CONVERTER', + `ifdef(`BASE'_$1, + `ifdef(`IGNORE_'$1,`', + `MAKEPRIM_TO_F($1,$2,`',64) + MAKEPRIM_TO_M($1,$2,`',64)')', + `ifdef(`SIZEDEP_'$1, + `MAKEPRIM_TO_F($1,$2,32,32)dnl + MAKEPRIM_TO_M($1,$2,32,32)dnl + MAKEPRIM_TO_F($1,$2,64,64)dnl + MAKEPRIM_TO_M($1,$2,64,64)', + `MAKE_TO_F($1,$2,32)dnl + MAKE_TO_F($1,$2,64)dnl + MAKE_TO_M($1,$2,32)dnl + MAKE_TO_M($1,$2,64)')')') + +define(`MAKE_TYPE_CONVERTERS', + `ifelse($#,1,`', + `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') + +divert(0) + +/* + * Sections of type ELF_T_BYTE are never byteswapped, consequently a + * simple memcpy suffices for both directions of conversion. + */ + +static void +libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap) +{ + (void) byteswap; + if (dst != src) + (void) memcpy(dst, src, count); +} + +/* + * Elf_Note structures comprise a fixed size header followed by variable + * length strings. The fixed size header needs to be byte swapped, but + * not the strings. + * + * Argument `count' denotes the total number of bytes to be converted. + */ +static void +libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t namesz, descsz, type; + Elf_Note *en; + size_t sz; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + while (count > sizeof(Elf_Note)) { + + READ_WORD(src, namesz); + READ_WORD(src, descsz); + READ_WORD(src, type); + + if (byteswap) { + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); + } + + en = (Elf_Note *) (uintptr_t) dst; + en->n_namesz = namesz; + en->n_descsz = descsz; + en->n_type = type; + + dst += sizeof(Elf_Note); + + ROUNDUP2(namesz, 4); + ROUNDUP2(descsz, 4); + + sz = namesz + descsz; + + if (count < sz) + sz = count; + + (void) memcpy(dst, src, sz); + + src += sz; + dst += sz; + count -= sz; + } +} + +static void +libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t namesz, descsz, type; + Elf_Note *en; + size_t sz; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + while (count > sizeof(Elf_Note)) { + + en = (Elf_Note *) (uintptr_t) src; + namesz = en->n_namesz; + descsz = en->n_descsz; + type = en->n_type; + + if (byteswap) { + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); + } + + + WRITE_WORD(dst, namesz); + WRITE_WORD(dst, descsz); + WRITE_WORD(dst, type); + + src += sizeof(Elf_Note); + + ROUNDUP2(namesz, 4); + ROUNDUP2(descsz, 4); + + sz = namesz + descsz; + + if (count < sz) + sz = count; + + (void) memcpy(dst, src, sz); + + src += sz; + dst += sz; + count -= sz; + } +} + +MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) + +struct converters { + void (*tof32)(char *dst, char *src, size_t cnt, int byteswap); + void (*tom32)(char *dst, char *src, size_t cnt, int byteswap); + void (*tof64)(char *dst, char *src, size_t cnt, int byteswap); + void (*tom64)(char *dst, char *src, size_t cnt, int byteswap); +}; + +divert(-1) +define(`CONV', + `ifdef(`IGNORE_'$1$2, + `.$3$2 = NULL', + `ifdef(`BASE_'$1, + `ifdef(`IGNORE_'$1, + `.$3$2 = NULL', + `.$3$2 = libelf_cvt_$1_$3')', + `ifdef(`SIZEDEP_'$1, + `.$3$2 = libelf_cvt_$1$2_$3', + `.$3$2 = libelf_cvt$2_$1_$3')')')') + +define(`CONVERTER_NAME', + `[ELF_T_$1] = { + CONV($1,32,tof), CONV($1,32,tom), + CONV($1,64,tof), CONV($1,64,tom) }, +')') + +define(`CONVERTER_NAMES', + `ifelse($#,1,`', + `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') + +undefine(`IGNORE_BYTE32', `IGNORE_BYTE64') +divert(0) + +static struct converters cvt[ELF_T_NUM] = { +CONVERTER_NAMES(ELF_TYPE_LIST) + + /* + * Types that needs hand-coded converters follow. + */ + + [ELF_T_BYTE] = { + .tof32 = libelf_cvt_BYTE_tox, + .tom32 = libelf_cvt_BYTE_tox, + .tof64 = libelf_cvt_BYTE_tox, + .tom64 = libelf_cvt_BYTE_tox + }, + [ELF_T_NOTE] = { + .tof32 = libelf_cvt_NOTE_tof, + .tom32 = libelf_cvt_NOTE_tom, + .tof64 = libelf_cvt_NOTE_tof, + .tom64 = libelf_cvt_NOTE_tom + } +}; + +void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) + (char *_dst, char *_src, size_t _cnt, int _byteswap) +{ + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); + + if (t >= ELF_T_NUM || + (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || + (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) + return (NULL); + + return ((elfclass == ELFCLASS32) ? + (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : + (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); +} diff --git a/lib/libelf/libelf_data.c b/lib/libelf/libelf_data.c new file mode 100644 index 0000000..4bab441 --- /dev/null +++ b/lib/libelf/libelf_data.c @@ -0,0 +1,85 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <libelf.h> +#include <osreldate.h> + +#include "_libelf.h" + +int +_libelf_xlate_shtype(uint32_t sht) +{ + switch (sht) { + case SHT_DYNAMIC: + return (ELF_T_DYN); + case SHT_DYNSYM: + return (ELF_T_SYM); + case SHT_FINI_ARRAY: + return (ELF_T_ADDR); + case SHT_GROUP: + return (ELF_T_WORD); + case SHT_HASH: + return (ELF_T_WORD); + case SHT_INIT_ARRAY: + return (ELF_T_ADDR); + case SHT_NOBITS: + return (ELF_T_BYTE); + case SHT_NOTE: + return (ELF_T_NOTE); + case SHT_PREINIT_ARRAY: + return (ELF_T_ADDR); + case SHT_PROGBITS: + return (ELF_T_BYTE); + case SHT_REL: + return (ELF_T_REL); + case SHT_RELA: + return (ELF_T_RELA); + case SHT_STRTAB: + return (ELF_T_BYTE); + case SHT_SYMTAB: + return (ELF_T_SYM); + case SHT_SYMTAB_SHNDX: + return (ELF_T_WORD); +#if __FreeBSD_version > 700009 + case SHT_GNU_verdef: /* == SHT_SUNW_verdef */ + return (ELF_T_VDEF); + case SHT_GNU_verneed: /* == SHT_SUNW_verneed */ + return (ELF_T_VNEED); + case SHT_GNU_versym: /* == SHT_SUNW_versym */ + return (-1); /* XXX */ + case SHT_SUNW_move: + return (ELF_T_MOVE); + case SHT_SUNW_syminfo: + return (ELF_T_SYMINFO); +#endif + default: + return (-1); + } +} + diff --git a/lib/libelf/libelf_ehdr.c b/lib/libelf/libelf_ehdr.c new file mode 100644 index 0000000..6c938b3 --- /dev/null +++ b/lib/libelf/libelf_ehdr.c @@ -0,0 +1,125 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <gelf.h> +#include <libelf.h> +#include <stdlib.h> + +#include "_libelf.h" + +#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; + 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); + + 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)); + + return (ehdr); +} diff --git a/lib/libelf/libelf_fsize.m4 b/lib/libelf/libelf_fsize.m4 new file mode 100644 index 0000000..93d1d92 --- /dev/null +++ b/lib/libelf/libelf_fsize.m4 @@ -0,0 +1,160 @@ +/*- + * 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 <libelf.h> + +#include "_libelf.h" + +/* + * Create an array of file sizes from the elf_type definitions + */ + +divert(-1) +include(SRCDIR`/elf_types.m4') + +/* + * Translations from structure definitions to the size of their file + * representations. + */ + +/* `Basic' types */ +define(`BYTE_SIZE', 1) +define(`IDENT_SIZE', `EI_NIDENT') +define(`NOTE_SIZE', 1) /* Elf_Note structures have variable length. */ + +/* Currently unimplemented types */ +define(`MOVEP_SIZE', 0) + +/* Overrides for 32 bit types that do not exist */ +define(`XWORD_SIZE32', 0) +define(`SXWORD_SIZE32', 0) + +ifelse(eval(OSRELDATE < 700009),1, + `define(`CAP_SIZE', 0) + define(`LWORD_SIZE', 0) + define(`MOVE_SIZE', 0) + define(`SYMINFO_SIZE', 0) + define(`VDEF_SIZE', 0) + define(`VNEED_SIZE', 0)',`') + +/* + * FSZ{32,64} define the sizes of 32 and 64 bit file structures respectively. + */ + +define(`FSZ32',`_FSZ32($1_DEF)') +define(`_FSZ32', + `ifelse($#,1,0, + `_BSZ32($1)+_FSZ32(shift($@))')') +define(`_BSZ32',`$2_SIZE32') + +define(`FSZ64',`_FSZ64($1_DEF)') +define(`_FSZ64', + `ifelse($#,1,0, + `_BSZ64($1)+_FSZ64(shift($@))')') +define(`_BSZ64',`$2_SIZE64') + +/* + * DEFINE_ELF_FSIZES(TYPE,NAME) + * + * Shorthand for defining for 32 and 64 versions + * of elf type TYPE. + * + * If TYPE`'_SIZE is defined, use its value for both 32 bit and 64 bit + * sizes. + * + * Otherwise, look for a explicit 32/64 bit size definition for TYPE, + * TYPE`'_SIZE32 or TYPE`'_SIZE64. If this definition is present, there + * is nothing further to do. + * + * Otherwise, if an Elf{32,64}_`'NAME structure definition is known, + * compute an expression that adds up the sizes of the structure's + * constituents. + * + * If such a structure definition is not known, treat TYPE as a primitive + * (i.e., integral) type and use sizeof(Elf{32,64}_`'NAME) to get its + * file representation size. + */ + +define(`DEFINE_ELF_FSIZE', + `ifdef($1`_SIZE', + `define($1_SIZE32,$1_SIZE) + define($1_SIZE64,$1_SIZE)', + `ifdef($1`_SIZE32',`', + `ifdef(`Elf32_'$2`_DEF', + `define($1_SIZE32,FSZ32(Elf32_$2))', + `define($1_SIZE32,`sizeof(Elf32_'$2`)')')') + ifdef($1`_SIZE64',`', + `ifdef(`Elf64_'$2`_DEF', + `define($1_SIZE64,FSZ64(Elf64_$2))', + `define($1_SIZE64,`sizeof(Elf64_'$2`)')')')')') + +define(`DEFINE_ELF_FSIZES', + `ifelse($#,1,`', + `DEFINE_ELF_FSIZE($1) + DEFINE_ELF_FSIZES(shift($@))')') + +DEFINE_ELF_FSIZES(ELF_TYPE_LIST) +DEFINE_ELF_FSIZE(`IDENT',`') # `IDENT' is a pseudo type + +define(`FSIZE', + `[ELF_T_$1] = { .fsz32 = $1_SIZE32, .fsz64 = $1_SIZE64 },') +define(`FSIZES', + `ifelse($#,1,`', + `FSIZE($1) +FSIZES(shift($@))')') + +divert(0) + +struct fsize { + size_t fsz32; + size_t fsz64; +}; + +static struct fsize fsize[ELF_T_NUM] = { +FSIZES(ELF_TYPE_LIST) +}; + +size_t +_libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c) +{ + size_t sz; + + sz = 0; + if (v != EV_CURRENT) + LIBELF_SET_ERROR(VERSION, 0); + else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST) + LIBELF_SET_ERROR(ARGUMENT, 0); + else { + sz = ec == ELFCLASS64 ? fsize[t].fsz64 : fsize[t].fsz32; + if (sz == 0) + LIBELF_SET_ERROR(UNIMPL, 0); + } + + return (sz*c); +} + diff --git a/lib/libelf/libelf_msize.m4 b/lib/libelf/libelf_msize.m4 new file mode 100644 index 0000000..cb0e2bb --- /dev/null +++ b/lib/libelf/libelf_msize.m4 @@ -0,0 +1,112 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/elf32.h> +#include <sys/elf64.h> + +#include <assert.h> +#include <libelf.h> +#include <string.h> + +#include "_libelf.h" + +/* WARNING: GENERATED FROM __file__. */ + +struct msize { + size_t msz32; + size_t msz64; +}; + +divert(-1) +include(SRCDIR`/elf_types.m4') + +define(BYTE_SIZE, 1) +define(NOTE_SIZE, 1) + +/* + * Unimplemented types. + */ +define(MOVEP_SIZE, 0) +define(SXWORD_SIZE32, 0) +define(XWORD_SIZE32, 0) + +ifelse(eval(OSRELDATE < 700009),1, + `define(`CAP_SIZE', 0) + define(`LWORD_SIZE', 0) + define(`MOVE_SIZE', 0) + define(`SYMINFO_SIZE', 0) + define(`VDEF_SIZE', 0) + define(`VNEED_SIZE', 0)',`') + +define(`DEFINE_ELF_MSIZE', + `ifdef($1`_SIZE', + `define($1_SIZE32,$1_SIZE) + define($1_SIZE64,$1_SIZE)', + `ifdef($1`_SIZE32',`', + `define($1_SIZE32,sizeof(Elf32_$2))') + ifdef($1`_SIZE64',`', + `define($1_SIZE64,sizeof(Elf64_$2))')')') +define(`DEFINE_ELF_MSIZES', + `ifelse($#,1,`', + `DEFINE_ELF_MSIZE($1) + DEFINE_ELF_MSIZES(shift($@))')') + +DEFINE_ELF_MSIZES(ELF_TYPE_LIST) + +define(`MSIZE', + `[ELF_T_$1] = { .msz32 = $1_SIZE32, .msz64 = $1_SIZE64 },') +define(`MSIZES', + `ifelse($#,1,`', + `MSIZE($1) +MSIZES(shift($@))')') + +divert(0) + +static struct msize msize[ELF_T_NUM] = { +MSIZES(ELF_TYPE_LIST) +}; + +size_t +_libelf_msize(Elf_Type t, int elfclass, unsigned int version) +{ + size_t sz; + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST); + + if (version != EV_CURRENT) { + LIBELF_SET_ERROR(VERSION, 0); + return (0); + } + + sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64; + + return (sz); +} diff --git a/lib/libelf/libelf_phdr.c b/lib/libelf/libelf_phdr.c new file mode 100644 index 0000000..5ba58d4 --- /dev/null +++ b/lib/libelf/libelf_phdr.c @@ -0,0 +1,165 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <gelf.h> +#include <libelf.h> +#include <stdlib.h> + +#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); + + 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; + 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) { + 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; + } 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 (ec == ELFCLASS32) { + eh32 = (Elf32_Ehdr *) ehdr; + eh32->e_phnum = count; + } else { + eh64 = (Elf64_Ehdr *) ehdr; + eh64->e_phnum = count; + } + + elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); + + return (nphdr); +} diff --git a/lib/libelf/libelf_shdr.c b/lib/libelf/libelf_shdr.c new file mode 100644 index 0000000..853cc90 --- /dev/null +++ b/lib/libelf/libelf_shdr.c @@ -0,0 +1,55 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <gelf.h> +#include <libelf.h> + +#include "_libelf.h" + +void * +_libelf_getshdr(Elf_Scn *s, int ec) +{ + Elf *e; + + if (s == NULL || (e = s->s_elf) == NULL || + e->e_kind != ELF_K_ELF) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + if (ec == ELFCLASSNONE) + ec = e->e_class; + + if (ec != e->e_class) { + LIBELF_SET_ERROR(CLASS, 0); + return (NULL); + } + + return ((void *) &s->s_shdr); +} diff --git a/lib/libelf/libelf_xlate.c b/lib/libelf/libelf_xlate.c new file mode 100644 index 0000000..65a47b5 --- /dev/null +++ b/lib/libelf/libelf_xlate.c @@ -0,0 +1,137 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <libelf.h> + +#include "_libelf.h" + +/* + * Translate to/from the file representation of ELF objects. + * + * Translation could potentially involve the following + * transformations: + * + * - an endianness conversion, + * - a change of layout, as the file representation of ELF objects + * can differ from their in-memory representation. + * - a change in representation due to a layout version change. + */ + +Elf_Data * +_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, + int elfclass, int direction) +{ + size_t cnt, dsz, fsz, msz; + uintptr_t sb, se, db, de; + + if (encoding == ELFDATANONE) + encoding = LIBELF_PRIVATE(byteorder); + + if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || + dst == NULL || src == NULL || dst == src) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return (NULL); + } + + assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); + assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); + + if (dst->d_version != src->d_version) { + LIBELF_SET_ERROR(UNIMPL, 0); + return (NULL); + } + + if (src->d_buf == NULL || dst->d_buf == NULL || + src->d_size == 0) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)(src->d_type, + (size_t) 1, src->d_version)) == 0) + return (NULL); + + msz = _libelf_msize(src->d_type, elfclass, src->d_version); + + assert(msz > 0); + + if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + cnt = src->d_size / msz; + dsz = cnt * fsz; + + if (dst->d_size < dsz) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + sb = (uintptr_t) src->d_buf; + se = sb + src->d_size; + db = (uintptr_t) dst->d_buf; + de = db + dst->d_size; + + /* + * Check for overlapping buffers. Note that db == sb is + * allowed, in which case the source buffer must also be large + * enough for `n' target objects. For file to native + * conversions, an in-place conversion is not always possible. + */ + if ((db == sb && dsz < src->d_size) || + (db != sb && de > sb && se > db)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + if ((direction == ELF_TOMEMORY ? db : sb) % + _libelf_malign(src->d_type, elfclass)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + dst->d_type = src->d_type; + dst->d_size = cnt * fsz; + + if (db == sb && encoding == LIBELF_PRIVATE(byteorder) && + fsz == msz) + return (dst); /* nothing more to do */ + + (_libelf_get_translator(src->d_type, direction, elfclass))(dst->d_buf, + src->d_buf, cnt, encoding != LIBELF_PRIVATE(byteorder)); + + return (dst); +} |