diff options
Diffstat (limited to 'libelf/lib')
62 files changed, 7235 insertions, 0 deletions
diff --git a/libelf/lib/32.fsize.c b/libelf/lib/32.fsize.c new file mode 100755 index 000000000..2d972f5c9 --- /dev/null +++ b/libelf/lib/32.fsize.c @@ -0,0 +1,59 @@ +/* +32.fsize.c - implementation of the elf32_fsize(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> + +const size_t +_elf32_fmsize[EV_CURRENT - EV_NONE][ELF_T_NUM][2] = { + { + { sizeof(unsigned char), sizeof(unsigned char) }, + { sizeof(Elf32_Addr), sizeof(__ext_Elf32_Addr) }, + { sizeof(Elf32_Dyn), sizeof(__ext_Elf32_Dyn) }, + { sizeof(Elf32_Ehdr), sizeof(__ext_Elf32_Ehdr) }, + { sizeof(Elf32_Half), sizeof(__ext_Elf32_Half) }, + { sizeof(Elf32_Off), sizeof(__ext_Elf32_Off) }, + { sizeof(Elf32_Phdr), sizeof(__ext_Elf32_Phdr) }, + { sizeof(Elf32_Rela), sizeof(__ext_Elf32_Rela) }, + { sizeof(Elf32_Rel), sizeof(__ext_Elf32_Rel) }, + { sizeof(Elf32_Shdr), sizeof(__ext_Elf32_Shdr) }, + { sizeof(Elf32_Sword), sizeof(__ext_Elf32_Sword) }, + { sizeof(Elf32_Sym), sizeof(__ext_Elf32_Sym) }, + { sizeof(Elf32_Word), sizeof(__ext_Elf32_Word) }, + }, +}; + +size_t +elf32_fsize(Elf_Type type, size_t count, unsigned ver) { + size_t n; + + if (!valid_version(ver)) { + seterr(ERROR_UNKNOWN_VERSION); + } + else if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + } + else if (!(n = _fsize32(ver, type))) { + seterr(ERROR_UNKNOWN_TYPE); + } + else if (count) { + return count * n; + } + return 0; +} diff --git a/libelf/lib/32.getehdr.c b/libelf/lib/32.getehdr.c new file mode 100755 index 000000000..37cde84f8 --- /dev/null +++ b/libelf/lib/32.getehdr.c @@ -0,0 +1,38 @@ +/* +32.getehdr.c - implementation of the elf32_getehdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf32_Ehdr* +elf32_getehdr(Elf *elf) { + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class != ELFCLASS32) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + return (Elf32_Ehdr*)elf->e_ehdr; + } + return NULL; +} diff --git a/libelf/lib/32.getphdr.c b/libelf/lib/32.getphdr.c new file mode 100755 index 000000000..3680eceab --- /dev/null +++ b/libelf/lib/32.getphdr.c @@ -0,0 +1,38 @@ +/* +32.getphdr.c - implementation of the elf32_getphdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf32_Phdr* +elf32_getphdr(Elf *elf) { + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class != ELFCLASS32) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + return (Elf32_Phdr*)elf->e_phdr; + } + return NULL; +} diff --git a/libelf/lib/32.getshdr.c b/libelf/lib/32.getshdr.c new file mode 100755 index 000000000..a1d2e35aa --- /dev/null +++ b/libelf/lib/32.getshdr.c @@ -0,0 +1,33 @@ +/* +32.getshdr.c - implementation of the elf32_getshdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf32_Shdr* +elf32_getshdr(Elf_Scn *scn) { + if (scn) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf); + if (scn->s_elf->e_class == ELFCLASS32) { + return &scn->s_shdr32; + } + seterr(ERROR_CLASSMISMATCH); + } + return NULL; +} diff --git a/libelf/lib/32.newehdr.c b/libelf/lib/32.newehdr.c new file mode 100755 index 000000000..403a3873b --- /dev/null +++ b/libelf/lib/32.newehdr.c @@ -0,0 +1,56 @@ +/* +32.newehdr.c - implementation of the elf32_newehdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf32_Ehdr* +elf32_newehdr(Elf *elf) { + Elf32_Ehdr *ehdr; + size_t size; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_readable) { + return elf32_getehdr(elf); + } + else if (!elf->e_ehdr) { + size = _msize32(_elf_version, ELF_T_EHDR); + elf_assert(size); + if ((ehdr = (Elf32_Ehdr*)malloc(size))) { + memset(ehdr, 0, size); + elf->e_ehdr = (char*)ehdr; + elf->e_free_ehdr = 1; + elf->e_ehdr_flags |= ELF_F_DIRTY; + elf->e_kind = ELF_K_ELF; + elf->e_class = ELFCLASS32; + return ehdr; + } + seterr(ERROR_MEM_EHDR); + } + else if (elf->e_class != ELFCLASS32) { + seterr(ERROR_CLASSMISMATCH); + } + else { + elf_assert(elf->e_kind == ELF_K_ELF); + return (Elf32_Ehdr*)elf->e_ehdr; + } + return NULL; +} diff --git a/libelf/lib/32.newphdr.c b/libelf/lib/32.newphdr.c new file mode 100755 index 000000000..79ca6228f --- /dev/null +++ b/libelf/lib/32.newphdr.c @@ -0,0 +1,64 @@ +/* +32.newphdr.c - implementation of the elf32_newphdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf32_Phdr* +elf32_newphdr(Elf *elf, size_t count) { + Elf32_Phdr *phdr = NULL; + Elf32_Ehdr *ehdr; + size_t size; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!elf->e_ehdr && !elf->e_readable) { + seterr(ERROR_NOEHDR); + } + else if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class != ELFCLASS32) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + ehdr = (Elf32_Ehdr*)elf->e_ehdr; + if (count) { + size = _msize32(_elf_version, ELF_T_PHDR); + elf_assert(size); + if (!(phdr = (Elf32_Phdr*)malloc(count * size))) { + seterr(ERROR_MEM_PHDR); + return NULL; + } + memset(phdr, 0, count * size); + } + if (elf->e_free_phdr) { + elf_assert(elf->e_phdr); + free(elf->e_phdr); + } + elf->e_phdr = (char*)phdr; + elf->e_free_phdr = phdr ? 1 : 0; + elf->e_phdr_flags |= ELF_F_DIRTY; + elf->e_phnum = ehdr->e_phnum = count; + elf->e_ehdr_flags |= ELF_F_DIRTY; + return phdr; + } + return NULL; +} diff --git a/libelf/lib/32.xlatetof.c b/libelf/lib/32.xlatetof.c new file mode 100755 index 000000000..0220a8209 --- /dev/null +++ b/libelf/lib/32.xlatetof.c @@ -0,0 +1,349 @@ +/* +32.xlatetof.c - implementation of the elf32_xlateto[fm](3) functions. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +/* + * Ugly, ugly + */ +#define x +#if defined/**/x +# define Cat2(a,b)a##b +# define Cat3(a,b,c)a##b##c +# define Exn(m1,m2,args)m1##m2##args +# define Ex1(m1,m2,a,b)m1##m2(a##b) +# define Ex2(m1,m2,a,b,c)m1##m2(a,b##c) +#else +# define Cat2(a,b)a/**/b +# define Cat3(a,b,c)a/**/b/**/c +# define Exn(m1,m2,args)m1/**/m2/**/args +# define Ex1(m1,m2,a,b)m1/**/m2(a/**/b) +# define Ex2(m1,m2,a,b,c)m1/**/m2(a,b/**/c) +#endif +#undef x + +/* + * auxiliary macros for execution order reversal + */ +#define seq_forw(a,b) a b +#define seq_back(a,b) b a + +/* + * function instantiator + */ +#define copy_type_e_io(name,e,io,tfrom,tto,copy) \ + static void \ + Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) { \ + const tfrom *from = (const tfrom*)src; \ + tto *to = (tto*)dst; \ + if (sizeof(tfrom) < sizeof(tto)) { \ + from += n; \ + to += n; \ + while (n-- > 0) { \ + --from; \ + --to; \ + copy(e,io,seq_back) \ + } \ + } \ + else { \ + while (n-- > 0) { \ + copy(e,io,seq_forw) \ + from++; \ + to++; \ + } \ + } \ + } + +#define copy_type_e(name,e,type,copy) \ + copy_type_e_io(name,e,tom,Cat2(__ext_,type),type,copy) \ + copy_type_e_io(name,e,tof,type,Cat2(__ext_,type),copy) + +/* + * master function instantiator + */ +#define copy_type(name,version,type,copy) \ + copy_type_e(Cat3(name,L,version),L,type,copy) \ + copy_type_e(Cat3(name,M,version),M,type,copy) + +/* + * scalar copying + */ +#define copy_scalar_tom(type) *to = Exn(__load_,type,(*from)); +#define copy_scalar_tof(type) Exn(__store_,type,(*to, *from)); + +/* + * structure member copying + */ +#define copy_tom(mb,type) to->mb = Exn(__load_,type,(from->mb)); +#define copy_tof(mb,type) Exn(__store_,type,(to->mb, from->mb)); + +/* + * structure member copying (direction independent) + */ +#define copy_byte(e,io,mb) to->mb = from->mb; +#define copy_addr(e,io,mb) Ex2(copy_,io,mb,u32,e) +#define copy_half(e,io,mb) Ex2(copy_,io,mb,u16,e) +#define copy_off(e,io,mb) Ex2(copy_,io,mb,u32,e) +#define copy_sword(e,io,mb) Ex2(copy_,io,mb,i32,e) +#define copy_word(e,io,mb) Ex2(copy_,io,mb,u32,e) +#define copy_arr(e,io,mb) \ + array_copy(to->mb, sizeof(to->mb), from->mb, sizeof(from->mb)); + +/* + * scalar copying (direction independent) + * these macros are used as `copy' arguments to copy_type() + */ +#define copy_addr_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) +#define copy_half_11(e,io,seq) Ex1(copy_scalar_,io,u16,e) +#define copy_off_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) +#define copy_sword_11(e,io,seq) Ex1(copy_scalar_,io,i32,e) +#define copy_word_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) + +/* + * structure copying (direction independent) + * these macros are used as `copy' arguments to copy_type() + */ +#define copy_dyn_11(e,io,seq) \ + seq(copy_sword(e,io,d_tag), \ + seq(copy_addr(e,io,d_un.d_ptr), \ + /**/)) +#define copy_ehdr_11(e,io,seq) \ + seq(copy_arr(e,io,e_ident), \ + seq(copy_half(e,io,e_type), \ + seq(copy_half(e,io,e_machine), \ + seq(copy_word(e,io,e_version), \ + seq(copy_addr(e,io,e_entry), \ + seq(copy_off(e,io,e_phoff), \ + seq(copy_off(e,io,e_shoff), \ + seq(copy_word(e,io,e_flags), \ + seq(copy_half(e,io,e_ehsize), \ + seq(copy_half(e,io,e_phentsize), \ + seq(copy_half(e,io,e_phnum), \ + seq(copy_half(e,io,e_shentsize), \ + seq(copy_half(e,io,e_shnum), \ + seq(copy_half(e,io,e_shstrndx), \ + /**/)))))))))))))) +#define copy_phdr_11(e,io,seq) \ + seq(copy_word(e,io,p_type), \ + seq(copy_off(e,io,p_offset), \ + seq(copy_addr(e,io,p_vaddr), \ + seq(copy_addr(e,io,p_paddr), \ + seq(copy_word(e,io,p_filesz), \ + seq(copy_word(e,io,p_memsz), \ + seq(copy_word(e,io,p_flags), \ + seq(copy_word(e,io,p_align), \ + /**/)))))))) +#define copy_rela_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_word(e,io,r_info), \ + seq(copy_sword(e,io,r_addend), \ + /**/))) +#define copy_rel_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_word(e,io,r_info), \ + /**/)) +#define copy_shdr_11(e,io,seq) \ + seq(copy_word(e,io,sh_name), \ + seq(copy_word(e,io,sh_type), \ + seq(copy_word(e,io,sh_flags), \ + seq(copy_addr(e,io,sh_addr), \ + seq(copy_off(e,io,sh_offset), \ + seq(copy_word(e,io,sh_size), \ + seq(copy_word(e,io,sh_link), \ + seq(copy_word(e,io,sh_info), \ + seq(copy_word(e,io,sh_addralign), \ + seq(copy_word(e,io,sh_entsize), \ + /**/)))))))))) +#define copy_sym_11(e,io,seq) \ + seq(copy_word(e,io,st_name), \ + seq(copy_addr(e,io,st_value), \ + seq(copy_word(e,io,st_size), \ + seq(copy_byte(e,io,st_info), \ + seq(copy_byte(e,io,st_other), \ + seq(copy_half(e,io,st_shndx), \ + /**/)))))) + +static void +byte_copy(unsigned char *dst, const unsigned char *src, size_t n) { + if (dst == src || !n) { + return; + } +#if HAVE_BROKEN_MEMMOVE + while (dst > src && dst < &src[n]) { + if (n <= 16) { + /* copy `manually' */ + while (n--) { + dst[n] = src[n]; + } + return; + } + /* copy upper half */ + byte_copy(&dst[n / 2], &src[n / 2], n - n / 2); + /* continue with lower half */ + n /= 2; + } +#endif + memmove(dst, src, n); +} + +static void +array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t slen) { + byte_copy(dst, src, dlen < slen ? dlen : slen); + if (dlen > slen) { + memset(dst + slen, 0, dlen - slen); + } +} + +/* + * instantiate copy functions + */ +copy_type(addr_32,,Elf32_Addr,copy_addr_11) +copy_type(half_32,,Elf32_Half,copy_half_11) +copy_type(off_32,,Elf32_Off,copy_off_11) +copy_type(sword_32,,Elf32_Sword,copy_sword_11) +copy_type(word_32,,Elf32_Word,copy_word_11) +copy_type(dyn_32,11,Elf32_Dyn,copy_dyn_11) +copy_type(ehdr_32,11,Elf32_Ehdr,copy_ehdr_11) +copy_type(phdr_32,11,Elf32_Phdr,copy_phdr_11) +copy_type(rela_32,11,Elf32_Rela,copy_rela_11) +copy_type(rel_32,11,Elf32_Rel,copy_rel_11) +copy_type(shdr_32,11,Elf32_Shdr,copy_shdr_11) +copy_type(sym_32,11,Elf32_Sym,copy_sym_11) + +typedef void (*xlator)(unsigned char*, const unsigned char*, size_t); +typedef xlator xltab[ELF_T_NUM][2]; + +/* + * translation table (32-bit, version 1 -> version 1) + */ +static const xltab +xlate32_11[/*encoding*/] = { + { + { byte_copy, byte_copy }, + { addr_32L_tom, addr_32L_tof }, + { dyn_32L11_tom, dyn_32L11_tof }, + { ehdr_32L11_tom, ehdr_32L11_tof }, + { half_32L_tom, half_32L_tof }, + { off_32L_tom, off_32L_tof }, + { phdr_32L11_tom, phdr_32L11_tof }, + { rela_32L11_tom, rela_32L11_tof }, + { rel_32L11_tom, rel_32L11_tof }, + { shdr_32L11_tom, shdr_32L11_tof }, + { sword_32L_tom, sword_32L_tof }, + { sym_32L11_tom, sym_32L11_tof }, + { word_32L_tom, word_32L_tof }, + }, + { + { byte_copy, byte_copy }, + { addr_32M_tom, addr_32M_tof }, + { dyn_32M11_tom, dyn_32M11_tof }, + { ehdr_32M11_tom, ehdr_32M11_tof }, + { half_32M_tom, half_32M_tof }, + { off_32M_tom, off_32M_tof }, + { phdr_32M11_tom, phdr_32M11_tof }, + { rela_32M11_tom, rela_32M11_tof }, + { rel_32M11_tom, rel_32M11_tof }, + { shdr_32M11_tom, shdr_32M11_tof }, + { sword_32M_tom, sword_32M_tof }, + { sym_32M11_tom, sym_32M11_tof }, + { word_32M_tom, word_32M_tof }, + }, +}; + +/* + * main translation table (32-bit) + */ +static const xltab *const +xlate32[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = { + { xlate32_11, }, +}; + +#define translator(sv,dv,enc,type,d) \ + (xlate32[(sv) - EV_NONE - 1] \ + [(dv) - EV_NONE - 1] \ + [(enc) - ELFDATA2LSB] \ + [(type) - ELF_T_BYTE] \ + [d]) + +/* + * direction-independent translation + */ +static Elf_Data* +elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) { + size_t ssize, dsize, count; + Elf_Type type; + int sv, dv; + xlator op; + + if (!src || !dst) { + return NULL; + } + if (!src->d_buf || !dst->d_buf) { + seterr(ERROR_NULLBUF); + return NULL; + } + if (!valid_encoding(encode)) { + seterr(ERROR_UNKNOWN_ENCODING); + return NULL; + } + sv = src->d_version; + dv = dst->d_version; + if (!valid_version(sv) || !valid_version(dv)) { + seterr(ERROR_UNKNOWN_VERSION); + return NULL; + } + type = src->d_type; + if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + ssize = _fmsize32(sv, type, 1 - tof); + dsize = _fmsize32(dv, type, tof); + op = translator(sv, dv, encode, type, tof); + if (!ssize || !dsize || !op) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + count = src->d_size / ssize; + if (dst->d_size < count * dsize) { + seterr(ERROR_DST2SMALL); + return NULL; + } + if (count) { + (*op)(dst->d_buf, src->d_buf, count); + } + dst->d_size = count * dsize; + dst->d_type = type; + return dst; +} + +/* + * finally, the "official" translation functions + */ +Elf_Data* +elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned encode) { + return elf32_xlate(dst, src, encode, 0); +} + +Elf_Data* +elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned encode) { + return elf32_xlate(dst, src, encode, 1); +} diff --git a/libelf/lib/64.xlatetof.c b/libelf/lib/64.xlatetof.c new file mode 100755 index 000000000..aa2d71c2c --- /dev/null +++ b/libelf/lib/64.xlatetof.c @@ -0,0 +1,430 @@ +/* +64.xlatetof.c - implementation of the elf64_xlateto[fm](3) functions. +Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#ifndef lint +static const char rcsid[] = "@(#) Id: 64.xlatetof.c,v 1.3 1998/08/25 15:22:24 michael Exp "; +#endif /* lint */ + +static __libelf_u64_t +__load_u64L(const unsigned char *from) { + return ((__libelf_u64_t)__load_u32L(from + 4) << 32) | (__libelf_u64_t)__load_u32L(from); +} + +static __libelf_u64_t +__load_u64M(const unsigned char *from) { + return ((__libelf_u64_t)__load_u32M(from) << 32) | (__libelf_u64_t)__load_u32M(from + 4); +} + +static __libelf_i64_t +__load_i64L(const unsigned char *from) { + return ((__libelf_i64_t)__load_i32L(from + 4) << 32) | (__libelf_u64_t)__load_u32L(from); +} + +static __libelf_i64_t +__load_i64M(const unsigned char *from) { + return ((__libelf_u64_t)__load_u32M(from) << 32) | (__libelf_i64_t)__load_i32M(from + 4); +} + +static void +__store_u64L(unsigned char *to, __libelf_u64_t v) { + __store_u32L(to, (unsigned long)v); + v >>= 32; + __store_u32L(to + 4, (unsigned long)v); +} + +static void +__store_u64M(unsigned char *to, __libelf_u64_t v) { + __store_u32M(to + 4, (unsigned long)v); + v >>= 32; + __store_u32M(to, (unsigned long)v); +} + +static void +__store_i64L(unsigned char *to, __libelf_u64_t v) { + __store_u32L(to, (unsigned long)v); + v >>= 32; + __store_i32L(to + 4, (unsigned long)v); +} + +static void +__store_i64M(unsigned char *to, __libelf_u64_t v) { + __store_u32M(to + 4, (unsigned long)v); + v >>= 32; + __store_i32M(to, (unsigned long)v); +} + +/* + * Ugly, ugly + */ +#define x +#if defined/**/x +# define Cat2(a,b)a##b +# define Cat3(a,b,c)a##b##c +# define Ex1(m1,m2,a,b)m1##m2(a##b) +# define Ex2(m1,m2,a,b,c)m1##m2(a,b##c) +#else +# define Cat2(a,b)a/**/b +# define Cat3(a,b,c)a/**/b/**/c +# define Ex1(m1,m2,a,b)m1/**/m2(a/**/b) +# define Ex2(m1,m2,a,b,c)m1/**/m2(a,b/**/c) +#endif +#undef x + +/* + * auxiliary macros for execution order reversal + */ +#define seq_forw(a,b) a b +#define seq_back(a,b) b a + +/* + * function instantiator + */ +#define copy_type_e_io(name,e,io,tfrom,tto,copy) \ + static void \ + Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) { \ + const tfrom *from = (const tfrom*)src; \ + tto *to = (tto*)dst; \ + if (sizeof(tfrom) < sizeof(tto)) { \ + from += n; \ + to += n; \ + while (n-- > 0) { \ + --from; \ + --to; \ + copy(e,io,seq_back) \ + } \ + } \ + else { \ + while (n-- > 0) { \ + copy(e,io,seq_forw) \ + from++; \ + to++; \ + } \ + } \ + } + +#define copy_type_e(name,e,type,copy) \ + copy_type_e_io(name,e,tom,Cat2(__ext_,type),type,copy) \ + copy_type_e_io(name,e,tof,type,Cat2(__ext_,type),copy) + +/* + * master function instantiator + */ +#define copy_type(name,version,type,copy) \ + copy_type_e(Cat3(name,L,version),L,type,copy) \ + copy_type_e(Cat3(name,M,version),M,type,copy) + +/* + * scalar copying + */ +#define copy_scalar_tom(type) *to = Cat2(__load_,type)(*from); +#define copy_scalar_tof(type) Cat2(__store_,type)(*to, *from); + +/* + * structure member copying + */ +#define copy_tom(mb,type) to->mb = Cat2(__load_,type)(from->mb); +#define copy_tof(mb,type) Cat2(__store_,type)(to->mb, from->mb); + +/* + * structure member copying (direction independent) + */ +#define copy_byte(e,io,mb) to->mb = from->mb; +#define copy_addr(e,io,mb) Ex2(copy_,io,mb,u64,e) +#define copy_half(e,io,mb) Ex2(copy_,io,mb,u16,e) +#define copy_off(e,io,mb) Ex2(copy_,io,mb,u64,e) +#define copy_sword(e,io,mb) Ex2(copy_,io,mb,i32,e) +#define copy_sxword(e,io,mb) Ex2(copy_,io,mb,i64,e) +#define copy_word(e,io,mb) Ex2(copy_,io,mb,u32,e) +#define copy_xword(e,io,mb) Ex2(copy_,io,mb,u64,e) +#define copy_arr(e,io,mb) \ + array_copy(to->mb, sizeof(to->mb), from->mb, sizeof(from->mb)); + +/* + * scalar copying (direction independent) + * these macros are used as `copy' arguments to copy_type() + */ +#define copy_addr_11(e,io,seq) Ex1(copy_scalar_,io,u64,e) +#define copy_half_11(e,io,seq) Ex1(copy_scalar_,io,u16,e) +#define copy_off_11(e,io,seq) Ex1(copy_scalar_,io,u64,e) +#define copy_sword_11(e,io,seq) Ex1(copy_scalar_,io,i32,e) +#define copy_sxword_11(e,io,seq)Ex1(copy_scalar_,io,i64,e) +#define copy_word_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) +#define copy_xword_11(e,io,seq) Ex1(copy_scalar_,io,u64,e) + +/* + * structure copying (direction independent) + * these macros are used as `copy' arguments to copy_type() + */ +#define copy_dyn_11(e,io,seq) \ + seq(copy_xword(e,io,d_tag), \ + seq(copy_addr(e,io,d_un.d_ptr), \ + /**/)) +#define copy_ehdr_11(e,io,seq) \ + seq(copy_arr(e,io,e_ident), \ + seq(copy_half(e,io,e_type), \ + seq(copy_half(e,io,e_machine), \ + seq(copy_word(e,io,e_version), \ + seq(copy_addr(e,io,e_entry), \ + seq(copy_off(e,io,e_phoff), \ + seq(copy_off(e,io,e_shoff), \ + seq(copy_word(e,io,e_flags), \ + seq(copy_half(e,io,e_ehsize), \ + seq(copy_half(e,io,e_phentsize), \ + seq(copy_half(e,io,e_phnum), \ + seq(copy_half(e,io,e_shentsize), \ + seq(copy_half(e,io,e_shnum), \ + seq(copy_half(e,io,e_shstrndx), \ + /**/)))))))))))))) +#define copy_phdr_11(e,io,seq) \ + seq(copy_word(e,io,p_type), \ + seq(copy_word(e,io,p_flags), \ + seq(copy_off(e,io,p_offset), \ + seq(copy_addr(e,io,p_vaddr), \ + seq(copy_addr(e,io,p_paddr), \ + seq(copy_xword(e,io,p_filesz), \ + seq(copy_xword(e,io,p_memsz), \ + seq(copy_xword(e,io,p_align), \ + /**/)))))))) +#if __LIBELF64_IRIX +#define copy_rela_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_word(e,io,r_sym), \ + seq(copy_byte(e,io,r_ssym), \ + seq(copy_byte(e,io,r_type3), \ + seq(copy_byte(e,io,r_type2), \ + seq(copy_byte(e,io,r_type), \ + seq(copy_sxword(e,io,r_addend), \ + /**/))))))) +#define copy_rel_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_word(e,io,r_sym), \ + seq(copy_byte(e,io,r_ssym), \ + seq(copy_byte(e,io,r_type3), \ + seq(copy_byte(e,io,r_type2), \ + seq(copy_byte(e,io,r_type), \ + /**/)))))) +#else /* __LIBELF64_IRIX */ +#define copy_rela_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_xword(e,io,r_info), \ + seq(copy_sxword(e,io,r_addend), \ + /**/))) +#define copy_rel_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_xword(e,io,r_info), \ + /**/)) +#endif /* __LIBELF64_IRIX */ +#define copy_shdr_11(e,io,seq) \ + seq(copy_word(e,io,sh_name), \ + seq(copy_word(e,io,sh_type), \ + seq(copy_xword(e,io,sh_flags), \ + seq(copy_addr(e,io,sh_addr), \ + seq(copy_off(e,io,sh_offset), \ + seq(copy_xword(e,io,sh_size), \ + seq(copy_word(e,io,sh_link), \ + seq(copy_word(e,io,sh_info), \ + seq(copy_xword(e,io,sh_addralign), \ + seq(copy_xword(e,io,sh_entsize), \ + /**/)))))))))) +#define copy_sym_11(e,io,seq) \ + seq(copy_word(e,io,st_name), \ + seq(copy_byte(e,io,st_info), \ + seq(copy_byte(e,io,st_other), \ + seq(copy_half(e,io,st_shndx), \ + seq(copy_addr(e,io,st_value), \ + seq(copy_xword(e,io,st_size), \ + /**/)))))) + +static void +byte_copy(unsigned char *dst, const unsigned char *src, size_t n) { + if (dst == src || !n) { + return; + } +#if HAVE_BROKEN_MEMMOVE + while (dst > src && dst < &src[n]) { + if (n <= 16) { + /* copy `manually' */ + while (n--) { + dst[n] = src[n]; + } + return; + } + /* copy upper half */ + byte_copy(&dst[n / 2], &src[n / 2], n - n / 2); + /* continue with lower half */ + n /= 2; + } +#endif + memmove(dst, src, n); +} + +static void +array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t slen) { + byte_copy(dst, src, dlen < slen ? dlen : slen); + if (dlen > slen) { + memset(dst + slen, 0, dlen - slen); + } +} + +/* + * instantiate copy functions + */ +copy_type(addr_64,_,Elf64_Addr,copy_addr_11) +copy_type(half_64,_,Elf64_Half,copy_half_11) +copy_type(off_64,_,Elf64_Off,copy_off_11) +copy_type(sword_64,_,Elf64_Sword,copy_sword_11) +copy_type(sxword_64,_,Elf64_Sxword,copy_sxword_11) +copy_type(word_64,_,Elf64_Word,copy_word_11) +copy_type(xword_64,_,Elf64_Xword,copy_xword_11) +copy_type(dyn_64,11,Elf64_Dyn,copy_dyn_11) +copy_type(ehdr_64,11,Elf64_Ehdr,copy_ehdr_11) +copy_type(phdr_64,11,Elf64_Phdr,copy_phdr_11) +copy_type(rela_64,11,Elf64_Rela,copy_rela_11) +copy_type(rel_64,11,Elf64_Rel,copy_rel_11) +copy_type(shdr_64,11,Elf64_Shdr,copy_shdr_11) +copy_type(sym_64,11,Elf64_Sym,copy_sym_11) + +typedef void (*xlator)(unsigned char*, const unsigned char*, size_t); +typedef xlator xltab[ELF_T_NUM][2]; + +/* + * translation table (64-bit, version 1 -> version 1) + */ +static const xltab +xlate64_11[/*encoding*/] = { + { + { byte_copy, byte_copy }, + { addr_64L__tom, addr_64L__tof }, + { dyn_64L11_tom, dyn_64L11_tof }, + { ehdr_64L11_tom, ehdr_64L11_tof }, + { half_64L__tom, half_64L__tof }, + { off_64L__tom, off_64L__tof }, + { phdr_64L11_tom, phdr_64L11_tof }, + { rela_64L11_tom, rela_64L11_tof }, + { rel_64L11_tom, rel_64L11_tof }, + { shdr_64L11_tom, shdr_64L11_tof }, + { sword_64L__tom, sword_64L__tof }, + { sym_64L11_tom, sym_64L11_tof }, + { word_64L__tom, word_64L__tof }, + { sxword_64L__tom, sxword_64L__tof }, + { xword_64L__tom, xword_64L__tof }, + }, + { + { byte_copy, byte_copy }, + { addr_64M__tom, addr_64M__tof }, + { dyn_64M11_tom, dyn_64M11_tof }, + { ehdr_64M11_tom, ehdr_64M11_tof }, + { half_64M__tom, half_64M__tof }, + { off_64M__tom, off_64M__tof }, + { phdr_64M11_tom, phdr_64M11_tof }, + { rela_64M11_tom, rela_64M11_tof }, + { rel_64M11_tom, rel_64M11_tof }, + { shdr_64M11_tom, shdr_64M11_tof }, + { sword_64M__tom, sword_64M__tof }, + { sym_64M11_tom, sym_64M11_tof }, + { word_64M__tom, word_64M__tof }, + { sxword_64M__tom, sxword_64M__tof }, + { xword_64M__tom, xword_64M__tof }, + }, +}; + +/* + * main translation table (64-bit) + */ +static const xltab *const +xlate64[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = { + { xlate64_11, }, +}; + +#define translator(sv,dv,enc,type,d) \ + (xlate64[(sv) - EV_NONE - 1] \ + [(dv) - EV_NONE - 1] \ + [(enc) - ELFDATA2LSB] \ + [(type) - ELF_T_BYTE] \ + [d]) + +/* + * direction-independent translation + */ +static Elf_Data* +elf64_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) { + size_t ssize, dsize, count; + Elf_Type type; + int sv, dv; + xlator op; + + if (!src || !dst) { + return NULL; + } + if (!src->d_buf || !dst->d_buf) { + seterr(ERROR_NULLBUF); + return NULL; + } + if (!valid_encoding(encode)) { + seterr(ERROR_UNKNOWN_ENCODING); + return NULL; + } + sv = src->d_version; + dv = dst->d_version; + if (!valid_version(sv) || !valid_version(dv)) { + seterr(ERROR_UNKNOWN_VERSION); + return NULL; + } + type = src->d_type; + if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + ssize = _fmsize(ELFCLASS64, sv, type, 1 - tof); + dsize = _fmsize(ELFCLASS64, dv, type, tof); + op = translator(sv, dv, encode, type, tof); + if (!ssize || !dsize || !op) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + count = src->d_size / ssize; + if (dst->d_size < count * dsize) { + seterr(ERROR_DST2SMALL); + return NULL; + } + if (count) { + (*op)(dst->d_buf, src->d_buf, count); + } + dst->d_size = count * dsize; + dst->d_type = type; + return dst; +} + +/* + * finally, the "official" translation functions + */ +Elf_Data* +elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned encode) { + return elf64_xlate(dst, src, encode, 0); +} + +Elf_Data* +elf64_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned encode) { + return elf64_xlate(dst, src, encode, 1); +} + diff --git a/libelf/lib/assert.c b/libelf/lib/assert.c new file mode 100755 index 000000000..9e76bed8e --- /dev/null +++ b/libelf/lib/assert.c @@ -0,0 +1,33 @@ +/* +assert.c - assert function for libelf. +Copyright (C) 1999 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) Id: assert.c,v 1.1 1999/11/04 19:16:36 michael Exp "; +#endif /* lint */ + +#include <stdio.h> + +void +__elf_assert(const char *file, unsigned line, const char *cond) { + fprintf(stderr, "%s:%u: libelf assertion failure: %s\n", + file, line, cond); + abort(); +} diff --git a/libelf/lib/begin.c b/libelf/lib/begin.c new file mode 100755 index 000000000..57f803ee1 --- /dev/null +++ b/libelf/lib/begin.c @@ -0,0 +1,340 @@ +/* +begin.c - implementation of the elf_begin(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ar.h> + +static const Elf _elf_init = INIT_ELF; +static const char fmag[] = ARFMAG; + +static unsigned long +getnum(const char *str, size_t len, int base, int *err) { + unsigned long result = 0; + + while (len && *str == ' ') { + str++; len--; + } + while (len && *str >= '0' && (*str - '0') < base) { + result = base * result + *str++ - '0'; len--; + } + while (len && *str == ' ') { + str++; len--; + } + if (len) { + *err = len; + } + return result; +} + +static void +_elf_init_ar(Elf *elf) { + struct ar_hdr *hdr; + size_t offset; + size_t size; + int err = 0; + + elf->e_kind = ELF_K_AR; + elf->e_idlen = SARMAG; + elf->e_off = SARMAG; + elf->e_cooked = 1; /* do not freeze archives! */ + + /* process special members */ + offset = SARMAG; + while (!elf->e_strtab && offset + sizeof(*hdr) <= elf->e_size) { + hdr = (struct ar_hdr*)(elf->e_data + offset); + if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) { + break; + } + if (hdr->ar_name[0] != '/') { + break; + } + size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err); + if (err || !size) { + break; + } + offset += sizeof(*hdr); + if (offset + size > elf->e_size) { + break; + } + if (hdr->ar_name[1] == '/' && hdr->ar_name[2] == ' ') { + elf->e_strtab = elf->e_data + offset; + elf->e_strlen = size; + break; + } + if (elf->e_symtab || hdr->ar_name[1] != ' ') { + break; + } + elf->e_symtab = elf->e_data + offset; + elf->e_symlen = size; + offset += size + (size & 1); + } +} + +static Elf_Arhdr* +_elf_arhdr(Elf *arf) { + struct ar_hdr *hdr; + Elf_Arhdr *arhdr; + size_t namelen; + size_t tmp; + char *name; + int err = 0; + + if (arf->e_off == arf->e_size) { + /* no error! */ + return NULL; + } + if (arf->e_off < 0 || arf->e_off > arf->e_size) { + seterr(ERROR_OUTSIDE); + return NULL; + } + if (arf->e_off + sizeof(*hdr) > arf->e_size) { + seterr(ERROR_TRUNC_ARHDR); + return NULL; + } + elf_assert(arf->e_data != NULL); + hdr = (struct ar_hdr*)(arf->e_data + arf->e_off); + if (memcmp(hdr->ar_fmag, fmag, sizeof(fmag) - 1)) { + seterr(ERROR_ARFMAG); + return NULL; + } + + name = hdr->ar_name; + for (namelen = sizeof(hdr->ar_name); namelen > 0; namelen--) { + if (name[namelen - 1] != ' ') { + break; + } + } + if (name[0] == '/') { + if (name[1] >= '0' && name[1] <= '9') { + if (!arf->e_strtab) { + seterr(ERROR_ARSTRTAB); + return NULL; + } + tmp = getnum(&name[1], namelen - 1, 10, &err); + if (err) { + seterr(ERROR_ARSPECIAL); + return NULL; + } + if (tmp < 0 || tmp >= arf->e_strlen) { + seterr(ERROR_ARSTRTAB); + return NULL; + } + for (namelen = tmp; namelen < arf->e_strlen; namelen++) { + if (arf->e_strtab[namelen] == '/') { + break; + } + } + if (namelen == arf->e_strlen) { + seterr(ERROR_ARSTRTAB); + return NULL; + } + name = arf->e_strtab + tmp; + namelen -= tmp; + } + else if (namelen != 1 && !(namelen == 2 && name[1] == '/')) { + seterr(ERROR_ARSPECIAL); + return NULL; + } + } + else if (namelen > 0 && name[namelen - 1] == '/') { + namelen--; + } + else { + namelen = 0; + } + + if (!(arhdr = (Elf_Arhdr*)malloc(sizeof(*arhdr) + + sizeof(hdr->ar_name) + namelen + 2))) { + seterr(ERROR_MEM_ARHDR); + return NULL; + } + + arhdr->ar_name = NULL; + arhdr->ar_rawname = (char*)(arhdr + 1); + arhdr->ar_date = getnum(hdr->ar_date, sizeof(hdr->ar_date), 10, &err); + arhdr->ar_uid = getnum(hdr->ar_uid, sizeof(hdr->ar_uid), 10, &err); + arhdr->ar_gid = getnum(hdr->ar_gid, sizeof(hdr->ar_gid), 10, &err); + arhdr->ar_mode = getnum(hdr->ar_mode, sizeof(hdr->ar_mode), 8, &err); + arhdr->ar_size = getnum(hdr->ar_size, sizeof(hdr->ar_size), 10, &err); + if (err) { + free(arhdr); + seterr(ERROR_ARHDR); + return NULL; + } + + memcpy(arhdr->ar_rawname, hdr->ar_name, sizeof(hdr->ar_name)); + arhdr->ar_rawname[sizeof(hdr->ar_name)] = '\0'; + + if (namelen) { + arhdr->ar_name = arhdr->ar_rawname + sizeof(hdr->ar_name) + 1; + memcpy(arhdr->ar_name, name, namelen); + arhdr->ar_name[namelen] = '\0'; + } + + return arhdr; +} + +Elf* +elf_begin(int fd, Elf_Cmd cmd, Elf *ref) { + Elf_Arhdr *arhdr = NULL; + size_t size = 0; + Elf *elf; + + elf_assert(_elf_init.e_magic == ELF_MAGIC); + if (_elf_version == EV_NONE) { + seterr(ERROR_VERSION_UNSET); + return NULL; + } + else if (cmd == ELF_C_NULL) { + return NULL; + } + else if (cmd == ELF_C_WRITE) { + ref = NULL; + } + else if (cmd != ELF_C_READ && cmd != ELF_C_RDWR) { + seterr(ERROR_INVALID_CMD); + return NULL; + } + else if (ref) { + elf_assert(ref->e_magic == ELF_MAGIC); + if (!ref->e_readable || (cmd == ELF_C_RDWR && !ref->e_writable)) { + seterr(ERROR_CMDMISMATCH); + return NULL; + } + if (ref->e_kind != ELF_K_AR) { + ref->e_count++; + return ref; + } + if (cmd == ELF_C_RDWR) { + seterr(ERROR_MEMBERWRITE); + return NULL; + } + if (fd != ref->e_fd) { + seterr(ERROR_FDMISMATCH); + return NULL; + } + if (!(arhdr = _elf_arhdr(ref))) { + return NULL; + } + size = arhdr->ar_size; + } + else if ((size = lseek(fd, 0L, 2)) == (size_t)-1L) { + seterr(ERROR_IO_GETSIZE); + return NULL; + } + + if (!(elf = (Elf*)malloc(sizeof(Elf)))) { + seterr(ERROR_MEM_ELF); + return NULL; + } + *elf = _elf_init; + elf->e_fd = fd; + elf->e_parent = ref; + elf->e_size = elf->e_dsize = size; + + if (cmd != ELF_C_READ) { + elf->e_writable = 1; + } + if (cmd != ELF_C_WRITE) { + elf->e_readable = 1; + } + else { + return elf; + } + + if (ref) { + size_t offset = ref->e_off + sizeof(struct ar_hdr); + Elf *xelf; + + elf_assert(arhdr); + elf->e_arhdr = arhdr; + elf->e_base = ref->e_base + offset; + /* + * Share the archive's memory image. To avoid + * multiple independent elf descriptors if the + * same member is requested twice, scan the list + * of open members for duplicates. + * + * I don't know how SVR4 handles this case. Don't rely on it. + */ + for (xelf = ref->e_members; xelf; xelf = xelf->e_link) { + elf_assert(xelf->e_parent == ref); + if (xelf->e_base == elf->e_base) { + free(arhdr); + free(elf); + xelf->e_count++; + return xelf; + } + } + /* + * The member's memory image may have been modified if + * the member has been processed before. Since we need the + * original image, we have to re-read the archive file. + * Will fail if the archive's file descriptor is disabled. + */ + if (size) { + elf->e_data = _elf_read(ref, ref->e_data + offset, offset, size); + if (!elf->e_data) { + free(arhdr); + free(elf); + return NULL; + } + } + else { + elf->e_data = NULL; + } + elf->e_next = offset + size + (size & 1); + elf->e_disabled = ref->e_disabled; + /* parent/child linking */ + elf->e_link = ref->e_members; + ref->e_members = elf; + ref->e_count++; + /* Slowaris compatibility - do not rely on this! */ + ref->e_off = elf->e_next; + } + else if (size) { +#if HAVE_MMAP + /* + * Using mmap on writable files will interfere with elf_update + */ + if (!elf->e_writable && (elf->e_data = _elf_mmap(elf))) { + elf->e_unmap_data = 1; + } + else +#endif + if (!(elf->e_data = _elf_read(elf, NULL, 0, size))) { + free(elf); + return NULL; + } + } + + elf->e_idlen = size; + if (size >= EI_NIDENT && !memcmp(elf->e_data, ELFMAG, SELFMAG)) { + elf->e_kind = ELF_K_ELF; + elf->e_idlen = EI_NIDENT; + elf->e_class = elf->e_data[EI_CLASS]; + elf->e_encoding = elf->e_data[EI_DATA]; + elf->e_version = elf->e_data[EI_VERSION]; + } + else if (size >= SARMAG && !memcmp(elf->e_data, ARMAG, SARMAG)) { + _elf_init_ar(elf); + } + + return elf; +} diff --git a/libelf/lib/byteswap.h b/libelf/lib/byteswap.h new file mode 100755 index 000000000..af7b1d66c --- /dev/null +++ b/libelf/lib/byteswap.h @@ -0,0 +1,73 @@ +/* +byteswap.h - C preprocessor macros for byte swapping. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#define lu(from,i,s) (((long)((unsigned char*)(from))[i])<<(s)) +#define li(from,i,s) (((long)((signed char*)(from))[i])<<(s)) + +#define __load_u16L(from) ((unsigned long)(lu(from,1,8)|lu(from,0,0))) +#define __load_u16M(from) ((unsigned long)(lu(from,0,8)|lu(from,1,0))) +#define __load_i16L(from) ((long)(li(from,1,8)|lu(from,0,0))) +#define __load_i16M(from) ((long)(li(from,0,8)|lu(from,1,0))) + +#define __load_u32L(from) ((unsigned long)(lu(from,3,24)| \ + lu(from,2,16)| \ + lu(from,1,8)| \ + lu(from,0,0))) +#define __load_u32M(from) ((unsigned long)(lu(from,0,24)| \ + lu(from,1,16)| \ + lu(from,2,8)| \ + lu(from,3,0))) +#define __load_i32L(from) ((long)(li(from,3,24)| \ + lu(from,2,16)| \ + lu(from,1,8)| \ + lu(from,0,0))) +#define __load_i32M(from) ((long)(li(from,0,24)| \ + lu(from,1,16)| \ + lu(from,2,8)| \ + lu(from,3,0))) + +#define su(to,i,v,s) (((char*)(to))[i]=((unsigned long)(v)>>(s))) +#define si(to,i,v,s) (((char*)(to))[i]=((long)(v)>>(s))) + +#define __store_u16L(to,v) (su(to,1,v,8),su(to,0,v,0)) +#define __store_u16M(to,v) (su(to,0,v,8),su(to,1,v,0)) +#define __store_i16L(to,v) (si(to,1,v,8),si(to,0,v,0)) +#define __store_i16M(to,v) (si(to,0,v,8),si(to,1,v,0)) + +#define __store_u32L(to,v) (su(to,3,v,24), \ + su(to,2,v,16), \ + su(to,1,v,8), \ + su(to,0,v,0)) +#define __store_u32M(to,v) (su(to,0,v,24), \ + su(to,1,v,16), \ + su(to,2,v,8), \ + su(to,3,v,0)) +#define __store_i32L(to,v) (si(to,3,v,24), \ + si(to,2,v,16), \ + si(to,1,v,8), \ + si(to,0,v,0)) +#define __store_i32M(to,v) (si(to,0,v,24), \ + si(to,1,v,16), \ + si(to,2,v,8), \ + si(to,3,v,0)) + +#endif /* _BYTESWAP_H */ diff --git a/libelf/lib/checksum.c b/libelf/lib/checksum.c new file mode 100755 index 000000000..48ae0948f --- /dev/null +++ b/libelf/lib/checksum.c @@ -0,0 +1,174 @@ +/* +checksum.c - implementation of the elf{32,64}_checksum(3) functions. +Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) Id: checksum.c,v 1.2 2001/10/01 22:30:10 michael Exp "; +#endif /* lint */ + +/* + * Compatibility note: + * + * The algorithm used in {elf32,elf64,gelf}_checksum() does not seem to + * be documented. I hope I got it right. My implementation does the + * following: + * + * - skip sections that do not have the SHF_ALLOC flag set + * - skip sections of type SHT_NULL, SHT_NOBITS, SHT_DYNSYM and + * SHT_DYNAMIC + * - add all data bytes from the remaining sections, modulo 2**32 + * - add upper and lower half of the result + * - subtract 0xffff if the result is > 0xffff + * - if any error occurs, return 0L + */ + +static int +skip_section(Elf_Scn *scn, unsigned cls) { + if (cls == ELFCLASS32) { + Elf32_Shdr *shdr = &scn->s_shdr32; + + if (!(shdr->sh_flags & SHF_ALLOC)) { + return 1; + } + switch (shdr->sh_type) { + case SHT_NULL: + case SHT_NOBITS: + /* Solaris seems to ignore these, too */ + case SHT_DYNSYM: + case SHT_DYNAMIC: + return 1; + } + } +#if __LIBELF64 + else if (cls == ELFCLASS64) { + Elf64_Shdr *shdr = &scn->s_shdr64; + + if (!(shdr->sh_flags & SHF_ALLOC)) { + return 1; + } + switch (shdr->sh_type) { + case SHT_NULL: + case SHT_NOBITS: + /* Solaris seems to ignore these, too */ + case SHT_DYNSYM: + case SHT_DYNAMIC: + return 1; + } + } +#endif /* __LIBELF64 */ + else { + seterr(ERROR_UNIMPLEMENTED); + } + return 0; +} + +static long +add_bytes(unsigned char *ptr, size_t len) { + long csum = 0; + + while (len--) { + csum += *ptr++; + } + return csum; +} + +static long +_elf_csum(Elf *elf) { + long csum = 0; + Elf_Data *data; + Elf_Scn *scn; + + if (!elf->e_ehdr && !_elf_cook(elf)) { + /* propagate errors from _elf_cook */ + return 0L; + } + seterr(0); + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + if (scn->s_index == SHN_UNDEF || skip_section(scn, elf->e_class)) { + continue; + } + data = NULL; + while ((data = elf_getdata(scn, data))) { + if (data->d_buf && data->d_size) { + csum += add_bytes(data->d_buf, data->d_size); + } + } + } + if (_elf_errno) { + return 0L; + } + csum = (csum & 0xffff) + ((csum >> 16) & 0xffff); + if (csum > 0xffff) { + csum -= 0xffff; + } + return csum; +} + +long +elf32_checksum(Elf *elf) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class != ELFCLASS32) { + seterr(ERROR_CLASSMISMATCH); + } + else { + return _elf_csum(elf); + } + } + return 0L; +} + +#if __LIBELF64 + +long +elf64_checksum(Elf *elf) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class != ELFCLASS64) { + seterr(ERROR_CLASSMISMATCH); + } + else { + return _elf_csum(elf); + } + } + return 0L; +} + +long +gelf_checksum(Elf *elf) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (!valid_class(elf->e_class)) { + seterr(ERROR_UNKNOWN_CLASS); + } + else { + return _elf_csum(elf); + } + } + return 0L; +} + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/cntl.c b/libelf/lib/cntl.c new file mode 100755 index 000000000..f1d97d678 --- /dev/null +++ b/libelf/lib/cntl.c @@ -0,0 +1,67 @@ +/* +cntl.c - implementation of the elf_cntl(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +int +elf_cntl(Elf *elf, Elf_Cmd cmd) { + Elf_Scn *scn; + Elf *child; + + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (cmd == ELF_C_FDREAD) { + if (!elf->e_readable) { + seterr(ERROR_WRONLY); + return -1; + } + } + else if (cmd != ELF_C_FDDONE) { + seterr(ERROR_INVALID_CMD); + return -1; + } + if (elf->e_disabled) { + return 0; + } + if (elf->e_kind == ELF_K_AR) { + for (child = elf->e_members; child; child = child->e_link) { + elf_assert(elf == child->e_parent); + if (elf_cntl(child, cmd)) { + return -1; + } + } + } + else if (elf->e_kind == ELF_K_ELF && cmd == ELF_C_FDREAD) { + if (!elf->e_ehdr && !_elf_cook(elf)) { + return -1; + } + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + if (scn->s_index == SHN_UNDEF || scn->s_type == SHT_NULL) { + continue; + } + else if (!elf_getdata(scn, NULL)) { + return -1; + } + } + } + elf->e_disabled = 1; + return 0; +} diff --git a/libelf/lib/cook.c b/libelf/lib/cook.c new file mode 100755 index 000000000..c61d8d49d --- /dev/null +++ b/libelf/lib/cook.c @@ -0,0 +1,236 @@ +/* +cook.c - read and translate ELF files. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +const Elf_Scn _elf_scn_init = INIT_SCN; +const Scn_Data _elf_data_init = INIT_DATA; + +const Elf_Type _elf_scn_types[SHT_NUM] = { + /* SHT_NULL */ ELF_T_BYTE, + /* SHT_PROGBITS */ ELF_T_BYTE, + /* SHT_SYMTAB */ ELF_T_SYM, + /* SHT_STRTAB */ ELF_T_BYTE, + /* SHT_RELA */ ELF_T_RELA, + /* SHT_HASH */ ELF_T_WORD, + /* SHT_DYNAMIC */ ELF_T_DYN, + /* SHT_NOTE */ ELF_T_BYTE, + /* SHT_NOBITS */ ELF_T_BYTE, + /* SHT_REL */ ELF_T_REL, + /* SHT_SHLIB */ ELF_T_BYTE, + /* SHT_DYNSYM */ ELF_T_SYM +}; + +#define truncerr(t) ((t)==ELF_T_EHDR?ERROR_TRUNC_EHDR: \ + ((t)==ELF_T_PHDR?ERROR_TRUNC_PHDR: \ + ERROR_INTERNAL)) +#define memerr(t) ((t)==ELF_T_EHDR?ERROR_MEM_EHDR: \ + ((t)==ELF_T_PHDR?ERROR_MEM_PHDR: \ + ERROR_INTERNAL)) + +static char* +_elf32_item(Elf *elf, Elf_Type type, unsigned n, size_t off, int *flag) { + Elf_Data src, dst; + + *flag = 0; + elf_assert(n); + elf_assert(valid_type(type)); + if (off < 0 || off > elf->e_size) { + seterr(ERROR_OUTSIDE); + return NULL; + } + + src.d_type = type; + src.d_version = elf->e_version; + src.d_size = n * _fsize32(src.d_version, type); + elf_assert(src.d_size); + if (off + src.d_size > elf->e_size) { + seterr(truncerr(type)); + return NULL; + } + + dst.d_version = _elf_version; + dst.d_size = n * _msize32(dst.d_version, type); + elf_assert(dst.d_size); + + elf_assert(elf->e_data); + if (elf->e_rawdata != elf->e_data && dst.d_size <= src.d_size) { + dst.d_buf = elf->e_data + off; + } + else if (!(dst.d_buf = malloc(dst.d_size))) { + seterr(memerr(type)); + return NULL; + } + else { + *flag = 1; + } + + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + off; + } + else { + src.d_buf = elf->e_data + off; + } + + if (elf32_xlatetom(&dst, &src, elf->e_encoding)) { + if (!*flag) { + elf->e_cooked = 1; + } + return (char*)dst.d_buf; + } + + if (*flag) { + free(dst.d_buf); + *flag = 0; + } + return NULL; +} + +#undef truncerr +#undef memerr + +static int +_elf32_cook(Elf *elf) { + Elf_Scn *scn; + Elf32_Ehdr *ehdr; + Elf32_Shdr *shdr; + Scn_Data *sd; + unsigned i; + int flag; + + elf->e_ehdr = _elf32_item(elf, ELF_T_EHDR, 1, 0, &flag); + if (!(ehdr = (Elf32_Ehdr*)elf->e_ehdr)) { + return 0; + } + if (flag) { + elf->e_free_ehdr = 1; + } + if (ehdr->e_phnum && ehdr->e_phoff) { + elf->e_phdr = _elf32_item(elf, ELF_T_PHDR, ehdr->e_phnum, ehdr->e_phoff, &flag); + if (!elf->e_phdr) { + return 0; + } + if (flag) { + elf->e_free_phdr = 1; + } + elf->e_phnum = ehdr->e_phnum; + } + if (ehdr->e_shnum && ehdr->e_shoff) { + Elf_Data src, dst; + struct tmp { + Elf_Scn scn; + Scn_Data data; + } *head; + + src.d_type = ELF_T_SHDR; + src.d_version = elf->e_version; + src.d_size = _fsize32(src.d_version, ELF_T_SHDR); + elf_assert(src.d_size); + dst.d_version = EV_CURRENT; + + if (ehdr->e_shoff < 0 || ehdr->e_shoff > elf->e_size) { + seterr(ERROR_OUTSIDE); + return 0; + } + if (ehdr->e_shoff + ehdr->e_shnum * src.d_size > elf->e_size) { + seterr(ERROR_TRUNC_SHDR); + return 0; + } + + if (!(head = (struct tmp*)malloc(ehdr->e_shnum * sizeof(*head)))) { + seterr(ERROR_MEM_SCN); + return 0; + } + for (scn = NULL, i = ehdr->e_shnum; i-- > 0; ) { + head[i].scn = _elf_scn_init; + head[i].data = _elf_data_init; + head[i].scn.s_link = scn; + if (!scn) { + elf->e_scn_n = &head[i].scn; + } + scn = &head[i].scn; + sd = &head[i].data; + + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + ehdr->e_shoff + i * src.d_size; + } + else { + src.d_buf = elf->e_data + ehdr->e_shoff + i * src.d_size; + } + dst.d_buf = shdr = &scn->s_shdr32; + dst.d_size = sizeof(Elf32_Shdr); + if (!(elf32_xlatetom(&dst, &src, elf->e_encoding))) { + elf->e_scn_n = NULL; + free(head); + return 0; + } + elf_assert(dst.d_size == sizeof(Elf32_Shdr)); + elf_assert(dst.d_type == ELF_T_SHDR); + + scn->s_elf = elf; + scn->s_index = i; + scn->s_data_1 = sd; + scn->s_data_n = sd; + scn->s_type = shdr->sh_type; + scn->s_size = shdr->sh_size; + scn->s_offset = shdr->sh_offset; + + sd->sd_scn = scn; + if (valid_scntype(shdr->sh_type)) { + sd->sd_data.d_type = _elf_scn_types[shdr->sh_type]; + } + else { + sd->sd_data.d_type = ELF_T_BYTE; + } + sd->sd_data.d_size = shdr->sh_size; + sd->sd_data.d_align = shdr->sh_addralign; + sd->sd_data.d_version = _elf_version; + } + elf_assert(scn == &head[0].scn); + elf->e_scn_1 = &head[0].scn; + head[0].scn.s_freeme = 1; + } + return 1; +} + +int +_elf_cook(Elf *elf) { + elf_assert(_elf_scn_init.s_magic == SCN_MAGIC); + elf_assert(_elf_data_init.sd_magic == DATA_MAGIC); + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + elf_assert(elf->e_kind == ELF_K_ELF); + elf_assert(!elf->e_ehdr); + if (!valid_version(elf->e_version)) { + seterr(ERROR_UNKNOWN_VERSION); + } + else if (!valid_encoding(elf->e_encoding)) { + seterr(ERROR_UNKNOWN_ENCODING); + } + else if (elf->e_class == ELFCLASS32) { + return _elf32_cook(elf); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return 0; +} diff --git a/libelf/lib/data.c b/libelf/lib/data.c new file mode 100755 index 000000000..e2f91dda3 --- /dev/null +++ b/libelf/lib/data.c @@ -0,0 +1,24 @@ +/* +data.c - libelf internal variables. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +unsigned _elf_version = EV_NONE; +int _elf_errno = 0; +int _elf_fill = 0; diff --git a/libelf/lib/elf_repl.h b/libelf/lib/elf_repl.h new file mode 100755 index 000000000..fed772176 --- /dev/null +++ b/libelf/lib/elf_repl.h @@ -0,0 +1,347 @@ +/* +elf_repl.h - public header file for systems that lack it. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _ELF_REPL_H +#define _ELF_REPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Scalar data types + */ +typedef unsigned long Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned long Elf32_Off; +typedef long Elf32_Sword; +typedef unsigned long Elf32_Word; + +#define ELF32_FSZ_ADDR 4 +#define ELF32_FSZ_HALF 2 +#define ELF32_FSZ_OFF 4 +#define ELF32_FSZ_SWORD 4 +#define ELF32_FSZ_WORD 4 + +/* + * ELF header + */ +#define EI_NIDENT 16 + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* + * e-ident + */ +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 +#define ELFDATANUM 3 + +/* + * e_type + */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_NUM 5 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* + * e_machine + */ +#define EM_NONE 0 +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel i386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel i486 (do not use this one) */ +#define EM_860 7 /* Intel i860 */ +#define EM_MIPS 8 /* MIPS R3000 */ +#define EM_NUM 9 + +/* + * e_ident[EI_VERSION], e_version + */ +#define EV_NONE 0 +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* + * Section header + */ +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* + * Special section indices + */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* + * sh_type + */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* + * sh_flags + */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* + * Symbol table + */ +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* + * Special symbol indices + */ +#define STN_UNDEF 0 + +/* + * Macros for manipulating st_info + */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* + * Symbol binding + */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_NUM 3 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* + * Symbol types + */ +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_NUM 5 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +/* + * Relocation + */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +/* + * Macros for manipulating r_info + */ +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + +/* + * Note entry header + */ +typedef struct { + Elf32_Word n_namesz; /* name size */ + Elf32_Word n_descsz; /* descriptor size */ + Elf32_Word n_type; /* descriptor type */ +} Elf32_Nhdr; + +/* + * Well-known descriptor types for ET_CORE files + */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 + +/* + * Program header + */ +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* + * p_type + */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_NUM 7 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* + * p_flags + */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 +#define PF_MASKPROC 0xf0000000 + +/* + * Dynamic structure + */ +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* + * Dynamic array tags + */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_NUM 24 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +#ifdef __cplusplus +} +#endif + +#endif /* _ELF_REPL_H */ diff --git a/libelf/lib/end.c b/libelf/lib/end.c new file mode 100755 index 000000000..5771fd3a9 --- /dev/null +++ b/libelf/lib/end.c @@ -0,0 +1,114 @@ +/* +end.c - implementation of the elf_end(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if HAVE_MMAP +#include <sys/mman.h> +#endif + +static void +_elf_free(void *ptr) { + if (ptr) { + free(ptr); + } +} + +static void +_elf_free_scns(Elf *elf, Elf_Scn *scn) { + Scn_Data *sd, *tmp; + Elf_Scn *freescn; + + for (freescn = NULL; scn; scn = scn->s_link) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf == elf); + for (sd = scn->s_data_1; sd; sd = tmp) { + tmp = sd->sd_link; + if (sd->sd_free_data) { + _elf_free(sd->sd_memdata); + } + if (sd->sd_freeme) { + free(sd); + } + } + if ((sd = scn->s_rawdata)) { + if (sd->sd_free_data) { + _elf_free(sd->sd_memdata); + } + if (sd->sd_freeme) { + free(sd); + } + } + if (scn->s_freeme) { + _elf_free(freescn); + freescn = scn; + } + } + _elf_free(freescn); +} + +int +elf_end(Elf *elf) { + Elf **siblings; + + if (!elf) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (--elf->e_count) { + return elf->e_count; + } + if (elf->e_parent) { + elf_assert(elf->e_parent->e_magic == ELF_MAGIC); + elf_assert(elf->e_parent->e_kind == ELF_K_AR); + siblings = &elf->e_parent->e_members; + while (*siblings) { + if (*siblings == elf) { + *siblings = elf->e_link; + break; + } + siblings = &(*siblings)->e_link; + } + elf_end(elf->e_parent); + _elf_free(elf->e_arhdr); + } +#if HAVE_MMAP + else if (elf->e_unmap_data) { + munmap(elf->e_data, elf->e_size); + } +#endif + else { + _elf_free(elf->e_data); + } + _elf_free_scns(elf, elf->e_scn_1); + if (elf->e_rawdata != elf->e_data) { + _elf_free(elf->e_rawdata); + } + if (elf->e_free_syms) { + _elf_free(elf->e_symtab); + } + if (elf->e_free_ehdr) { + _elf_free(elf->e_ehdr); + } + if (elf->e_free_phdr) { + _elf_free(elf->e_phdr); + } + free(elf); + return 0; +} diff --git a/libelf/lib/errmsg.c b/libelf/lib/errmsg.c new file mode 100755 index 000000000..2414a088d --- /dev/null +++ b/libelf/lib/errmsg.c @@ -0,0 +1,69 @@ +/* +errmsg.c - implementation of the elf_errmsg(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if HAVE_GETTEXT +# undef HAVE_CATGETS +# include <libintl.h> +#else +# define dgettext(dom, str) str +#endif + +#if HAVE_CATGETS +# include <nl_types.h> +static nl_catd _libelf_cat = (nl_catd)0; +#endif + +#if HAVE_GETTEXT || HAVE_CATGETS +static const char domain[] = "libelf"; +#endif + +static const char *const _messages[] = { +#define __err__(a,b) b, +#include <errors.h> /* include string tables from errors.h */ +#undef __err__ +}; + +const char* +elf_errmsg(int err) { + if (err == 0) { + err = _elf_errno; + if (err == 0) { + return NULL; + } + } + else if (err == -1) { + err = _elf_errno; + } + + if (err < 0 || err >= ERROR_NUM || _messages[err] == NULL) { + err = ERROR_UNKNOWN; + } + +#if HAVE_CATGETS + if (_libelf_cat == (nl_catd)0) { + _libelf_cat = catopen(domain, 0); + } + if (_libelf_cat != (nl_catd)-1) { + return catgets(_libelf_cat, 1, err + 1, _messages[err]); + } +#endif + return dgettext(domain, _messages[err]); +} diff --git a/libelf/lib/errno.c b/libelf/lib/errno.c new file mode 100755 index 000000000..aa4ede2e1 --- /dev/null +++ b/libelf/lib/errno.c @@ -0,0 +1,28 @@ +/* +errno.c - implementation of the elf_errno(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +int +elf_errno(void) { + int tmp = _elf_errno; + + _elf_errno = 0; + return tmp; +} diff --git a/libelf/lib/errors.h b/libelf/lib/errors.h new file mode 100755 index 000000000..ea0f2b4be --- /dev/null +++ b/libelf/lib/errors.h @@ -0,0 +1,79 @@ +/* +errors.h - exhaustive list of all error codes and messages for libelf. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* dummy for xgettext */ +#define _(str) str + +__err__(ERROR_OK, _("no error")) +__err__(ERROR_UNKNOWN, _("unknown error")) +__err__(ERROR_INTERNAL, _("Internal error: unknown reason")) +__err__(ERROR_UNIMPLEMENTED, _("Internal error: not implemented")) +__err__(ERROR_WRONLY, _("Request error: update(ELF_C_WRITE) on read-only file")) +__err__(ERROR_INVALID_CMD, _("Request error: ELF_C_* invalid")) +__err__(ERROR_FDDISABLED, _("Request error: file descriptor disabled")) +__err__(ERROR_NOTARCHIVE, _("Request error: not an archive")) +__err__(ERROR_BADOFF, _("Request error: offset out of range")) +__err__(ERROR_UNKNOWN_VERSION, _("Request error: unknown version")) +__err__(ERROR_CMDMISMATCH, _("Request error: ELF_C_* mismatch with parent")) +__err__(ERROR_MEMBERWRITE, _("Request error: archive member begin() for writing")) +__err__(ERROR_FDMISMATCH, _("Request error: archive/member file descriptor mismatch")) +__err__(ERROR_NOTELF, _("Request error: not an ELF file")) +__err__(ERROR_CLASSMISMATCH, _("Request error: class file/memory mismatch")) +__err__(ERROR_UNKNOWN_TYPE, _("Request error: ELF_T_* invalid")) +__err__(ERROR_UNKNOWN_ENCODING, _("Request error: unknown data encoding")) +__err__(ERROR_DST2SMALL, _("Request error: destination too small")) +__err__(ERROR_NULLBUF, _("Request error: d_buf is NULL")) +__err__(ERROR_UNKNOWN_CLASS, _("Request error: unknown ELF class")) +__err__(ERROR_ELFSCNMISMATCH, _("Request error: scn/elf descriptor mismatch")) +__err__(ERROR_NOSUCHSCN, _("Request error: no section at index")) +__err__(ERROR_NULLSCN, _("Request error: can't manipulate null section")) +__err__(ERROR_SCNDATAMISMATCH, _("Request error: data/scn mismatch")) +__err__(ERROR_NOSTRTAB, _("Request error: no string table")) +__err__(ERROR_BADSTROFF, _("Request error: string table offset out of range")) +__err__(ERROR_RDONLY, _("Request error: update() for write on read-only file")) +__err__(ERROR_IO_SEEK, _("I/O error: seek")) +__err__(ERROR_IO_2BIG, _("I/O error: file too big for memory")) +__err__(ERROR_IO_READ, _("I/O error: raw read")) +__err__(ERROR_IO_GETSIZE, _("I/O error: get file size")) +__err__(ERROR_IO_WRITE, _("I/O error: output write")) +__err__(ERROR_IO_TRUNC, _("I/O error: output truncate")) +__err__(ERROR_VERSION_UNSET, _("Sequence error: version not set")) +__err__(ERROR_NOEHDR, _("Sequence error: must create ehdr first")) +__err__(ERROR_OUTSIDE, _("Format error: reference outside file")) +__err__(ERROR_TRUNC_ARHDR, _("Format error: archive header truncated")) +__err__(ERROR_ARFMAG, _("Format error: archive fmag")) +__err__(ERROR_ARHDR, _("Format error: archive header")) +__err__(ERROR_TRUNC_MEMBER, _("Format error: archive member truncated")) +__err__(ERROR_SIZE_ARSYMTAB, _("Format error: archive symbol table size")) +__err__(ERROR_ARSTRTAB, _("Format error: archive string table")) +__err__(ERROR_ARSPECIAL, _("Format error: archive special name unknown")) +__err__(ERROR_TRUNC_EHDR, _("Format error: ehdr truncated")) +__err__(ERROR_TRUNC_PHDR, _("Format error: phdr table truncated")) +__err__(ERROR_TRUNC_SHDR, _("Format error: shdr table truncated")) +__err__(ERROR_TRUNC_SCN, _("Format error: data region truncated")) +__err__(ERROR_SCN2SMALL, _("Format error: section sh_size too small for data")) +__err__(ERROR_MEM_ELF, _("Memory error: elf descriptor")) +__err__(ERROR_MEM_ARSYMTAB, _("Memory error: archive symbol table")) +__err__(ERROR_MEM_ARHDR, _("Memory error: archive member header")) +__err__(ERROR_MEM_EHDR, _("Memory error: ehdr")) +__err__(ERROR_MEM_PHDR, _("Memory error: phdr table")) +__err__(ERROR_MEM_SHDR, _("Memory error: shdr table")) +__err__(ERROR_MEM_SCN, _("Memory error: section descriptor")) +__err__(ERROR_MEM_SCNDATA, _("Memory error: section data")) +__err__(ERROR_MEM_OUTBUF, _("Memory error: output file space")) diff --git a/libelf/lib/ext_types.h b/libelf/lib/ext_types.h new file mode 100755 index 000000000..5dbadfffc --- /dev/null +++ b/libelf/lib/ext_types.h @@ -0,0 +1,127 @@ +/* +ext_types.h - external representation of ELF data types. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _EXT_TYPES_H +#define _EXT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Scalar data types + */ +typedef unsigned char __ext_Elf32_Addr [ELF32_FSZ_ADDR]; +typedef unsigned char __ext_Elf32_Half [ELF32_FSZ_HALF]; +typedef unsigned char __ext_Elf32_Off [ELF32_FSZ_OFF]; +typedef unsigned char __ext_Elf32_Sword [ELF32_FSZ_SWORD]; +typedef unsigned char __ext_Elf32_Word [ELF32_FSZ_WORD]; + +/* + * ELF header + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + __ext_Elf32_Half e_type; + __ext_Elf32_Half e_machine; + __ext_Elf32_Word e_version; + __ext_Elf32_Addr e_entry; + __ext_Elf32_Off e_phoff; + __ext_Elf32_Off e_shoff; + __ext_Elf32_Word e_flags; + __ext_Elf32_Half e_ehsize; + __ext_Elf32_Half e_phentsize; + __ext_Elf32_Half e_phnum; + __ext_Elf32_Half e_shentsize; + __ext_Elf32_Half e_shnum; + __ext_Elf32_Half e_shstrndx; +} __ext_Elf32_Ehdr; + +/* + * Section header + */ +typedef struct { + __ext_Elf32_Word sh_name; + __ext_Elf32_Word sh_type; + __ext_Elf32_Word sh_flags; + __ext_Elf32_Addr sh_addr; + __ext_Elf32_Off sh_offset; + __ext_Elf32_Word sh_size; + __ext_Elf32_Word sh_link; + __ext_Elf32_Word sh_info; + __ext_Elf32_Word sh_addralign; + __ext_Elf32_Word sh_entsize; +} __ext_Elf32_Shdr; + +/* + * Symbol table + */ +typedef struct { + __ext_Elf32_Word st_name; + __ext_Elf32_Addr st_value; + __ext_Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + __ext_Elf32_Half st_shndx; +} __ext_Elf32_Sym; + +/* + * Relocation + */ +typedef struct { + __ext_Elf32_Addr r_offset; + __ext_Elf32_Word r_info; +} __ext_Elf32_Rel; + +typedef struct { + __ext_Elf32_Addr r_offset; + __ext_Elf32_Word r_info; + __ext_Elf32_Sword r_addend; +} __ext_Elf32_Rela; + +/* + * Program header + */ +typedef struct { + __ext_Elf32_Word p_type; + __ext_Elf32_Off p_offset; + __ext_Elf32_Addr p_vaddr; + __ext_Elf32_Addr p_paddr; + __ext_Elf32_Word p_filesz; + __ext_Elf32_Word p_memsz; + __ext_Elf32_Word p_flags; + __ext_Elf32_Word p_align; +} __ext_Elf32_Phdr; + +/* + * Dynamic structure + */ +typedef struct { + __ext_Elf32_Sword d_tag; + union { + __ext_Elf32_Word d_val; + __ext_Elf32_Addr d_ptr; + } d_un; +} __ext_Elf32_Dyn; + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT_TYPES_H */ diff --git a/libelf/lib/fill.c b/libelf/lib/fill.c new file mode 100755 index 000000000..dc33256dc --- /dev/null +++ b/libelf/lib/fill.c @@ -0,0 +1,25 @@ +/* +fill.c - implementation of the elf_fill(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +void +elf_fill(int fill) { + _elf_fill = fill; +} diff --git a/libelf/lib/flag.c b/libelf/lib/flag.c new file mode 100755 index 000000000..58117998a --- /dev/null +++ b/libelf/lib/flag.c @@ -0,0 +1,88 @@ +/* +flag.c - implementation of the elf_flag*(3) functions. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +static unsigned +_elf_flag(unsigned *f, Elf_Cmd cmd, unsigned flags) { + if (cmd == ELF_C_SET) { + return *f |= flags; + } + if (cmd == ELF_C_CLR) { + return *f &= ~flags; + } + seterr(ERROR_INVALID_CMD); + return 0; +} + +unsigned +elf_flagdata(Elf_Data *data, Elf_Cmd cmd, unsigned flags) { + Scn_Data *sd = (Scn_Data*)data; + + if (!sd) { + return 0; + } + elf_assert(sd->sd_magic == DATA_MAGIC); + return _elf_flag(&sd->sd_data_flags, cmd, flags); +} + +unsigned +elf_flagehdr(Elf *elf, Elf_Cmd cmd, unsigned flags) { + if (!elf) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + return _elf_flag(&elf->e_ehdr_flags, cmd, flags); +} + +unsigned +elf_flagelf(Elf *elf, Elf_Cmd cmd, unsigned flags) { + if (!elf) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + return _elf_flag(&elf->e_elf_flags, cmd, flags); +} + +unsigned +elf_flagphdr(Elf *elf, Elf_Cmd cmd, unsigned flags) { + if (!elf) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + return _elf_flag(&elf->e_phdr_flags, cmd, flags); +} + +unsigned +elf_flagscn(Elf_Scn *scn, Elf_Cmd cmd, unsigned flags) { + if (!scn) { + return 0; + } + elf_assert(scn->s_magic == SCN_MAGIC); + return _elf_flag(&scn->s_scn_flags, cmd, flags); +} + +unsigned +elf_flagshdr(Elf_Scn *scn, Elf_Cmd cmd, unsigned flags) { + if (!scn) { + return 0; + } + elf_assert(scn->s_magic == SCN_MAGIC); + return _elf_flag(&scn->s_shdr_flags, cmd, flags); +} diff --git a/libelf/lib/gelf.h b/libelf/lib/gelf.h new file mode 100755 index 000000000..a1494a1b5 --- /dev/null +++ b/libelf/lib/gelf.h @@ -0,0 +1,153 @@ +/* +gelf.h - public header file for libelf. +Copyright (C) 2000 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* @(#) Id: gelf.h,v 1.8 2001/10/05 19:05:25 michael Exp */ + +#ifndef _GELF_H +#define _GELF_H + +#if __LIBELF_INTERNAL__ +#include <libelf.h> +#else /* __LIBELF_INTERNAL__ */ +#include <libelf/libelf.h> +#endif /* __LIBELF_INTERNAL__ */ + +#if __LIBELF_NEED_LINK_H +#include <link.h> +#endif /* __LIBELF_NEED_LINK_H */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef __P +# if __STDC__ || defined(__cplusplus) +# define __P(args) args +# else /* __STDC__ || defined(__cplusplus) */ +# define __P(args) () +# endif /* __STDC__ || defined(__cplusplus) */ +#endif /* __P */ + +#if !__LIBELF64 + +#error "GElf is not supported on this system." + +#else /* __LIBELF64 */ + +typedef Elf64_Addr GElf_Addr; +typedef Elf64_Half GElf_Half; +typedef Elf64_Off GElf_Off; +typedef Elf64_Sword GElf_Sword; +typedef Elf64_Word GElf_Word; +typedef Elf64_Sxword GElf_Sxword; +typedef Elf64_Xword GElf_Xword; + +typedef Elf64_Ehdr GElf_Ehdr; +typedef Elf64_Phdr GElf_Phdr; +typedef Elf64_Shdr GElf_Shdr; +typedef Elf64_Dyn GElf_Dyn; +typedef Elf64_Rel GElf_Rel; +typedef Elf64_Rela GElf_Rela; +typedef Elf64_Sym GElf_Sym; + +/* + * Symbol versioning + */ +#if __LIBELF_SYMBOL_VERSIONS +typedef Elf64_Verdef GElf_Verdef; +typedef Elf64_Verneed GElf_Verneed; +typedef Elf64_Verdaux GElf_Verdaux; +typedef Elf64_Vernaux GElf_Vernaux; +#endif /* __LIBELF_SYMBOL_VERSIONS */ + +/* + * These types aren't implemented (yet) + * +typedef Elf64_Move GElf_Move; +typedef Elf64_Syminfo GElf_Syminfo; + */ + +/* + * Generic macros + */ +#define GELF_ST_BIND ELF64_ST_BIND +#define GELF_ST_TYPE ELF64_ST_TYPE +#define GELF_ST_INFO ELF64_ST_INFO + +#define GELF_R_TYPE ELF64_R_TYPE +#define GELF_R_SYM ELF64_R_SYM +#define GELF_R_INFO ELF64_R_INFO + +/* + * Function declarations + */ +extern int gelf_getclass __P((Elf *__elf)); + +extern size_t gelf_fsize __P((Elf *__elf, Elf_Type __type, size_t __count, unsigned __ver)); + +extern Elf_Data *gelf_xlatetof __P((Elf *__elf, Elf_Data *__dst, const Elf_Data *__src, unsigned __encode)); +extern Elf_Data *gelf_xlatetom __P((Elf *__elf, Elf_Data *__dst, const Elf_Data *__src, unsigned __encode)); + +extern GElf_Ehdr *gelf_getehdr __P((Elf *__elf, GElf_Ehdr *__dst)); +extern int gelf_update_ehdr __P((Elf *__elf, GElf_Ehdr *__src)); +extern unsigned long gelf_newehdr __P((Elf *__elf, int __elfclass)); + +extern GElf_Phdr *gelf_getphdr __P((Elf *__elf, int ndx, GElf_Phdr *__dst)); +extern int gelf_update_phdr __P((Elf *__elf, int ndx, GElf_Phdr *__src)); +extern unsigned long gelf_newphdr __P((Elf *__elf, size_t __phnum)); + +extern GElf_Shdr *gelf_getshdr __P((Elf_Scn *__scn, GElf_Shdr *__dst)); +extern int gelf_update_shdr __P((Elf_Scn *__scn, GElf_Shdr *__src)); + +extern GElf_Dyn *gelf_getdyn __P((Elf_Data *__src, int __ndx, GElf_Dyn *__dst)); +extern int gelf_update_dyn __P((Elf_Data *__dst, int __ndx, GElf_Dyn *__src)); + +extern GElf_Rel *gelf_getrel __P((Elf_Data *__src, int __ndx, GElf_Rel *__dst)); +extern int gelf_update_rel __P((Elf_Data *__dst, int __ndx, GElf_Rel *__src)); + +extern GElf_Rela *gelf_getrela __P((Elf_Data *__src, int __ndx, GElf_Rela *__dst)); +extern int gelf_update_rela __P((Elf_Data *__dst, int __ndx, GElf_Rela *__src)); + +extern GElf_Sym *gelf_getsym __P((Elf_Data *__src, int __ndx, GElf_Sym *__dst)); +extern int gelf_update_sym __P((Elf_Data *__dst, int __ndx, GElf_Sym *__src)); + +extern long gelf_checksum __P((Elf *__elf)); + +/* + * These functions aren't implemented (yet) + * +extern GElf_Move *gelf_getmove __P((Elf_Data *__src, int __ndx, GElf_Move *__src)); +extern int gelf_update_move __P((Elf_Data *__dst, int __ndx, GElf_Move *__src)); + * +extern GElf_Syminfo* gelf_getsyminfo __P((Elf_Data *__src, int __ndx, GElf_Syminfo *__dst)); +extern int gelf_update_syminfo __P((Elf_Data *__dst, int __ndx, GElf_Syminfo *__src)); + */ + +/* + * Extensions (not available in other versions of libelf) + */ +extern size_t gelf_msize __P((Elf *__elf, Elf_Type __type, size_t __count, unsigned __ver)); + +#endif /* __LIBELF64 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GELF_H */ diff --git a/libelf/lib/gelfehdr.c b/libelf/lib/gelfehdr.c new file mode 100755 index 000000000..9b88080c0 --- /dev/null +++ b/libelf/lib/gelfehdr.c @@ -0,0 +1,138 @@ +/* +gelfehdr.c - gelf_* translation functions. +Copyright (C) 2000 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) Id: gelfehdr.c,v 1.3 2001/10/07 19:33:03 michael Exp "; +#endif /* lint */ + +#define check_and_copy(type, d, s, name, eret) \ + do { \ + if (sizeof((d)->name) < sizeof((s)->name) \ + && (type)(s)->name != (s)->name) { \ + seterr(ERROR_BADVALUE); \ + return (eret); \ + } \ + (d)->name = (type)(s)->name; \ + } while (0) + +GElf_Ehdr* +gelf_getehdr(Elf *elf, GElf_Ehdr *dst) { + GElf_Ehdr buf; + char *tmp; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + tmp = _elf_getehdr(elf, elf->e_class); + if (!tmp) { + return NULL; + } + if (!dst) { + dst = &buf; + } + if (elf->e_class == ELFCLASS64) { + *dst = *(Elf64_Ehdr*)tmp; + } + else if (elf->e_class == ELFCLASS32) { + Elf32_Ehdr *src = (Elf32_Ehdr*)tmp; + + memcpy(dst->e_ident, src->e_ident, EI_NIDENT); + check_and_copy(GElf_Half, dst, src, e_type, NULL); + check_and_copy(GElf_Half, dst, src, e_machine, NULL); + check_and_copy(GElf_Word, dst, src, e_version, NULL); + check_and_copy(GElf_Addr, dst, src, e_entry, NULL); + check_and_copy(GElf_Off, dst, src, e_phoff, NULL); + check_and_copy(GElf_Off, dst, src, e_shoff, NULL); + check_and_copy(GElf_Word, dst, src, e_flags, NULL); + check_and_copy(GElf_Half, dst, src, e_ehsize, NULL); + check_and_copy(GElf_Half, dst, src, e_phentsize, NULL); + check_and_copy(GElf_Half, dst, src, e_phnum, NULL); + check_and_copy(GElf_Half, dst, src, e_shentsize, NULL); + check_and_copy(GElf_Half, dst, src, e_shnum, NULL); + check_and_copy(GElf_Half, dst, src, e_shstrndx, NULL); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Ehdr*)malloc(sizeof(GElf_Ehdr)); + if (!dst) { + seterr(ERROR_MEM_EHDR); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_ehdr(Elf *elf, GElf_Ehdr *src) { + char *tmp; + + if (!elf || !src) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + tmp = _elf_getehdr(elf, elf->e_class); + if (!tmp) { + return 0; + } + if (elf->e_class == ELFCLASS64) { + *(Elf64_Ehdr*)tmp = *src; + } + else if (elf->e_class == ELFCLASS32) { + Elf32_Ehdr *dst = (Elf32_Ehdr*)tmp; + + memcpy(dst->e_ident, src->e_ident, EI_NIDENT); + check_and_copy(Elf32_Half, dst, src, e_type, 0); + check_and_copy(Elf32_Half, dst, src, e_machine, 0); + check_and_copy(Elf32_Word, dst, src, e_version, 0); + check_and_copy(Elf32_Addr, dst, src, e_entry, 0); + check_and_copy(Elf32_Off, dst, src, e_phoff, 0); + check_and_copy(Elf32_Off, dst, src, e_shoff, 0); + check_and_copy(Elf32_Word, dst, src, e_flags, 0); + check_and_copy(Elf32_Half, dst, src, e_ehsize, 0); + check_and_copy(Elf32_Half, dst, src, e_phentsize, 0); + check_and_copy(Elf32_Half, dst, src, e_phnum, 0); + check_and_copy(Elf32_Half, dst, src, e_shentsize, 0); + check_and_copy(Elf32_Half, dst, src, e_shnum, 0); + check_and_copy(Elf32_Half, dst, src, e_shstrndx, 0); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/gelfphdr.c b/libelf/lib/gelfphdr.c new file mode 100755 index 000000000..c5737a9eb --- /dev/null +++ b/libelf/lib/gelfphdr.c @@ -0,0 +1,146 @@ +/* +gelfphdr.c - gelf_* translation functions. +Copyright (C) 2000 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) Id: gelfphdr.c,v 1.3 2001/10/07 19:33:03 michael Exp "; +#endif /* lint */ + +#define check_and_copy(type, d, s, name, eret) \ + do { \ + if (sizeof((d)->name) < sizeof((s)->name) \ + && (type)(s)->name != (s)->name) { \ + seterr(ERROR_BADVALUE); \ + return (eret); \ + } \ + (d)->name = (type)(s)->name; \ + } while (0) + +GElf_Phdr* +gelf_getphdr(Elf *elf, int ndx, GElf_Phdr *dst) { + GElf_Phdr buf; + char *tmp; + size_t n; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + tmp = _elf_getphdr(elf, elf->e_class); + if (!tmp) { + return NULL; + } + if (ndx < 0 || ndx >= elf->e_phnum) { + seterr(ERROR_BADINDEX); + return NULL; + } + n = _msize(elf->e_class, _elf_version, ELF_T_PHDR); + if (n == 0) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (!dst) { + dst = &buf; + } + if (elf->e_class == ELFCLASS64) { + *dst = *(Elf64_Phdr*)(tmp + ndx * n); + } + else if (elf->e_class == ELFCLASS32) { + Elf32_Phdr *src = (Elf32_Phdr*)(tmp + ndx * n); + + check_and_copy(GElf_Word, dst, src, p_type, NULL); + check_and_copy(GElf_Word, dst, src, p_flags, NULL); + check_and_copy(GElf_Off, dst, src, p_offset, NULL); + check_and_copy(GElf_Addr, dst, src, p_vaddr, NULL); + check_and_copy(GElf_Addr, dst, src, p_paddr, NULL); + check_and_copy(GElf_Xword, dst, src, p_filesz, NULL); + check_and_copy(GElf_Xword, dst, src, p_memsz, NULL); + check_and_copy(GElf_Xword, dst, src, p_align, NULL); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Phdr*)malloc(sizeof(GElf_Phdr)); + if (!dst) { + seterr(ERROR_MEM_PHDR); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_phdr(Elf *elf, int ndx, GElf_Phdr *src) { + char *tmp; + size_t n; + + if (!elf || !src) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + tmp = _elf_getphdr(elf, elf->e_class); + if (!tmp) { + return 0; + } + if (ndx < 0 || ndx >= elf->e_phnum) { + seterr(ERROR_BADINDEX); + return 0; + } + n = _msize(elf->e_class, _elf_version, ELF_T_PHDR); + if (n == 0) { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + if (elf->e_class == ELFCLASS64) { + *(Elf64_Phdr*)(tmp + ndx * n) = *src; + } + else if (elf->e_class == ELFCLASS32) { + Elf32_Phdr *dst = (Elf32_Phdr*)(tmp + ndx * n); + + check_and_copy(Elf32_Word, dst, src, p_type, 0); + check_and_copy(Elf32_Off, dst, src, p_offset, 0); + check_and_copy(Elf32_Addr, dst, src, p_vaddr, 0); + check_and_copy(Elf32_Addr, dst, src, p_paddr, 0); + check_and_copy(Elf32_Word, dst, src, p_filesz, 0); + check_and_copy(Elf32_Word, dst, src, p_memsz, 0); + check_and_copy(Elf32_Word, dst, src, p_flags, 0); + check_and_copy(Elf32_Word, dst, src, p_align, 0); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/gelfshdr.c b/libelf/lib/gelfshdr.c new file mode 100755 index 000000000..93e6a0cf4 --- /dev/null +++ b/libelf/lib/gelfshdr.c @@ -0,0 +1,123 @@ +/* +gelfshdr.c - gelf_* translation functions. +Copyright (C) 2000 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) Id: gelfshdr.c,v 1.4 2001/10/07 19:33:03 michael Exp "; +#endif /* lint */ + +#define check_and_copy(type, d, s, name, eret) \ + do { \ + if (sizeof((d)->name) < sizeof((s)->name) \ + && (type)(s)->name != (s)->name) { \ + seterr(ERROR_BADVALUE); \ + return (eret); \ + } \ + (d)->name = (type)(s)->name; \ + } while (0) + +GElf_Shdr* +gelf_getshdr(Elf_Scn *scn, GElf_Shdr *dst) { + GElf_Shdr buf; + + if (!scn) { + return NULL; + } + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf); + elf_assert(scn->s_elf->e_magic == ELF_MAGIC); + if (!dst) { + dst = &buf; + } + if (scn->s_elf->e_class == ELFCLASS64) { + *dst = scn->s_shdr64; + } + else if (scn->s_elf->e_class == ELFCLASS32) { + Elf32_Shdr *src = &scn->s_shdr32; + + check_and_copy(GElf_Word, dst, src, sh_name, NULL); + check_and_copy(GElf_Word, dst, src, sh_type, NULL); + check_and_copy(GElf_Xword, dst, src, sh_flags, NULL); + check_and_copy(GElf_Addr, dst, src, sh_addr, NULL); + check_and_copy(GElf_Off, dst, src, sh_offset, NULL); + check_and_copy(GElf_Xword, dst, src, sh_size, NULL); + check_and_copy(GElf_Word, dst, src, sh_link, NULL); + check_and_copy(GElf_Word, dst, src, sh_info, NULL); + check_and_copy(GElf_Xword, dst, src, sh_addralign, NULL); + check_and_copy(GElf_Xword, dst, src, sh_entsize, NULL); + } + else if (valid_class(scn->s_elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Shdr*)malloc(sizeof(GElf_Shdr)); + if (!dst) { + seterr(ERROR_MEM_SHDR); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *src) { + if (!scn || !src) { + return 0; + } + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf); + elf_assert(scn->s_elf->e_magic == ELF_MAGIC); + if (scn->s_elf->e_class == ELFCLASS64) { + scn->s_shdr64 = *src; + } + else if (scn->s_elf->e_class == ELFCLASS32) { + Elf32_Shdr *dst = &scn->s_shdr32; + + check_and_copy(Elf32_Word, dst, src, sh_name, 0); + check_and_copy(Elf32_Word, dst, src, sh_type, 0); + check_and_copy(Elf32_Word, dst, src, sh_flags, 0); + check_and_copy(Elf32_Addr, dst, src, sh_addr, 0); + check_and_copy(Elf32_Off, dst, src, sh_offset, 0); + check_and_copy(Elf32_Word, dst, src, sh_size, 0); + check_and_copy(Elf32_Word, dst, src, sh_link, 0); + check_and_copy(Elf32_Word, dst, src, sh_info, 0); + check_and_copy(Elf32_Word, dst, src, sh_addralign, 0); + check_and_copy(Elf32_Word, dst, src, sh_entsize, 0); + } + else if (valid_class(scn->s_elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/gelftrans.c b/libelf/lib/gelftrans.c new file mode 100755 index 000000000..7a265b90c --- /dev/null +++ b/libelf/lib/gelftrans.c @@ -0,0 +1,407 @@ +/* +gelftrans.c - gelf_* translation functions. +Copyright (C) 2000 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) Id: gelftrans.c,v 1.6 2001/10/07 19:33:03 michael Exp "; +#endif /* lint */ + +#define check_and_copy(type, d, s, name, eret) \ + do { \ + if (sizeof((d)->name) < sizeof((s)->name) \ + && (type)(s)->name != (s)->name) { \ + seterr(ERROR_BADVALUE); \ + return (eret); \ + } \ + (d)->name = (type)(s)->name; \ + } while (0) + +/* + * These macros are missing on some Linux systems + */ +#if !defined(ELF32_R_SYM) || !defined(ELF32_R_TYPE) || !defined(ELF32_R_INFO) +# undef ELF32_R_SYM +# undef ELF32_R_TYPE +# undef ELF32_R_INFO +# define ELF32_R_SYM(i) ((i)>>8) +# define ELF32_R_TYPE(i) ((unsigned char)(i)) +# define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) +#endif /* !defined(...) */ + +#if !defined(ELF64_R_SYM) || !defined(ELF64_R_TYPE) || !defined(ELF64_R_INFO) +# undef ELF64_R_SYM +# undef ELF64_R_TYPE +# undef ELF64_R_INFO +# define ELF64_R_SYM(i) ((i)>>32) +# define ELF64_R_TYPE(i) ((i)&0xffffffffL) +# define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+((t)&0xffffffffL)) +#endif /* !defined(...) */ + +static char* +get_addr_and_class(const Elf_Data *data, int ndx, Elf_Type type, unsigned *cls) { + Scn_Data *sd = (Scn_Data*)data; + Elf_Scn *scn; + Elf *elf; + size_t n; + + if (!sd) { + return NULL; + } + elf_assert(sd->sd_magic == DATA_MAGIC); + scn = sd->sd_scn; + elf_assert(scn); + elf_assert(scn->s_magic == SCN_MAGIC); + elf = scn->s_elf; + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return NULL; + } + if (!valid_class(elf->e_class)) { + seterr(ERROR_UNKNOWN_CLASS); + return NULL; + } + if (data->d_type != type) { + seterr(ERROR_BADTYPE); + return NULL; + } + n = _msize(elf->e_class, data->d_version, type); + if (n == 0) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (ndx < 0 || data->d_size < (ndx + 1) * n) { + seterr(ERROR_BADINDEX); + return NULL; + } + if (!data->d_buf) { + seterr(ERROR_NULLBUF); + return NULL; + } + if (cls) { + *cls = elf->e_class; + } + return (char*)data->d_buf + n * ndx; +} + +GElf_Sym* +gelf_getsym(Elf_Data *src, int ndx, GElf_Sym *dst) { + GElf_Sym buf; + unsigned cls; + char *tmp; + + if (!dst) { + dst = &buf; + } + tmp = get_addr_and_class(src, ndx, ELF_T_SYM, &cls); + if (!tmp) { + return NULL; + } + if (cls == ELFCLASS64) { + *dst = *(Elf64_Sym*)tmp; + } + else if (cls == ELFCLASS32) { + Elf32_Sym *src = (Elf32_Sym*)tmp; + + check_and_copy(GElf_Word, dst, src, st_name, NULL); + check_and_copy(unsigned char, dst, src, st_info, NULL); + check_and_copy(unsigned char, dst, src, st_other, NULL); + check_and_copy(GElf_Half, dst, src, st_shndx, NULL); + check_and_copy(GElf_Addr, dst, src, st_value, NULL); + check_and_copy(GElf_Xword, dst, src, st_size, NULL); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Sym*)malloc(sizeof(GElf_Sym)); + if (!dst) { + seterr(ERROR_MEM_SYM); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_sym(Elf_Data *dst, int ndx, GElf_Sym *src) { + unsigned cls; + char *tmp; + + tmp = get_addr_and_class(dst, ndx, ELF_T_SYM, &cls); + if (!tmp) { + return 0; + } + if (cls == ELFCLASS64) { + *(Elf64_Sym*)tmp = *src; + } + else if (cls == ELFCLASS32) { + Elf32_Sym *dst = (Elf32_Sym*)tmp; + + check_and_copy(Elf32_Word, dst, src, st_name, 0); + check_and_copy(Elf32_Addr, dst, src, st_value, 0); + check_and_copy(Elf32_Word, dst, src, st_size, 0); + check_and_copy(unsigned char, dst, src, st_info, 0); + check_and_copy(unsigned char, dst, src, st_other, 0); + check_and_copy(Elf32_Half, dst, src, st_shndx, 0); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + return 1; +} + +GElf_Dyn* +gelf_getdyn(Elf_Data *src, int ndx, GElf_Dyn *dst) { + GElf_Dyn buf; + unsigned cls; + char *tmp; + + if (!dst) { + dst = &buf; + } + tmp = get_addr_and_class(src, ndx, ELF_T_DYN, &cls); + if (!tmp) { + return NULL; + } + if (cls == ELFCLASS64) { + *dst = *(Elf64_Dyn*)tmp; + } + else if (cls == ELFCLASS32) { + Elf32_Dyn *src = (Elf32_Dyn*)tmp; + + check_and_copy(GElf_Sxword, dst, src, d_tag, NULL); + check_and_copy(GElf_Xword, dst, src, d_un.d_val, NULL); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Dyn*)malloc(sizeof(GElf_Dyn)); + if (!dst) { + seterr(ERROR_MEM_DYN); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_dyn(Elf_Data *dst, int ndx, GElf_Dyn *src) { + unsigned cls; + char *tmp; + + tmp = get_addr_and_class(dst, ndx, ELF_T_DYN, &cls); + if (!tmp) { + return 0; + } + if (cls == ELFCLASS64) { + *(Elf64_Dyn*)tmp = *src; + } + else if (cls == ELFCLASS32) { + Elf32_Dyn *dst = (Elf32_Dyn*)tmp; + + check_and_copy(Elf32_Sword, dst, src, d_tag, 0); + check_and_copy(Elf32_Word, dst, src, d_un.d_val, 0); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + return 1; +} + +GElf_Rela* +gelf_getrela(Elf_Data *src, int ndx, GElf_Rela *dst) { + GElf_Rela buf; + unsigned cls; + char *tmp; + + if (!dst) { + dst = &buf; + } + tmp = get_addr_and_class(src, ndx, ELF_T_RELA, &cls); + if (!tmp) { + return NULL; + } + if (cls == ELFCLASS64) { + *dst = *(Elf64_Rela*)tmp; + } + else if (cls == ELFCLASS32) { + Elf32_Rela *src = (Elf32_Rela*)tmp; + + check_and_copy(GElf_Addr, dst, src, r_offset, NULL); + dst->r_info = ELF64_R_INFO((Elf64_Xword)ELF32_R_SYM(src->r_info), + (Elf64_Xword)ELF32_R_TYPE(src->r_info)); + check_and_copy(GElf_Sxword, dst, src, r_addend, NULL); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Rela*)malloc(sizeof(GElf_Rela)); + if (!dst) { + seterr(ERROR_MEM_RELA); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_rela(Elf_Data *dst, int ndx, GElf_Rela *src) { + unsigned cls; + char *tmp; + + tmp = get_addr_and_class(dst, ndx, ELF_T_RELA, &cls); + if (!tmp) { + return 0; + } + if (cls == ELFCLASS64) { + *(Elf64_Rela*)tmp = *src; + } + else if (cls == ELFCLASS32) { + Elf32_Rela *dst = (Elf32_Rela*)tmp; + + check_and_copy(Elf32_Addr, dst, src, r_offset, 0); + if (ELF64_R_SYM(src->r_info) > 0xffffffUL + || ELF64_R_TYPE(src->r_info) > 0xffUL) { + seterr(ERROR_BADVALUE); + return 0; + } + dst->r_info = ELF32_R_INFO((Elf32_Word)ELF64_R_SYM(src->r_info), + (Elf32_Word)ELF64_R_TYPE(src->r_info)); + check_and_copy(Elf32_Sword, dst, src, r_addend, 0); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + return 1; +} + +GElf_Rel* +gelf_getrel(Elf_Data *src, int ndx, GElf_Rel *dst) { + GElf_Rel buf; + unsigned cls; + char *tmp; + + if (!dst) { + dst = &buf; + } + tmp = get_addr_and_class(src, ndx, ELF_T_REL, &cls); + if (!tmp) { + return NULL; + } + if (cls == ELFCLASS64) { + *dst = *(Elf64_Rel*)tmp; + } + else if (cls == ELFCLASS32) { + Elf32_Rel *src = (Elf32_Rel*)tmp; + + check_and_copy(GElf_Addr, dst, src, r_offset, NULL); + dst->r_info = ELF64_R_INFO((Elf64_Xword)ELF32_R_SYM(src->r_info), + (Elf64_Xword)ELF32_R_TYPE(src->r_info)); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (dst == &buf) { + dst = (GElf_Rel*)malloc(sizeof(GElf_Rel)); + if (!dst) { + seterr(ERROR_MEM_REL); + return NULL; + } + *dst = buf; + } + return dst; +} + +int +gelf_update_rel(Elf_Data *dst, int ndx, GElf_Rel *src) { + unsigned cls; + char *tmp; + + tmp = get_addr_and_class(dst, ndx, ELF_T_REL, &cls); + if (!tmp) { + return 0; + } + if (cls == ELFCLASS64) { + *(Elf64_Rel*)tmp = *src; + } + else if (cls == ELFCLASS32) { + Elf32_Rel *dst = (Elf32_Rel*)tmp; + + check_and_copy(Elf32_Addr, dst, src, r_offset, 0); + if (ELF64_R_SYM(src->r_info) > 0xffffffUL + || ELF64_R_TYPE(src->r_info) > 0xffUL) { + seterr(ERROR_BADVALUE); + return 0; + } + dst->r_info = ELF32_R_INFO((Elf32_Word)ELF64_R_SYM(src->r_info), + (Elf32_Word)ELF64_R_TYPE(src->r_info)); + } + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + return 1; +} + +#if 0 + +GElf_Syminfo* +gelf_getsyminfo(Elf_Data *src, int ndx, GElf_Syminfo *dst) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; +} + +int +gelf_update_syminfo(Elf_Data *dst, int ndx, GElf_Syminfo *src) { + seterr(ERROR_UNIMPLEMENTED); + return 0; +} + +GElf_Move* +gelf_getmove(Elf_Data *src, int ndx, GElf_Move *src) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; +} + +int +gelf_update_move(Elf_Data *dst, int ndx, GElf_Move *src) { + seterr(ERROR_UNIMPLEMENTED); + return 0; +} + +#endif + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/getarhdr.c b/libelf/lib/getarhdr.c new file mode 100755 index 000000000..deef09735 --- /dev/null +++ b/libelf/lib/getarhdr.c @@ -0,0 +1,33 @@ +/* +getarhdr.c - implementation of the elf_getarhdr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Arhdr* +elf_getarhdr(Elf *elf) { + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_arhdr) { + return elf->e_arhdr; + } + seterr(ERROR_NOTARCHIVE); + return NULL; +} diff --git a/libelf/lib/getarsym.c b/libelf/lib/getarsym.c new file mode 100755 index 000000000..f492b974f --- /dev/null +++ b/libelf/lib/getarsym.c @@ -0,0 +1,83 @@ +/* +getarsym.c - implementation of the elf_getarsym(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <byteswap.h> + +Elf_Arsym* +elf_getarsym(Elf *elf, size_t *ptr) { + Elf_Arsym *syms; + size_t count; + size_t tmp; + size_t i; + char *s; + char *e; + + if (!ptr) { + ptr = &tmp; + } + *ptr = 0; + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_AR) { + seterr(ERROR_NOTARCHIVE); + return NULL; + } + if (elf->e_symtab && !elf->e_free_syms) { + if (elf->e_symlen < 4) { + seterr(ERROR_SIZE_ARSYMTAB); + return NULL; + } + count = __load_u32M(elf->e_symtab); + if (elf->e_symlen < 4 * (count + 1)) { + seterr(ERROR_SIZE_ARSYMTAB); + return NULL; + } + if (!(syms = (Elf_Arsym*)malloc((count + 1) * sizeof(*syms)))) { + seterr(ERROR_MEM_ARSYMTAB); + return NULL; + } + s = elf->e_symtab + 4 * (count + 1); + e = elf->e_symtab + elf->e_symlen; + for (i = 0; i < count; i++, s++) { + syms[i].as_name = s; + while (s < e && *s) { + s++; + } + if (s >= e) { + seterr(ERROR_SIZE_ARSYMTAB); + free(syms); + return NULL; + } + elf_assert(!*s); + syms[i].as_hash = elf_hash(syms[i].as_name); + syms[i].as_off = __load_u32M(elf->e_symtab + 4 * (i + 1)); + } + syms[count].as_name = NULL; + syms[count].as_hash = ~0UL; + syms[count].as_off = 0; + elf->e_symtab = (char*)syms; + elf->e_symlen = count + 1; + elf->e_free_syms = 1; + } + *ptr = elf->e_symlen; + return (Elf_Arsym*)elf->e_symtab; +} diff --git a/libelf/lib/getbase.c b/libelf/lib/getbase.c new file mode 100755 index 000000000..e2d924e44 --- /dev/null +++ b/libelf/lib/getbase.c @@ -0,0 +1,29 @@ +/* +getbase.c - implementation of the elf_getbase(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +off_t +elf_getbase(Elf *elf) { + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + return (off_t)elf->e_base; +} diff --git a/libelf/lib/getdata.c b/libelf/lib/getdata.c new file mode 100755 index 000000000..fb6be910b --- /dev/null +++ b/libelf/lib/getdata.c @@ -0,0 +1,129 @@ +/* +getdata.c - implementation of the elf_getdata(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +static Elf_Data* +_elf32_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) { + Elf_Data src, dst; + size_t fsize, msize; + int flag = 0; + + src = dst = sd->sd_data; + src.d_version = elf->e_version; + fsize = _fsize32(src.d_version, src.d_type); + elf_assert(fsize); + msize = _msize32(dst.d_version, src.d_type); + elf_assert(msize); + if (fsize != msize) { + dst.d_size = (dst.d_size / fsize) * msize; + } + + elf_assert(elf->e_data); + if (elf->e_rawdata != elf->e_data && dst.d_size <= src.d_size) { + dst.d_buf = elf->e_data + scn->s_offset; + } + else if (!(dst.d_buf = malloc(dst.d_size))) { + seterr(ERROR_MEM_SCNDATA); + return NULL; + } + else { + flag = 1; + } + + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + scn->s_offset; + } + else { + src.d_buf = elf->e_data + scn->s_offset; + } + + if (elf32_xlatetom(&dst, &src, elf->e_encoding)) { + sd->sd_memdata = (char*)dst.d_buf; + sd->sd_data = dst; + if (!(sd->sd_free_data = flag)) { + elf->e_cooked = 1; + } + return (Elf_Data*)sd; + } + + if (flag) { + free(dst.d_buf); + } + return NULL; +} + +Elf_Data* +elf_getdata(Elf_Scn *scn, Elf_Data *data) { + Scn_Data *sd = (Scn_Data*)data; + Elf *elf; + + if (!scn) { + return NULL; + } + elf_assert(scn->s_magic == SCN_MAGIC); + if (scn->s_index == SHN_UNDEF) { + seterr(ERROR_NULLSCN); + } + else if (sd) { + if (sd->sd_scn == scn) { + /* + * sd_link allocated by elf_newdata(). + */ + return (Elf_Data*)sd->sd_link; + } + seterr(ERROR_SCNDATAMISMATCH); + } + else if ((sd = scn->s_data_1)) { + elf = scn->s_elf; + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + if (sd->sd_freeme) { + /* allocated by elf_newdata() */ + return (Elf_Data*)sd; + } + else if (scn->s_type == SHT_NULL) { + seterr(ERROR_NULLSCN); + } + else if (sd->sd_memdata) { + /* already cooked */ + return (Elf_Data*)sd; + } + else if (scn->s_offset < 0 || scn->s_offset > elf->e_size) { + seterr(ERROR_OUTSIDE); + } + else if (scn->s_type == SHT_NOBITS || !scn->s_size) { + /* no data to read */ + return (Elf_Data*)sd; + } + else if (scn->s_offset + scn->s_size > elf->e_size) { + seterr(ERROR_TRUNC_SCN); + } + else if (elf->e_class == ELFCLASS32) { + return _elf32_cook_scn(elf, scn, sd); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + } + return NULL; +} diff --git a/libelf/lib/getident.c b/libelf/lib/getident.c new file mode 100755 index 000000000..dcc15cfb6 --- /dev/null +++ b/libelf/lib/getident.c @@ -0,0 +1,44 @@ +/* +getident.c - implementation of the elf_getident(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +char* +elf_getident(Elf *elf, size_t *ptr) { + size_t tmp; + + if (!ptr) { + ptr = &tmp; + } + if (!elf) { + *ptr = 0; + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + *ptr = elf->e_idlen; + return elf->e_data; + } + if (elf->e_ehdr || _elf_cook(elf)) { + *ptr = elf->e_idlen; + return elf->e_ehdr; + } + *ptr = 0; + return NULL; +} diff --git a/libelf/lib/getscn.c b/libelf/lib/getscn.c new file mode 100755 index 000000000..7599620f8 --- /dev/null +++ b/libelf/lib/getscn.c @@ -0,0 +1,44 @@ +/* +getscn.c - implementation of the elf_getscn(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Scn* +elf_getscn(Elf *elf, size_t index) { + Elf_Scn *scn; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf == elf); + if (scn->s_index == index) { + return scn; + } + } + seterr(ERROR_NOSUCHSCN); + } + return NULL; +} diff --git a/libelf/lib/hash.c b/libelf/lib/hash.c new file mode 100755 index 000000000..b5967bbad --- /dev/null +++ b/libelf/lib/hash.c @@ -0,0 +1,35 @@ +/* +hash.c - implementation of the elf_hash(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +unsigned long +elf_hash(const char *name) { + unsigned long hash = 0; + unsigned long tmp; + unsigned char c; + + while ((c = *name++)) { + hash = (hash << 4) + c; + if ((tmp = hash & 0xf0000000)) { + hash ^= tmp | (tmp >> 24); + } + } + return hash; +} diff --git a/libelf/lib/input.c b/libelf/lib/input.c new file mode 100755 index 000000000..ed8b40d98 --- /dev/null +++ b/libelf/lib/input.c @@ -0,0 +1,77 @@ +/* +input.c - low-level input for libelf. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if HAVE_MMAP +#include <sys/mman.h> +#endif + +void* +_elf_read(Elf *elf, void *buffer, size_t off, size_t len) { + void *tmp; + + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + elf_assert(off >= 0 && off + len <= elf->e_size); + if (elf->e_disabled) { + seterr(ERROR_FDDISABLED); + } + else if (len) { + off += elf->e_base; + if (lseek(elf->e_fd, off, 0) != (off_t)off) { + seterr(ERROR_IO_SEEK); + } + else if (!(tmp = buffer) && !(tmp = malloc(len))) { + seterr(ERROR_IO_2BIG); + } + else if (read(elf->e_fd, tmp, len) != (int)len) { + seterr(ERROR_IO_READ); + if (tmp != buffer) { + free(tmp); + } + } + else { + return tmp; + } + } + return NULL; +} + +void* +_elf_mmap(Elf *elf) { +#if HAVE_MMAP + void *tmp; + + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + elf_assert(elf->e_base == 0); + if (elf->e_disabled) { + seterr(ERROR_FDDISABLED); + } + else if (elf->e_size) { + tmp = (void*)mmap(0, elf->e_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE, elf->e_fd, 0); + if (tmp != (void*)-1) { + return tmp; + } + } +#endif + return NULL; +} diff --git a/libelf/lib/kind.c b/libelf/lib/kind.c new file mode 100755 index 000000000..8bc2ab36c --- /dev/null +++ b/libelf/lib/kind.c @@ -0,0 +1,29 @@ +/* +kind.c - implementation of the elf_kind(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Kind +elf_kind(Elf *elf) { + if (!elf) { + return ELF_K_NONE; + } + elf_assert(elf->e_magic == ELF_MAGIC); + return elf->e_kind; +} diff --git a/libelf/lib/libelf.h b/libelf/lib/libelf.h new file mode 100755 index 000000000..7d09150e5 --- /dev/null +++ b/libelf/lib/libelf.h @@ -0,0 +1,202 @@ +/* +libelf.h - public header file for libelf. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _LIBELF_H +#define _LIBELF_H + +#include <sys/types.h> + +#if __LIBELF_INTERNAL__ +#include <sys_elf.h> +#else +#include <libelf/sys_elf.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __P +# if __STDC__ || defined(__cplusplus) +# define __P(args) args +# else +# define __P(args) () +# endif +#endif + +/* + * Commands + */ +typedef enum { + ELF_C_NULL = 0, /* must be first, 0 */ + ELF_C_READ, + ELF_C_WRITE, + ELF_C_CLR, + ELF_C_SET, + ELF_C_FDDONE, + ELF_C_FDREAD, + ELF_C_RDWR, + ELF_C_NUM /* must be last */ +} Elf_Cmd; + +/* + * Flags + */ +#define ELF_F_DIRTY 0x1 +#define ELF_F_LAYOUT 0x4 + +/* + * File types + */ +typedef enum { + ELF_K_NONE = 0, /* must be first, 0 */ + ELF_K_AR, + ELF_K_COFF, + ELF_K_ELF, + ELF_K_NUM /* must be last */ +} Elf_Kind; + +/* + * Data types + */ +typedef enum { + ELF_T_BYTE = 0, /* must be first, 0 */ + ELF_T_ADDR, + ELF_T_DYN, + ELF_T_EHDR, + ELF_T_HALF, + ELF_T_OFF, + ELF_T_PHDR, + ELF_T_RELA, + ELF_T_REL, + ELF_T_SHDR, + ELF_T_SWORD, + ELF_T_SYM, + ELF_T_WORD, + ELF_T_NUM /* must be last */ +} Elf_Type; + +/* + * Elf descriptor + */ +typedef struct Elf Elf; + +/* + * Section descriptor + */ +typedef struct Elf_Scn Elf_Scn; + +/* + * Archive member header + */ +typedef struct { + char* ar_name; + time_t ar_date; + long ar_uid; + long ar_gid; + unsigned long ar_mode; + off_t ar_size; + char* ar_rawname; +} Elf_Arhdr; + +/* + * Archive symbol table + */ +typedef struct { + char* as_name; + size_t as_off; + unsigned long as_hash; +} Elf_Arsym; + +/* + * Data descriptor + */ +typedef struct { + void* d_buf; + Elf_Type d_type; + size_t d_size; + off_t d_off; + size_t d_align; + unsigned d_version; +} Elf_Data; + +/* + * Function declarations + */ +extern Elf *elf_begin __P((int __fd, Elf_Cmd __cmd, Elf *__ref)); +extern int elf_cntl __P((Elf *__elf, Elf_Cmd __cmd)); +extern int elf_end __P((Elf *__elf)); +extern const char *elf_errmsg __P((int __err)); +extern int elf_errno __P((void)); +extern void elf_fill __P((int __fill)); +extern unsigned elf_flagdata __P((Elf_Data *__data, Elf_Cmd __cmd, + unsigned __flags)); +extern unsigned elf_flagehdr __P((Elf *__elf, Elf_Cmd __cmd, + unsigned __flags)); +extern unsigned elf_flagelf __P((Elf *__elf, Elf_Cmd __cmd, + unsigned __flags)); +extern unsigned elf_flagphdr __P((Elf *__elf, Elf_Cmd __cmd, + unsigned __flags)); +extern unsigned elf_flagscn __P((Elf_Scn *__scn, Elf_Cmd __cmd, + unsigned __flags)); +extern unsigned elf_flagshdr __P((Elf_Scn *__scn, Elf_Cmd __cmd, + unsigned __flags)); +extern size_t elf32_fsize __P((Elf_Type __type, size_t __count, + unsigned __ver)); +extern Elf_Arhdr *elf_getarhdr __P((Elf *__elf)); +extern Elf_Arsym *elf_getarsym __P((Elf *__elf, size_t *__ptr)); +extern off_t elf_getbase __P((Elf *__elf)); +extern Elf_Data *elf_getdata __P((Elf_Scn *__scn, Elf_Data *__data)); +extern Elf32_Ehdr *elf32_getehdr __P((Elf *__elf)); +extern char *elf_getident __P((Elf *__elf, size_t *__ptr)); +extern Elf32_Phdr *elf32_getphdr __P((Elf *__elf)); +extern Elf_Scn *elf_getscn __P((Elf *__elf, size_t __index)); +extern Elf32_Shdr *elf32_getshdr __P((Elf_Scn *__scn)); +extern unsigned long elf_hash __P((const char *__name)); +extern Elf_Kind elf_kind __P((Elf *__elf)); +extern size_t elf_ndxscn __P((Elf_Scn *__scn)); +extern Elf_Data *elf_newdata __P((Elf_Scn *__scn)); +extern Elf32_Ehdr *elf32_newehdr __P((Elf *__elf)); +extern Elf32_Phdr *elf32_newphdr __P((Elf *__elf, size_t __count)); +extern Elf_Scn *elf_newscn __P((Elf *__elf)); +extern Elf_Cmd elf_next __P((Elf *__elf)); +extern Elf_Scn *elf_nextscn __P((Elf *__elf, Elf_Scn *__scn)); +extern size_t elf_rand __P((Elf *__elf, size_t __offset)); +extern Elf_Data *elf_rawdata __P((Elf_Scn *__scn, Elf_Data *__data)); +extern char *elf_rawfile __P((Elf *__elf, size_t *__ptr)); +extern char *elf_strptr __P((Elf *__elf, size_t __section, size_t __offset)); +extern off_t elf_update __P((Elf *__elf, Elf_Cmd __cmd)); +extern unsigned elf_version __P((unsigned __ver)); +extern Elf_Data *elf32_xlatetof __P((Elf_Data *__dst, const Elf_Data *__src, + unsigned __encode)); +extern Elf_Data *elf32_xlatetom __P((Elf_Data *__dst, const Elf_Data *__src, + unsigned __encode)); + +/* + * More function declarations + * These functions are NOT available + * in the SYSV version of libelf! + */ +extern size_t elf_delscn __P((Elf *__elf, Elf_Scn *__scn)); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBELF_H */ diff --git a/libelf/lib/memset.c b/libelf/lib/memset.c new file mode 100755 index 000000000..02d844c9b --- /dev/null +++ b/libelf/lib/memset.c @@ -0,0 +1,49 @@ +/* +memset.c - dumb and inefficient replacement for memset(3). +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#if STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +extern void bcopy(); +extern void *memcpy(); +#endif + +#if !HAVE_MEMCPY +# define memcpy(d,s,n) bcopy(s,d,n) +#endif + +void* +__memset(void *s, int c, size_t n) { + if (n > 64) { + __memset((char*)s + n / 2, c, n - n / 2); + memcpy(s, (char*)s + n / 2, n / 2); + } + else { + while (n > 0) { + ((char*)s)[--n] = c; + } + } +} diff --git a/libelf/lib/ndxscn.c b/libelf/lib/ndxscn.c new file mode 100755 index 000000000..3283e6b6b --- /dev/null +++ b/libelf/lib/ndxscn.c @@ -0,0 +1,29 @@ +/* +ndxscn.c - implementation of the elf_ndxscn(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +size_t +elf_ndxscn(Elf_Scn *scn) { + if (!scn) { + return SHN_UNDEF; + } + elf_assert(scn->s_magic == SCN_MAGIC); + return scn->s_index; +} diff --git a/libelf/lib/newdata.c b/libelf/lib/newdata.c new file mode 100755 index 000000000..ef2b697da --- /dev/null +++ b/libelf/lib/newdata.c @@ -0,0 +1,52 @@ +/* +newdata.c - implementation of the elf_newdata(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Data* +elf_newdata(Elf_Scn *scn) { + Scn_Data *sd; + + if (!scn) { + return NULL; + } + elf_assert(scn->s_magic == SCN_MAGIC); + if (scn->s_index == SHN_UNDEF) { + seterr(ERROR_NULLSCN); + } + else if (!(sd = (Scn_Data*)malloc(sizeof(*sd)))) { + seterr(ERROR_MEM_SCNDATA); + } + else { + *sd = _elf_data_init; + sd->sd_scn = scn; + sd->sd_data_flags = ELF_F_DIRTY; + sd->sd_freeme = 1; + sd->sd_data.d_version = _elf_version; + if (scn->s_data_n) { + scn->s_data_n->sd_link = sd; + } + else { + scn->s_data_1 = sd; + } + scn->s_data_n = sd; + return (Elf_Data*)sd; + } + return NULL; +} diff --git a/libelf/lib/newscn.c b/libelf/lib/newscn.c new file mode 100755 index 000000000..8963e02a8 --- /dev/null +++ b/libelf/lib/newscn.c @@ -0,0 +1,80 @@ +/* +newscn.c - implementation of the elf_newscn(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +static Elf_Scn* +_buildscn(Elf *elf) { + Elf_Scn *scn; + + elf_assert(elf); + elf_assert(elf->e_ehdr); + elf_assert(_elf_scn_init.s_magic == SCN_MAGIC); + while ((scn = (Elf_Scn*)malloc(sizeof(*scn)))) { + *scn = _elf_scn_init; + scn->s_elf = elf; + scn->s_scn_flags = ELF_F_DIRTY; + scn->s_shdr_flags = ELF_F_DIRTY; + scn->s_freeme = 1; + if (elf->e_scn_n) { + scn->s_index = elf->e_scn_n->s_index + 1; + elf->e_scn_n->s_link = scn; + elf->e_scn_n = scn; + return scn; + } + elf_assert(scn->s_index == SHN_UNDEF); + elf->e_scn_1 = elf->e_scn_n = scn; + } + seterr(ERROR_MEM_SCN); + return NULL; +} + +Elf_Scn* +elf_newscn(Elf *elf) { + Elf_Scn *scn; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!elf->e_readable && !elf->e_ehdr) { + seterr(ERROR_NOEHDR); + } + else if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (!elf->e_ehdr && !_elf_cook(elf)) { + return NULL; + } + else if (elf->e_class == ELFCLASS32) { + if (!(scn = _buildscn(elf))) { + return NULL; + } + ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = scn->s_index + 1; + elf->e_ehdr_flags |= ELF_F_DIRTY; + return scn; + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return NULL; +} diff --git a/libelf/lib/next.c b/libelf/lib/next.c new file mode 100755 index 000000000..68975170e --- /dev/null +++ b/libelf/lib/next.c @@ -0,0 +1,38 @@ +/* +next.c - implementation of the elf_next(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Cmd +elf_next(Elf *elf) { + if (!elf) { + return ELF_C_NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!elf->e_parent) { + return ELF_C_NULL; + } + elf_assert(elf->e_parent->e_magic == ELF_MAGIC); + elf_assert(elf->e_parent->e_kind == ELF_K_AR); + elf->e_parent->e_off = elf->e_next; + if (elf->e_next == elf->e_parent->e_size) { + return ELF_C_NULL; + } + return ELF_C_READ; +} diff --git a/libelf/lib/nextscn.c b/libelf/lib/nextscn.c new file mode 100755 index 000000000..c00d0e00d --- /dev/null +++ b/libelf/lib/nextscn.c @@ -0,0 +1,50 @@ +/* +nextscn.c - implementation of the elf_nextscn(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Scn* +elf_nextscn(Elf *elf, Elf_Scn *scn) { + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (scn) { + elf_assert(scn->s_magic == SCN_MAGIC); + if (scn->s_elf == elf) { + return scn->s_link; + } + seterr(ERROR_ELFSCNMISMATCH); + } + else if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + elf_assert(elf->e_ehdr); + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf == elf); + if (scn->s_index == 1) { + return scn; + } + } + seterr(ERROR_NOSUCHSCN); + } + return NULL; +} diff --git a/libelf/lib/nlist.c b/libelf/lib/nlist.c new file mode 100755 index 000000000..49bedb326 --- /dev/null +++ b/libelf/lib/nlist.c @@ -0,0 +1,170 @@ +/* +nlist.c - implementation of the nlist(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <nlist.h> +#include <fcntl.h> + +struct hash { + const char* name; + unsigned long hash; + Elf32_Sym* sym; +}; + +static int +_elf_nlist(Elf *elf, struct nlist *nl) { + Elf_Scn *symtab = NULL; + Elf_Scn *strtab = NULL; + Elf_Data *symdata; + Elf_Data *strdata; + Elf32_Ehdr *ehdr; + Elf32_Shdr *shdr; + Elf_Scn *scn; + Elf32_Sym *symbols; + const char *strings; + unsigned nsymbols; + unsigned nstrings; + unsigned i; + const char *name; + struct hash *table; + unsigned nhash; + unsigned long hash; + unsigned long j; + + if (!(ehdr = elf32_getehdr(elf))) { + return -1; + } + scn = NULL; + elf_errno(); + while ((scn = elf_nextscn(elf, scn))) { + if (!(shdr = elf32_getshdr(scn))) { + return -1; + } + if (shdr->sh_type != SHT_SYMTAB && shdr->sh_type != SHT_DYNSYM) { + continue; + } + symtab = scn; + strtab = elf_getscn(elf, shdr->sh_link); + if (shdr->sh_type == SHT_SYMTAB) { + break; + } + } + if (elf_errno()) { + return -1; + } + symdata = elf_getdata(symtab, NULL); + strdata = elf_getdata(strtab, NULL); + if (!symdata || !strdata) { + return -1; + } + symbols = (Elf32_Sym*)symdata->d_buf; + strings = (const char*)strdata->d_buf; + nsymbols = symdata->d_size / sizeof(Elf32_Sym); + nstrings = strdata->d_size; + if (!symbols || !strings || !nsymbols || !nstrings) { + return -1; + } + + /* + * build a simple hash table + */ + nhash = 3 * nsymbols - 4; + if (!(table = (struct hash*)malloc(nhash * sizeof(*table)))) { + return -1; + } + for (i = 0; i < nhash; i++) { + table[i].name = NULL; + } + for (i = 1; i < nsymbols; i++) { + if (symbols[i].st_name < 0 || symbols[i].st_name >= nstrings) { + free(table); + return -1; + } + if (symbols[i].st_name == 0) { + continue; + } + name = strings + symbols[i].st_name; + hash = elf_hash(name); + for (j = hash; table[j %= nhash].name; j += 3) { + if (table[j].hash != hash) { + continue; + } + if (table[j].name == name || !strcmp(table[j].name, name)) { + break; + } + } + table[j].hash = hash; + table[j].name = name; + table[j].sym = &symbols[i]; + } + + /* + * symbol lookup + */ + for (i = 0; (name = nl[i].n_name) && *name; i++) { + hash = elf_hash(name); + for (j = hash; table[j %= nhash].name; j += 3) { + if (table[j].hash == hash && !strcmp(table[j].name, name)) { + break; + } + } + if (table[j].name) { + nl[i].n_value = table[j].sym->st_value; + nl[i].n_scnum = table[j].sym->st_shndx; + } + else { + nl[i].n_value = 0; + nl[i].n_scnum = 0; + } + /* + * this needs more work + */ + nl[i].n_type = 0; + nl[i].n_sclass = 0; + nl[i].n_numaux = 0; + } + free(table); + return 0; +} + +int +nlist(const char *filename, struct nlist *nl) { + int result = -1; + unsigned oldver; + Elf *elf; + int fd; + + if ((oldver = elf_version(EV_CURRENT)) != EV_NONE) { + if ((fd = open(filename, O_RDONLY)) != -1) { + if ((elf = elf_begin(fd, ELF_C_READ, NULL))) { + result = _elf_nlist(elf, nl); + elf_end(elf); + } + close(fd); + } + elf_version(oldver); + } + if (result) { + while (nl->n_name && *nl->n_name) { + nl->n_value = 0; + nl++; + } + } + return result; +} diff --git a/libelf/lib/nlist.h b/libelf/lib/nlist.h new file mode 100755 index 000000000..8514f9008 --- /dev/null +++ b/libelf/lib/nlist.h @@ -0,0 +1,46 @@ +/* +nlist.h - public header file for nlist(3). +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _NLIST_H +#define _NLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct nlist { + char* n_name; + long n_value; + short n_scnum; + unsigned short n_type; + char n_sclass; + char n_numaux; +}; + +#if __STDC__ || defined(__cplusplus) +extern int nlist(const char *__filename, struct nlist *__nl); +#else +extern int nlist(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NLIST_H */ diff --git a/libelf/lib/opt.delscn.c b/libelf/lib/opt.delscn.c new file mode 100755 index 000000000..718df6a60 --- /dev/null +++ b/libelf/lib/opt.delscn.c @@ -0,0 +1,131 @@ +/* +opt.delscn.c - implementation of the elf_delscn(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +size_t +elf_delscn(Elf *elf, Elf_Scn *scn) { + Elf32_Shdr *shdr; + Elf_Scn *pscn; + Scn_Data *sd; + Scn_Data *tmp; + size_t index; + + if (!elf || !scn) { + return SHN_UNDEF; + } + elf_assert(elf->e_magic == ELF_MAGIC); + elf_assert(scn->s_magic == SCN_MAGIC); + if (scn->s_elf != elf) { + seterr(ERROR_ELFSCNMISMATCH); + return SHN_UNDEF; + } + elf_assert(elf->e_scn_1); + if (scn == elf->e_scn_1) { + seterr(ERROR_NULLSCN); + return SHN_UNDEF; + } + for (pscn = elf->e_scn_1; pscn->s_link; pscn = pscn->s_link) { + if (pscn->s_link == scn) { + break; + } + } + if (pscn->s_link != scn) { + seterr(ERROR_ELFSCNMISMATCH); + return SHN_UNDEF; + } + if (elf->e_scn_n == scn) { + elf->e_scn_n = pscn; + } + pscn->s_link = scn->s_link; + index = scn->s_index; + /* + * free section + */ + for (sd = scn->s_data_1; sd; sd = tmp) { + tmp = sd->sd_link; + if (sd->sd_free_data && sd->sd_memdata) { + free(sd->sd_memdata); + } + if (sd->sd_freeme) { + free(sd); + } + } + if ((sd = scn->s_rawdata)) { + if (sd->sd_free_data && sd->sd_memdata) { + free(sd->sd_memdata); + } + if (sd->sd_freeme) { + free(sd); + } + } + if (scn->s_freeme) { + elf_assert(scn->s_index > 0); + free(scn); + } + /* + * adjust section indices + */ + for (scn = pscn->s_link; scn; scn = scn->s_link) { + elf_assert(scn->s_index > index); + scn->s_index--; + } + /* + * adjust header and well-known section headers + */ + if (elf->e_class == ELFCLASS32) { + elf_assert(elf->e_ehdr); + ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = elf->e_scn_n->s_index + 1; + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + shdr = &scn->s_shdr32; + switch (shdr->sh_type) { + case SHT_REL: + case SHT_RELA: + if (shdr->sh_info == index) { + shdr->sh_info = SHN_UNDEF; + } + else if (shdr->sh_info > index) { + shdr->sh_info--; + } + /* fall through */ + case SHT_DYNSYM: + case SHT_DYNAMIC: + case SHT_HASH: + case SHT_SYMTAB: + if (shdr->sh_link == index) { + shdr->sh_link = SHN_UNDEF; + } + else if (shdr->sh_link > index) { + shdr->sh_link--; + } + /* fall through */ + default: + break; + } + } + return index; + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return SHN_UNDEF; +} diff --git a/libelf/lib/private.h b/libelf/lib/private.h new file mode 100755 index 000000000..211843dc9 --- /dev/null +++ b/libelf/lib/private.h @@ -0,0 +1,339 @@ +/* +private.h - private definitions for libelf. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _PRIVATE_H +#define _PRIVATE_H + +#define __LIBELF_INTERNAL__ 1 + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#if STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +extern char *malloc(); +extern void free(), bcopy(), bzero(); +extern int strcmp(), strncmp(), memcmp(); +extern void *memcpy(), *memmove(), *memset(); +#endif + +#if HAVE_UNISTD_H +# include <unistd.h> +#else +extern int read(), write(); +extern off_t lseek(); +#endif + +#if !HAVE_MEMCMP +# define memcmp strncmp +#endif +#if !HAVE_MEMCPY +# define memcpy(d,s,n) bcopy(s,d,n) +#endif +#if !HAVE_MEMMOVE +# define memmove(d,s,n) bcopy(s,d,n) +#endif + +/* + * if c is 0, replace slow memset() substitute with bzero(). + */ +#if !HAVE_MEMSET +# define memset(d,c,n) ((char)(c)?(void)__memset(d,c,n):bzero(d,n)) +extern void *__memset(); +#endif + +#if HAVE_STRUCT_NLIST_DECLARATION +# define nlist __override_nlist_declaration +#endif + +#if NEED_LINK_H +# include <link.h> +#endif + +#include <libelf.h> + +#if HAVE_STRUCT_NLIST_DECLARATION +# undef nlist +#endif + +typedef struct Scn_Data Scn_Data; + +/* + * ELF descriptor + */ +struct Elf { + /* common */ + size_t e_size; /* file/member size */ + size_t e_dsize; /* size of memory image */ + Elf_Kind e_kind; /* kind of file */ + char* e_data; /* file/member data */ + char* e_rawdata; /* file/member raw data */ + size_t e_idlen; /* identifier size */ + int e_fd; /* file descriptor */ + unsigned e_count; /* activation count */ + /* archive members (still common) */ + Elf* e_parent; /* NULL if not an archive member */ + size_t e_next; /* 0 if not an archive member */ + size_t e_base; /* 0 if not an archive member */ + Elf* e_link; /* next archive member or NULL */ + Elf_Arhdr* e_arhdr; /* archive member header or NULL */ + /* archives */ + size_t e_off; /* current member offset (for elf_begin) */ + Elf* e_members; /* linked list of active archive members */ + char* e_symtab; /* archive symbol table */ + size_t e_symlen; /* length of archive symbol table */ + char* e_strtab; /* archive string table */ + size_t e_strlen; /* length of archive string table */ + /* ELF files */ + unsigned e_class; /* ELF class */ + unsigned e_encoding; /* ELF data encoding */ + unsigned e_version; /* ELF version */ + char* e_ehdr; /* ELF header */ + char* e_phdr; /* ELF program header table */ + size_t e_phnum; /* size of program header table */ + Elf_Scn* e_scn_1; /* first section */ + Elf_Scn* e_scn_n; /* last section */ + unsigned e_elf_flags; /* elf flags (ELF_F_*) */ + unsigned e_ehdr_flags; /* ehdr flags (ELF_F_*) */ + unsigned e_phdr_flags; /* phdr flags (ELF_F_*) */ + /* misc flags */ + unsigned e_readable : 1; /* file is readable */ + unsigned e_writable : 1; /* file is writable */ + unsigned e_disabled : 1; /* e_fd has been disabled */ + unsigned e_cooked : 1; /* e_data was modified */ + unsigned e_free_syms : 1; /* e_symtab is malloc'ed */ + unsigned e_free_ehdr : 1; /* e_ehdr is malloc'ed */ + unsigned e_free_phdr : 1; /* e_phdr is malloc'ed */ + unsigned e_unmap_data : 1; /* e_data is mmap'ed */ + /* magic number for debugging */ + long e_magic; +}; + +#define ELF_MAGIC 0x012b649e + +#define INIT_ELF {\ + /* e_size */ 0,\ + /* e_dsize */ 0,\ + /* e_kind */ ELF_K_NONE,\ + /* e_data */ NULL,\ + /* e_rawdata */ NULL,\ + /* e_idlen */ 0,\ + /* e_fd */ -1,\ + /* e_count */ 1,\ + /* e_parent */ NULL,\ + /* e_next */ 0,\ + /* e_base */ 0,\ + /* e_link */ NULL,\ + /* e_arhdr */ NULL,\ + /* e_off */ 0,\ + /* e_members */ NULL,\ + /* e_symtab */ NULL,\ + /* e_symlen */ 0,\ + /* e_strtab */ NULL,\ + /* e_strlen */ 0,\ + /* e_class */ ELFCLASSNONE,\ + /* e_encoding */ ELFDATANONE,\ + /* e_version */ EV_NONE,\ + /* e_ehdr */ NULL,\ + /* e_phdr */ NULL,\ + /* e_phnum */ 0,\ + /* e_scn_1 */ NULL,\ + /* e_scn_n */ NULL,\ + /* e_elf_flags */ 0,\ + /* e_ehdr_flags */ 0,\ + /* e_phdr_flags */ 0,\ + /* e_readable */ 0,\ + /* e_writable */ 0,\ + /* e_disabled */ 0,\ + /* e_cooked */ 0,\ + /* e_free_syms */ 0,\ + /* e_free_ehdr */ 0,\ + /* e_free_phdr */ 0,\ + /* e_unmap_data */ 0,\ + /* e_magic */ ELF_MAGIC\ +} + +/* + * Section descriptor + */ +struct Elf_Scn { + Elf_Scn* s_link; /* pointer to next Elf_Scn */ + Elf* s_elf; /* pointer to elf descriptor */ + size_t s_index; /* number of this section */ + unsigned s_scn_flags; /* section flags (ELF_F_*) */ + unsigned s_shdr_flags; /* shdr flags (ELF_F_*) */ + Scn_Data* s_data_1; /* first data buffer */ + Scn_Data* s_data_n; /* last data buffer */ + Scn_Data* s_rawdata; /* raw data buffer */ + /* data copied from shdr */ + unsigned s_type; /* section type */ + size_t s_offset; /* section offset */ + size_t s_size; /* section size */ + /* misc flags */ + unsigned s_freeme : 1; /* this Elf_Scn was malloc'ed */ + /* section header */ + union { + Elf32_Shdr u_shdr32; + } s_uhdr; + /* magic number for debugging */ + long s_magic; +}; +#define s_shdr32 s_uhdr.u_shdr32 + +#define SCN_MAGIC 0x012c747d + +#define INIT_SCN {\ + /* s_link */ NULL,\ + /* s_elf */ NULL,\ + /* s_index */ 0,\ + /* s_scn_flags */ 0,\ + /* s_shdr_flags */ 0,\ + /* s_data_1 */ NULL,\ + /* s_data_n */ NULL,\ + /* s_rawdata */ NULL,\ + /* s_type */ SHT_NULL,\ + /* s_offset */ 0,\ + /* s_size */ 0,\ + /* s_freeme */ 0,\ + /* s_uhdr */ {{0,}},\ + /* s_magic */ SCN_MAGIC\ +} + +/* + * Data descriptor + */ +struct Scn_Data { + Elf_Data sd_data; /* must be first! */ + Scn_Data* sd_link; /* pointer to next Scn_Data */ + Elf_Scn* sd_scn; /* pointer to section */ + char* sd_memdata; /* memory image of section */ + unsigned sd_data_flags; /* data flags (ELF_F_*) */ + /* misc flags */ + unsigned sd_freeme : 1; /* this Scn_Data was malloc'ed */ + unsigned sd_free_data : 1; /* sd_memdata is malloc'ed */ + /* magic number for debugging */ + long sd_magic; +}; + +#define DATA_MAGIC 0x01072639 + +#define INIT_DATA {\ + {\ + /* d_buf */ NULL,\ + /* d_type */ ELF_T_BYTE,\ + /* d_size */ 0,\ + /* d_off */ 0,\ + /* d_align */ 0,\ + /* d_version */ EV_NONE\ + },\ + /* sd_link */ NULL,\ + /* sd_scn */ NULL,\ + /* sd_memdata */ NULL,\ + /* sd_data_flags */ 0,\ + /* sd_freeme */ 0,\ + /* sd_free_data */ 0,\ + /* sd_magic */ DATA_MAGIC\ +} + +/* + * Private status variables + */ +extern unsigned _elf_version; +extern int _elf_errno; +extern int _elf_fill; + +/* + * Private functions + */ +extern void *_elf_read __P((Elf*, void*, size_t, size_t)); +extern void *_elf_mmap __P((Elf*)); +extern int _elf_cook __P((Elf*)); + +/* + * Private data + */ +extern const Elf_Scn _elf_scn_init; +extern const Scn_Data _elf_data_init; +extern const Elf_Type _elf_scn_types[SHT_NUM]; +extern const size_t _elf32_fmsize[EV_CURRENT - EV_NONE][ELF_T_NUM][2]; + +/* + * Access macros for _elf32_fmsize + */ +#define _fmsize32(v,t,w) (_elf32_fmsize[(v)-EV_NONE-1][(t)-ELF_T_BYTE][(w)]) +#define _fsize32(v,t) _fmsize32((v),(t),1) +#define _msize32(v,t) _fmsize32((v),(t),0) + +/* + * Various checks + */ +#define valid_class(c) ((c) >= ELFCLASS32 && (c) <= ELFCLASS64) +#define valid_encoding(e) ((e) >= ELFDATA2LSB && (e) <= ELFDATA2MSB) +#define valid_version(v) ((v) > EV_NONE && (v) <= EV_CURRENT) +#define valid_type(t) ((t) >= ELF_T_BYTE && (t) < ELF_T_NUM) +#define valid_scntype(s) ((s) >= SHT_NULL && (s) < SHT_NUM) + +/* + * Error codes + */ +enum { +#define __err__(a,b) a, +#include <errors.h> /* include constants from errors.h */ +#undef __err__ +ERROR_NUM +}; + +#define seterr(err) (_elf_errno = (err)) + +/* + * Sizes of data types (external representation) + */ +#ifndef ELF32_FSZ_ADDR +/* + * These definitions should be in <elf.h>, but... + */ +# define ELF32_FSZ_ADDR 4 +# define ELF32_FSZ_HALF 2 +# define ELF32_FSZ_OFF 4 +# define ELF32_FSZ_SWORD 4 +# define ELF32_FSZ_WORD 4 +#endif + +/* + * Debugging + */ +#if ENABLE_DEBUG +# include <stdio.h> +# if __STDC__ +# define elf_assert(x) ((void)((x)||__elf_assert(__FILE__,__LINE__,#x))) +# else +# define elf_assert(x) ((void)((x)||__elf_assert(__FILE__,__LINE__,"x"))) +# endif +# define __elf_assert(f,l,x) (fprintf(stderr,\ + "%s:%u: libelf assertion failure: %s\n",(f),(l),(x)),abort(),0) +#else +# define elf_assert(x) ((void)0) +#endif + +#endif /* _PRIVATE_H */ diff --git a/libelf/lib/rand.c b/libelf/lib/rand.c new file mode 100755 index 000000000..8e915228e --- /dev/null +++ b/libelf/lib/rand.c @@ -0,0 +1,39 @@ +/* +rand.c - implementation of the elf_rand(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +size_t +elf_rand(Elf *elf, size_t offset) { + if (!elf) { + return 0; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_AR) { + seterr(ERROR_NOTARCHIVE); + } + else if (offset <= 0 || offset > elf->e_size) { + seterr(ERROR_BADOFF); + } + else { + elf->e_off = offset; + return offset; + } + return 0; +} diff --git a/libelf/lib/rawdata.c b/libelf/lib/rawdata.c new file mode 100755 index 000000000..c2b26ed35 --- /dev/null +++ b/libelf/lib/rawdata.c @@ -0,0 +1,83 @@ +/* +rawdata.c - implementation of the elf_rawdata(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +Elf_Data* +elf_rawdata(Elf_Scn *scn, Elf_Data *data) { + Scn_Data *sd; + Elf *elf; + + if (!scn) { + return NULL; + } + elf_assert(scn->s_magic == SCN_MAGIC); + elf = scn->s_elf; + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + if (!elf->e_readable) { + return NULL; + } + else if (scn->s_index == SHN_UNDEF || scn->s_type == SHT_NULL) { + seterr(ERROR_NULLSCN); + } + else if (data) { + return NULL; + } + else if ((sd = scn->s_rawdata)) { + return (Elf_Data*)sd; + } + else if (scn->s_offset < 0 || scn->s_offset > elf->e_size) { + seterr(ERROR_OUTSIDE); + } + else if (scn->s_type != SHT_NOBITS + && scn->s_offset + scn->s_size > elf->e_size) { + seterr(ERROR_TRUNC_SCN); + } + else if (!(sd = (Scn_Data*)malloc(sizeof(*sd)))) { + seterr(ERROR_MEM_SCNDATA); + } + else { + *sd = _elf_data_init; + sd->sd_scn = scn; + sd->sd_freeme = 1; + sd->sd_data.d_size = scn->s_size; + sd->sd_data.d_version = _elf_version; + if (scn->s_type != SHT_NOBITS && scn->s_size) { + if (!(sd->sd_memdata = (char*)malloc(scn->s_size))) { + seterr(ERROR_IO_2BIG); + free(sd); + return NULL; + } + else if (elf->e_rawdata) { + memcpy(sd->sd_memdata, elf->e_rawdata + scn->s_offset, scn->s_size); + } + else if (!_elf_read(elf, sd->sd_memdata, scn->s_offset, scn->s_size)) { + free(sd->sd_memdata); + free(sd); + return NULL; + } + sd->sd_data.d_buf = sd->sd_memdata; + sd->sd_free_data = 1; + } + scn->s_rawdata = sd; + return (Elf_Data*)sd; + } + return NULL; +} diff --git a/libelf/lib/rawfile.c b/libelf/lib/rawfile.c new file mode 100755 index 000000000..0cf33733b --- /dev/null +++ b/libelf/lib/rawfile.c @@ -0,0 +1,48 @@ +/* +rawfile.c - implementation of the elf_rawfile(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +char* +elf_rawfile(Elf *elf, size_t *ptr) { + size_t tmp; + + if (!ptr) { + ptr = &tmp; + } + *ptr = 0; + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!elf->e_readable) { + return NULL; + } + else if (elf->e_size && !elf->e_rawdata) { + elf_assert(elf->e_data); + if (!elf->e_cooked) { + elf->e_rawdata = elf->e_data; + } + else if (!(elf->e_rawdata = _elf_read(elf, NULL, 0, elf->e_size))) { + return NULL; + } + *ptr = elf->e_size; + } + return elf->e_rawdata; +} diff --git a/libelf/lib/strptr.c b/libelf/lib/strptr.c new file mode 100755 index 000000000..dd774fb21 --- /dev/null +++ b/libelf/lib/strptr.c @@ -0,0 +1,49 @@ +/* +strptr.c - implementation of the elf_strptr(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +char* +elf_strptr(Elf *elf, size_t section, size_t offset) { + Elf_Scn *scn; + Elf_Data *sd; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!(scn = elf_getscn(elf, section))) { + return NULL; + } + if (scn->s_type != SHT_STRTAB) { + seterr(ERROR_NOSTRTAB); + return NULL; + } + if (offset >= 0 && offset < scn->s_size) { + sd = NULL; + while ((sd = elf_getdata(scn, sd))) { + if (sd->d_buf && offset >= (size_t)sd->d_off + && offset < (size_t)sd->d_off + sd->d_size) { + return (char*)sd->d_buf + (offset - sd->d_off); + } + } + } + seterr(ERROR_BADSTROFF); + return NULL; +} diff --git a/libelf/lib/swap64.c b/libelf/lib/swap64.c new file mode 100755 index 000000000..667cbacc0 --- /dev/null +++ b/libelf/lib/swap64.c @@ -0,0 +1,81 @@ +/* +swap64.c - 64-bit byte swapping functions. +Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <byteswap.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) Id: swap64.c,v 1.2 2001/10/07 19:33:03 michael Exp "; +#endif /* lint */ + +__libelf_u64_t +_elf_load_u64L(const unsigned char *from) { + return ((__libelf_u64_t)__load_u32L(from + 4) << 32) + | (__libelf_u64_t)__load_u32L(from); +} + +__libelf_u64_t +_elf_load_u64M(const unsigned char *from) { + return ((__libelf_u64_t)__load_u32M(from) << 32) + | (__libelf_u64_t)__load_u32M(from + 4); +} + +__libelf_i64_t +_elf_load_i64L(const unsigned char *from) { + return ((__libelf_i64_t)__load_i32L(from + 4) << 32) + | (__libelf_u64_t)__load_u32L(from); +} + +__libelf_i64_t +_elf_load_i64M(const unsigned char *from) { + return ((__libelf_i64_t)__load_i32M(from) << 32) + | (__libelf_u64_t)__load_u32M(from + 4); +} + +void +_elf_store_u64L(unsigned char *to, __libelf_u64_t v) { + __store_u32L(to, (__libelf_u32_t)v); + v >>= 32; + __store_u32L(to + 4, (__libelf_u32_t)v); +} + +void +_elf_store_u64M(unsigned char *to, __libelf_u64_t v) { + __store_u32M(to + 4, (__libelf_u32_t)v); + v >>= 32; + __store_u32M(to, (__libelf_u32_t)v); +} + +void +_elf_store_i64L(unsigned char *to, __libelf_u64_t v) { + __store_u32L(to, (__libelf_u32_t)v); + v >>= 32; + __store_i32L(to + 4, (__libelf_u32_t)v); +} + +void +_elf_store_i64M(unsigned char *to, __libelf_u64_t v) { + __store_u32M(to + 4, (__libelf_u32_t)v); + v >>= 32; + __store_i32M(to, (__libelf_u32_t)v); +} + +#endif /* __LIBELF64 */ diff --git a/libelf/lib/sys_elf.h.in b/libelf/lib/sys_elf.h.in new file mode 100755 index 000000000..fd6beb70a --- /dev/null +++ b/libelf/lib/sys_elf.h.in @@ -0,0 +1,80 @@ +/* +sys_elf.h.in - configure template for private "switch" file. +Copyright (C) 1998 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* @(#) Id: sys_elf.h.in,v 1.3 1998/06/04 15:26:48 michael Exp */ + +/* + * DO NOT USE THIS IN APPLICATIONS - #include <libelf.h> INSTEAD! + */ + +/* Define to `<elf.h>' or `<sys/elf.h>' if one of them is present */ +#undef __LIBELF_HEADER_ELF_H + +/* Define if you want 64-bit support (and your system supports it) */ +#undef __LIBELF64 + +/* Define if you want 64-bit support, and are running IRIX */ +#undef __LIBELF64_IRIX + +/* Define if you want 64-bit support, and are running Linux */ +#undef __LIBELF64_LINUX + +/* Define to a 64-bit signed integer type if one exists */ +#undef __libelf_i64_t + +/* Define to a 64-bit unsigned integer type if one exists */ +#undef __libelf_u64_t + +/* Define to a 32-bit signed integer type if one exists */ +#undef __libelf_i32_t + +/* Define to a 32-bit unsigned integer type if one exists */ +#undef __libelf_u32_t + +/* Define to a 16-bit signed integer type if one exists */ +#undef __libelf_i16_t + +/* Define to a 16-bit unsigned integer type if one exists */ +#undef __libelf_u16_t + +/* + * Ok, now get the correct instance of elf.h... + */ +#ifdef __LIBELF_HEADER_ELF_H +# include __LIBELF_HEADER_ELF_H +#else /* __LIBELF_HEADER_ELF_H */ +# if __LIBELF_INTERNAL__ +# include <elf_repl.h> +# else /* __LIBELF_INTERNAL__ */ +# include <libelf/elf_repl.h> +# endif /* __LIBELF_INTERNAL__ */ +#endif /* __LIBELF_HEADER_ELF_H */ + +/* + * Workaround for broken <elf.h> on Linux... + */ +#if __LIBELF64 && __LIBELF64_LINUX +typedef __libelf_u64_t Elf64_Addr; +typedef __libelf_u16_t Elf64_Half; +typedef __libelf_u64_t Elf64_Off; +typedef __libelf_i32_t Elf64_Sword; +typedef __libelf_i64_t Elf64_Sxword; +typedef __libelf_u32_t Elf64_Word; +typedef __libelf_u64_t Elf64_Xword; +#endif /* __LIBELF64 && __LIBELF64_LINUX */ diff --git a/libelf/lib/update.c b/libelf/lib/update.c new file mode 100755 index 000000000..40d998b57 --- /dev/null +++ b/libelf/lib/update.c @@ -0,0 +1,518 @@ +/* +update.c - implementation of the elf_update(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +#if HAVE_MMAP +#include <sys/mman.h> +#endif + +static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8); +#define native_encoding (*(unsigned char*)&__encoding) + +#define rewrite(var,val,f) \ + do{if((var)!=(val)){(var)=(val);(f)|=ELF_F_DIRTY;}}while(0) + +#define align(var,val) \ + do{if((val)>1){(var)+=(val)-1;(var)-=(var)%(val);}}while(0) + +#define max(a,b) ((a)>(b)?(a):(b)) + +static off_t +_elf32_layout(Elf *elf, unsigned *flag) { + int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0; + Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr; + size_t off = 0; + unsigned version; + unsigned encoding; + size_t entsize; + unsigned shnum; + Elf_Scn *scn; + + *flag = elf->e_elf_flags | elf->e_phdr_flags; + + if ((version = ehdr->e_version) == EV_NONE) { + version = EV_CURRENT; + } + if (!valid_version(version)) { + seterr(ERROR_UNKNOWN_VERSION); + return -1; + } + if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) { + encoding = native_encoding; + } + if (!valid_encoding(encoding)) { + seterr(ERROR_UNKNOWN_ENCODING); + return -1; + } + entsize = _fsize32(version, ELF_T_EHDR); elf_assert(entsize); + rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags); + off = entsize; + + rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags); + if (elf->e_phnum) { + entsize = _fsize32(version, ELF_T_PHDR); elf_assert(entsize); + rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags); + if (layout) { + align(off, 4); + rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags); + off += elf->e_phnum * entsize; + } + else { + off = max(off, ehdr->e_phoff + elf->e_phnum * entsize); + } + } + else { + rewrite(ehdr->e_phentsize, 0, elf->e_ehdr_flags); + if (layout) { + rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags); + } + } + + for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) { + Elf32_Shdr *shdr = &scn->s_shdr32; + size_t scn_align = 1; + size_t len = 0; + Scn_Data *sd; + + elf_assert(scn->s_index == shnum); + + *flag |= scn->s_scn_flags | scn->s_shdr_flags; + + if (scn->s_index == SHN_UNDEF) { + rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags); + if (layout) { + rewrite(shdr->sh_offset, 0, scn->s_shdr_flags); + rewrite(shdr->sh_size, 0, scn->s_shdr_flags); + rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags); + } + continue; + } +#if 1 + if (shdr->sh_type == SHT_NULL) { + continue; + } +#endif + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + size_t fsize, msize; + + if (shdr->sh_type == SHT_NOBITS) { + fsize = sd->sd_data.d_size; + } + else if (!valid_type(sd->sd_data.d_type)) { + /* can't translate */ + fsize = sd->sd_data.d_size; + } + else { + msize = _msize32(sd->sd_data.d_version, sd->sd_data.d_type); + elf_assert(msize); + fsize = _fsize32(version, sd->sd_data.d_type); + elf_assert(fsize); + fsize = (sd->sd_data.d_size / msize) * fsize; + } + + if (layout) { + align(len, sd->sd_data.d_align); + scn_align = max(scn_align, sd->sd_data.d_align); + rewrite(sd->sd_data.d_off, (off_t)len, sd->sd_data_flags); + len += fsize; + } + else { + len = max(len, sd->sd_data.d_off + fsize); + } + + *flag |= sd->sd_data_flags; + } + + if (valid_scntype(shdr->sh_type)) { + Elf_Type type = _elf_scn_types[shdr->sh_type]; + size_t fsize; + + elf_assert(valid_type(type)); + if (type != ELF_T_BYTE) { + fsize = _fsize32(version, type); + elf_assert(fsize); + rewrite(shdr->sh_entsize, fsize, scn->s_shdr_flags); + } + } + + if (layout) { + align(off, scn_align); + rewrite(shdr->sh_offset, off, scn->s_shdr_flags); + rewrite(shdr->sh_size, len, scn->s_shdr_flags); + rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags); + + if (shdr->sh_type != SHT_NOBITS) { + off += len; + } + } + else if (len > shdr->sh_size) { + seterr(ERROR_SCN2SMALL); + return -1; + } + else if (shdr->sh_type != SHT_NOBITS) { + off = max(off, shdr->sh_offset + shdr->sh_size); + } + else { + off = max(off, shdr->sh_offset); + } + } + + rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags); + if (shnum) { + entsize = _fsize32(version, ELF_T_SHDR); elf_assert(entsize); + rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags); + if (layout) { + align(off, 4); + rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags); + off += shnum * entsize; + } + else { + off = max(off, ehdr->e_shoff + shnum * entsize); + } + } + else { + rewrite(ehdr->e_shentsize, 0, elf->e_ehdr_flags); + if (layout) { + rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags); + } + } + + rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS32, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags); + rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags); + rewrite(ehdr->e_version, version, elf->e_ehdr_flags); + + *flag |= elf->e_ehdr_flags; + + return off; +} + +#define ptrinside(p,a,l) ((p)>=(a)&&(p)<(a)+(l)) +#define newptr(p,o,n) ((p)=((p)-(o))+(n)) + +static int +_elf32_update_pointers(Elf *elf, char *outbuf, size_t len) { + Elf_Scn *scn; + Elf32_Shdr *shdr; + Scn_Data *sd; + char *data, *rawdata; + + elf_assert(elf); + elf_assert(elf->e_data); + elf_assert(!elf->e_parent); + elf_assert(!elf->e_unmap_data); + elf_assert(elf->e_kind == ELF_K_ELF); + elf_assert(len >= EI_NIDENT); + + /* resize memory images */ + if (len <= elf->e_dsize) { + /* don't shorten the memory image */ + data = elf->e_data; + } + else if ((data = (char*)realloc(elf->e_data, len))) { + elf->e_dsize = len; + } + else { + seterr(ERROR_IO_2BIG); + return -1; + } + if (elf->e_rawdata == elf->e_data) { + /* update frozen raw image */ + memcpy(data, outbuf, len); + elf->e_data = elf->e_rawdata = data; + return 0; + } + if (elf->e_rawdata) { + /* update raw image */ + if (!(rawdata = (char*)realloc(elf->e_rawdata, len))) { + seterr(ERROR_IO_2BIG); + return -1; + } + memcpy(rawdata, outbuf, len); + elf->e_rawdata = rawdata; + } + if (data == elf->e_data) { + /* nothing more to do */ + return 0; + } + /* adjust internal pointers */ + if (elf->e_ehdr && !elf->e_free_ehdr) { + elf_assert(ptrinside(elf->e_ehdr, elf->e_data, elf->e_dsize)); + newptr(elf->e_ehdr, elf->e_data, data); + } + if (elf->e_phdr && !elf->e_free_phdr) { + elf_assert(ptrinside(elf->e_phdr, elf->e_data, elf->e_dsize)); + newptr(elf->e_phdr, elf->e_data, data); + } + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + if ((sd = scn->s_data_1) && sd->sd_memdata && !sd->sd_free_data) { + elf_assert(ptrinside(sd->sd_memdata, elf->e_data, elf->e_dsize)); + if (sd->sd_data.d_buf == sd->sd_memdata) { + newptr(sd->sd_memdata, elf->e_data, data); + sd->sd_data.d_buf = sd->sd_memdata; + } + else { + newptr(sd->sd_memdata, elf->e_data, data); + } + } + if ((sd = scn->s_rawdata) && sd->sd_memdata && sd->sd_free_data) { + shdr = &scn->s_shdr32; + if (!(rawdata = (char*)realloc(sd->sd_memdata, shdr->sh_size))) { + seterr(ERROR_IO_2BIG); + return -1; + } + memcpy(rawdata, outbuf + shdr->sh_offset, shdr->sh_size); + if (sd->sd_data.d_buf == sd->sd_memdata) { + sd->sd_data.d_buf = rawdata; + } + sd->sd_memdata = rawdata; + } + } + elf->e_data = data; + return 0; +} + +static off_t +_elf32_write(Elf *elf, char *outbuf, size_t len) { + Elf32_Ehdr *ehdr; + Elf32_Shdr *shdr; + Elf_Scn *scn; + Scn_Data *sd; + Elf_Data src; + Elf_Data dst; + unsigned encode; + size_t fsize; + size_t msize; + + if (!len) { + return len; + } + + ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr); + encode = ehdr->e_ident[EI_DATA]; + + src.d_buf = ehdr; + src.d_type = ELF_T_EHDR; + src.d_size = _msize32(_elf_version, ELF_T_EHDR); + src.d_version = _elf_version; + dst.d_buf = outbuf; + dst.d_size = ehdr->e_ehsize; + dst.d_version = ehdr->e_version; + if (!elf32_xlatetof(&dst, &src, encode)) { + return -1; + } + + if (ehdr->e_phnum) { + src.d_buf = elf->e_phdr; + src.d_type = ELF_T_PHDR; + src.d_size = ehdr->e_phnum * _msize32(_elf_version, ELF_T_PHDR); + src.d_version = _elf_version; + dst.d_buf = outbuf + ehdr->e_phoff; + dst.d_size = ehdr->e_phnum * ehdr->e_phentsize; + dst.d_version = ehdr->e_version; + if (!elf32_xlatetof(&dst, &src, encode)) { + return -1; + } + } + + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + shdr = &scn->s_shdr32; + src.d_buf = shdr; + src.d_type = ELF_T_SHDR; + src.d_size = sizeof(*shdr); + src.d_version = EV_CURRENT; + dst.d_buf = outbuf + ehdr->e_shoff + scn->s_index * ehdr->e_shentsize; + dst.d_size = ehdr->e_shentsize; + dst.d_version = ehdr->e_version; + if (!elf32_xlatetof(&dst, &src, encode)) { + return -1; + } + + if (scn->s_index == SHN_UNDEF) { + continue; + } + if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) { + continue; + } + if (scn->s_data_1 && !elf_getdata(scn, NULL)) { + return -1; + } + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + src = sd->sd_data; + if (!src.d_size) { + continue; + } + if (!src.d_buf) { + seterr(ERROR_NULLBUF); + return -1; + } + dst.d_buf = outbuf + shdr->sh_offset + src.d_off; + dst.d_size = src.d_size; + dst.d_version = ehdr->e_version; + if (valid_type(src.d_type)) { + msize = _msize32(src.d_version, src.d_type); + elf_assert(msize); + fsize = _fsize32(dst.d_version, src.d_type); + elf_assert(fsize); + if (msize != fsize) { + dst.d_size = (src.d_size / msize) * fsize; + } + } + else { + src.d_type = ELF_T_BYTE; + } + if (!elf32_xlatetof(&dst, &src, encode)) { + return -1; + } + } + } + + /* cleanup */ + if (elf->e_readable && _elf32_update_pointers(elf, outbuf, len)) { + return -1; + } + /* NOTE: ehdr is no longer valid! */ + ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr); + elf->e_encoding = ehdr->e_ident[EI_DATA]; + elf->e_version = ehdr->e_ident[EI_VERSION]; + elf->e_elf_flags &= ~ELF_F_DIRTY; + elf->e_ehdr_flags &= ~ELF_F_DIRTY; + elf->e_phdr_flags &= ~ELF_F_DIRTY; + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + scn->s_scn_flags &= ~ELF_F_DIRTY; + scn->s_shdr_flags &= ~ELF_F_DIRTY; + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + sd->sd_data_flags &= ~ELF_F_DIRTY; + } + if (elf->e_readable) { + shdr = &scn->s_shdr32; + scn->s_type = shdr->sh_type; + scn->s_size = shdr->sh_size; + scn->s_offset = shdr->sh_offset; + } + } + elf->e_size = len; + return len; +} + +off_t +elf_update(Elf *elf, Elf_Cmd cmd) { + unsigned flag; + off_t len; + char *buf; + int err; + + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (cmd == ELF_C_WRITE) { + if (!elf->e_writable) { + seterr(ERROR_RDONLY); + return -1; + } + if (elf->e_disabled) { + seterr(ERROR_FDDISABLED); + return -1; + } + } + else if (cmd != ELF_C_NULL) { + seterr(ERROR_INVALID_CMD); + return -1; + } + + if (!elf->e_ehdr) { + seterr(ERROR_NOEHDR); + } + else if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class == ELFCLASS32) { + len = _elf32_layout(elf, &flag); + if (len == -1 || cmd != ELF_C_WRITE || !(flag & ELF_F_DIRTY)) { + return len; + } + if (!len) { + /* can this happen at all??? */ + return len; + } +#if HAVE_FTRUNCATE + ftruncate(elf->e_fd, 0); +#endif +#if HAVE_MMAP + /* + * Make sure the file is (at least) len bytes long + */ +#if HAVE_FTRUNCATE + if (ftruncate(elf->e_fd, len)) { +#else + { +#endif + if (lseek(elf->e_fd, (long)len - 1, 0) != (long)len - 1) { + seterr(ERROR_IO_SEEK); + return -1; + } + if (write(elf->e_fd, "", 1) != 1) { + seterr(ERROR_IO_WRITE); + return -1; + } + } + buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, + elf->e_fd, 0); + if (buf != (char*)-1) { + if ((char)_elf_fill) { + memset(buf, _elf_fill, len); + } + err = _elf32_write(elf, buf, len); + munmap(buf, len); + return err; + } +#endif + if (!(buf = (char*)malloc(len))) { + seterr(ERROR_MEM_OUTBUF); + return -1; + } + memset(buf, _elf_fill, len); + err = _elf32_write(elf, buf, len); + if (err == len) { + if (lseek(elf->e_fd, 0L, 0)) { + seterr(ERROR_IO_SEEK); + err = -1; + } + else if (write(elf->e_fd, buf, len) != len) { + seterr(ERROR_IO_WRITE); + err = -1; + } + } + free(buf); + return err; + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return -1; +} diff --git a/libelf/lib/verdef.h b/libelf/lib/verdef.h new file mode 100755 index 000000000..66da492bf --- /dev/null +++ b/libelf/lib/verdef.h @@ -0,0 +1,269 @@ +/* +verdef.h - copy versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef lint +static const char verdef_h_rcsid[] = "@(#) Id: verdef.h,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +#if VER_DEF_CURRENT != 1 +#error libelf currently does not support VER_DEF_CURRENT != 1 +#endif /* VER_DEF_CURRENT != 1 */ + +#if TOFILE + +static void +__store_verdaux(verdaux_ftype *dst, const verdaux_mtype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + __store_u32L(dst->vda_name, src->vda_name); + __store_u32L(dst->vda_next, src->vda_next); + } + else { + __store_u32M(dst->vda_name, src->vda_name); + __store_u32M(dst->vda_next, src->vda_next); + } +} + +static void +__store_verdef(verdef_ftype *dst, const verdef_mtype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + __store_u16L(dst->vd_version, src->vd_version); + __store_u16L(dst->vd_flags, src->vd_flags); + __store_u16L(dst->vd_ndx, src->vd_ndx); + __store_u16L(dst->vd_cnt, src->vd_cnt); + __store_u32L(dst->vd_hash, src->vd_hash); + __store_u32L(dst->vd_aux, src->vd_aux); + __store_u32L(dst->vd_next, src->vd_next); + } + else { + __store_u16M(dst->vd_version, src->vd_version); + __store_u16M(dst->vd_flags, src->vd_flags); + __store_u16M(dst->vd_ndx, src->vd_ndx); + __store_u16M(dst->vd_cnt, src->vd_cnt); + __store_u32M(dst->vd_hash, src->vd_hash); + __store_u32M(dst->vd_aux, src->vd_aux); + __store_u32M(dst->vd_next, src->vd_next); + } +} + +typedef verdaux_mtype verdaux_stype; +typedef verdaux_ftype verdaux_dtype; +typedef verdef_mtype verdef_stype; +typedef verdef_ftype verdef_dtype; +typedef align_mtype verdef_atype; + +#define copy_verdaux_srctotmp(d, s, e) (*(d) = *(s)) +#define copy_verdaux_tmptodst(d, s, e) __store_verdaux((d), (s), (e)) +#define copy_verdef_srctotmp(d, s, e) (*(d) = *(s)) +#define copy_verdef_tmptodst(d, s, e) __store_verdef((d), (s), (e)) + +#define translator_suffix 11_tof + +#else /* TOFILE */ + +static void +__load_verdaux(verdaux_mtype *dst, const verdaux_ftype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + dst->vda_name = __load_u32L(src->vda_name); + dst->vda_next = __load_u32L(src->vda_next); + } + else { + dst->vda_name = __load_u32M(src->vda_name); + dst->vda_next = __load_u32M(src->vda_next); + } +} + +static void +__load_verdef(verdef_mtype *dst, const verdef_ftype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + dst->vd_version = __load_u16L(src->vd_version); + dst->vd_flags = __load_u16L(src->vd_flags); + dst->vd_ndx = __load_u16L(src->vd_ndx); + dst->vd_cnt = __load_u16L(src->vd_cnt); + dst->vd_hash = __load_u32L(src->vd_hash); + dst->vd_aux = __load_u32L(src->vd_aux); + dst->vd_next = __load_u32L(src->vd_next); + } + else { + dst->vd_version = __load_u16M(src->vd_version); + dst->vd_flags = __load_u16M(src->vd_flags); + dst->vd_ndx = __load_u16M(src->vd_ndx); + dst->vd_cnt = __load_u16M(src->vd_cnt); + dst->vd_hash = __load_u32M(src->vd_hash); + dst->vd_aux = __load_u32M(src->vd_aux); + dst->vd_next = __load_u32M(src->vd_next); + } +} + +typedef verdaux_ftype verdaux_stype; +typedef verdaux_mtype verdaux_dtype; +typedef verdef_ftype verdef_stype; +typedef verdef_mtype verdef_dtype; +typedef align_ftype verdef_atype; + +#define copy_verdaux_srctotmp(d, s, e) __load_verdaux((d), (s), (e)) +#define copy_verdaux_tmptodst(d, s, e) (*(d) = *(s)) +#define copy_verdef_srctotmp(d, s, e) __load_verdef((d), (s), (e)) +#define copy_verdef_tmptodst(d, s, e) (*(d) = *(s)) + +#define translator_suffix 11_tom + +#endif /* TOFILE */ + +#define cat3(a,b,c) a##b##c +#define xlt3(p,e,s) cat3(p,e,s) +#define xltprefix(x) xlt3(x,_,class_suffix) +#define translator(x,e) xlt3(xltprefix(_elf_##x),e,translator_suffix) + +static size_t +xlt_verdef(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc) { + size_t doff; + size_t soff; + + if (n < sizeof(verdef_stype)) { + return 0; + } + soff = doff = 0; + for (;;) { + const verdef_stype *svd; + verdef_dtype *dvd; + verdef_mtype vd; + size_t acount; + size_t aoff; + size_t save = doff; + + /* + * allocate space in dst buffer + */ + dvd = (verdef_dtype*)(dst + doff); + doff += sizeof(verdef_dtype); + /* + * load and check src + */ + svd = (verdef_stype*)(src + soff); + copy_verdef_srctotmp(&vd, svd, enc); + if (vd.vd_version < 1 + || vd.vd_version > VER_DEF_CURRENT) { + seterr(ERROR_VERDEF_VERSION); + return (size_t)-1; + } + if (vd.vd_cnt < 1 + || vd.vd_aux == 0 + || vd.vd_aux % sizeof(verdef_atype) + || vd.vd_aux < sizeof(verdef_stype)) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + /* + * get Verdaux offset and advance to next Verdef + */ + aoff = soff + vd.vd_aux; + if (vd.vd_next != 0) { + if (vd.vd_next % sizeof(verdef_atype) + || vd.vd_next < sizeof(verdef_stype)) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + soff += vd.vd_next; + if (soff + sizeof(verdef_stype) > n) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + } + /* + * read Verdaux array + */ + for (acount = 1; ; acount++) { + const verdaux_stype *svda; + verdaux_dtype *dvda; + verdaux_mtype vda; + + /* + * check for src buffer overflow + */ + if (aoff + sizeof(verdaux_stype) > n) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + /* + * allocate space in dst buffer + */ + dvda = (verdaux_dtype*)(dst + doff); + doff += sizeof(verdaux_dtype); + /* + * load and check src + */ + svda = (verdaux_stype*)(src + aoff); + copy_verdaux_srctotmp(&vda, svda, enc); + if (vda.vda_next != 0) { + if (vda.vda_next % sizeof(verdef_atype) + || vda.vda_next < sizeof(verdaux_stype)) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + aoff += vda.vda_next; + vda.vda_next = sizeof(verdaux_dtype); + } + /* + * copy Verdaux to dst buffer + */ + if (dst) { + copy_verdaux_tmptodst(dvda, &vda, enc); + } + /* + * end check + */ + if (vda.vda_next == 0) { + break; + } + } + /* + * parameter check + */ + if (acount != vd.vd_cnt) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + /* + * copy Verdef to dst buffer + */ + if (dst) { + vd.vd_aux = sizeof(verdef_dtype); + if (vd.vd_next != 0) { + vd.vd_next = doff - save; + } + copy_verdef_tmptodst(dvd, &vd, enc); + } + /* + * end check + */ + if (vd.vd_next == 0) { + return doff; + } + } +} + +size_t +translator(verdef,L)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verdef(dst, src, n, ELFDATA2LSB); +} + +size_t +translator(verdef,M)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verdef(dst, src, n, ELFDATA2MSB); +} diff --git a/libelf/lib/verdef_32_tof.c b/libelf/lib/verdef_32_tof.c new file mode 100755 index 000000000..475a786a9 --- /dev/null +++ b/libelf/lib/verdef_32_tof.c @@ -0,0 +1,53 @@ +/* +verdef_32_tof.c - copy 32-bit versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#if __LIBELF_SYMBOL_VERSIONS + +#ifndef lint +static const char rcsid[] = "@(#) Id: verdef_32_tof.c,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +typedef Elf32_Verdaux verdaux_mtype; +typedef Elf32_Verdef verdef_mtype; +typedef Elf32_Vernaux vernaux_mtype; +typedef Elf32_Verneed verneed_mtype; +typedef Elf32_Word align_mtype; + +typedef __ext_Elf32_Verdaux verdaux_ftype; +typedef __ext_Elf32_Verdef verdef_ftype; +typedef __ext_Elf32_Vernaux vernaux_ftype; +typedef __ext_Elf32_Verneed verneed_ftype; +typedef __ext_Elf32_Word align_ftype; + +#define class_suffix 32 + +#undef TOFILE +#define TOFILE 1 + +/* + * Include shared code + */ +#include "verdef.h" +#include "verneed.h" + +#endif /* __LIBELF_SYMBOL_VERSIONS */ diff --git a/libelf/lib/verdef_32_tom.c b/libelf/lib/verdef_32_tom.c new file mode 100755 index 000000000..86d5c2318 --- /dev/null +++ b/libelf/lib/verdef_32_tom.c @@ -0,0 +1,53 @@ +/* +verdef_32_tom.c - copy 32-bit versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#if __LIBELF_SYMBOL_VERSIONS + +#ifndef lint +static const char rcsid[] = "@(#) Id: verdef_32_tom.c,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +typedef Elf32_Verdaux verdaux_mtype; +typedef Elf32_Verdef verdef_mtype; +typedef Elf32_Vernaux vernaux_mtype; +typedef Elf32_Verneed verneed_mtype; +typedef Elf32_Word align_mtype; + +typedef __ext_Elf32_Verdaux verdaux_ftype; +typedef __ext_Elf32_Verdef verdef_ftype; +typedef __ext_Elf32_Vernaux vernaux_ftype; +typedef __ext_Elf32_Verneed verneed_ftype; +typedef __ext_Elf32_Word align_ftype; + +#define class_suffix 32 + +#undef TOFILE +#define TOFILE 0 + +/* + * Include shared code + */ +#include "verdef.h" +#include "verneed.h" + +#endif /* __LIBELF_SYMBOL_VERSIONS */ diff --git a/libelf/lib/verdef_64_tof.c b/libelf/lib/verdef_64_tof.c new file mode 100755 index 000000000..6804b5ecb --- /dev/null +++ b/libelf/lib/verdef_64_tof.c @@ -0,0 +1,53 @@ +/* +verdef_64_tof.c - copy 64-bit versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#if __LIBELF64 && __LIBELF_SYMBOL_VERSIONS + +#ifndef lint +static const char rcsid[] = "@(#) Id: verdef_64_tof.c,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +typedef Elf64_Verdaux verdaux_mtype; +typedef Elf64_Verdef verdef_mtype; +typedef Elf64_Vernaux vernaux_mtype; +typedef Elf64_Verneed verneed_mtype; +typedef Elf64_Word align_mtype; + +typedef __ext_Elf64_Verdaux verdaux_ftype; +typedef __ext_Elf64_Verdef verdef_ftype; +typedef __ext_Elf64_Vernaux vernaux_ftype; +typedef __ext_Elf64_Verneed verneed_ftype; +typedef __ext_Elf64_Word align_ftype; + +#define class_suffix 64 + +#undef TOFILE +#define TOFILE 1 + +/* + * Include shared code + */ +#include "verdef.h" +#include "verneed.h" + +#endif /* __LIBELF64 && __LIBELF_SYMBOL_VERSIONS */ diff --git a/libelf/lib/verdef_64_tom.c b/libelf/lib/verdef_64_tom.c new file mode 100755 index 000000000..151939d49 --- /dev/null +++ b/libelf/lib/verdef_64_tom.c @@ -0,0 +1,53 @@ +/* +verdef_64_tom.c - copy 64-bit versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#if __LIBELF64 && __LIBELF_SYMBOL_VERSIONS + +#ifndef lint +static const char rcsid[] = "@(#) Id: verdef_64_tom.c,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +typedef Elf64_Verdaux verdaux_mtype; +typedef Elf64_Verdef verdef_mtype; +typedef Elf64_Vernaux vernaux_mtype; +typedef Elf64_Verneed verneed_mtype; +typedef Elf64_Word align_mtype; + +typedef __ext_Elf64_Verdaux verdaux_ftype; +typedef __ext_Elf64_Verdef verdef_ftype; +typedef __ext_Elf64_Vernaux vernaux_ftype; +typedef __ext_Elf64_Verneed verneed_ftype; +typedef __ext_Elf64_Word align_ftype; + +#define class_suffix 64 + +#undef TOFILE +#define TOFILE 0 + +/* + * Include shared code + */ +#include "verdef.h" +#include "verneed.h" + +#endif /* __LIBELF64 && __LIBELF_SYMBOL_VERSIONS */ diff --git a/libelf/lib/verneed.h b/libelf/lib/verneed.h new file mode 100755 index 000000000..9af8389fd --- /dev/null +++ b/libelf/lib/verneed.h @@ -0,0 +1,273 @@ +/* +verneed.h - copy versioning information. +Copyright (C) 2001 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef lint +static const char verneed_h_rcsid[] = "@(#) Id: verneed.h,v 1.1 2001/10/07 20:03:02 michael Exp "; +#endif /* lint */ + +#if VER_NEED_CURRENT != 1 +#error libelf currently does not support VER_NEED_CURRENT != 1 +#endif /* VER_NEED_CURRENT != 1 */ + +#if TOFILE + +static void +__store_vernaux(vernaux_ftype *dst, const vernaux_mtype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + __store_u32L(dst->vna_hash, src->vna_hash); + __store_u16L(dst->vna_flags, src->vna_flags); + __store_u16L(dst->vna_other, src->vna_other); + __store_u32L(dst->vna_name, src->vna_name); + __store_u32L(dst->vna_next, src->vna_next); + } + else { + __store_u32M(dst->vna_hash, src->vna_hash); + __store_u16M(dst->vna_flags, src->vna_flags); + __store_u16M(dst->vna_other, src->vna_other); + __store_u32M(dst->vna_name, src->vna_name); + __store_u32M(dst->vna_next, src->vna_next); + } +} + +static void +__store_verneed(verneed_ftype *dst, const verneed_mtype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + __store_u16L(dst->vn_version, src->vn_version); + __store_u16L(dst->vn_cnt, src->vn_cnt); + __store_u32L(dst->vn_file, src->vn_file); + __store_u32L(dst->vn_aux, src->vn_aux); + __store_u32L(dst->vn_next, src->vn_next); + } + else { + __store_u16M(dst->vn_version, src->vn_version); + __store_u16M(dst->vn_cnt, src->vn_cnt); + __store_u32M(dst->vn_file, src->vn_file); + __store_u32M(dst->vn_aux, src->vn_aux); + __store_u32M(dst->vn_next, src->vn_next); + } +} + +typedef vernaux_mtype vernaux_stype; +typedef vernaux_ftype vernaux_dtype; +typedef verneed_mtype verneed_stype; +typedef verneed_ftype verneed_dtype; +typedef align_mtype verneed_atype; + +#define copy_vernaux_srctotmp(d, s, e) (*(d) = *(s)) +#define copy_vernaux_tmptodst(d, s, e) __store_vernaux((d), (s), (e)) +#define copy_verneed_srctotmp(d, s, e) (*(d) = *(s)) +#define copy_verneed_tmptodst(d, s, e) __store_verneed((d), (s), (e)) + +#define translator_suffix 11_tof + +#else /* TOFILE */ + +static void +__load_vernaux(vernaux_mtype *dst, const vernaux_ftype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + dst->vna_hash = __load_u32L(src->vna_hash); + dst->vna_flags = __load_u16L(src->vna_flags); + dst->vna_other = __load_u16L(src->vna_other); + dst->vna_name = __load_u32L(src->vna_name); + dst->vna_next = __load_u32L(src->vna_next); + } + else { + dst->vna_hash = __load_u32M(src->vna_hash); + dst->vna_flags = __load_u16M(src->vna_flags); + dst->vna_other = __load_u16M(src->vna_other); + dst->vna_name = __load_u32M(src->vna_name); + dst->vna_next = __load_u32M(src->vna_next); + } +} + +static void +__load_verneed(verneed_mtype *dst, const verneed_ftype *src, unsigned enc) { + if (enc == ELFDATA2LSB) { + dst->vn_version = __load_u16L(src->vn_version); + dst->vn_cnt = __load_u16L(src->vn_cnt); + dst->vn_file = __load_u32L(src->vn_file); + dst->vn_aux = __load_u32L(src->vn_aux); + dst->vn_next = __load_u32L(src->vn_next); + } + else { + dst->vn_version = __load_u16M(src->vn_version); + dst->vn_cnt = __load_u16M(src->vn_cnt); + dst->vn_file = __load_u32M(src->vn_file); + dst->vn_aux = __load_u32M(src->vn_aux); + dst->vn_next = __load_u32M(src->vn_next); + } +} + +typedef vernaux_ftype vernaux_stype; +typedef vernaux_mtype vernaux_dtype; +typedef verneed_ftype verneed_stype; +typedef verneed_mtype verneed_dtype; +typedef align_ftype verneed_atype; + +#define copy_vernaux_srctotmp(d, s, e) __load_vernaux((d), (s), (e)) +#define copy_vernaux_tmptodst(d, s, e) (*(d) = *(s)) +#define copy_verneed_srctotmp(d, s, e) __load_verneed((d), (s), (e)) +#define copy_verneed_tmptodst(d, s, e) (*(d) = *(s)) + +#define translator_suffix 11_tom + +#endif /* TOFILE */ + +#define cat3(a,b,c) a##b##c +#define xlt3(p,e,s) cat3(p,e,s) +#define xltprefix(x) xlt3(x,_,class_suffix) +#define translator(x,e) xlt3(xltprefix(_elf_##x),e,translator_suffix) + +static size_t +xlt_verneed(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc) { + size_t doff; + size_t soff; + + if (n < sizeof(verneed_stype)) { + return 0; + } + soff = doff = 0; + for (;;) { + const verneed_stype *svn; + verneed_dtype *dvn; + verneed_mtype vn; + size_t acount; + size_t aoff; + size_t save = doff; + + /* + * allocate space in dst buffer + */ + dvn = (verneed_dtype*)(dst + doff); + doff += sizeof(verneed_dtype); + /* + * load and check src + */ + svn = (verneed_stype*)(src + soff); + copy_verneed_srctotmp(&vn, svn, enc); + if (vn.vn_version < 1 + || vn.vn_version > VER_NEED_CURRENT) { + seterr(ERROR_VERNEED_VERSION); + return (size_t)-1; + } + if (vn.vn_cnt < 1 + || vn.vn_aux == 0 + || vn.vn_aux % sizeof(verneed_atype) + || vn.vn_aux < sizeof(verneed_stype)) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + /* + * get Vernaux offset and advance to next Verneed + */ + aoff = soff + vn.vn_aux; + if (vn.vn_next != 0) { + if (vn.vn_next % sizeof(verneed_atype) + || vn.vn_next < sizeof(verneed_stype)) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + soff += vn.vn_next; + if (soff + sizeof(verneed_stype) > n) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + } + /* + * read Vernaux array + */ + for (acount = 1; ; acount++) { + const vernaux_stype *svna; + vernaux_dtype *dvna; + vernaux_mtype vna; + + /* + * check for src buffer overflow + */ + if (aoff + sizeof(vernaux_stype) > n) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + /* + * allocate space in dst buffer + */ + dvna = (vernaux_dtype*)(dst + doff); + doff += sizeof(vernaux_dtype); + /* + * load and check src + */ + svna = (vernaux_stype*)(src + aoff); + copy_vernaux_srctotmp(&vna, svna, enc); + if (vna.vna_next != 0) { + if (vna.vna_next % sizeof(verneed_atype) + || vna.vna_next < sizeof(vernaux_stype)) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + aoff += vna.vna_next; + vna.vna_next = sizeof(vernaux_dtype); + } + /* + * copy Vernaux to dst buffer + */ + if (dst) { + copy_vernaux_tmptodst(dvna, &vna, enc); + } + /* + * end check + */ + if (vna.vna_next == 0) { + break; + } + } + /* + * parameter check + */ + if (acount != vn.vn_cnt) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + /* + * copy Verneed to dst buffer + */ + if (dst) { + vn.vn_aux = sizeof(verneed_dtype); + if (vn.vn_next != 0) { + vn.vn_next = doff - save; + } + copy_verneed_tmptodst(dvn, &vn, enc); + } + /* + * end check + */ + if (vn.vn_next == 0) { + return doff; + } + } +} + +size_t +translator(verneed,L)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verneed(dst, src, n, ELFDATA2LSB); +} + +size_t +translator(verneed,M)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verneed(dst, src, n, ELFDATA2MSB); +} diff --git a/libelf/lib/version.c b/libelf/lib/version.c new file mode 100755 index 000000000..1576f3935 --- /dev/null +++ b/libelf/lib/version.c @@ -0,0 +1,36 @@ +/* +version.c - implementation of the elf_version(3) function. +Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <private.h> + +unsigned +elf_version(unsigned ver) { + unsigned tmp; + + if (ver == EV_NONE) { + return EV_CURRENT; + } + if (!valid_version(ver)) { + seterr(ERROR_UNKNOWN_VERSION); + return EV_NONE; + } + tmp = _elf_version == EV_NONE ? EV_CURRENT : _elf_version; + _elf_version = ver; + return tmp; +} |