diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/32.fsize.c | 155 | ||||
-rw-r--r-- | lib/32.getehdr.c | 56 | ||||
-rw-r--r-- | lib/32.getphdr.c | 56 | ||||
-rw-r--r-- | lib/32.getshdr.c | 58 | ||||
-rw-r--r-- | lib/32.newehdr.c | 80 | ||||
-rw-r--r-- | lib/32.newphdr.c | 118 | ||||
-rw-r--r-- | lib/32.xlatetof.c | 438 | ||||
-rw-r--r-- | lib/64.xlatetof.c | 512 | ||||
-rw-r--r-- | lib/Makefile.in | 278 | ||||
-rw-r--r-- | lib/Makefile.w32 | 166 | ||||
-rw-r--r-- | lib/assert.c | 33 | ||||
-rw-r--r-- | lib/begin.c | 429 | ||||
-rw-r--r-- | lib/build.bat | 36 | ||||
-rw-r--r-- | lib/byteswap.h | 95 | ||||
-rw-r--r-- | lib/checksum.c | 178 | ||||
-rw-r--r-- | lib/cntl.c | 71 | ||||
-rw-r--r-- | lib/config.h.w32 | 161 | ||||
-rw-r--r-- | lib/cook.c | 501 | ||||
-rw-r--r-- | lib/data.c | 36 | ||||
-rw-r--r-- | lib/elf_repl.h | 996 | ||||
-rw-r--r-- | lib/end.c | 118 | ||||
-rw-r--r-- | lib/errmsg.c | 77 | ||||
-rw-r--r-- | lib/errno.c | 32 | ||||
-rw-r--r-- | lib/errors.h | 100 | ||||
-rw-r--r-- | lib/ext_types.h | 334 | ||||
-rw-r--r-- | lib/fill.c | 29 | ||||
-rw-r--r-- | lib/flag.c | 92 | ||||
-rw-r--r-- | lib/gelf.h | 155 | ||||
-rw-r--r-- | lib/gelfehdr.c | 140 | ||||
-rw-r--r-- | lib/gelfphdr.c | 148 | ||||
-rw-r--r-- | lib/gelfshdr.c | 125 | ||||
-rw-r--r-- | lib/gelftrans.c | 407 | ||||
-rw-r--r-- | lib/getarhdr.c | 37 | ||||
-rw-r--r-- | lib/getaroff.c | 40 | ||||
-rw-r--r-- | lib/getarsym.c | 87 | ||||
-rw-r--r-- | lib/getbase.c | 33 | ||||
-rw-r--r-- | lib/getdata.c | 157 | ||||
-rw-r--r-- | lib/getident.c | 48 | ||||
-rw-r--r-- | lib/getscn.c | 48 | ||||
-rw-r--r-- | lib/hash.c | 38 | ||||
-rw-r--r-- | lib/input.c | 106 | ||||
-rw-r--r-- | lib/kind.c | 33 | ||||
-rw-r--r-- | lib/libelf.def | 82 | ||||
-rw-r--r-- | lib/libelf.h | 305 | ||||
-rw-r--r-- | lib/memset.c | 53 | ||||
-rw-r--r-- | lib/ndxscn.c | 33 | ||||
-rw-r--r-- | lib/newdata.c | 56 | ||||
-rw-r--r-- | lib/newscn.c | 145 | ||||
-rw-r--r-- | lib/next.c | 42 | ||||
-rw-r--r-- | lib/nextscn.c | 54 | ||||
-rw-r--r-- | lib/nlist.c | 253 | ||||
-rw-r--r-- | lib/nlist.h | 48 | ||||
-rw-r--r-- | lib/opt.delscn.c | 205 | ||||
-rw-r--r-- | lib/private.h | 446 | ||||
-rw-r--r-- | lib/rand.c | 43 | ||||
-rw-r--r-- | lib/rawdata.c | 89 | ||||
-rw-r--r-- | lib/rawfile.c | 54 | ||||
-rw-r--r-- | lib/strptr.c | 150 | ||||
-rw-r--r-- | lib/swap64.c | 81 | ||||
-rw-r--r-- | lib/sys_elf.h.in | 130 | ||||
-rw-r--r-- | lib/sys_elf.h.w32 | 130 | ||||
-rw-r--r-- | lib/update.c | 1021 | ||||
-rw-r--r-- | lib/verdef.h | 241 | ||||
-rw-r--r-- | lib/verdef_32_tof.c | 53 | ||||
-rw-r--r-- | lib/verdef_32_tom.c | 53 | ||||
-rw-r--r-- | lib/verdef_64_tof.c | 53 | ||||
-rw-r--r-- | lib/verdef_64_tom.c | 53 | ||||
-rw-r--r-- | lib/verneed.h | 245 | ||||
-rw-r--r-- | lib/version.c | 44 | ||||
-rw-r--r-- | lib/x.elfext.c | 190 | ||||
-rw-r--r-- | lib/x.movscn.c | 112 | ||||
-rw-r--r-- | lib/x.remscn.c | 119 |
72 files changed, 11420 insertions, 0 deletions
diff --git a/lib/32.fsize.c b/lib/32.fsize.c new file mode 100644 index 0000000..1815fa1 --- /dev/null +++ b/lib/32.fsize.c @@ -0,0 +1,155 @@ +/* +32.fsize.c - implementation of the elf{32,64}_fsize(3) functions. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> +#include <ext_types.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.fsize.c,v 1.13 2008/05/23 08:15:33 michael Exp $"; +#endif /* lint */ + +const size_t +_elf_fmsize[2][EV_CURRENT - EV_NONE][ELF_T_NUM][2] = { + /* ELFCLASS32 */ + { + /* version 1 */ + { + { 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) }, + { 0, 0 }, /* there is no Elf32_Sxword */ + { 0, 0 }, /* there is no Elf32_Xword */ + /* XXX: check Solaris values */ + { 0, 0 }, /* Elf32_Verdef/Verdaux size varies */ + { 0, 0 }, /* Elf32_Verneed/Vernaux size varies */ + }, + }, +#if __LIBELF64 + /* ELFCLASS64 */ + { + /* version 1 */ + { + { sizeof(unsigned char), sizeof(unsigned char) }, + { sizeof(Elf64_Addr), sizeof(__ext_Elf64_Addr) }, + { sizeof(Elf64_Dyn), sizeof(__ext_Elf64_Dyn) }, + { sizeof(Elf64_Ehdr), sizeof(__ext_Elf64_Ehdr) }, + { sizeof(Elf64_Half), sizeof(__ext_Elf64_Half) }, + { sizeof(Elf64_Off), sizeof(__ext_Elf64_Off) }, + { sizeof(Elf64_Phdr), sizeof(__ext_Elf64_Phdr) }, + { sizeof(Elf64_Rela), sizeof(__ext_Elf64_Rela) }, + { sizeof(Elf64_Rel), sizeof(__ext_Elf64_Rel) }, + { sizeof(Elf64_Shdr), sizeof(__ext_Elf64_Shdr) }, + { sizeof(Elf64_Sword), sizeof(__ext_Elf64_Sword) }, + { sizeof(Elf64_Sym), sizeof(__ext_Elf64_Sym) }, + { sizeof(Elf64_Word), sizeof(__ext_Elf64_Word) }, + { sizeof(Elf64_Sxword), sizeof(__ext_Elf64_Sxword) }, + { sizeof(Elf64_Xword), sizeof(__ext_Elf64_Xword) }, + /* XXX: check Solaris values */ + { 0, 0 }, /* Elf64_Verdef/Verdaux size varies */ + { 0, 0 }, /* Elf64_Verneed/Vernaux size varies */ + }, + }, +#endif /* __LIBELF64 */ +}; + +static size_t +_elf_fsize(unsigned cls, Elf_Type type, unsigned ver) { + size_t n = 0; + + if (!valid_version(ver)) { + seterr(ERROR_UNKNOWN_VERSION); + } + else if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + } + else if (!(n = _fsize(cls, ver, type))) { + seterr(ERROR_UNKNOWN_TYPE); + } + return n; +} + +size_t +elf32_fsize(Elf_Type type, size_t count, unsigned ver) { + return count * _elf_fsize(ELFCLASS32, type, ver); +} + +#if __LIBELF64 + +size_t +elf64_fsize(Elf_Type type, size_t count, unsigned ver) { + return count * _elf_fsize(ELFCLASS64, type, ver); +} + +size_t +gelf_fsize(Elf *elf, Elf_Type type, size_t count, unsigned ver) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (valid_class(elf->e_class)) { + return count * _elf_fsize(elf->e_class, type, ver); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + } + return 0; +} + +/* + * Extension: report memory size + */ +size_t +gelf_msize(Elf *elf, Elf_Type type, size_t count, unsigned ver) { + size_t n; + + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (!valid_class(elf->e_class)) { + seterr(ERROR_UNKNOWN_CLASS); + } + else if (!valid_version(ver)) { + seterr(ERROR_UNKNOWN_VERSION); + } + else if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + } + else if (!(n = _msize(elf->e_class, ver, type))) { + seterr(ERROR_UNKNOWN_TYPE); + } + else { + return count * n; + } + } + return 0; +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.getehdr.c b/lib/32.getehdr.c new file mode 100644 index 0000000..5690dd0 --- /dev/null +++ b/lib/32.getehdr.c @@ -0,0 +1,56 @@ +/* +32.getehdr.c - implementation of the elf{32,64}_getehdr(3) functions. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.getehdr.c,v 1.9 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +char* +_elf_getehdr(Elf *elf, unsigned cls) { + 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 != cls) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + return elf->e_ehdr; + } + return NULL; +} + +Elf32_Ehdr* +elf32_getehdr(Elf *elf) { + return (Elf32_Ehdr*)_elf_getehdr(elf, ELFCLASS32); +} + +#if __LIBELF64 + +Elf64_Ehdr* +elf64_getehdr(Elf *elf) { + return (Elf64_Ehdr*)_elf_getehdr(elf, ELFCLASS64); +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.getphdr.c b/lib/32.getphdr.c new file mode 100644 index 0000000..c34b8c7 --- /dev/null +++ b/lib/32.getphdr.c @@ -0,0 +1,56 @@ +/* +32.getphdr.c - implementation of the elf{32,64}_getphdr(3) functions. +Copyright (C) 1995 - 2000 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.getphdr.c,v 1.11 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +char* +_elf_getphdr(Elf *elf, unsigned cls) { + 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 != cls) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + return elf->e_phdr; + } + return NULL; +} + +Elf32_Phdr* +elf32_getphdr(Elf *elf) { + return (Elf32_Phdr*)_elf_getphdr(elf, ELFCLASS32); +} + +#if __LIBELF64 + +Elf64_Phdr* +elf64_getphdr(Elf *elf) { + return (Elf64_Phdr*)_elf_getphdr(elf, ELFCLASS64); +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.getshdr.c b/lib/32.getshdr.c new file mode 100644 index 0000000..498cc5a --- /dev/null +++ b/lib/32.getshdr.c @@ -0,0 +1,58 @@ +/* +32.getshdr.c - implementation of the elf{32,64}_getshdr(3) functions. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.getshdr.c,v 1.10 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +Elf32_Shdr* +elf32_getshdr(Elf_Scn *scn) { + 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 (scn->s_elf->e_class == ELFCLASS32) { + return &scn->s_shdr32; + } + seterr(ERROR_CLASSMISMATCH); + return NULL; +} + +#if __LIBELF64 + +Elf64_Shdr* +elf64_getshdr(Elf_Scn *scn) { + 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 (scn->s_elf->e_class == ELFCLASS64) { + return &scn->s_shdr64; + } + seterr(ERROR_CLASSMISMATCH); + return NULL; +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.newehdr.c b/lib/32.newehdr.c new file mode 100644 index 0000000..fd59fb7 --- /dev/null +++ b/lib/32.newehdr.c @@ -0,0 +1,80 @@ +/* + * 32.newehdr.c - implementation of the elf{32,64}_newehdr(3) functions. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.newehdr.c,v 1.16 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +static char* +_elf_newehdr(Elf *elf, unsigned cls) { + size_t size; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_readable) { + return _elf_getehdr(elf, cls); + } + else if (!elf->e_ehdr) { + size = _msize(cls, _elf_version, ELF_T_EHDR); + elf_assert(size); + if ((elf->e_ehdr = (char*)malloc(size))) { + memset(elf->e_ehdr, 0, size); + elf->e_ehdr_flags |= ELF_F_DIRTY; + elf->e_kind = ELF_K_ELF; + elf->e_class = cls; + return elf->e_ehdr; + } + seterr(ERROR_MEM_EHDR); + } + else if (elf->e_class != cls) { + seterr(ERROR_CLASSMISMATCH); + } + else { + elf_assert(elf->e_kind == ELF_K_ELF); + return elf->e_ehdr; + } + return NULL; +} + +Elf32_Ehdr* +elf32_newehdr(Elf *elf) { + return (Elf32_Ehdr*)_elf_newehdr(elf, ELFCLASS32); +} + +#if __LIBELF64 + +Elf64_Ehdr* +elf64_newehdr(Elf *elf) { + return (Elf64_Ehdr*)_elf_newehdr(elf, ELFCLASS64); +} + +unsigned long +gelf_newehdr(Elf *elf, int cls) { + if (!valid_class(cls) || !_msize(cls, _elf_version, ELF_T_EHDR)) { + seterr(ERROR_UNKNOWN_CLASS); + return 0; + } + return (unsigned long)_elf_newehdr(elf, cls); +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.newphdr.c b/lib/32.newphdr.c new file mode 100644 index 0000000..91c63df --- /dev/null +++ b/lib/32.newphdr.c @@ -0,0 +1,118 @@ +/* + * 32.newphdr.c - implementation of the elf{32,64}_newphdr(3) functions. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.newphdr.c,v 1.16 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +static char* +_elf_newphdr(Elf *elf, size_t count, unsigned cls) { + size_t extcount = 0; + Elf_Scn *scn = NULL; + char *phdr = NULL; + 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 != cls) { + seterr(ERROR_CLASSMISMATCH); + } + else if (elf->e_ehdr || _elf_cook(elf)) { + size = _msize(cls, _elf_version, ELF_T_PHDR); + elf_assert(size); + if (!(scn = _elf_first_scn(elf))) { + return NULL; + } + if (count) { + if (!(phdr = (char*)malloc(count * size))) { + seterr(ERROR_MEM_PHDR); + return NULL; + } + memset(phdr, 0, count * size); + } + elf_assert(elf->e_ehdr); + elf->e_phnum = count; + if (count >= PN_XNUM) { + /* + * get NULL section (create it if necessary) + */ + extcount = count; + count = PN_XNUM; + } + if (cls == ELFCLASS32) { + ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum = count; + scn->s_shdr32.sh_info = extcount; + } +#if __LIBELF64 + else if (cls == ELFCLASS64) { + ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum = count; + scn->s_shdr64.sh_info = extcount; + } +#endif /* __LIBELF64 */ + else { + seterr(ERROR_UNIMPLEMENTED); + if (phdr) { + free(phdr); + } + return NULL; + } + if (elf->e_phdr) { + free(elf->e_phdr); + } + elf->e_phdr = phdr; + elf->e_phdr_flags |= ELF_F_DIRTY; + elf->e_ehdr_flags |= ELF_F_DIRTY; + scn->s_scn_flags |= ELF_F_DIRTY; + return phdr; + } + return NULL; +} + +Elf32_Phdr* +elf32_newphdr(Elf *elf, size_t count) { + return (Elf32_Phdr*)_elf_newphdr(elf, count, ELFCLASS32); +} + +#if __LIBELF64 + +Elf64_Phdr* +elf64_newphdr(Elf *elf, size_t count) { + return (Elf64_Phdr*)_elf_newphdr(elf, count, ELFCLASS64); +} + +unsigned long +gelf_newphdr(Elf *elf, size_t phnum) { + if (!valid_class(elf->e_class)) { + seterr(ERROR_UNKNOWN_CLASS); + return 0; + } + return (unsigned long)_elf_newphdr(elf, phnum, elf->e_class); +} + +#endif /* __LIBELF64 */ diff --git a/lib/32.xlatetof.c b/lib/32.xlatetof.c new file mode 100644 index 0000000..068bac5 --- /dev/null +++ b/lib/32.xlatetof.c @@ -0,0 +1,438 @@ +/* + * 32.xlatetof.c - implementation of the elf32_xlateto[fm](3) functions. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 32.xlatetof.c,v 1.27 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +/* + * Ugly, ugly + */ +#ifdef _WIN32 +# 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 /* _WIN32 */ +# 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 +#endif /* _WIN32 */ + +/* + * 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 size_t \ + Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) { \ + n /= sizeof(tfrom); \ + if (n && dst) { \ + const tfrom *from = (const tfrom*)src; \ + tto *to = (tto*)dst; \ + size_t i; \ + \ + if (sizeof(tfrom) < sizeof(tto)) { \ + from += n; \ + to += n; \ + for (i = 0; i < n; i++) { \ + --from; \ + --to; \ + copy(e,io,seq_back) \ + } \ + } \ + else { \ + for (i = 0; i < n; i++) { \ + copy(e,io,seq_forw) \ + from++; \ + to++; \ + } \ + } \ + } \ + return n * sizeof(tto); \ + } + +#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,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), \ + nullcopy)) +#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), \ + nullcopy)))))))))))))) +#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), \ + nullcopy)))))))) +#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), \ + nullcopy))) +#define copy_rel_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_word(e,io,r_info), \ + nullcopy)) +#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), \ + nullcopy)))))))))) +#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), \ + nullcopy)))))) + +#define nullcopy /**/ + +static size_t +byte_copy(unsigned char *dst, const unsigned char *src, size_t n) { + if (n && dst && dst != src) { +#if HAVE_BROKEN_MEMMOVE + size_t i; + + if (dst >= src + n || dst + n <= src) { + memcpy(dst, src, n); + } + else if (dst < src) { + for (i = 0; i < n; i++) { + dst[i] = src[i]; + } + } + else { + for (i = n; --i; ) { + dst[i] = src[i]; + } + } +#else /* HAVE_BROKEN_MEMMOVE */ + memmove(dst, src, n); +#endif /* HAVE_BROKEN_MEMMOVE */ + } + return 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 size_t (*xlator)(unsigned char*, const unsigned char*, size_t); +typedef xlator xltab[ELF_T_NUM][2]; + +/* + * translation table (32-bit, version 1 -> version 1) + */ +#if PIC +static xltab +#else /* PIC */ +static const xltab +#endif /* PIC */ +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 }, + { 0, 0 }, /* there is no Sxword */ + { 0, 0 }, /* there is no Xword */ +#if __LIBELF_SYMBOL_VERSIONS + { _elf_verdef_32L11_tom, _elf_verdef_32L11_tof }, + { _elf_verneed_32L11_tom, _elf_verneed_32L11_tof }, +#else /* __LIBELF_SYMBOL_VERSIONS */ + { 0, 0 }, + { 0, 0 }, +#endif /* __LIBELF_SYMBOL_VERSIONS */ + }, + { + { 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 }, + { 0, 0 }, /* there is no Sxword */ + { 0, 0 }, /* there is no Xword */ +#if __LIBELF_SYMBOL_VERSIONS + { _elf_verdef_32M11_tom, _elf_verdef_32M11_tof }, + { _elf_verneed_32M11_tom, _elf_verneed_32M11_tof }, +#else /* __LIBELF_SYMBOL_VERSIONS */ + { 0, 0 }, + { 0, 0 }, +#endif /* __LIBELF_SYMBOL_VERSIONS */ + }, +}; + +/* + * main translation table (32-bit) + */ +#if PIC +static xltab* +#else /* PIC */ +static const xltab *const +#endif /* PIC */ +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]) + +/* + * destination buffer size + */ +size_t +_elf32_xltsize(const Elf_Data *src, unsigned dv, unsigned encode, int tof) { + Elf_Type type = src->d_type; + unsigned sv = src->d_version; + xlator op; + + if (!valid_version(sv) || !valid_version(dv)) { + seterr(ERROR_UNKNOWN_VERSION); + return (size_t)-1; + } + if (tof) { + /* + * Encoding doesn't really matter (the translator only looks at + * the source, which resides in memory), but we need a proper + * encoding to select a translator... + */ + encode = ELFDATA2LSB; + } + else if (!valid_encoding(encode)) { + seterr(ERROR_UNKNOWN_ENCODING); + return (size_t)-1; + } + if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + return (size_t)-1; + } + if (!(op = translator(sv, dv, encode, type, tof))) { + seterr(ERROR_UNKNOWN_TYPE); + return (size_t)-1; + } + return (*op)(NULL, src->d_buf, src->d_size); +} + +/* + * direction-independent translation + */ +static Elf_Data* +elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) { + Elf_Type type; + int dv; + int sv; + size_t dsize; + size_t tmp; + 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; + } + op = translator(sv, dv, encode, type, tof); + if (!op) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + dsize = (*op)(NULL, src->d_buf, src->d_size); + if (dsize == (size_t)-1) { + return NULL; + } + if (dst->d_size < dsize) { + seterr(ERROR_DST2SMALL); + return NULL; + } + if (dsize) { + tmp = (*op)(dst->d_buf, src->d_buf, src->d_size); + if (tmp == (size_t)-1) { + return NULL; + } + elf_assert(tmp == dsize); + } + dst->d_size = 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/lib/64.xlatetof.c b/lib/64.xlatetof.c new file mode 100644 index 0000000..c66f000 --- /dev/null +++ b/lib/64.xlatetof.c @@ -0,0 +1,512 @@ +/* + * 64.xlatetof.c - implementation of the elf64_xlateto[fm](3) functions. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> +#include <ext_types.h> +#include <byteswap.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: 64.xlatetof.c,v 1.27 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +/* + * Ugly, ugly + */ +#ifdef _WIN32 +# 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 /* _WIN32 */ +# 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 +#endif /* _WIN32 */ + +/* + * 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 size_t \ + Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) { \ + n /= sizeof(tfrom); \ + if (n && dst) { \ + const tfrom *from = (const tfrom*)src; \ + tto *to = (tto*)dst; \ + size_t i; \ + \ + if (sizeof(tfrom) < sizeof(tto)) { \ + from += n; \ + to += n; \ + for (i = 0; i < n; i++) { \ + --from; \ + --to; \ + copy(e,io,seq_back) \ + } \ + } \ + else { \ + for (i = 0; i < n; i++) { \ + copy(e,io,seq_forw) \ + from++; \ + to++; \ + } \ + } \ + } \ + return n * sizeof(tto); \ + } + +#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_word(e,io,mb) Ex2(copy_,io,mb,u32,e) +#define copy_sxword(e,io,mb) Ex2(copy_,io,mb,i64,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_word_11(e,io,seq) Ex1(copy_scalar_,io,u32,e) +#define copy_sxword_11(e,io,seq)Ex1(copy_scalar_,io,i64,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), \ + nullcopy)) +#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), \ + nullcopy)))))))))))))) +#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), \ + nullcopy)))))))) +#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), \ + nullcopy))))))) +#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), \ + nullcopy)))))) +#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), \ + nullcopy))) +#define copy_rel_11(e,io,seq) \ + seq(copy_addr(e,io,r_offset), \ + seq(copy_xword(e,io,r_info), \ + nullcopy)) +#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), \ + nullcopy)))))))))) +#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), \ + nullcopy)))))) + +#define nullcopy /**/ + +static size_t +byte_copy(unsigned char *dst, const unsigned char *src, size_t n) { + if (n && dst && dst != src) { +#if HAVE_BROKEN_MEMMOVE + size_t i; + + if (dst >= src + n || dst + n <= src) { + memcpy(dst, src, n); + } + else if (dst < src) { + for (i = 0; i < n; i++) { + dst[i] = src[i]; + } + } + else { + for (i = n; --i; ) { + dst[i] = src[i]; + } + } +#else /* HAVE_BROKEN_MEMMOVE */ + memmove(dst, src, n); +#endif /* HAVE_BROKEN_MEMMOVE */ + } + return 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(word_64,_,Elf64_Word,copy_word_11) +copy_type(sxword_64,_,Elf64_Sxword,copy_sxword_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 size_t (*xlator)(unsigned char*, const unsigned char*, size_t); +typedef xlator xltab[ELF_T_NUM][2]; + +/* + * translation table (64-bit, version 1 -> version 1) + */ +#if PIC +static xltab +#else /* PIC */ +static const xltab +#endif /* PIC */ +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 }, +#if __LIBELF_SYMBOL_VERSIONS + { _elf_verdef_64L11_tom, _elf_verdef_64L11_tof }, + { _elf_verneed_64L11_tom, _elf_verneed_64L11_tof }, +#else /* __LIBELF_SYMBOL_VERSIONS */ + { 0, 0 }, + { 0, 0 }, +#endif /* __LIBELF_SYMBOL_VERSIONS */ + }, + { + { 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 }, +#if __LIBELF_SYMBOL_VERSIONS + { _elf_verdef_64M11_tom, _elf_verdef_64M11_tof }, + { _elf_verneed_64M11_tom, _elf_verneed_64M11_tof }, +#else /* __LIBELF_SYMBOL_VERSIONS */ + { 0, 0 }, + { 0, 0 }, +#endif /* __LIBELF_SYMBOL_VERSIONS */ + }, +}; + +/* + * main translation table (64-bit) + */ +#if PIC +static xltab* +#else /* PIC */ +static const xltab *const +#endif /* PIC */ +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]) + +/* + * destination buffer size + */ +size_t +_elf64_xltsize(const Elf_Data *src, unsigned dv, unsigned encode, int tof) { + Elf_Type type = src->d_type; + unsigned sv = src->d_version; + xlator op; + + if (!valid_version(sv) || !valid_version(dv)) { + seterr(ERROR_UNKNOWN_VERSION); + return (size_t)-1; + } + if (tof) { + /* + * Encoding doesn't really matter (the translator only looks at + * the source, which resides in memory), but we need a proper + * encoding to select a translator... + */ + encode = ELFDATA2LSB; + } + else if (!valid_encoding(encode)) { + seterr(ERROR_UNKNOWN_ENCODING); + return (size_t)-1; + } + if (!valid_type(type)) { + seterr(ERROR_UNKNOWN_TYPE); + return (size_t)-1; + } + if (!(op = translator(sv, dv, encode, type, tof))) { + seterr(ERROR_UNKNOWN_TYPE); + return (size_t)-1; + } + return (*op)(NULL, src->d_buf, src->d_size); +} + +/* + * direction-independent translation + */ +static Elf_Data* +elf64_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) { + Elf_Type type; + int dv; + int sv; + size_t dsize; + size_t tmp; + 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; + } + op = translator(sv, dv, encode, type, tof); + if (!op) { + seterr(ERROR_UNKNOWN_TYPE); + return NULL; + } + dsize = (*op)(NULL, src->d_buf, src->d_size); + if (dsize == (size_t)-1) { + return NULL; + } + if (dst->d_size < dsize) { + seterr(ERROR_DST2SMALL); + return NULL; + } + if (dsize) { + tmp = (*op)(dst->d_buf, src->d_buf, src->d_size); + if (tmp == (size_t)-1) { + return NULL; + } + elf_assert(tmp == dsize); + } + dst->d_size = 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); +} + +Elf_Data* +gelf_xlatetom(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class == ELFCLASS32) { + return elf32_xlatetom(dst, src, encode); + } + else if (elf->e_class == ELFCLASS64) { + return elf64_xlatetom(dst, src, encode); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + } + return NULL; +} + +Elf_Data* +gelf_xlatetof(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode) { + if (elf) { + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + } + else if (elf->e_class == ELFCLASS32) { + return elf32_xlatetof(dst, src, encode); + } + else if (elf->e_class == ELFCLASS64) { + return elf64_xlatetof(dst, src, encode); + } + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + } + return NULL; +} + +#endif /* __LIBELF64__ */ diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..92a129f --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,278 @@ +# lib/Makefile for libelf. +# Copyright (C) 1995 - 2009 Michael Riepe +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# @(#) $Id: Makefile.in,v 1.40 2009/11/01 13:04:19 michael Exp $ + +instroot = + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +includedir = @includedir@ +installdirs = $(libdir) $(includedir) $(includedir)/libelf + +CC = @CC@ +LD = @LD@ +AR = ar +MV = mv -f +RM = rm -f +LN_S = @LN_S@ +RANLIB = @RANLIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +DEFS = -DHAVE_CONFIG_H +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +DEPSHLIBS = @DEPSHLIBS@ + +DO_SHLIB = @DO_SHLIB@ +PICFLAGS = @PICFLAGS@ +SHLIB_SFX = @SHLIB_SFX@ +SHLINK_SFX = @SHLINK_SFX@ +SONAME_SFX = @SONAME_SFX@ +LINK_SHLIB = @LINK_SHLIB@ +INSTALL_SHLIB = @INSTALL_SHLIB@ + +SHLIB = libelf$(SHLIB_SFX) +SHLINK = libelf$(SHLINK_SFX) +SONAME = libelf$(SONAME_SFX) + +# install includes in includedir? +DO_COMPAT = @DO_COMPAT@ + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +# no user serviceable parts below + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +MAJOR = @MAJOR@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +topdir = .. +subdir = lib + +.SUFFIXES: +.SUFFIXES: .c .o +.c.o: + @$(RM) $@ $(@:.o=.os) + if test -n "$(PICFLAGS)"; then \ + $(COMPILE) $(PICFLAGS) $< && $(MV) $@ $(@:.o=.os); \ + else true; fi + $(COMPILE) $< + +INCLUDES = -I$(topdir) -I. -I$(srcdir) + +# generic sources +SRCS1 = begin.c cntl.c end.c errmsg.c errno.c fill.c flag.c getarhdr.c \ + getarsym.c getbase.c getdata.c getident.c getscn.c hash.c kind.c \ + ndxscn.c newdata.c newscn.c next.c nextscn.c rand.c rawdata.c \ + rawfile.c strptr.c update.c version.c checksum.c getaroff.c +OBJS1 = begin.o cntl.o end.o errmsg.o errno.o fill.o flag.o getarhdr.o \ + getarsym.o getbase.o getdata.o getident.o getscn.o hash.o kind.o \ + ndxscn.o newdata.o newscn.o next.o nextscn.o rand.o rawdata.o \ + rawfile.o strptr.o update.o version.o checksum.o getaroff.o + +# 32-bit sources +SRCS2 = 32.fsize.c 32.getehdr.c 32.getphdr.c 32.getshdr.c 32.newehdr.c \ + 32.newphdr.c 32.xlatetof.c +OBJS2 = 32.fsize.o 32.getehdr.o 32.getphdr.o 32.getshdr.o 32.newehdr.o \ + 32.newphdr.o 32.xlatetof.o + +# support +SRCS3 = cook.c data.c input.c assert.c +OBJS3 = cook.o data.o input.o assert.o + +# nlist +SRCS4 = nlist.c +OBJS4 = nlist.o + +# opt +SRCS5 = opt.delscn.c x.remscn.c x.movscn.c x.elfext.c +OBJS5 = opt.delscn.o x.remscn.o x.movscn.o x.elfext.o + +# 64-bit sources +SRCS64 = 64.xlatetof.c gelfehdr.c gelfphdr.c gelfshdr.c gelftrans.c swap64.c +OBJS64 = 64.xlatetof.o gelfehdr.o gelfphdr.o gelfshdr.o gelftrans.o swap64.o + +# Versioning sources +SRCS_V = verdef_32_tof.c verdef_32_tom.c verdef_64_tof.c verdef_64_tom.c +OBJS_V = verdef_32_tof.o verdef_32_tom.o verdef_64_tof.o verdef_64_tom.o +HDRS_V = verdef.h verneed.h + +SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) $(SRCS5) $(SRCS64) $(SRCS_V) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJS5) $(OBJS64) $(OBJS_V) + +# missing functions +LIBSRCS = memset.c +LIBOBJS = @LIBOBJS@ + +# public header files +HDRS = libelf.h nlist.h gelf.h + +# public header files (created by configure) +AUXHDRS = sys_elf.h + +# private header files +PRIVHDRS = byteswap.h errors.h ext_types.h private.h elf_repl.h \ + $(HDRS_V) + +DISTFILES = $(SRCS) $(LIBSRCS) $(HDRS) $(PRIVHDRS) Makefile.in sys_elf.h.in \ + Makefile.w32 build.bat config.h.w32 libelf.def sys_elf.h.w32 + +all: libelf.a shared-$(DO_SHLIB) + +check: + +shared-yes: $(SHLIB) +shared-no: + +libelf.a: $(OBJS) $(LIBOBJS) + @$(RM) $@ + $(AR) rcv $@ $(OBJS) $(LIBOBJS) + $(RANLIB) $@ + +$(SHLIB): libelf.a + @$(RM) $(SHLIB) + $(LINK_SHLIB) -o $(SHLIB) $(OBJS:.o=.os) $(LIBOBJS:.o=.os) $(DEPSHLIBS) + if test "$(SONAME)" = "$(SHLIB)"; then true; else \ + $(RM) $(SONAME) && $(LN_S) $(SHLIB) $(SONAME); \ + fi + if test "$(SHLINK)" = "$(SHLIB)"; then true; else \ + $(RM) $(SHLINK) && $(LN_S) $(SHLIB) $(SHLINK); \ + fi + +install: install-data \ + install-shared-$(DO_SHLIB) install-compat-$(DO_COMPAT) + +installdirs: $(top_srcdir)/mkinstalldirs + dirs="$(installdirs)"; for dir in $$dirs; do \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(instroot)$$dir; \ + done + +install-data: all installdirs + $(INSTALL_DATA) libelf.a $(instroot)$(libdir) + -cd $(instroot)$(libdir) && $(RANLIB) libelf.a + files="$(HDRS) $(AUXHDRS) elf_repl.h"; for file in $$files; do \ + if test -r $$file; then \ + $(INSTALL_DATA) $$file $(instroot)$(includedir)/libelf; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$file $(instroot)$(includedir)/libelf; \ + fi; \ + done + +uninstall: uninstall-data \ + uninstall-shared-$(DO_SHLIB) uninstall-compat-$(DO_COMPAT) + +uninstall-data: + $(RM) $(instroot)$(libdir)/libelf.a + $(RM) -r $(instroot)$(includedir)/libelf + +install-shared-yes: install-shared +install-shared-no: +install-shared: installdirs $(SHLIB) + $(INSTALL_SHLIB) $(SHLIB) $(instroot)$(libdir) + if test "$(SONAME)" = "$(SHLIB)"; then true; else \ + cd $(instroot)$(libdir) && $(RM) $(SONAME) && $(LN_S) $(SHLIB) $(SONAME); \ + fi + if test "$(SHLINK)" = "$(SHLIB)"; then true; else \ + cd $(instroot)$(libdir) && $(RM) $(SHLINK) && $(LN_S) $(SHLIB) $(SHLINK); \ + fi + +uninstall-shared-yes: uninstall-shared +uninstall-shared-no: +uninstall-shared: + cd $(instroot)$(libdir) && $(RM) $(SHLIB) $(SONAME) $(SHLINK) + +install-compat-yes: install-compat +install-compat-no: +install-compat: installdirs + files="$(HDRS)"; for file in $$files; do \ + if test -f $(instroot)$(includedir)/$$file; then true; else \ + echo "#include <libelf/$$file>" > $(instroot)$(includedir)/$$file; \ + fi; \ + done + +uninstall-compat-yes: uninstall-compat +uninstall-compat-no: +uninstall-compat: + files="$(HDRS)"; for file in $$files; do \ + if grep "^#include <libelf/$$file>\$$" $(instroot)$(includedir)/$$file >/dev/null 2>&1; then \ + $(RM) $(instroot)$(includedir)/$$file; \ + else true; fi; \ + done + +mostlyclean: + $(RM) *.o *.a *.os $(SHLIB) $(SONAME) $(SHLINK) + $(RM) *~ core a.out errlist + +clean: mostlyclean + +distclean: clean + $(RM) stamp-h $(AUXHDRS) + $(RM) Makefile + +maintainer-clean: distclean + +# maintainer only + +MAINT = @MAINT@ + +distdir = $(PACKAGE)-$(VERSION) +distsubdir = $(topdir)/$(distdir)/$(subdir) +$(MAINT)dist: $(DISTFILES) + if test -d $(distsubdir); then true; else mkdir $(distsubdir); fi + files="$(DISTFILES)"; for file in $$files; do \ + ln $(srcdir)/$$file $(distsubdir) || \ + cp -p $(srcdir)/$$file $(distsubdir) || exit 1; \ + done + +# For the justification of the following Makefile rules, see node +# `Automatic Remaking' in GNU Autoconf documentation. + +$(MAINT)Makefile: Makefile.in $(topdir)/config.status + cd $(topdir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + +$(MAINT)sys_elf.h: stamp-h +$(MAINT)stamp-h: sys_elf.h.in $(topdir)/config.status + cd $(topdir) && CONFIG_FILES= CONFIG_HEADERS=$(subdir)/sys_elf.h ./config.status + $(RM) stamp-h && echo timestamp > stamp-h + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: + +# dependencies +$(OBJS): private.h $(topdir)/config.h libelf.h gelf.h errors.h $(AUXHDRS) +32.fsize.o: ext_types.h +32.xlatetof.o: byteswap.h ext_types.h +64.xlatetof.o: byteswap.h ext_types.h +getarsym.o: byteswap.h +memset.o: $(topdir)/config.h +nlist.o: nlist.h +swap64.o: byteswap.h +$(OBJS_V): byteswap.h ext_types.h $(HDRS_V) diff --git a/lib/Makefile.w32 b/lib/Makefile.w32 new file mode 100644 index 0000000..7ee810c --- /dev/null +++ b/lib/Makefile.w32 @@ -0,0 +1,166 @@ +# lib/Makefile.w32 - Makefile for W32 port.
+# Copyright (C) 1995 - 2009 Michael Riepe
+#
+# 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: Makefile.w32,v 1.3 2009/11/01 13:04:19 michael Exp $
+
+instroot =
+
+prefix =
+exec_prefix =
+libdir =
+includedir =
+installdirs = $(libdir) $(includedir) $(includedir)/libelf
+
+CC = cl /nologo
+LD = link /nologo
+AR =
+MV =
+RM = del
+LN_S =
+RANLIB =
+INSTALL =
+INSTALL_DATA =
+INSTALL_PROGRAM =
+
+CFLAGS = /O2 /W2 /TC /MD
+CPPFLAGS =
+DEFS = /DHAVE_CONFIG_H
+LDFLAGS =
+LIBS =
+DEPSHLIBS =
+
+DO_SHLIB =
+PICFLAGS =
+SHLIB_SFX = .dll
+SHLINK_SFX =
+SONAME_SFX =
+LINK_SHLIB = $(LD) /DLL $(LDFLAGS)
+
+SHLIB = libelf$(SHLIB_SFX)
+SHLINK = libelf$(SHLINK_SFX)
+SONAME = libelf$(SONAME_SFX)
+
+# install includes in includedir?
+DO_COMPAT =
+
+INCLUDES = /I.
+
+COMPILE = $(CC) /c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+# no user serviceable parts below
+
+PACKAGE = libelf
+VERSION = 0.8.9
+MAJOR = 0
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+
+topdir = ..
+subdir = lib
+
+.SUFFIXES:
+.SUFFIXES: .obj .c
+.c.obj:
+ $(COMPILE) $<
+
+# generic sources
+SRCS1 = begin.c cntl.c end.c errmsg.c errno.c fill.c flag.c getarhdr.c \
+ getarsym.c getbase.c getdata.c getident.c getscn.c hash.c kind.c \
+ ndxscn.c newdata.c newscn.c next.c nextscn.c rand.c rawdata.c \
+ rawfile.c strptr.c update.c version.c checksum.c getaroff.c
+OBJS1 = $(SRCS1:.c=.obj)
+
+# 32-bit sources
+SRCS2 = 32.fsize.c 32.getehdr.c 32.getphdr.c 32.getshdr.c 32.newehdr.c \
+ 32.newphdr.c 32.xlatetof.c
+OBJS2 = $(SRCS2:.c=.obj)
+
+# support
+SRCS3 = cook.c data.c input.c assert.c
+OBJS3 = $(SRCS3:.c=.obj)
+
+# nlist
+SRCS4 = nlist.c
+OBJS4 = $(SRCS4:.c=.obj)
+
+# opt
+SRCS5 = opt.delscn.c x.remscn.c x.movscn.c x.elfext.c
+OBJS5 = $(SRCS5:.c=.obj)
+
+# 64-bit sources
+SRCS64 = 64.xlatetof.c gelfehdr.c gelfphdr.c gelfshdr.c gelftrans.c swap64.c
+OBJS64 = $(SRCS64:.c=.obj)
+
+# Versioning sources
+SRCS_V = verdef_32_tof.c verdef_32_tom.c verdef_64_tof.c verdef_64_tom.c
+OBJS_V = $(SRCS_V:.c=.obj)
+HDRS_V = verdef.h verneed.h
+
+SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) $(SRCS5) $(SRCS64) $(SRCS_V)
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJS5) $(OBJS64) $(OBJS_V)
+
+# missing functions
+LIBSRCS = memset.c
+LIBOBJS =
+
+# public header files
+HDRS = libelf.h nlist.h gelf.h
+
+# public header files (created by configure)
+AUXHDRS = sys_elf.h
+
+# private header files
+PRIVHDRS = byteswap.h errors.h ext_types.h private.h elf_repl.h $(HDRS_V)
+
+DISTFILES = $(SRCS) $(LIBSRCS) $(HDRS) $(PRIVHDRS) Makefile.in sys_elf.h.in
+
+all: $(OBJS) $(SHLIB)
+
+check:
+
+$(SHLIB): libelf.def $(OBJS) $(LIBOBJS)
+ -@$(RM) $(SHLIB)
+ $(LINK_SHLIB) /OUT:"$(SHLIB)" /DEF:"libelf.def" $(OBJS) $(LIBOBJS) kernel32.lib
+
+install:
+
+mostlyclean:
+ -$(RM) *.obj
+ -$(RM) $(SHLIB)
+ -$(RM) libelf.lib
+ -$(RM) libelf.exp
+
+clean: mostlyclean
+
+distclean: clean
+ -$(RM) $(AUXHDRS)
+
+maintainer-clean: distclean
+
+# dependencies
+$(OBJS): private.h config.h libelf.h gelf.h errors.h $(AUXHDRS)
+32.fsize.obj: ext_types.h
+32.xlatetof.obj: byteswap.h ext_types.h
+64.xlatetof.obj: byteswap.h ext_types.h
+getarsym.obj: byteswap.h
+memset.obj: config.h
+nlist.obj: nlist.h
+swap64.obj: byteswap.h
+$(OBJS_V): byteswap.h ext_types.h $(HDRS_V)
diff --git a/lib/assert.c b/lib/assert.c new file mode 100644 index 0000000..18bd041 --- /dev/null +++ b/lib/assert.c @@ -0,0 +1,33 @@ +/* +assert.c - assert function for libelf. +Copyright (C) 1999 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: assert.c,v 1.5 2008/05/23 08:15:34 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/lib/begin.c b/lib/begin.c new file mode 100644 index 0000000..1a7a229 --- /dev/null +++ b/lib/begin.c @@ -0,0 +1,429 @@ +/* + * begin.c - implementation of the elf_begin(3) and elf_memory(3) functions. + * Copyright (C) 1995 - 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: begin.c,v 1.22 2009/11/01 13:04:19 michael Exp $"; +#endif /* lint */ + +static const Elf _elf_init = INIT_ELF; +static const char fmag[] = ARFMAG; + +static unsigned long +getnum(const char *str, size_t len, int base, size_t *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; + size_t err = 0; + + elf->e_kind = ELF_K_AR; + elf->e_idlen = SARMAG; + elf->e_off = SARMAG; + + /* 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 (hdr->ar_name[1] != ' ') { + break; + } + /* + * Windows (.lib) archives provide two symbol tables + * The first one is the one we want. + */ + if (!elf->e_symtab) { + 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; + size_t 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--; + } + /* XXX some broken software omits the trailing slash + 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; + } + if (arf->e_off + sizeof(struct ar_hdr) + arhdr->ar_size > arf->e_size) { + free(arhdr); + seterr(ERROR_TRUNC_MEMBER); + 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; +} + +static void +_elf_check_type(Elf *elf, size_t size) { + 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); + } +} + +Elf* +elf_begin(int fd, Elf_Cmd cmd, Elf *ref) { + Elf_Arhdr *arhdr = NULL; + size_t size = 0; + off_t off; + 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 (ref->e_memory) { + fd = ref->e_fd; + } + else if (fd != ref->e_fd) { + seterr(ERROR_FDMISMATCH); + return NULL; + } + if (!(arhdr = _elf_arhdr(ref))) { + return NULL; + } + size = arhdr->ar_size; + } + else if ((off = lseek(fd, (off_t)0, SEEK_END)) == (off_t)-1 + || (off_t)(size = off) != off) { + 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; + } + } + if (size == 0) { + elf->e_data = NULL; + } +#if 1 + else { + /* + * Archive members may be misaligned. Freezing them will + * cause libelf to allocate buffers for translated data, + * which should be properly aligned in all cases. + */ + elf_assert(!ref->e_cooked); + elf->e_data = elf->e_rawdata = ref->e_data + offset; + } +#else + else if (ref->e_data == ref->e_rawdata) { + elf_assert(!ref->e_cooked); + /* + * archive is frozen - freeze member, too + */ + elf->e_data = elf->e_rawdata = ref->e_data + offset; + } + else { + elf_assert(!ref->e_memory); + elf->e_data = ref->e_data + offset; + /* + * 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 (!ref->e_cooked) { + ref->e_cooked = 1; + } + else if (!_elf_read(ref, elf->e_data, offset, size)) { + free(arhdr); + free(elf); + return NULL; + } + } +#endif + elf->e_next = offset + size + (size & 1); + elf->e_disabled = ref->e_disabled; + elf->e_memory = ref->e_memory; + /* 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 /* HAVE_MMAP */ + if (!(elf->e_data = _elf_read(elf, NULL, 0, size))) { + free(elf); + return NULL; + } + } + + _elf_check_type(elf, size); + return elf; +} + +Elf* +elf_memory(char *image, size_t size) { + Elf *elf; + + elf_assert(_elf_init.e_magic == ELF_MAGIC); + if (_elf_version == EV_NONE) { + seterr(ERROR_VERSION_UNSET); + return NULL; + } + else if (size == 0 || image == NULL) { + /* TODO: set error code? */ + return NULL; + } + + if (!(elf = (Elf*)malloc(sizeof(Elf)))) { + seterr(ERROR_MEM_ELF); + return NULL; + } + *elf = _elf_init; + elf->e_size = elf->e_dsize = size; + elf->e_data = elf->e_rawdata = image; + elf->e_readable = 1; + elf->e_disabled = 1; + elf->e_memory = 1; + + _elf_check_type(elf, size); + return elf; +} + +#if __LIBELF64 + +int +gelf_getclass(Elf *elf) { + if (elf && elf->e_kind == ELF_K_ELF && valid_class(elf->e_class)) { + return elf->e_class; + } + return ELFCLASSNONE; +} + +#endif /* __LIBELF64 */ diff --git a/lib/build.bat b/lib/build.bat new file mode 100644 index 0000000..d930d71 --- /dev/null +++ b/lib/build.bat @@ -0,0 +1,36 @@ +@echo off
+
+rem lib/build.bat - build script for W32 port
+rem Copyright (C) 2004 - 2006 Michael Riepe
+rem
+rem This library is free software; you can redistribute it and/or
+rem modify it under the terms of the GNU Library General Public
+rem License as published by the Free Software Foundation; either
+rem version 2 of the License, or (at your option) any later version.
+rem
+rem This library is distributed in the hope that it will be useful,
+rem but WITHOUT ANY WARRANTY; without even the implied warranty of
+rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+rem Library General Public License for more details.
+rem
+rem You should have received a copy of the GNU Library General Public
+rem License along with this library; if not, write to the Free Software
+rem Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+rem @(#) $Id: build.bat,v 1.1 2006/08/21 18:03:48 michael Exp $
+
+rem *** BEGIN EDIT HERE ***
+rem Please uncomment the line that suits your system:
+rem call "C:\Program Files\Microsoft Visual Studio\VC98\bin\vcvars32.bat"
+rem call "C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"
+rem call "C:\Programme\Microsoft Visual Studio\VC98\bin\vcvars32.bat"
+rem call "C:\Programme\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"
+rem OR, if you have to set the path to the compiler directly:
+rem set PATH="C:\PATH\TO\COMPILER\BINARY;%PATH%"
+rem Of course, you'll have to enter the correct path above.
+rem You may also have to change CC (default: cl.exe) in Makefile.w32.
+rem *** END EDIT HERE ***
+
+copy config.h.w32 config.h
+copy sys_elf.h.w32 sys_elf.h
+nmake /nologo /f Makefile.w32 %1
diff --git a/lib/byteswap.h b/lib/byteswap.h new file mode 100644 index 0000000..7526d12 --- /dev/null +++ b/lib/byteswap.h @@ -0,0 +1,95 @@ +/* +byteswap.h - functions and macros for byte swapping. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +/* @(#) $Id: byteswap.h,v 1.7 2008/05/23 08:15:34 michael Exp $ */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#define lu(from,i,s) (((__libelf_u32_t)((unsigned char*)(from))[i])<<(s)) +#define li(from,i,s) (((__libelf_i32_t)(( signed char*)(from))[i])<<(s)) + +#define __load_u16L(from) ((__libelf_u32_t) \ + (lu(from,1,8) | lu(from,0,0))) +#define __load_u16M(from) ((__libelf_u32_t) \ + (lu(from,0,8) | lu(from,1,0))) +#define __load_i16L(from) ((__libelf_i32_t) \ + (li(from,1,8) | lu(from,0,0))) +#define __load_i16M(from) ((__libelf_i32_t) \ + (li(from,0,8) | lu(from,1,0))) + +#define __load_u32L(from) ((__libelf_u32_t) \ + (lu(from,3,24) | lu(from,2,16) | lu(from,1,8) | lu(from,0,0))) +#define __load_u32M(from) ((__libelf_u32_t) \ + (lu(from,0,24) | lu(from,1,16) | lu(from,2,8) | lu(from,3,0))) +#define __load_i32L(from) ((__libelf_i32_t) \ + (li(from,3,24) | lu(from,2,16) | lu(from,1,8) | lu(from,0,0))) +#define __load_i32M(from) ((__libelf_i32_t) \ + (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]=((__libelf_u32_t)(v)>>(s))) +#define si(to,i,v,s) (((char*)(to))[i]=((__libelf_i32_t)(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)) + +#if __LIBELF64 + +/* + * conversion functions from swap64.c + */ +extern __libelf_u64_t _elf_load_u64L(const unsigned char *from); +extern __libelf_u64_t _elf_load_u64M(const unsigned char *from); +extern __libelf_i64_t _elf_load_i64L(const unsigned char *from); +extern __libelf_i64_t _elf_load_i64M(const unsigned char *from); +extern void _elf_store_u64L(unsigned char *to, __libelf_u64_t v); +extern void _elf_store_u64M(unsigned char *to, __libelf_u64_t v); +extern void _elf_store_i64L(unsigned char *to, __libelf_u64_t v); +extern void _elf_store_i64M(unsigned char *to, __libelf_u64_t v); + +/* + * aliases for existing conversion code + */ +#define __load_u64L _elf_load_u64L +#define __load_u64M _elf_load_u64M +#define __load_i64L _elf_load_i64L +#define __load_i64M _elf_load_i64M +#define __store_u64L _elf_store_u64L +#define __store_u64M _elf_store_u64M +#define __store_i64L _elf_store_i64L +#define __store_i64M _elf_store_i64M + +#endif /* __LIBELF64 */ + +#endif /* _BYTESWAP_H */ diff --git a/lib/checksum.c b/lib/checksum.c new file mode 100644 index 0000000..f9e964b --- /dev/null +++ b/lib/checksum.c @@ -0,0 +1,178 @@ +/* +checksum.c - implementation of the elf{32,64}_checksum(3) functions. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: checksum.c,v 1.7 2008/05/23 08:15:34 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_size) { + if (data->d_buf == NULL) { + seterr(ERROR_NULLBUF); + return 0L; + } + 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/lib/cntl.c b/lib/cntl.c new file mode 100644 index 0000000..3f7c5d4 --- /dev/null +++ b/lib/cntl.c @@ -0,0 +1,71 @@ +/* +cntl.c - implementation of the elf_cntl(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: cntl.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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/lib/config.h.w32 b/lib/config.h.w32 new file mode 100644 index 0000000..c4ec0f7 --- /dev/null +++ b/lib/config.h.w32 @@ -0,0 +1,161 @@ +/*
+ * lib/config.h.w32 - configuration file for W32 port
+ * Copyright (C) 2004 - 2006 Michael Riepe
+ *
+ * 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: config.h.w32,v 1.2 2006/09/07 15:55:42 michael Exp $
+ */
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you want to include extra debugging code */
+#define ENABLE_DEBUG 1
+
+/* Define if memmove() does not copy overlapping arrays correctly */
+#undef HAVE_BROKEN_MEMMOVE
+
+/* Define if you have the catgets function. */
+#undef HAVE_CATGETS
+
+/* Define if you have the dgettext function. */
+#undef HAVE_DGETTEXT
+
+/* Define if you have the memset function. */
+#define HAVE_MEMSET 1
+
+/* Define if struct nlist is declared in <elf.h> or <sys/elf.h> */
+#undef HAVE_STRUCT_NLIST_DECLARATION
+
+/* Define if Elf32_Dyn is declared in <link.h> */
+#undef __LIBELF_NEED_LINK_H
+
+/* Define if Elf32_Dyn is declared in <sys/link.h> */
+#undef __LIBELF_NEED_SYS_LINK_H
+
+/* 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) */
+#define __LIBELF64 1
+
+/* 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 if you want symbol versioning (and your system supports it) */
+#define __LIBELF_SYMBOL_VERSIONS 1
+
+/* Define if symbol versioning uses Sun section type (SHT_SUNW_*) */
+#define __LIBELF_SUN_SYMBOL_VERSIONS 1
+
+/* Define if symbol versioning uses GNU section types (SHT_GNU_*) */
+#undef __LIBELF_GNU_SYMBOL_VERSIONS
+
+/* Define to a 64-bit signed integer type if one exists */
+#define __libelf_i64_t __int64
+
+/* Define to a 64-bit unsigned integer type if one exists */
+#define __libelf_u64_t unsigned __int64
+
+/* Define to a 32-bit signed integer type if one exists */
+#define __libelf_i32_t int
+
+/* Define to a 32-bit unsigned integer type if one exists */
+#define __libelf_u32_t unsigned int
+
+/* Define to a 16-bit signed integer type if one exists */
+#define __libelf_i16_t short int
+
+/* Define to a 16-bit unsigned integer type if one exists */
+#define __libelf_u16_t unsigned short int
+
+/* The number of bytes in a __int64. */
+#define SIZEOF___INT64 8
+
+/* The number of bytes in a int. */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long. */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long long. */
+#define SIZEOF_LONG_LONG 0
+
+/* The number of bytes in a short. */
+#define SIZEOF_SHORT 2
+
+/* Define if you have the ftruncate function. */
+#undef HAVE_FTRUNCATE
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the memcmp function. */
+#define HAVE_MEMCMP 1
+
+/* Define if you have the memcpy function. */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the memset function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the <ar.h> header file. */
+#undef HAVE_AR_H
+
+/* Define if you have the <elf.h> header file. */
+#undef HAVE_ELF_H
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <gelf.h> header file. */
+#undef HAVE_GELF_H
+
+/* Define if you have the <libelf.h> header file. */
+#undef HAVE_LIBELF_H
+
+/* Define if you have the <link.h> header file. */
+#undef HAVE_LINK_H
+
+/* Define if you have the <nlist.h> header file. */
+#undef HAVE_NLIST_H
+
+/* Define if you have the <sys/elf.h> header file. */
+#undef HAVE_SYS_ELF_H
+
+/* Define if you have the <sys/link.h> header file. */
+#undef HAVE_SYS_LINK_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
diff --git a/lib/cook.c b/lib/cook.c new file mode 100644 index 0000000..066b6f2 --- /dev/null +++ b/lib/cook.c @@ -0,0 +1,501 @@ +/* + * cook.c - read and translate ELF files. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: cook.c,v 1.29 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +const Elf_Scn _elf_scn_init = INIT_SCN; +const Scn_Data _elf_data_init = INIT_DATA; + +Elf_Type +_elf_scn_type(unsigned t) { + switch (t) { + case SHT_DYNAMIC: return ELF_T_DYN; + case SHT_DYNSYM: return ELF_T_SYM; + case SHT_HASH: return ELF_T_WORD; + case SHT_REL: return ELF_T_REL; + case SHT_RELA: return ELF_T_RELA; + case SHT_SYMTAB: return ELF_T_SYM; + case SHT_SYMTAB_SHNDX: return ELF_T_WORD; /* XXX: really? */ +#if __LIBELF_SYMBOL_VERSIONS +#if __LIBELF_SUN_SYMBOL_VERSIONS + case SHT_SUNW_verdef: return ELF_T_VDEF; + case SHT_SUNW_verneed: return ELF_T_VNEED; + case SHT_SUNW_versym: return ELF_T_HALF; +#else /* __LIBELF_SUN_SYMBOL_VERSIONS */ + case SHT_GNU_verdef: return ELF_T_VDEF; + case SHT_GNU_verneed: return ELF_T_VNEED; + case SHT_GNU_versym: return ELF_T_HALF; +#endif /* __LIBELF_SUN_SYMBOL_VERSIONS */ +#endif /* __LIBELF_SYMBOL_VERSIONS */ + } + return ELF_T_BYTE; +} + +/* + * Check for overflow on 32-bit systems + */ +#define overflow(a,b,t) (sizeof(a) < sizeof(t) && (t)(a) != (b)) + +#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)) + +Elf_Data* +_elf_xlatetom(const Elf *elf, Elf_Data *dst, const Elf_Data *src) { + if (elf->e_class == ELFCLASS32) { + return elf32_xlatetom(dst, src, elf->e_encoding); + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + return elf64_xlatetom(dst, src, elf->e_encoding); + } +#endif /* __LIBELF64 */ + seterr(ERROR_UNIMPLEMENTED); + return NULL; +} + +static char* +_elf_item(void *buf, Elf *elf, Elf_Type type, size_t off) { + Elf_Data src, dst; + + 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 = _fsize(elf->e_class, src.d_version, type); + elf_assert(src.d_size); + if ((elf->e_size - off) < src.d_size) { + seterr(truncerr(type)); + return NULL; + } + + dst.d_version = _elf_version; + dst.d_size = _msize(elf->e_class, dst.d_version, type); + elf_assert(dst.d_size); + + if (!(dst.d_buf = buf) && !(dst.d_buf = malloc(dst.d_size))) { + seterr(memerr(type)); + return NULL; + } + + elf_assert(elf->e_data); + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + off; + } + else { + src.d_buf = elf->e_data + off; + } + + if (_elf_xlatetom(elf, &dst, &src)) { + return (char*)dst.d_buf; + } + if (dst.d_buf != buf) { + free(dst.d_buf); + } + return NULL; +} + +static int +_elf_cook_phdr(Elf *elf) { + size_t num, off, entsz; + + if (elf->e_class == ELFCLASS32) { + num = ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum; + off = ((Elf32_Ehdr*)elf->e_ehdr)->e_phoff; + entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_phentsize; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + num = ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum; + off = ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff; + entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_phentsize; + /* + * Check for overflow on 32-bit systems + */ + if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff, Elf64_Off)) { + seterr(ERROR_OUTSIDE); + return 0; + } + } +#endif /* __LIBELF64 */ + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + if (off) { + Elf_Scn *scn; + size_t size; + unsigned i; + char *p; + + if (num == PN_XNUM) { + /* + * Overflow in ehdr->e_phnum. + * Get real value from first SHDR. + */ + if (!(scn = elf->e_scn_1)) { + seterr(ERROR_NOSUCHSCN); + return 0; + } + if (elf->e_class == ELFCLASS32) { + num = scn->s_shdr32.sh_info; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + num = scn->s_shdr64.sh_info; + } +#endif /* __LIBELF64 */ + /* we already had this + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + */ + } + + size = _fsize(elf->e_class, elf->e_version, ELF_T_PHDR); + elf_assert(size); +#if ENABLE_EXTENDED_FORMAT + if (entsz < size) { +#else /* ENABLE_EXTENDED_FORMAT */ + if (entsz != size) { +#endif /* ENABLE_EXTENDED_FORMAT */ + seterr(ERROR_EHDR_PHENTSIZE); + return 0; + } + size = _msize(elf->e_class, _elf_version, ELF_T_PHDR); + elf_assert(size); + if (!(p = malloc(num * size))) { + seterr(memerr(ELF_T_PHDR)); + return 0; + } + for (i = 0; i < num; i++) { + if (!_elf_item(p + i * size, elf, ELF_T_PHDR, off + i * entsz)) { + free(p); + return 0; + } + } + elf->e_phdr = p; + elf->e_phnum = num; + } + return 1; +} + +static int +_elf_cook_shdr(Elf *elf) { + size_t num, off, entsz; + + if (elf->e_class == ELFCLASS32) { + num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum; + off = ((Elf32_Ehdr*)elf->e_ehdr)->e_shoff; + entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_shentsize; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum; + off = ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff; + entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_shentsize; + /* + * Check for overflow on 32-bit systems + */ + if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff, Elf64_Off)) { + seterr(ERROR_OUTSIDE); + return 0; + } + } +#endif /* __LIBELF64 */ + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + if (off) { + struct tmp { + Elf_Scn scn; + Scn_Data data; + } *head; + Elf_Data src, dst; + Elf_Scn *scn; + Scn_Data *sd; + unsigned i; + + if (off < 0 || off > elf->e_size) { + seterr(ERROR_OUTSIDE); + return 0; + } + + src.d_type = ELF_T_SHDR; + src.d_version = elf->e_version; + src.d_size = _fsize(elf->e_class, src.d_version, ELF_T_SHDR); + elf_assert(src.d_size); +#if ENABLE_EXTENDED_FORMAT + if (entsz < src.d_size) { +#else /* ENABLE_EXTENDED_FORMAT */ + if (entsz != src.d_size) { +#endif /* ENABLE_EXTENDED_FORMAT */ + seterr(ERROR_EHDR_SHENTSIZE); + return 0; + } + dst.d_version = EV_CURRENT; + + if (num == 0) { + union { + Elf32_Shdr sh32; +#if __LIBELF64 + Elf64_Shdr sh64; +#endif /* __LIBELF64 */ + } u; + + /* + * Overflow in ehdr->e_shnum. + * Get real value from first SHDR. + */ + if (elf->e_size - off < entsz) { + seterr(ERROR_TRUNC_SHDR); + return 0; + } + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + off; + } + else { + src.d_buf = elf->e_data + off; + } + dst.d_buf = &u; + dst.d_size = sizeof(u); + if (!_elf_xlatetom(elf, &dst, &src)) { + return 0; + } + elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR)); + elf_assert(dst.d_type == ELF_T_SHDR); + if (elf->e_class == ELFCLASS32) { + num = u.sh32.sh_size; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + num = u.sh64.sh_size; + /* + * Check for overflow on 32-bit systems + */ + if (overflow(num, u.sh64.sh_size, Elf64_Xword)) { + seterr(ERROR_OUTSIDE); + return 0; + } + } +#endif /* __LIBELF64 */ + } + + if ((elf->e_size - off) / entsz < num) { + seterr(ERROR_TRUNC_SHDR); + return 0; + } + + if (!(head = (struct tmp*)malloc(num * sizeof(struct tmp)))) { + seterr(ERROR_MEM_SCN); + return 0; + } + for (scn = NULL, i = num; 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 + off + i * entsz; + } + else { + src.d_buf = elf->e_data + off + i * entsz; + } + dst.d_buf = &scn->s_uhdr; + dst.d_size = sizeof(scn->s_uhdr); + if (!_elf_xlatetom(elf, &dst, &src)) { + elf->e_scn_n = NULL; + free(head); + return 0; + } + elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_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; + + sd->sd_scn = scn; + + if (elf->e_class == ELFCLASS32) { + Elf32_Shdr *shdr = &scn->s_shdr32; + + scn->s_type = shdr->sh_type; + scn->s_size = shdr->sh_size; + scn->s_offset = shdr->sh_offset; + sd->sd_data.d_align = shdr->sh_addralign; + sd->sd_data.d_type = _elf_scn_type(scn->s_type); + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + Elf64_Shdr *shdr = &scn->s_shdr64; + + scn->s_type = shdr->sh_type; + scn->s_size = shdr->sh_size; + scn->s_offset = shdr->sh_offset; + sd->sd_data.d_align = shdr->sh_addralign; + /* + * Check for overflow on 32-bit systems + */ + if (overflow(scn->s_size, shdr->sh_size, Elf64_Xword) + || overflow(scn->s_offset, shdr->sh_offset, Elf64_Off) + || overflow(sd->sd_data.d_align, shdr->sh_addralign, Elf64_Xword)) { + seterr(ERROR_OUTSIDE); + return 0; + } + sd->sd_data.d_type = _elf_scn_type(scn->s_type); + /* + * QUIRKS MODE: + * + * Some 64-bit architectures use 64-bit entries in the + * .hash section. This violates the ELF standard, and + * should be fixed. It's mostly harmless as long as the + * binary and the machine running your program have the + * same byte order, but you're in trouble if they don't, + * and if the entry size is wrong. + * + * As a workaround, I let libelf guess the right size + * for the binary. This relies pretty much on the fact + * that the binary provides correct data in the section + * headers. If it doesn't, it's probably broken anyway. + * Therefore, libelf uses a standard conforming value + * when it's not absolutely sure. + */ + if (scn->s_type == SHT_HASH) { + int override = 0; + + /* + * sh_entsize must reflect the entry size + */ + if (shdr->sh_entsize == ELF64_FSZ_ADDR) { + override++; + } + /* + * sh_size must be a multiple of sh_entsize + */ + if (shdr->sh_size % ELF64_FSZ_ADDR == 0) { + override++; + } + /* + * There must be room for at least 2 entries + */ + if (shdr->sh_size >= 2 * ELF64_FSZ_ADDR) { + override++; + } + /* + * sh_addralign must be correctly set + */ + if (shdr->sh_addralign == ELF64_FSZ_ADDR) { + override++; + } + /* + * The section must be properly aligned + */ + if (shdr->sh_offset % ELF64_FSZ_ADDR == 0) { + override++; + } + /* XXX: also look at the data? */ + /* + * Make a conservative decision... + */ + if (override >= 5) { + sd->sd_data.d_type = ELF_T_ADDR; + } + } + /* + * END QUIRKS MODE. + */ + } +#endif /* __LIBELF64 */ + /* we already had this + else { + seterr(ERROR_UNIMPLEMENTED); + return 0; + } + */ + + sd->sd_data.d_size = scn->s_size; + 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; +} + +static int +_elf_cook_file(Elf *elf) { + elf->e_ehdr = _elf_item(NULL, elf, ELF_T_EHDR, 0); + if (!elf->e_ehdr) { + return 0; + } + /* + * Note: _elf_cook_phdr may require the first section header! + */ + if (!_elf_cook_shdr(elf)) { + return 0; + } + if (!_elf_cook_phdr(elf)) { + return 0; + } + 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 (valid_class(elf->e_class)) { + return _elf_cook_file(elf); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return 0; +} diff --git a/lib/data.c b/lib/data.c new file mode 100644 index 0000000..53d78c3 --- /dev/null +++ b/lib/data.c @@ -0,0 +1,36 @@ +/* + * data.c - libelf internal variables. + * Copyright (C) 1995 - 1998, 2007 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: data.c,v 1.8 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +unsigned _elf_version = EV_NONE; +int _elf_errno = 0; +int _elf_fill = 0; + +#if ENABLE_SANITY_CHECKS +#define SANITY_CHECKS -1 +#else +#define SANITY_CHECKS 0 +#endif + +int _elf_sanity_checks = SANITY_CHECKS; diff --git a/lib/elf_repl.h b/lib/elf_repl.h new file mode 100644 index 0000000..c5cf90f --- /dev/null +++ b/lib/elf_repl.h @@ -0,0 +1,996 @@ +/* + * elf_repl.h - public header file for systems that lack it. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: elf_repl.h,v 1.22 2009/11/01 13:04:19 michael Exp $ */ + +/* + * NEVER INCLUDE THIS FILE DIRECTLY - USE <libelf.h> INSTEAD! + */ + +#ifndef _ELF_REPL_H +#define _ELF_REPL_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Scalar data types + */ +typedef __libelf_u32_t Elf32_Addr; +typedef __libelf_u16_t Elf32_Half; +typedef __libelf_u32_t Elf32_Off; +typedef __libelf_i32_t Elf32_Sword; +typedef __libelf_u32_t 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 + +#if __LIBELF64 + +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_u32_t Elf64_Word; +typedef __libelf_i64_t Elf64_Sxword; +typedef __libelf_u64_t Elf64_Xword; + +#define ELF64_FSZ_ADDR 8 +#define ELF64_FSZ_HALF 2 +#define ELF64_FSZ_OFF 8 +#define ELF64_FSZ_SWORD 4 +#define ELF64_FSZ_WORD 4 +#define ELF64_FSZ_SXWORD 8 +#define ELF64_FSZ_XWORD 8 + +/* + * Blame Sun for this... + */ +typedef __libelf_u64_t Elf64_Lword; +typedef __libelf_u64_t Elf32_Lword; + +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; +#endif /* __LIBELF64 */ + +/* + * 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_OSABI 7 +#define EI_ABIVERSION 8 +#define EI_PAD 9 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* + * e_ident[EI_CLASS] + */ +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +/* + * e_ident[EI_DATA] + */ +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 +#define ELFDATANUM 3 + +/* + * e_ident[EI_OSABI] + */ +#define ELFOSABI_NONE 0 /* No extensions or unspecified */ +#define ELFOSABI_SYSV ELFOSABI_NONE +#define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* Linux */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* Open BSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +/* these are probably obsolete: */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* standalone (embedded) application */ + + +/* + * 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_LOOS 0xfe00 +#define ET_HIOS 0xfeff +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* + * e_machine + */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#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 80860 */ +#define EM_MIPS 8 /* MIPS I Architecture */ +#define EM_S370 9 /* IBM System/370 Processor */ +#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */ +#define EM_SPARC64 11 /* SPARC 64-bit */ +#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ +#define EM_S390 22 /* IBM System/390 Processor */ +#define EM_V800 36 /* NEC V800 */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC Version 9 */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor */ +#define EM_ARC 45 /* Argonaut RISC Core, Argonaut Technologies Inc. */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel IA-64 processor architecture */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola ColdFire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Star*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor family */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_AMD64 EM_X86_64 +#define EM_PDSP 63 /* Sony DSP Processor */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ +#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ +#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit microcontroller */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */ +#define EM_NS32K 97 /* National Semiconductor 32000 series */ +#define EM_TPC 98 /* Tenor Network TPC processor */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor */ +#define EM_ST200 100 /* STMicroelectronics (www.st.com) ST200 microcontroller */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */ +#define EM_MAX 102 /* MAX Processor */ +#define EM_CR 103 /* National Semiconductor CompactRISC microprocessor */ +#define EM_F2MC16 104 /* Fujitsu F2MC16 */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller msp430 */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors */ +#define EM_SEP 108 /* Sharp embedded microprocessor */ +#define EM_ARCA 109 /* Arca RISC Microprocessor */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */ +#define EM_NUM 111 + +/* + * 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; + +#if __LIBELF64 +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; +#endif /* __LIBELF64 */ + +/* + * Special section indices + */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_LOOS 0xff20 +#define SHN_HIOS 0xff3f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_XINDEX 0xffff +#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_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_NUM 19 +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* + * Solaris extensions + */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_SUNW_versym 0x6fffffff +#define SHT_HISUNW 0x6fffffff + +#define SHT_SPARC_GOTDATA 0x70000000 +#define SHT_AMD64_UNWIND 0x70000001 + +/* + * GNU extensions + */ +#define SHT_GNU_verdef 0x6ffffffd +#define SHT_GNU_verneed 0x6ffffffe +#define SHT_GNU_versym 0x6fffffff + +/* + * sh_flags + */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MERGE 0x10 +#define SHF_STRINGS 0x20 +#define SHF_INFO_LINK 0x40 +#define SHF_LINK_ORDER 0x80 +#define SHF_OS_NONCONFORMING 0x100 +#define SHF_GROUP 0x200 +#define SHF_TLS 0x400 +#define SHF_MASKOS 0x0ff00000 +#define SHF_MASKPROC 0xf0000000 + +/* + * Solaris extensions + */ +#define SHF_AMD64_LARGE 0x10000000 +#define SHF_ORDERED 0x40000000 +#define SHF_EXCLUDE 0x80000000 + +/* + * Section group flags + */ +#define GRP_COMDAT 0x1 +#define GRP_MASKOS 0x0ff00000 +#define GRP_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; + +#if __LIBELF64 +typedef struct { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; +#endif /* __LIBELF64 */ + +/* + * 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)) + +#if __LIBELF64 +#define ELF64_ST_BIND(i) ((i)>>4) +#define ELF64_ST_TYPE(i) ((i)&0xf) +#define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) +#endif /* __LIBELF64 */ + +/* + * Symbol binding + */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_NUM 3 +#define STB_LOOS 10 +#define STB_HIOS 12 +#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_COMMON 5 +#define STT_TLS 6 +#define STT_NUM 7 +#define STT_LOOS 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +/* + * Macros for manipulating st_other + */ +#define ELF32_ST_VISIBILITY(o) ((o)&0x3) +#if __LIBELF64 +#define ELF64_ST_VISIBILITY(o) ((o)&0x3) +#endif /* __LIBELF64 */ + +/* + * Symbol visibility + */ +#define STV_DEFAULT 0 +#define STV_INTERNAL 1 +#define STV_HIDDEN 2 +#define STV_PROTECTED 3 + +/* + * 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; + +#if __LIBELF64 +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; +#endif /* __LIBELF64 */ + +/* + * 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)) + +#if __LIBELF64 +#define ELF64_R_SYM(i) ((Elf64_Xword)(i)>>32) +#define ELF64_R_TYPE(i) ((i)&0xffffffffL) +#define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+((t)&0xffffffffL)) +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +/* Solaris and GNU use this layout. Be compatible. */ +/* XXX: Latest ELF specs say it's 64-bit!!! */ +typedef struct { + Elf64_Word n_namesz; /* name size */ + Elf64_Word n_descsz; /* descriptor size */ + Elf64_Word n_type; /* descriptor type */ +} Elf64_Nhdr; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; +#endif /* __LIBELF64 */ + +/* + * Special numbers + */ +#define PN_XNUM 0xffff + +/* + * 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_TLS 7 +#define PT_NUM 8 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* + * Solaris extensions + */ + +#define PT_SUNW_UNWIND 0x6464e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa +#define PT_SUNWSTACK 0x6ffffffb +#define PT_SUNWDTRACE 0x6ffffffc +#define PT_SUNWCAP 0x6ffffffd +#define PT_HISUNW 0x6fffffff + +/* + * p_flags + */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 +#define PF_MASKOS 0x0ff00000 +#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; + +#if __LIBELF64 +typedef struct { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; +#endif /* __LIBELF64 */ + +/* + * Dynamic array tags + */ + /* d_un exec shared */ +#define DT_NULL 0 /* ign. mand. mand. */ +#define DT_NEEDED 1 /* d_val opt. opt. */ +#define DT_PLTRELSZ 2 /* d_val opt. opt. */ +#define DT_PLTGOT 3 /* d_ptr opt. opt. */ +#define DT_HASH 4 /* d_ptr mand. mand. */ +#define DT_STRTAB 5 /* d_ptr mand. mand. */ +#define DT_SYMTAB 6 /* d_ptr mand. mand. */ +#define DT_RELA 7 /* d_ptr mand. opt. */ +#define DT_RELASZ 8 /* d_val mand. opt. */ +#define DT_RELAENT 9 /* d_val mand. opt. */ +#define DT_STRSZ 10 /* d_val mand. mand. */ +#define DT_SYMENT 11 /* d_val mand. mand. */ +#define DT_INIT 12 /* d_ptr opt. opt. */ +#define DT_FINI 13 /* d_ptr opt. opt. */ +#define DT_SONAME 14 /* d_val ign. opt. */ +#define DT_RPATH 15 /* d_val opt. ign. */ +#define DT_SYMBOLIC 16 /* ign. ign. opt. */ +#define DT_REL 17 /* d_ptr mand. opt. */ +#define DT_RELSZ 18 /* d_val mand. opt. */ +#define DT_RELENT 19 /* d_val mand. opt. */ +#define DT_PLTREL 20 /* d_val opt. opt. */ +#define DT_DEBUG 21 /* d_ptr opt. ign. */ +#define DT_TEXTREL 22 /* ign. opt. opt. */ +#define DT_JMPREL 23 /* d_ptr opt. opt. */ +#define DT_BIND_NOW 24 /* ign. opt. opt. */ +#define DT_INIT_ARRAY 25 /* d_ptr opt. opt. */ +#define DT_FINI_ARRAY 26 /* d_ptr opt. opt. */ +#define DT_INIT_ARRAYSZ 27 /* d_val opt. opt. */ +#define DT_FINI_ARRAYSZ 28 /* d_val opt. opt. */ +#define DT_RUNPATH 29 /* d_val opt. opt. */ +#define DT_FLAGS 30 /* d_val opt. opt. */ +#define DT_ENCODING 32 /* odd/even encoding rule starts here */ +#define DT_PREINIT_ARRAY 32 /* d_ptr opt. ign. */ +#define DT_PREINIT_ARRAYSZ 33 /* d_val opt. ign. */ +#define DT_NUM 34 +#define DT_LOOS 0x6000000D +#define DT_HIOS 0x6ffff000 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* + * DT_FLAGS values + */ +#define DF_ORIGIN 0x1 +#define DF_SYMBOLIC 0x2 +#define DF_TEXTREL 0x4 +#define DF_BIND_NOW 0x8 +#define DF_STATIC_TLS 0x10 + +/* + * Solaris extensions + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc +#define DT_POSFLAG_1 0x6ffffdfd +#define DT_SYMINSZ 0x6ffffdfe +#define DT_SYMINENT 0x6ffffdff +#define DT_VALRNGHI 0x6ffffdff + +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_CONFIG 0x6ffffefa +#define DT_DEPAUDIT 0x6ffffefb +#define DT_AUDIT 0x6ffffefc +#define DT_PLTPAD 0x6ffffefd +#define DT_MOVETAB 0x6ffffefe +#define DT_SYMINFO 0x6ffffeff +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff + +#define DT_AUXILIARY 0x7ffffffd +#define DT_USED 0x7ffffffe +#define DT_FILTER 0x7fffffff + +/* + * GNU extensions + */ +#define DT_VERSYM 0x6ffffff0 + +/* + * DT_FEATURE_1 values + */ +#define DTF_1_PARINIT 0x1 +#define DTF_1_CONFEXP 0x2 + +/* + * DT_POSFLAG_1 values + */ +#define DF_P1_LAZYLOAD 0x1 +#define DF_P1_GROUPPERM 0x2 + +/* + * DT_FLAGS_1 values + */ +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONFALT 0x00002000 +#define DF_1_ENDFILTEE 0x00004000 +#define DF_1_DISPRELDNE 0x00008000 +#define DF_1_DISPRELPND 0x00010000 + +/* + * Syminfo structure + */ +typedef struct { + Elf32_Half si_boundto; + Elf32_Half si_flags; +} Elf32_Syminfo; + +#if __LIBELF64 +typedef struct { + Elf64_Half si_boundto; + Elf64_Half si_flags; +} Elf64_Syminfo; +#endif /* __LIBELF64 */ + +/* + * Syminfo version (stored in unused first entry) + */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * si_boundto special values + */ +#define SYMINFO_BT_LOWRESERVE 0xff00 +#define SYMINFO_BT_PARENT 0xfffe /* bound to parent */ +#define SYMINFO_BT_SELF 0xffff /* bound to self */ + +/* + * si_flags + */ +#define SYMINFO_FLG_DIRECT 0x01 /* bound to an object */ +#define SYMINFO_FLG_PASSTHRU 0x02 /* pass-thru symbol */ +#define SYMINFO_FLG_COPY 0x04 /* result of a copy relocation */ +#define SYMINFO_FLG_LAZYLOAD 0x08 /* bound to lazy-loaded object */ + +/* + * Version definitions + */ +typedef struct { + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct { + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct { + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct { + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +#if __LIBELF64 + +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +#endif /* __LIBELF64 */ + +/* + * vd_version + */ +#define VER_DEF_NONE 0 +#define VER_DEF_CURRENT 1 +#define VER_DEF_NUM 2 + +/* + * vn_version + */ +#define VER_NEED_NONE 0 +#define VER_NEED_CURRENT 1 +#define VER_NEED_NUM 2 + +/* + * vd_flags / vna_flags + */ +#define VER_FLG_BASE 0x1 /* vd_flags only */ +#define VER_FLG_WEAK 0x2 + +/* + * Elf*_Versym special values + */ +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 + +/* + * Solaris extensions + */ + +/* + * Move section + */ +#if __LIBELF64 + +typedef struct { + Elf32_Lword m_value; + Elf32_Word m_info; + Elf32_Word m_poffset; + Elf32_Half m_repeat; + Elf32_Half m_stride; +} Elf32_Move; + +typedef struct { + Elf64_Lword m_value; + Elf64_Xword m_info; + Elf64_Xword m_poffset; + Elf64_Half m_repeat; + Elf64_Half m_stride; +} Elf64_Move; + +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, sz) (((sym)<<8)+(unsigned char)(sz)) + +#define ELF64_M_SYM(info) ((Elf64_Xword)(info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, sz) (((Elf64_Xword)(sym)<<8)+(unsigned char)(sz)) + +#endif /* __LIBELF64 */ + +/* + * Capabilities + */ + +typedef struct { + Elf32_Word c_tag; + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +#if __LIBELF64 + +typedef struct { + Elf64_Xword c_tag; + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +#endif /* __LIBELF64 */ + +#define CA_SUNW_NULL 0 /* c_un ignored */ +#define CA_SUNW_HW_1 1 /* c_un.c_val */ +#define CA_SUNW_SF_1 2 /* c_un.c_val */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _ELF_REPL_H */ diff --git a/lib/end.c b/lib/end.c new file mode 100644 index 0000000..c604239 --- /dev/null +++ b/lib/end.c @@ -0,0 +1,118 @@ +/* + * end.c - implementation of the elf_end(3) function. + * Copyright (C) 1995 - 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: end.c,v 1.12 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +#if HAVE_MMAP +#include <sys/mman.h> +#endif /* HAVE_MMAP */ + +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) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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 /* HAVE_MMAP */ + else if (!elf->e_memory) { + _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); + } + _elf_free(elf->e_ehdr); + _elf_free(elf->e_phdr); + free(elf); + return 0; +} diff --git a/lib/errmsg.c b/lib/errmsg.c new file mode 100644 index 0000000..883243f --- /dev/null +++ b/lib/errmsg.c @@ -0,0 +1,77 @@ +/* + * errmsg.c - implementation of the elf_errmsg(3) function. + * Copyright (C) 1995 - 1999, 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: errmsg.c,v 1.11 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +#if HAVE_DGETTEXT +# undef HAVE_CATGETS +# include <libintl.h> +#else /* HAVE_DGETTEXT */ +# define dgettext(dom, str) str +#endif /* HAVE_DGETTEXT */ + +#if HAVE_CATGETS +# include <nl_types.h> +static nl_catd _libelf_cat = (nl_catd)0; +#endif /* HAVE_CATGETS */ + +#if HAVE_DGETTEXT || HAVE_CATGETS +static const char domain[] = "libelf"; +#endif /* HAVE_DGETTEXT || HAVE_CATGETS */ + +#if PIC +static const char *_messages[] = { +#else /* PIC */ +static const char *const _messages[] = { +#endif /* PIC */ +#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 /* HAVE_CATGETS */ + return dgettext(domain, _messages[err]); +} diff --git a/lib/errno.c b/lib/errno.c new file mode 100644 index 0000000..1902322 --- /dev/null +++ b/lib/errno.c @@ -0,0 +1,32 @@ +/* +errno.c - implementation of the elf_errno(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: errno.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +int +elf_errno(void) { + int tmp = _elf_errno; + + _elf_errno = 0; + return tmp; +} diff --git a/lib/errors.h b/lib/errors.h new file mode 100644 index 0000000..80ee70b --- /dev/null +++ b/lib/errors.h @@ -0,0 +1,100 @@ +/* + * errors.h - exhaustive list of all error codes and messages for libelf. + * Copyright (C) 1995 - 2003, 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: errors.h,v 1.18 2008/05/23 08:15:34 michael Exp $ */ + +/* 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: cntl(ELF_C_FDREAD) on write-only file")) +__err__(ERROR_INVALID_CMD, _("Request error: invalid ELF_C_* argument")) +__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 ELF version")) +__err__(ERROR_CMDMISMATCH, _("Request error: ELF_C_* argument does not match")) +__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: invalid ELF_T_* argument")) +__err__(ERROR_UNKNOWN_ENCODING, _("Request error: unknown data encoding")) +__err__(ERROR_DST2SMALL, _("Request error: destination buffer 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: section does not belong to file")) +__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 does not belong to section")) +__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(ELF_C_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: can't truncate output file")) +__err__(ERROR_VERSION_UNSET, _("Sequence error: must set ELF version first")) +__err__(ERROR_NOEHDR, _("Sequence error: must create ELF header 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: ELF header truncated")) +__err__(ERROR_TRUNC_PHDR, _("Format error: program header table truncated")) +__err__(ERROR_TRUNC_SHDR, _("Format error: section header table truncated")) +__err__(ERROR_TRUNC_SCN, _("Format error: data region truncated")) +__err__(ERROR_ALIGN_PHDR, _("Format error: program header table alignment")) +__err__(ERROR_ALIGN_SHDR, _("Format error: section header table alignment")) +__err__(ERROR_VERDEF_FORMAT, _("Format error: bad parameter in Verdef record")) +__err__(ERROR_VERDEF_VERSION, _("Format error: unknown Verdef version")) +__err__(ERROR_VERNEED_FORMAT, _("Format error: bad parameter in Verneed record")) +__err__(ERROR_VERNEED_VERSION, _("Format error: unknown Verneed version")) +__err__(ERROR_EHDR_SHNUM, _("Format error: bad e_shnum value")) +__err__(ERROR_EHDR_SHENTSIZE, _("Format error: bad e_shentsize value")) +__err__(ERROR_EHDR_PHENTSIZE, _("Format error: bad e_phentsize value")) +__err__(ERROR_UNTERM, _("Format error: unterminated string in string table")) +__err__(ERROR_SCN2SMALL, _("Layout error: section size too small for data")) +__err__(ERROR_SCN_OVERLAP, _("Layout error: overlapping sections")) +__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: ELF header")) +__err__(ERROR_MEM_PHDR, _("Memory error: program header table")) +__err__(ERROR_MEM_SHDR, _("Memory error: section header 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")) +__err__(ERROR_MEM_TEMPORARY, _("Memory error: temporary buffer")) +__err__(ERROR_BADVALUE, _("GElf error: value out of range")) +__err__(ERROR_BADINDEX, _("GElf error: index out of range")) +__err__(ERROR_BADTYPE, _("GElf error: type mismatch")) +__err__(ERROR_MEM_SYM, _("GElf error: not enough memory for GElf_Sym")) +__err__(ERROR_MEM_DYN, _("GElf error: not enough memory for GElf_Dyn")) +__err__(ERROR_MEM_RELA, _("GElf error: not enough memory for GElf_Rela")) +__err__(ERROR_MEM_REL, _("GElf error: not enough memory for GElf_Rel")) diff --git a/lib/ext_types.h b/lib/ext_types.h new file mode 100644 index 0000000..ead116d --- /dev/null +++ b/lib/ext_types.h @@ -0,0 +1,334 @@ +/* +ext_types.h - external representation of ELF data types. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +/* @(#) $Id: ext_types.h,v 1.9 2008/05/23 08:15:34 michael Exp $ */ + +#ifndef _EXT_TYPES_H +#define _EXT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * 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]; + +#if __LIBELF64 + +typedef unsigned char __ext_Elf32_Lword [8]; + +typedef unsigned char __ext_Elf64_Addr [ELF64_FSZ_ADDR]; +typedef unsigned char __ext_Elf64_Half [ELF64_FSZ_HALF]; +typedef unsigned char __ext_Elf64_Off [ELF64_FSZ_OFF]; +typedef unsigned char __ext_Elf64_Sword [ELF64_FSZ_SWORD]; +typedef unsigned char __ext_Elf64_Word [ELF64_FSZ_WORD]; +typedef unsigned char __ext_Elf64_Sxword[ELF64_FSZ_SXWORD]; +typedef unsigned char __ext_Elf64_Xword [ELF64_FSZ_XWORD]; + +typedef unsigned char __ext_Elf64_Lword [8]; + +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + unsigned char e_ident[EI_NIDENT]; + __ext_Elf64_Half e_type; + __ext_Elf64_Half e_machine; + __ext_Elf64_Word e_version; + __ext_Elf64_Addr e_entry; + __ext_Elf64_Off e_phoff; + __ext_Elf64_Off e_shoff; + __ext_Elf64_Word e_flags; + __ext_Elf64_Half e_ehsize; + __ext_Elf64_Half e_phentsize; + __ext_Elf64_Half e_phnum; + __ext_Elf64_Half e_shentsize; + __ext_Elf64_Half e_shnum; + __ext_Elf64_Half e_shstrndx; +} __ext_Elf64_Ehdr; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + __ext_Elf64_Word sh_name; + __ext_Elf64_Word sh_type; + __ext_Elf64_Xword sh_flags; + __ext_Elf64_Addr sh_addr; + __ext_Elf64_Off sh_offset; + __ext_Elf64_Xword sh_size; + __ext_Elf64_Word sh_link; + __ext_Elf64_Word sh_info; + __ext_Elf64_Xword sh_addralign; + __ext_Elf64_Xword sh_entsize; +} __ext_Elf64_Shdr; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + __ext_Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + __ext_Elf64_Half st_shndx; + __ext_Elf64_Addr st_value; + __ext_Elf64_Xword st_size; +} __ext_Elf64_Sym; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + __ext_Elf64_Addr r_offset; +#if __LIBELF64_IRIX + __ext_Elf64_Word r_sym; + unsigned char r_ssym; + unsigned char r_type3; + unsigned char r_type2; + unsigned char r_type; +#else /* __LIBELF64_IRIX */ + __ext_Elf64_Xword r_info; +#endif /* __LIBELF64_IRIX */ +} __ext_Elf64_Rel; + +typedef struct { + __ext_Elf64_Addr r_offset; +#if __LIBELF64_IRIX + __ext_Elf64_Word r_sym; + unsigned char r_ssym; + unsigned char r_type3; + unsigned char r_type2; + unsigned char r_type; +#else /* __LIBELF64_IRIX */ + __ext_Elf64_Xword r_info; +#endif /* __LIBELF64_IRIX */ + __ext_Elf64_Sxword r_addend; +} __ext_Elf64_Rela; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + __ext_Elf64_Word p_type; + __ext_Elf64_Word p_flags; + __ext_Elf64_Off p_offset; + __ext_Elf64_Addr p_vaddr; + __ext_Elf64_Addr p_paddr; + __ext_Elf64_Xword p_filesz; + __ext_Elf64_Xword p_memsz; + __ext_Elf64_Xword p_align; +} __ext_Elf64_Phdr; +#endif /* __LIBELF64 */ + +/* + * 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; + +#if __LIBELF64 +typedef struct { + __ext_Elf64_Sxword d_tag; + union { + __ext_Elf64_Xword d_val; + __ext_Elf64_Addr d_ptr; + } d_un; +} __ext_Elf64_Dyn; +#endif /* __LIBELF64 */ + +/* + * Version definitions + */ +typedef struct { + __ext_Elf32_Half vd_version; + __ext_Elf32_Half vd_flags; + __ext_Elf32_Half vd_ndx; + __ext_Elf32_Half vd_cnt; + __ext_Elf32_Word vd_hash; + __ext_Elf32_Word vd_aux; + __ext_Elf32_Word vd_next; +} __ext_Elf32_Verdef; + +typedef struct { + __ext_Elf32_Word vda_name; + __ext_Elf32_Word vda_next; +} __ext_Elf32_Verdaux; + +typedef struct { + __ext_Elf32_Half vn_version; + __ext_Elf32_Half vn_cnt; + __ext_Elf32_Word vn_file; + __ext_Elf32_Word vn_aux; + __ext_Elf32_Word vn_next; +} __ext_Elf32_Verneed; + +typedef struct { + __ext_Elf32_Word vna_hash; + __ext_Elf32_Half vna_flags; + __ext_Elf32_Half vna_other; + __ext_Elf32_Word vna_name; + __ext_Elf32_Word vna_next; +} __ext_Elf32_Vernaux; + +#if __LIBELF64 + +typedef struct { + __ext_Elf64_Half vd_version; + __ext_Elf64_Half vd_flags; + __ext_Elf64_Half vd_ndx; + __ext_Elf64_Half vd_cnt; + __ext_Elf64_Word vd_hash; + __ext_Elf64_Word vd_aux; + __ext_Elf64_Word vd_next; +} __ext_Elf64_Verdef; + +typedef struct { + __ext_Elf64_Word vda_name; + __ext_Elf64_Word vda_next; +} __ext_Elf64_Verdaux; + +typedef struct { + __ext_Elf64_Half vn_version; + __ext_Elf64_Half vn_cnt; + __ext_Elf64_Word vn_file; + __ext_Elf64_Word vn_aux; + __ext_Elf64_Word vn_next; +} __ext_Elf64_Verneed; + +typedef struct { + __ext_Elf64_Word vna_hash; + __ext_Elf64_Half vna_flags; + __ext_Elf64_Half vna_other; + __ext_Elf64_Word vna_name; + __ext_Elf64_Word vna_next; +} __ext_Elf64_Vernaux; + +#endif /* __LIBELF64 */ + +/* + * Move section + */ +#if __LIBELF64 + +typedef struct { + __ext_Elf32_Lword m_value; + __ext_Elf32_Word m_info; + __ext_Elf32_Word m_poffset; + __ext_Elf32_Half m_repeat; + __ext_Elf32_Half m_stride; +} __ext_Elf32_Move; + +typedef struct { + __ext_Elf64_Lword m_value; + __ext_Elf64_Xword m_info; + __ext_Elf64_Xword m_poffset; + __ext_Elf64_Half m_repeat; + __ext_Elf64_Half m_stride; +} __ext_Elf64_Move; + +#endif /* __LIBELF64 */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXT_TYPES_H */ diff --git a/lib/fill.c b/lib/fill.c new file mode 100644 index 0000000..e64cc14 --- /dev/null +++ b/lib/fill.c @@ -0,0 +1,29 @@ +/* +fill.c - implementation of the elf_fill(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: fill.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +void +elf_fill(int fill) { + _elf_fill = fill; +} diff --git a/lib/flag.c b/lib/flag.c new file mode 100644 index 0000000..1845ff9 --- /dev/null +++ b/lib/flag.c @@ -0,0 +1,92 @@ +/* +flag.c - implementation of the elf_flag*(3) functions. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: flag.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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/lib/gelf.h b/lib/gelf.h new file mode 100644 index 0000000..5af0558 --- /dev/null +++ b/lib/gelf.h @@ -0,0 +1,155 @@ +/* + * gelf.h - public header file for libelf. + * Copyright (C) 2000 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: gelf.h,v 1.16 2008/05/23 08:15:34 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> +#elif __LIBELF_NEED_SYS_LINK_H +#include <sys/link.h> +#endif /* __LIBELF_NEED_LINK_H */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef __P +# if (__STDC__ + 0) || defined(__cplusplus) || defined(_WIN32) +# 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/lib/gelfehdr.c b/lib/gelfehdr.c new file mode 100644 index 0000000..fa7c019 --- /dev/null +++ b/lib/gelfehdr.c @@ -0,0 +1,140 @@ +/* + * gelfehdr.c - gelf_* translation functions. + * Copyright (C) 2000 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: gelfehdr.c,v 1.9 2008/05/23 08:15:34 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); + } + 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); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/lib/gelfphdr.c b/lib/gelfphdr.c new file mode 100644 index 0000000..2635b4a --- /dev/null +++ b/lib/gelfphdr.c @@ -0,0 +1,148 @@ +/* + * gelfphdr.c - gelf_* translation functions. + * Copyright (C) 2000 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: gelfphdr.c,v 1.9 2008/05/23 08:15:34 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); + } + 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); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/lib/gelfshdr.c b/lib/gelfshdr.c new file mode 100644 index 0000000..c295c18 --- /dev/null +++ b/lib/gelfshdr.c @@ -0,0 +1,125 @@ +/* + * gelfshdr.c - gelf_* translation functions. + * Copyright (C) 2000 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: gelfshdr.c,v 1.10 2008/05/23 08:15:34 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); + } + 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); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return 0; + } + return 1; +} + +#endif /* __LIBELF64 */ diff --git a/lib/gelftrans.c b/lib/gelftrans.c new file mode 100644 index 0000000..dcd0cdd --- /dev/null +++ b/lib/gelftrans.c @@ -0,0 +1,407 @@ +/* +gelftrans.c - gelf_* translation functions. +Copyright (C) 2000 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: gelftrans.c,v 1.10 2008/05/23 08:15:34 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/lib/getarhdr.c b/lib/getarhdr.c new file mode 100644 index 0000000..874b337 --- /dev/null +++ b/lib/getarhdr.c @@ -0,0 +1,37 @@ +/* +getarhdr.c - implementation of the elf_getarhdr(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getarhdr.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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/lib/getaroff.c b/lib/getaroff.c new file mode 100644 index 0000000..fce977d --- /dev/null +++ b/lib/getaroff.c @@ -0,0 +1,40 @@ +/* + * getaroff.c - implementation of the elf_getaroff(3) function. + * Copyright (C) 2009 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getaroff.c,v 1.1 2009/11/01 13:04:19 michael Exp $"; +#endif /* lint */ + +off_t +elf_getaroff(Elf *elf) { + Elf *ref; + + if (!elf) { + return (off_t)-1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!(ref = elf->e_parent)) { + return (off_t)-1; + } + elf_assert(ref->e_magic == ELF_MAGIC); + elf_assert(elf->e_base >= ref->e_base + SARMAG + sizeof(struct ar_hdr)); + return (off_t)(elf->e_base - ref->e_base - sizeof(struct ar_hdr)); +} diff --git a/lib/getarsym.c b/lib/getarsym.c new file mode 100644 index 0000000..6069676 --- /dev/null +++ b/lib/getarsym.c @@ -0,0 +1,87 @@ +/* + * getarsym.c - implementation of the elf_getarsym(3) function. + * Copyright (C) 1995 - 1998, 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> +#include <byteswap.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getarsym.c,v 1.9 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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((unsigned char*)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/lib/getbase.c b/lib/getbase.c new file mode 100644 index 0000000..6831629 --- /dev/null +++ b/lib/getbase.c @@ -0,0 +1,33 @@ +/* +getbase.c - implementation of the elf_getbase(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getbase.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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/lib/getdata.c b/lib/getdata.c new file mode 100644 index 0000000..a65b7aa --- /dev/null +++ b/lib/getdata.c @@ -0,0 +1,157 @@ +/* +getdata.c - implementation of the elf_getdata(3) function. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getdata.c,v 1.13 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +static Elf_Data* +_elf_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) { + Elf_Data dst; + Elf_Data src; + int flag = 0; + size_t dlen; + + elf_assert(elf->e_data); + + /* + * Prepare source + */ + src = sd->sd_data; + src.d_version = elf->e_version; + if (elf->e_rawdata) { + src.d_buf = elf->e_rawdata + scn->s_offset; + } + else { + src.d_buf = elf->e_data + scn->s_offset; + } + + /* + * Prepare destination (needs prepared source!) + */ + dst = sd->sd_data; + if (elf->e_class == ELFCLASS32) { + dlen = _elf32_xltsize(&src, dst.d_version, elf->e_encoding, 0); + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + dlen = _elf64_xltsize(&src, dst.d_version, elf->e_encoding, 0); + } +#endif /* __LIBELF64 */ + else { + elf_assert(valid_class(elf->e_class)); + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + if (dlen == (size_t)-1) { + return NULL; + } + dst.d_size = dlen; + 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; + } + + /* + * Translate data + */ + if (_elf_xlatetom(elf, &dst, &src)) { + sd->sd_memdata = (char*)dst.d_buf; + sd->sd_data = dst; + if (!(sd->sd_free_data = flag)) { + elf->e_cooked = 1; + } + return &sd->sd_data; + } + + if (flag) { + free(dst.d_buf); + } + return NULL; +} + +Elf_Data* +elf_getdata(Elf_Scn *scn, Elf_Data *data) { + Scn_Data *sd; + Elf *elf; + + if (!scn) { + return NULL; + } + elf_assert(scn->s_magic == SCN_MAGIC); + if (scn->s_index == SHN_UNDEF) { + seterr(ERROR_NULLSCN); + } + else if (data) { + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + if (data == &sd->sd_data) { + /* + * sd_link allocated by elf_newdata(). + */ + return &sd->sd_link->sd_data; + } + } + seterr(ERROR_SCNDATAMISMATCH); + } + else if ((sd = scn->s_data_1)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + elf = scn->s_elf; + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + if (sd->sd_freeme) { + /* allocated by elf_newdata() */ + return &sd->sd_data; + } + else if (scn->s_type == SHT_NULL) { + seterr(ERROR_NULLSCN); + } + else if (sd->sd_memdata) { + /* already cooked */ + return &sd->sd_data; + } + 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 &sd->sd_data; + } + else if (scn->s_offset + scn->s_size > elf->e_size) { + seterr(ERROR_TRUNC_SCN); + } + else if (valid_class(elf->e_class)) { + return _elf_cook_scn(elf, scn, sd); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + } + return NULL; +} diff --git a/lib/getident.c b/lib/getident.c new file mode 100644 index 0000000..d9758f4 --- /dev/null +++ b/lib/getident.c @@ -0,0 +1,48 @@ +/* +getident.c - implementation of the elf_getident(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getident.c,v 1.7 2008/05/23 08:15:34 michael Exp $"; +#endif /* lint */ + +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/lib/getscn.c b/lib/getscn.c new file mode 100644 index 0000000..a78eae9 --- /dev/null +++ b/lib/getscn.c @@ -0,0 +1,48 @@ +/* +getscn.c - implementation of the elf_getscn(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: getscn.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/hash.c b/lib/hash.c new file mode 100644 index 0000000..a2555b6 --- /dev/null +++ b/lib/hash.c @@ -0,0 +1,38 @@ +/* +hash.c - implementation of the elf_hash(3) function. +Copyright (C) 1995 - 2002 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: hash.c,v 1.10 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +unsigned long +elf_hash(const unsigned char *name) { + unsigned long hash = 0; + unsigned long tmp; + + while (*name) { + hash = (hash << 4) + (unsigned char)*name++; + if ((tmp = hash & 0xf0000000)) { + hash ^= tmp | (tmp >> 24); + } + } + return hash; +} diff --git a/lib/input.c b/lib/input.c new file mode 100644 index 0000000..751970a --- /dev/null +++ b/lib/input.c @@ -0,0 +1,106 @@ +/* + * input.c - low-level input for libelf. + * Copyright (C) 1995 - 2001, 2005 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: input.c,v 1.11 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +#include <errno.h> + +#if HAVE_MMAP +#include <sys/mman.h> +#endif /* HAVE_MMAP */ + +static int +xread(int fd, char *buffer, size_t len) { + size_t done = 0; + size_t n; + + while (done < len) { + n = read(fd, buffer + done, len - done); + if (n == 0) { + /* premature end of file */ + return -1; + } + else if (n != (size_t)-1) { + /* some bytes read, continue */ + done += n; + } + else if (errno != EAGAIN && errno != EINTR) { + /* real error */ + return -1; + } + } + return 0; +} + +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_t)off, SEEK_SET) != (off_t)off) { + seterr(ERROR_IO_SEEK); + } + else if (!(tmp = buffer) && !(tmp = malloc(len))) { + seterr(ERROR_IO_2BIG); + } + else if (xread(elf->e_fd, tmp, 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 /* HAVE_MMAP */ + return NULL; +} diff --git a/lib/kind.c b/lib/kind.c new file mode 100644 index 0000000..6f84f32 --- /dev/null +++ b/lib/kind.c @@ -0,0 +1,33 @@ +/* +kind.c - implementation of the elf_kind(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: kind.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/libelf.def b/lib/libelf.def new file mode 100644 index 0000000..d77897b --- /dev/null +++ b/lib/libelf.def @@ -0,0 +1,82 @@ +LIBRARY libelf
+VERSION 0.8
+EXPORTS
+ elf_begin
+ elf_cntl
+ elf_delscn
+ elf_end
+ elf_errmsg
+ elf_errno
+ elf_fill
+ elf_flagdata
+ elf_flagehdr
+ elf_flagelf
+ elf_flagphdr
+ elf_flagscn
+ elf_flagshdr
+ elf_getarhdr
+ elf_getarsym
+ elf_getbase
+ elf_getdata
+ elf_getident
+ elf_getscn
+ elf_hash
+ elf_kind
+ elf_memory
+ elf_ndxscn
+ elf_newdata
+ elf_newscn
+ elf_next
+ elf_nextscn
+ elf_rand
+ elf_rawdata
+ elf_rawfile
+ elf_strptr
+ elf_update
+ elf_version
+ elf32_checksum
+ elf32_fsize
+ elf32_getehdr
+ elf32_getphdr
+ elf32_getshdr
+ elf32_newehdr
+ elf32_newphdr
+ elf32_xlatetof
+ elf32_xlatetom
+ elf64_checksum
+ elf64_fsize
+ elf64_getehdr
+ elf64_getphdr
+ elf64_getshdr
+ elf64_newehdr
+ elf64_newphdr
+ elf64_xlatetof
+ elf64_xlatetom
+ elfx_movscn
+ elfx_remscn
+ gelf_checksum
+ gelf_fsize
+ gelf_getclass
+ gelf_getdyn
+ gelf_getehdr
+ gelf_getphdr
+ gelf_getrel
+ gelf_getrela
+ gelf_getshdr
+ gelf_getsym
+ gelf_msize
+ gelf_newehdr
+ gelf_newphdr
+ gelf_update_dyn
+ gelf_update_ehdr
+ gelf_update_phdr
+ gelf_update_rel
+ gelf_update_rela
+ gelf_update_shdr
+ gelf_update_sym
+ gelf_xlatetof
+ gelf_xlatetom
+ elf_getphnum
+ elf_getshnum
+ elf_getshstrndx
+ elfx_update_shstrndx
diff --git a/lib/libelf.h b/lib/libelf.h new file mode 100644 index 0000000..3ebd0f3 --- /dev/null +++ b/lib/libelf.h @@ -0,0 +1,305 @@ +/* + * libelf.h - public header file for libelf. + * Copyright (C) 1995 - 2008 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: libelf.h,v 1.29 2009/07/07 17:57:43 michael Exp $ */ + +#ifndef _LIBELF_H +#define _LIBELF_H + +#include <stddef.h> /* for size_t */ +#include <sys/types.h> + +#if __LIBELF_INTERNAL__ +#include <sys_elf.h> +#else /* __LIBELF_INTERNAL__ */ +#include <libelf/sys_elf.h> +#endif /* __LIBELF_INTERNAL__ */ + +#if defined __GNUC__ && !defined __cplusplus +#define DEPRECATED __attribute__((deprecated)) +#else +#define DEPRECATED /* nothing */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef __P +# if (__STDC__ + 0) || defined(__cplusplus) || defined(_WIN32) +# define __P(args) args +# else /* __STDC__ || defined(__cplusplus) */ +# define __P(args) () +# endif /* __STDC__ || defined(__cplusplus) */ +#endif /* __P */ + +/* + * 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 +/* + * Allow sections to overlap when ELF_F_LAYOUT is in effect. + * Note that this flag ist NOT portable, and that it may render + * the output file unusable. Use with extreme caution! + */ +#define ELF_F_LAYOUT_OVERLAP 0x10000000 + +/* + * 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, + /* + * New stuff for 64-bit. + * + * Most implementations add ELF_T_SXWORD after ELF_T_SWORD + * which breaks binary compatibility with earlier versions. + * If this causes problems for you, contact me. + */ + ELF_T_SXWORD, + ELF_T_XWORD, + /* + * Symbol versioning. Sun broke binary compatibility (again!), + * but I won't. + */ + ELF_T_VDEF, + ELF_T_VNEED, + 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 Elf *elf_memory __P((char *__image, size_t __size)); +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 unsigned 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)); + +/* + * Additional functions found on Solaris + */ +extern long elf32_checksum __P((Elf *__elf)); + +#if __LIBELF64 +/* + * 64-bit ELF functions + * Not available on all platforms + */ +extern Elf64_Ehdr *elf64_getehdr __P((Elf *__elf)); +extern Elf64_Ehdr *elf64_newehdr __P((Elf *__elf)); +extern Elf64_Phdr *elf64_getphdr __P((Elf *__elf)); +extern Elf64_Phdr *elf64_newphdr __P((Elf *__elf, size_t __count)); +extern Elf64_Shdr *elf64_getshdr __P((Elf_Scn *__scn)); +extern size_t elf64_fsize __P((Elf_Type __type, size_t __count, + unsigned __ver)); +extern Elf_Data *elf64_xlatetof __P((Elf_Data *__dst, const Elf_Data *__src, + unsigned __encode)); +extern Elf_Data *elf64_xlatetom __P((Elf_Data *__dst, const Elf_Data *__src, + unsigned __encode)); + +/* + * Additional functions found on Solaris + */ +extern long elf64_checksum __P((Elf *__elf)); + +#endif /* __LIBELF64 */ + +/* + * ELF format extensions + * + * These functions return 0 on failure, 1 on success. Since other + * implementations of libelf may behave differently (there was quite + * some confusion about the correct values), they are now officially + * deprecated and should be replaced with the three new functions below. + */ +DEPRECATED extern int elf_getphnum __P((Elf *__elf, size_t *__resultp)); +DEPRECATED extern int elf_getshnum __P((Elf *__elf, size_t *__resultp)); +DEPRECATED extern int elf_getshstrndx __P((Elf *__elf, size_t *__resultp)); +/* + * Replacement functions (return -1 on failure, 0 on success). + */ +extern int elf_getphdrnum __P((Elf *__elf, size_t *__resultp)); +extern int elf_getshdrnum __P((Elf *__elf, size_t *__resultp)); +extern int elf_getshdrstrndx __P((Elf *__elf, size_t *__resultp)); + +/* + * Convenience functions + * + * elfx_update_shstrndx is elf_getshstrndx's counterpart. + * It should be used to set the e_shstrndx member. + * There is no update function for e_shnum or e_phnum + * because libelf handles them internally. + */ +extern int elfx_update_shstrndx __P((Elf *__elf, size_t __index)); + +/* + * Experimental extensions: + * + * elfx_movscn() moves section `__scn' directly after section `__after'. + * elfx_remscn() removes section `__scn'. Both functions update + * the section indices; elfx_remscn() also adjusts the ELF header's + * e_shnum member. The application is responsible for updating other + * data (in particular, e_shstrndx and the section headers' sh_link and + * sh_info members). + * + * elfx_movscn() returns the new index of the moved section. + * elfx_remscn() returns the original index of the removed section. + * A return value of zero indicates an error. + */ +extern size_t elfx_movscn __P((Elf *__elf, Elf_Scn *__scn, Elf_Scn *__after)); +extern size_t elfx_remscn __P((Elf *__elf, Elf_Scn *__scn)); + +/* + * elf_delscn() is obsolete. Please use elfx_remscn() instead. + */ +extern size_t elf_delscn __P((Elf *__elf, Elf_Scn *__scn)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LIBELF_H */ diff --git a/lib/memset.c b/lib/memset.c new file mode 100644 index 0000000..e398bb5 --- /dev/null +++ b/lib/memset.c @@ -0,0 +1,53 @@ +/* + * memset.c - replacement for memset(3), using duff's device. + * Copyright (C) 1995 - 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#ifndef lint +static const char rcsid[] = "@(#) $Id: memset.c,v 1.11 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +#include <stddef.h> /* for size_t */ +#include <sys/types.h> + +void* +_elf_memset(void *s, int c, size_t n) { + char *t = (char*)s; + + if (n) { + switch (n % 8u) { + do { + n -= 8; + default: + case 0: *t++ = (char)c; + case 7: *t++ = (char)c; + case 6: *t++ = (char)c; + case 5: *t++ = (char)c; + case 4: *t++ = (char)c; + case 3: *t++ = (char)c; + case 2: *t++ = (char)c; + case 1: *t++ = (char)c; + } + while (n > 8); + } + } + return s; +} diff --git a/lib/ndxscn.c b/lib/ndxscn.c new file mode 100644 index 0000000..c9ab9a8 --- /dev/null +++ b/lib/ndxscn.c @@ -0,0 +1,33 @@ +/* +ndxscn.c - implementation of the elf_ndxscn(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: ndxscn.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/newdata.c b/lib/newdata.c new file mode 100644 index 0000000..2a6eeba --- /dev/null +++ b/lib/newdata.c @@ -0,0 +1,56 @@ +/* +newdata.c - implementation of the elf_newdata(3) function. +Copyright (C) 1995 - 2000 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: newdata.c,v 1.10 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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 &sd->sd_data; + } + return NULL; +} diff --git a/lib/newscn.c b/lib/newscn.c new file mode 100644 index 0000000..69ba65d --- /dev/null +++ b/lib/newscn.c @@ -0,0 +1,145 @@ +/* + * newscn.c - implementation of the elf_newscn(3) function. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: newscn.c,v 1.13 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +int +_elf_update_shnum(Elf *elf, size_t shnum) { + size_t extshnum = 0; + Elf_Scn *scn; + + elf_assert(elf); + elf_assert(elf->e_ehdr); + scn = elf->e_scn_1; + elf_assert(scn); + elf_assert(scn->s_index == 0); + if (shnum >= SHN_LORESERVE) { + extshnum = shnum; + shnum = 0; + } + if (elf->e_class == ELFCLASS32) { + ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = shnum; + scn->s_shdr32.sh_size = extshnum; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum = shnum; + scn->s_shdr64.sh_size = extshnum; + } +#endif /* __LIBELF64 */ + else { + if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return -1; + } + elf->e_ehdr_flags |= ELF_F_DIRTY; + scn->s_shdr_flags |= ELF_F_DIRTY; + return 0; +} + +static Elf_Scn* +_makescn(Elf *elf, size_t index) { + Elf_Scn *scn; + + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + elf_assert(elf->e_ehdr); + elf_assert(_elf_scn_init.s_magic == SCN_MAGIC); + if (!(scn = (Elf_Scn*)malloc(sizeof(*scn)))) { + seterr(ERROR_MEM_SCN); + return NULL; + } + *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; + scn->s_index = index; + return scn; +} + +Elf_Scn* +_elf_first_scn(Elf *elf) { + Elf_Scn *scn; + + elf_assert(elf); + elf_assert(elf->e_magic == ELF_MAGIC); + if ((scn = elf->e_scn_1)) { + return scn; + } + if ((scn = _makescn(elf, 0))) { + elf->e_scn_1 = elf->e_scn_n = scn; + if (_elf_update_shnum(elf, 1)) { + free(scn); + elf->e_scn_1 = elf->e_scn_n = scn = NULL; + } + } + return scn; +} + +static Elf_Scn* +_buildscn(Elf *elf) { + Elf_Scn *scn; + + if (!_elf_first_scn(elf)) { + return NULL; + } + scn = elf->e_scn_n; + elf_assert(scn); + if (!(scn = _makescn(elf, scn->s_index + 1))) { + return NULL; + } + if (_elf_update_shnum(elf, scn->s_index + 1)) { + free(scn); + return NULL; + } + elf->e_scn_n = elf->e_scn_n->s_link = scn; + return scn; +} + +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 ((scn = _buildscn(elf))) { + return scn; + } + return NULL; +} diff --git a/lib/next.c b/lib/next.c new file mode 100644 index 0000000..bf9a67b --- /dev/null +++ b/lib/next.c @@ -0,0 +1,42 @@ +/* +next.c - implementation of the elf_next(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: next.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/nextscn.c b/lib/nextscn.c new file mode 100644 index 0000000..4543f83 --- /dev/null +++ b/lib/nextscn.c @@ -0,0 +1,54 @@ +/* +nextscn.c - implementation of the elf_nextscn(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: nextscn.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/nlist.c b/lib/nlist.c new file mode 100644 index 0000000..933d33f --- /dev/null +++ b/lib/nlist.c @@ -0,0 +1,253 @@ +/* + * nlist.c - implementation of the nlist(3) function. + * Copyright (C) 1995 - 2004 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> +#include <nlist.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: nlist.c,v 1.15 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +#if !defined(_WIN32) +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +extern int open(); +#endif /* HAVE_FCNTL_H */ +#endif /* defined(_WIN32) */ + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif /* O_RDONLY */ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif /* O_BINARY */ + +#define FILE_OPEN_MODE (O_RDONLY | O_BINARY) + +#define PRIME 217 + +struct hash { + const char* name; + unsigned long hash; + unsigned next; +}; + +static const char* +symbol_name(Elf *elf, const void *syms, const char *names, size_t nlimit, size_t index) { + size_t off; + + if (elf->e_class == ELFCLASS32) { + off = ((Elf32_Sym*)syms)[index].st_name; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + off = ((Elf64_Sym*)syms)[index].st_name; + } +#endif /* __LIBELF64 */ + else { + return NULL; + } + if (off >= 0 && off < nlimit) { + return &names[off]; + } + return NULL; +} + +static void +copy_symbol(Elf *elf, struct nlist *np, const void *syms, size_t index) { + if (elf->e_class == ELFCLASS32) { + np->n_value = ((Elf32_Sym*)syms)[index].st_value; + np->n_scnum = ((Elf32_Sym*)syms)[index].st_shndx; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + np->n_value = ((Elf64_Sym*)syms)[index].st_value; + np->n_scnum = ((Elf64_Sym*)syms)[index].st_shndx; + } +#endif /* __LIBELF64 */ + /* + * this needs more work + */ + np->n_type = 0; + np->n_sclass = 0; + np->n_numaux = 0; +} + +static int +_elf_nlist(Elf *elf, struct nlist *nl) { + unsigned first[PRIME]; + Elf_Scn *symtab = NULL; + Elf_Scn *strtab = NULL; + Elf_Data *symdata; + Elf_Data *strdata; + size_t symsize; + size_t nsymbols; + const char *name; + struct hash *table; + unsigned long hash; + unsigned i; + struct nlist *np; + + /* + * Get and translate ELF header, section table and so on. + * Must be class independent, so don't use elf32_get*(). + */ + if (elf->e_kind != ELF_K_ELF) { + return -1; + } + if (!elf->e_ehdr && !_elf_cook(elf)) { + return -1; + } + + /* + * Find symbol table. If there is none, try dynamic symbols. + */ + for (symtab = elf->e_scn_1; symtab; symtab = symtab->s_link) { + if (symtab->s_type == SHT_SYMTAB) { + break; + } + if (symtab->s_type == SHT_DYNSYM) { + strtab = symtab; + } + } + if (!symtab && !(symtab = strtab)) { + return -1; + } + + /* + * Get associated string table. + */ + i = 0; + if (elf->e_class == ELFCLASS32) { + i = symtab->s_shdr32.sh_link; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + i = symtab->s_shdr64.sh_link; + } +#endif /* __LIBELF64 */ + if (i == 0) { + return -1; + } + for (strtab = elf->e_scn_1; strtab; strtab = strtab->s_link) { + if (strtab->s_index == i) { + break; + } + } + if (!strtab || strtab->s_type != SHT_STRTAB) { + return -1; + } + + /* + * Get and translate section data. + */ + symdata = elf_getdata(symtab, NULL); + strdata = elf_getdata(strtab, NULL); + if (!symdata || !strdata) { + return -1; + } + symsize = _msize(elf->e_class, _elf_version, ELF_T_SYM); + elf_assert(symsize); + nsymbols = symdata->d_size / symsize; + if (!symdata->d_buf || !strdata->d_buf || !nsymbols || !strdata->d_size) { + return -1; + } + + /* + * Build a simple hash table. + */ + if (!(table = (struct hash*)malloc(nsymbols * sizeof(*table)))) { + return -1; + } + for (i = 0; i < PRIME; i++) { + first[i] = 0; + } + for (i = 0; i < nsymbols; i++) { + table[i].name = NULL; + table[i].hash = 0; + table[i].next = 0; + } + for (i = 1; i < nsymbols; i++) { + name = symbol_name(elf, symdata->d_buf, strdata->d_buf, + strdata->d_size, i); + if (name == NULL) { + free(table); + return -1; + } + if (*name != '\0') { + table[i].name = name; + table[i].hash = elf_hash((unsigned char*)name); + hash = table[i].hash % PRIME; + table[i].next = first[hash]; + first[hash] = i; + } + } + + /* + * Lookup symbols, one by one. + */ + for (np = nl; (name = np->n_name) && *name; np++) { + hash = elf_hash((unsigned char*)name); + for (i = first[hash % PRIME]; i; i = table[i].next) { + if (table[i].hash == hash && !strcmp(table[i].name, name)) { + break; + } + } + if (i) { + copy_symbol(elf, np, symdata->d_buf, i); + } + else { + np->n_value = 0; + np->n_scnum = 0; + np->n_type = 0; + np->n_sclass = 0; + np->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, FILE_OPEN_MODE)) != -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/lib/nlist.h b/lib/nlist.h new file mode 100644 index 0000000..27a452e --- /dev/null +++ b/lib/nlist.h @@ -0,0 +1,48 @@ +/* + * nlist.h - public header file for nlist(3). + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: nlist.h,v 1.10 2008/05/23 08:15:35 michael Exp $ */ + +#ifndef _NLIST_H +#define _NLIST_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct nlist { + char* n_name; + long n_value; + short n_scnum; + unsigned short n_type; + char n_sclass; + char n_numaux; +}; + +#if (__STDC__ + 0) || defined(__cplusplus) || defined(_WIN32) +extern int nlist(const char *__filename, struct nlist *__nl); +#else /* __STDC__ || defined(__cplusplus) */ +extern int nlist(); +#endif /* __STDC__ || defined(__cplusplus) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _NLIST_H */ diff --git a/lib/opt.delscn.c b/lib/opt.delscn.c new file mode 100644 index 0000000..2201155 --- /dev/null +++ b/lib/opt.delscn.c @@ -0,0 +1,205 @@ +/* +opt.delscn.c - implementation of the elf_delscn(3) function. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: opt.delscn.c,v 1.12 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +static size_t +_newindex(size_t old, size_t index) { + return old == index ? SHN_UNDEF : (old > index ? old - 1 : old); +} + +static void +_elf32_update_shdr(Elf *elf, size_t index) { + Elf32_Shdr *shdr; + Elf_Scn *scn; + + ((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: + shdr->sh_info = _newindex(shdr->sh_info, index); + /* fall through */ + case SHT_DYNSYM: + case SHT_DYNAMIC: + case SHT_HASH: + case SHT_SYMTAB: +#if __LIBELF_SYMBOL_VERSIONS +#if __LIBELF_SUN_SYMBOL_VERSIONS + case SHT_SUNW_verdef: + case SHT_SUNW_verneed: + case SHT_SUNW_versym: +#else /* __LIBELF_SUN_SYMBOL_VERSIONS */ + case SHT_GNU_verdef: + case SHT_GNU_verneed: + case SHT_GNU_versym: +#endif /* __LIBELF_SUN_SYMBOL_VERSIONS */ +#endif /* __LIBELF_SYMBOL_VERSIONS */ + shdr->sh_link = _newindex(shdr->sh_link, index); + /* fall through */ + default: + break; + } + } +} + +#if __LIBELF64 + +static void +_elf64_update_shdr(Elf *elf, size_t index) { + Elf64_Shdr *shdr; + Elf_Scn *scn; + + ((Elf64_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_shdr64; + switch (shdr->sh_type) { + case SHT_REL: + case SHT_RELA: + shdr->sh_info = _newindex(shdr->sh_info, index); + /* fall through */ + case SHT_DYNSYM: + case SHT_DYNAMIC: + case SHT_HASH: + case SHT_SYMTAB: +#if __LIBELF_SYMBOL_VERSIONS +#if __LIBELF_SUN_SYMBOL_VERSIONS + case SHT_SUNW_verdef: + case SHT_SUNW_verneed: + case SHT_SUNW_versym: +#else /* __LIBELF_SUN_SYMBOL_VERSIONS */ + case SHT_GNU_verdef: + case SHT_GNU_verneed: + case SHT_GNU_versym: +#endif /* __LIBELF_SUN_SYMBOL_VERSIONS */ +#endif /* __LIBELF_SYMBOL_VERSIONS */ + shdr->sh_link = _newindex(shdr->sh_link, index); + /* fall through */ + default: + break; + } + } +} + +#endif /* __LIBELF64 */ + +size_t +elf_delscn(Elf *elf, Elf_Scn *scn) { + 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); + elf_assert(elf->e_ehdr); + 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; + } + + /* + * Find previous section. + */ + 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; + } + /* + * Unlink section. + */ + if (elf->e_scn_n == scn) { + elf->e_scn_n = pscn; + } + pscn->s_link = scn->s_link; + index = scn->s_index; + /* + * Free section descriptor and data. + */ + for (sd = scn->s_data_1; sd; sd = tmp) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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 ELF header and well-known section headers. + */ + if (elf->e_class == ELFCLASS32) { + _elf32_update_shdr(elf, index); + return index; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + _elf64_update_shdr(elf, index); + return index; + } +#endif /* __LIBELF64 */ + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return SHN_UNDEF; +} diff --git a/lib/private.h b/lib/private.h new file mode 100644 index 0000000..2b772dc --- /dev/null +++ b/lib/private.h @@ -0,0 +1,446 @@ +/* + * private.h - private definitions for libelf. + * Copyright (C) 1995 - 2007 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @(#) $Id: private.h,v 1.40 2009/11/01 13:04:19 michael Exp $ */ + +#ifndef _PRIVATE_H +#define _PRIVATE_H + +#define __LIBELF_INTERNAL__ 1 + +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +/* + * Workaround for GLIBC bug: + * include <stdint.h> before <sys/types.h> + */ +#if HAVE_STDINT_H +#include <stdint.h> +#endif +#include <sys/types.h> + +#if STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else /* STDC_HEADERS */ +extern void *malloc(), *realloc(); +extern void free(), bcopy(), abort(); +extern int strcmp(), strncmp(), memcmp(); +extern void *memcpy(), *memmove(), *memset(); +#endif /* STDC_HEADERS */ + +#if defined(_WIN32) +#include <io.h> +#else +#if HAVE_UNISTD_H +# include <unistd.h> +#else /* HAVE_UNISTD_H */ +extern int read(), write(), close(); +extern off_t lseek(); +#if HAVE_FTRUNCATE +extern int ftruncate(); +#endif /* HAVE_FTRUNCATE */ +#endif /* HAVE_UNISTD_H */ +#endif /* defined(_WIN32) */ + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif /* SEEK_SET */ +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif /* SEEK_CUR */ +#ifndef SEEK_END +#define SEEK_END 2 +#endif /* SEEK_END */ + +#if !HAVE_MEMCMP +# define memcmp strncmp +#endif /* !HAVE_MEMCMP */ +#if !HAVE_MEMCPY +# define memcpy(d,s,n) bcopy(s,d,n) +#endif /* !HAVE_MEMCPY */ +#if !HAVE_MEMMOVE +# define memmove(d,s,n) bcopy(s,d,n) +#endif /* !HAVE_MEMMOVE */ + +#if !HAVE_MEMSET +# define memset _elf_memset +extern void *_elf_memset(); +#endif /* !HAVE_MEMSET */ + +#if HAVE_STRUCT_NLIST_DECLARATION +# define nlist __override_nlist_declaration +#endif /* HAVE_STRUCT_NLIST_DECLARATION */ + +#if __LIBELF_NEED_LINK_H +# include <link.h> +#elif __LIBELF_NEED_SYS_LINK_H +# include <sys/link.h> +#endif /* __LIBELF_NEED_LINK_H */ + +#if HAVE_AR_H +#include <ar.h> +#else /* HAVE_AR_H */ + +#define ARMAG "!<arch>\n" +#define SARMAG 8 + +struct ar_hdr { + char ar_name[16]; + char ar_date[12]; + char ar_uid[6]; + char ar_gid[6]; + char ar_mode[8]; + char ar_size[10]; + char ar_fmag[2]; +}; + +#define ARFMAG "`\n" + +#endif /* HAVE_AR_H */ + +#include <libelf.h> + +#if HAVE_STRUCT_NLIST_DECLARATION +# undef nlist +#endif /* HAVE_STRUCT_NLIST_DECLARATION */ + +#if __LIBELF64 +#include <gelf.h> +#endif /* __LIBELF64 */ + +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_unmap_data : 1; /* e_data is mmap'ed */ + unsigned e_memory : 1; /* created by elf_memory() */ + /* 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_unmap_data */ 0,\ + /* e_memory */ 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 { +#if __LIBELF64 + Elf64_Shdr u_shdr64; +#endif /* __LIBELF64 */ + Elf32_Shdr u_shdr32; + } s_uhdr; + /* magic number for debugging */ + long s_magic; +}; +#define s_shdr32 s_uhdr.u_shdr32 +#define s_shdr64 s_uhdr.u_shdr64 + +#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; +extern int _elf_sanity_checks; +#define SANITY_CHECK_STRPTR (1u << 0) + +/* + * 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*)); +extern char *_elf_getehdr __P((Elf*, unsigned)); +extern char *_elf_getphdr __P((Elf*, unsigned)); +extern Elf_Data *_elf_xlatetom __P((const Elf*, Elf_Data*, const Elf_Data*)); +extern Elf_Type _elf_scn_type __P((unsigned)); +extern size_t _elf32_xltsize __P((const Elf_Data *__src, unsigned __dv, unsigned __encode, int __tof)); +extern size_t _elf64_xltsize __P((const Elf_Data *__src, unsigned __dv, unsigned __encode, int __tof)); +extern int _elf_update_shnum(Elf *__elf, size_t __shnum); +extern Elf_Scn *_elf_first_scn(Elf *__elf); + +/* + * Special translators + */ +extern size_t _elf_verdef_32L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_32L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_32M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_32M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_64L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_64L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_64M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verdef_64M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_32L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_32L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_32M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_32M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_64L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_64L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_64M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n)); +extern size_t _elf_verneed_64M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n)); + +/* + * Private data + */ +extern const Elf_Scn _elf_scn_init; +extern const Scn_Data _elf_data_init; +extern const size_t _elf_fmsize[2][EV_CURRENT - EV_NONE][ELF_T_NUM][2]; + +/* + * Access macros for _elf_fmsize[] + */ +#define _fmsize(c,v,t,w) \ + (_elf_fmsize[(c)-ELFCLASS32][(v)-EV_NONE-1][(t)-ELF_T_BYTE][(w)]) +#define _fsize(c,v,t) _fmsize((c),(v),(t),1) +#define _msize(c,v,t) _fmsize((c),(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) ((unsigned)(t) < ELF_T_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) + * These definitions should be in <elf.h>, but... + */ +#ifndef ELF32_FSZ_ADDR +# 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 /* ELF32_FSZ_ADDR */ +#ifndef ELF64_FSZ_ADDR +# define ELF64_FSZ_ADDR 8 +# define ELF64_FSZ_HALF 2 +# define ELF64_FSZ_OFF 8 +# define ELF64_FSZ_SWORD 4 +# define ELF64_FSZ_SXWORD 8 +# define ELF64_FSZ_WORD 4 +# define ELF64_FSZ_XWORD 8 +#endif /* ELF64_FSZ_ADDR */ + +/* + * More missing pieces, in no particular order + */ +#ifndef SHT_SYMTAB_SHNDX +#define SHT_SYMTAB_SHNDX 18 +#endif /* SHT_SYMTAB_SHNDX */ + +#ifndef SHN_XINDEX +#define SHN_XINDEX 0xffff +#endif /* SHN_XINDEX */ + +#ifndef PN_XNUM +#define PN_XNUM 0xffff +#endif /* PN_XNUM */ + +/* + * Debugging + */ +#if ENABLE_DEBUG +extern void __elf_assert __P((const char*, unsigned, const char*)); +# if (__STDC__ + 0) +# define elf_assert(x) do{if(!(x))__elf_assert(__FILE__,__LINE__,#x);}while(0) +# else /* __STDC__ */ +# define elf_assert(x) do{if(!(x))__elf_assert(__FILE__,__LINE__,"x");}while(0) +# endif /* __STDC__ */ +#else /* ENABLE_DEBUG */ +# define elf_assert(x) do{}while(0) +#endif /* ENABLE_DEBUG */ + +/* + * Return values for certain functions + */ +#define LIBELF_SUCCESS 1 +#define LIBELF_FAILURE 0 + +#endif /* _PRIVATE_H */ diff --git a/lib/rand.c b/lib/rand.c new file mode 100644 index 0000000..9cad126 --- /dev/null +++ b/lib/rand.c @@ -0,0 +1,43 @@ +/* +rand.c - implementation of the elf_rand(3) function. +Copyright (C) 1995 - 1998 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: rand.c,v 1.7 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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/lib/rawdata.c b/lib/rawdata.c new file mode 100644 index 0000000..5d9a9f3 --- /dev/null +++ b/lib/rawdata.c @@ -0,0 +1,89 @@ +/* +rawdata.c - implementation of the elf_rawdata(3) function. +Copyright (C) 1995 - 2000 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: rawdata.c,v 1.10 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +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)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + return &sd->sd_data; + } + 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 &sd->sd_data; + } + return NULL; +} diff --git a/lib/rawfile.c b/lib/rawfile.c new file mode 100644 index 0000000..43335c4 --- /dev/null +++ b/lib/rawfile.c @@ -0,0 +1,54 @@ +/* + * rawfile.c - implementation of the elf_rawfile(3) function. + * Copyright (C) 1995 - 2009 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: rawfile.c,v 1.8 2009/05/22 17:07:46 michael Exp $"; +#endif /* lint */ + +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) { + if (!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/lib/strptr.c b/lib/strptr.c new file mode 100644 index 0000000..30e217e --- /dev/null +++ b/lib/strptr.c @@ -0,0 +1,150 @@ +/* + * strptr.c - implementation of the elf_strptr(3) function. + * Copyright (C) 1995 - 2007 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: strptr.c,v 1.12 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +char* +elf_strptr(Elf *elf, size_t section, size_t offset) { + Elf_Data *data; + Elf_Scn *scn; + size_t n; + char *s; + + if (!elf) { + return NULL; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (!(scn = elf_getscn(elf, section))) { + return NULL; + } + if (scn->s_index == SHN_UNDEF) { + seterr(ERROR_NOSTRTAB); + return NULL; + } + /* + * checking the section header is more appropriate + */ + if (elf->e_class == ELFCLASS32) { + if (scn->s_shdr32.sh_type != SHT_STRTAB) { + seterr(ERROR_NOSTRTAB); + return NULL; + } + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + if (scn->s_shdr64.sh_type != SHT_STRTAB) { + seterr(ERROR_NOSTRTAB); + return NULL; + } + } +#endif /* __LIBELF64 */ + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + return NULL; + } + else { + seterr(ERROR_UNKNOWN_CLASS); + return NULL; + } + /* + * Find matching buffer + */ + n = 0; + data = NULL; + if (elf->e_elf_flags & ELF_F_LAYOUT) { + /* + * Programmer is responsible for d_off + * Note: buffers may be in any order! + */ + while ((data = elf_getdata(scn, data))) { + n = data->d_off; + if (offset >= n && offset - n < data->d_size) { + /* + * Found it + */ + break; + } + } + } + else { + /* + * Calculate offsets myself + */ + while ((data = elf_getdata(scn, data))) { + if (data->d_align > 1) { + n += data->d_align - 1; + n -= n % data->d_align; + } + if (offset < n) { + /* + * Invalid offset: points into a hole + */ + seterr(ERROR_BADSTROFF); + return NULL; + } + if (offset - n < data->d_size) { + /* + * Found it + */ + break; + } + n += data->d_size; + } + } + if (data == NULL) { + /* + * Not found + */ + seterr(ERROR_BADSTROFF); + return NULL; + } + if (data->d_buf == NULL) { + /* + * Buffer is NULL (usually the programmers' fault) + */ + seterr(ERROR_NULLBUF); + return NULL; + } + offset -= n; + s = (char*)data->d_buf; + if (!(_elf_sanity_checks & SANITY_CHECK_STRPTR)) { + return s + offset; + } + /* + * Perform extra sanity check + */ + for (n = offset; n < data->d_size; n++) { + if (s[n] == '\0') { + /* + * Return properly NUL terminated string + */ + return s + offset; + } + } + /* + * String is not NUL terminated + * Return error to avoid SEGV in application + */ + seterr(ERROR_UNTERM); + return NULL; +} diff --git a/lib/swap64.c b/lib/swap64.c new file mode 100644 index 0000000..397bd5b --- /dev/null +++ b/lib/swap64.c @@ -0,0 +1,81 @@ +/* +swap64.c - 64-bit byte swapping functions. +Copyright (C) 1995 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> +#include <byteswap.h> + +#if __LIBELF64 + +#ifndef lint +static const char rcsid[] = "@(#) $Id: swap64.c,v 1.6 2008/05/23 08:15:35 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/lib/sys_elf.h.in b/lib/sys_elf.h.in new file mode 100644 index 0000000..b71a20d --- /dev/null +++ b/lib/sys_elf.h.in @@ -0,0 +1,130 @@ +/* +sys_elf.h.in - configure template for private "switch" file. +Copyright (C) 1998 - 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +/* @(#) $Id: sys_elf.h.in,v 1.13 2008/05/23 08:57:07 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 Elf32_Dyn is declared in <link.h> */ +#undef __LIBELF_NEED_LINK_H + +/* Define if Elf32_Dyn is declared in <sys/link.h> */ +#undef __LIBELF_NEED_SYS_LINK_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 if you want symbol versioning (and your system supports it) */ +#undef __LIBELF_SYMBOL_VERSIONS + +/* 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 */ + +/* + * On some systems, <elf.h> is severely broken. Try to fix it. + */ +#ifdef __LIBELF_HEADER_ELF_H + +# ifndef ELF32_FSZ_ADDR +# 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 /* ELF32_FSZ_ADDR */ + +# ifndef STN_UNDEF +# define STN_UNDEF 0 +# endif /* STN_UNDEF */ + +# if __LIBELF64 + +# ifndef ELF64_FSZ_ADDR +# define ELF64_FSZ_ADDR 8 +# define ELF64_FSZ_HALF 2 +# define ELF64_FSZ_OFF 8 +# define ELF64_FSZ_SWORD 4 +# define ELF64_FSZ_WORD 4 +# define ELF64_FSZ_SXWORD 8 +# define ELF64_FSZ_XWORD 8 +# endif /* ELF64_FSZ_ADDR */ + +# ifndef ELF64_ST_BIND +# define ELF64_ST_BIND(i) ((i)>>4) +# define ELF64_ST_TYPE(i) ((i)&0xf) +# define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) +# endif /* ELF64_ST_BIND */ + +# ifndef ELF64_R_SYM +# define ELF64_R_SYM(i) ((Elf64_Xword)(i)>>32) +# define ELF64_R_TYPE(i) ((i)&0xffffffffL) +# define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+((t)&0xffffffffL)) +# endif /* ELF64_R_SYM */ + +# if __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_u32_t Elf64_Word; +typedef __libelf_i64_t Elf64_Sxword; +typedef __libelf_u64_t Elf64_Xword; +# endif /* __LIBELF64_LINUX */ + +# endif /* __LIBELF64 */ +#endif /* __LIBELF_HEADER_ELF_H */ diff --git a/lib/sys_elf.h.w32 b/lib/sys_elf.h.w32 new file mode 100644 index 0000000..0f93c55 --- /dev/null +++ b/lib/sys_elf.h.w32 @@ -0,0 +1,130 @@ +/*
+ * lib/sys_elf.h.w32 - internal configuration file for W32 port
+ * Copyright (C) 2004 - 2006 Michael Riepe
+ *
+ * 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.w32,v 1.2 2006/09/07 15:55:42 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 Elf32_Dyn is declared in <link.h> */
+#undef __LIBELF_NEED_LINK_H
+
+/* Define if Elf32_Dyn is declared in <sys/link.h> */
+#undef __LIBELF_NEED_SYS_LINK_H
+
+/* Define if you want 64-bit support (and your system supports it) */
+#define __LIBELF64 1
+
+/* 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 if you want symbol versioning (and your system supports it) */
+#define __LIBELF_SYMBOL_VERSIONS 1
+
+/* Define to a 64-bit signed integer type if one exists */
+#define __libelf_i64_t __int64
+
+/* Define to a 64-bit unsigned integer type if one exists */
+#define __libelf_u64_t unsigned __int64
+
+/* Define to a 32-bit signed integer type if one exists */
+#define __libelf_i32_t int
+
+/* Define to a 32-bit unsigned integer type if one exists */
+#define __libelf_u32_t unsigned int
+
+/* Define to a 16-bit signed integer type if one exists */
+#define __libelf_i16_t short int
+
+/* Define to a 16-bit unsigned integer type if one exists */
+#define __libelf_u16_t unsigned short int
+
+/*
+ * 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 */
+
+/*
+ * On some systems, <elf.h> is severely broken. Try to fix it.
+ */
+#ifdef __LIBELF_HEADER_ELF_H
+
+# ifndef ELF32_FSZ_ADDR
+# 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 /* ELF32_FSZ_ADDR */
+
+# ifndef STN_UNDEF
+# define STN_UNDEF 0
+# endif /* STN_UNDEF */
+
+# if __LIBELF64
+
+# ifndef ELF64_FSZ_ADDR
+# define ELF64_FSZ_ADDR 8
+# define ELF64_FSZ_HALF 2
+# define ELF64_FSZ_OFF 8
+# define ELF64_FSZ_SWORD 4
+# define ELF64_FSZ_WORD 4
+# define ELF64_FSZ_SXWORD 8
+# define ELF64_FSZ_XWORD 8
+# endif /* ELF64_FSZ_ADDR */
+
+# ifndef ELF64_ST_BIND
+# define ELF64_ST_BIND(i) ((i)>>4)
+# define ELF64_ST_TYPE(i) ((i)&0xf)
+# define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
+# endif /* ELF64_ST_BIND */
+
+# ifndef ELF64_R_SYM
+# define ELF64_R_SYM(i) ((Elf64_Xword)(i)>>32)
+# define ELF64_R_TYPE(i) ((i)&0xffffffffL)
+# define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+((t)&0xffffffffL))
+# endif /* ELF64_R_SYM */
+
+# if __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_u32_t Elf64_Word;
+typedef __libelf_i64_t Elf64_Sxword;
+typedef __libelf_u64_t Elf64_Xword;
+# endif /* __LIBELF64_LINUX */
+
+# endif /* __LIBELF64 */
+#endif /* __LIBELF_HEADER_ELF_H */
diff --git a/lib/update.c b/lib/update.c new file mode 100644 index 0000000..085ddea --- /dev/null +++ b/lib/update.c @@ -0,0 +1,1021 @@ +/* + * update.c - implementation of the elf_update(3) function. + * Copyright (C) 1995 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: update.c,v 1.34 2009/05/22 17:08:09 michael Exp $"; +#endif /* lint */ + +#include <errno.h> + +#if HAVE_MMAP +#include <sys/mman.h> +#endif /* HAVE_MMAP */ + +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) + +#undef max +#define max(a,b) ((a)>(b)?(a):(b)) + +static off_t +scn_data_layout(Elf_Scn *scn, unsigned v, unsigned type, size_t *algn, unsigned *flag) { + Elf *elf = scn->s_elf; + Elf_Data *data; + int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0; + size_t scn_align = 1; + size_t len = 0; + Scn_Data *sd; + size_t fsize; + + if (!(sd = scn->s_data_1)) { + /* no data in section */ + *algn = scn_align; + return (off_t)len; + } + /* load data from file, if any */ + if (!(data = elf_getdata(scn, NULL))) { + return (off_t)-1; + } + elf_assert(data == &sd->sd_data); + for (; sd; sd = sd->sd_link) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + + if (!valid_version(sd->sd_data.d_version)) { + return (off_t)-1; + } + + fsize = sd->sd_data.d_size; + if (fsize && type != SHT_NOBITS && valid_type(sd->sd_data.d_type)) { + if (elf->e_class == ELFCLASS32) { + fsize = _elf32_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1); + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + fsize = _elf64_xltsize(&sd->sd_data, v, ELFDATA2LSB, 1); + } +#endif /* __LIBELF64 */ + else { + elf_assert(valid_class(elf->e_class)); + seterr(ERROR_UNIMPLEMENTED); + return (off_t)-1; + } + if (fsize == (size_t)-1) { + return (off_t)-1; + } + } + + 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; + } + *algn = scn_align; + return (off_t)len; +} + +static size_t +scn_entsize(const Elf *elf, unsigned version, unsigned stype) { + Elf_Type type; + + switch ((type = _elf_scn_type(stype))) { + case ELF_T_BYTE: + return 0; + case ELF_T_VDEF: + case ELF_T_VNEED: + return 0; /* What else can I do? Thank you, Sun! */ + default: + return _fsize(elf->e_class, version, type); + } +} + +static off_t +_elf32_layout(Elf *elf, unsigned *flag) { + int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0; + int allow_overlap = (elf->e_elf_flags & ELF_F_LAYOUT_OVERLAP) != 0; + Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr; + size_t off = 0; + unsigned version; + unsigned encoding; + size_t align_addr; + size_t entsize; + unsigned phnum; + 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 = _fsize(ELFCLASS32, version, ELF_T_EHDR); + elf_assert(entsize); + rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags); + off = entsize; + + align_addr = _fsize(ELFCLASS32, version, ELF_T_ADDR); + elf_assert(align_addr); + + if ((phnum = elf->e_phnum)) { + entsize = _fsize(ELFCLASS32, version, ELF_T_PHDR); + elf_assert(entsize); + if (layout) { + align(off, align_addr); + rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags); + off += phnum * entsize; + } + else { + off = max(off, ehdr->e_phoff + phnum * entsize); + } + } + else { + entsize = 0; + if (layout) { + rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags); + } + } + if (phnum >= PN_XNUM) { + Elf_Scn *scn = elf->e_scn_1; + Elf32_Shdr *shdr = &scn->s_shdr32; + + elf_assert(scn); + elf_assert(scn->s_index == 0); + rewrite(shdr->sh_info, phnum, scn->s_shdr_flags); + *flag |= scn->s_shdr_flags; + phnum = PN_XNUM; + } + rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags); + rewrite(ehdr->e_phentsize, entsize, 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; + off_t len; + + elf_assert(scn->s_index == shnum); + + *flag |= scn->s_scn_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); + } + *flag |= scn->s_shdr_flags; + continue; + } + if (shdr->sh_type == SHT_NULL) { + *flag |= scn->s_shdr_flags; + continue; + } + + len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag); + if (len == -1) { + return -1; + } + + /* + * Never override the program's choice. + */ + if (shdr->sh_entsize == 0) { + entsize = scn_entsize(elf, version, shdr->sh_type); + if (entsize > 1) { + rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags); + } + } + + if (layout) { + align(off, scn_align); + rewrite(shdr->sh_offset, off, scn->s_shdr_flags); + rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags); + rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags); + + if (shdr->sh_type != SHT_NOBITS) { + off += (size_t)len; + } + } + else if ((size_t)len > shdr->sh_size) { + seterr(ERROR_SCN2SMALL); + return -1; + } + else { + Elf_Scn *scn2; + size_t end1, end2; + + end1 = shdr->sh_offset; + if (shdr->sh_type != SHT_NOBITS) { + end1 += shdr->sh_size; + } + if (!allow_overlap && shdr->sh_offset < off) { + /* + * check for overlapping sections + */ + for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) { + if (scn2 == scn) { + break; + } + end2 = scn2->s_shdr32.sh_offset; + if (scn2->s_shdr32.sh_type != SHT_NOBITS) { + end2 += scn2->s_shdr32.sh_size; + } + if (end1 > scn2->s_shdr32.sh_offset + && end2 > shdr->sh_offset) { + seterr(ERROR_SCN_OVERLAP); + return -1; + } + } + } + if (off < end1) { + off = end1; + } + } + *flag |= scn->s_shdr_flags; + } + + if (shnum) { + entsize = _fsize(ELFCLASS32, version, ELF_T_SHDR); + elf_assert(entsize); + if (layout) { + align(off, align_addr); + rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags); + off += shnum * entsize; + } + else { + off = max(off, ehdr->e_shoff + shnum * entsize); + } + } + else { + entsize = 0; + if (layout) { + rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags); + } + } + if (shnum >= SHN_LORESERVE) { + Elf_Scn *scn = elf->e_scn_1; + Elf32_Shdr *shdr = &scn->s_shdr32; + + elf_assert(scn->s_index == 0); + rewrite(shdr->sh_size, shnum, scn->s_shdr_flags); + *flag |= scn->s_shdr_flags; + shnum = 0; + } + rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags); + rewrite(ehdr->e_shentsize, entsize, 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; +} + +#if __LIBELF64 + +static off_t +_elf64_layout(Elf *elf, unsigned *flag) { + int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0; + int allow_overlap = (elf->e_elf_flags & ELF_F_LAYOUT_OVERLAP) != 0; + Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf->e_ehdr; + size_t off = 0; + unsigned version; + unsigned encoding; + size_t align_addr; + size_t entsize; + unsigned phnum; + 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 = _fsize(ELFCLASS64, version, ELF_T_EHDR); + elf_assert(entsize); + rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags); + off = entsize; + + align_addr = _fsize(ELFCLASS64, version, ELF_T_ADDR); + elf_assert(align_addr); + + if ((phnum = elf->e_phnum)) { + entsize = _fsize(ELFCLASS64, version, ELF_T_PHDR); + elf_assert(entsize); + if (layout) { + align(off, align_addr); + rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags); + off += phnum * entsize; + } + else { + off = max(off, ehdr->e_phoff + phnum * entsize); + } + } + else { + entsize = 0; + if (layout) { + rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags); + } + } + if (phnum >= PN_XNUM) { + Elf_Scn *scn = elf->e_scn_1; + Elf32_Shdr *shdr = &scn->s_shdr32; + + /* modify first section header, too! */ + elf_assert(scn); + elf_assert(scn->s_index == 0); + rewrite(shdr->sh_info, phnum, scn->s_shdr_flags); + *flag |= scn->s_shdr_flags; + phnum = PN_XNUM; + } + rewrite(ehdr->e_phnum, phnum, elf->e_ehdr_flags); + rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags); + + for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) { + Elf64_Shdr *shdr = &scn->s_shdr64; + size_t scn_align = 1; + off_t len; + + elf_assert(scn->s_index == shnum); + + *flag |= scn->s_scn_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); + } + *flag |= scn->s_shdr_flags; + continue; + } + if (shdr->sh_type == SHT_NULL) { + *flag |= scn->s_shdr_flags; + continue; + } + + len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag); + if (len == -1) { + return -1; + } + + /* + * Never override the program's choice. + */ + if (shdr->sh_entsize == 0) { + entsize = scn_entsize(elf, version, shdr->sh_type); + if (entsize > 1) { + rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags); + } + } + + if (layout) { + align(off, scn_align); + rewrite(shdr->sh_offset, off, scn->s_shdr_flags); + rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags); + rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags); + + if (shdr->sh_type != SHT_NOBITS) { + off += (size_t)len; + } + } + else if ((size_t)len > shdr->sh_size) { + seterr(ERROR_SCN2SMALL); + return -1; + } + else { + Elf_Scn *scn2; + size_t end1, end2; + + end1 = shdr->sh_offset; + if (shdr->sh_type != SHT_NOBITS) { + end1 += shdr->sh_size; + } + if (!allow_overlap && shdr->sh_offset < off) { + /* + * check for overlapping sections + */ + for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) { + if (scn2 == scn) { + break; + } + end2 = scn2->s_shdr64.sh_offset; + if (scn2->s_shdr64.sh_type != SHT_NOBITS) { + end2 += scn2->s_shdr64.sh_size; + } + if (end1 > scn2->s_shdr64.sh_offset + && end2 > shdr->sh_offset) { + seterr(ERROR_SCN_OVERLAP); + return -1; + } + } + } + if (off < end1) { + off = end1; + } + } + *flag |= scn->s_shdr_flags; + } + + if (shnum) { + entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR); + elf_assert(entsize); + if (layout) { + align(off, align_addr); + rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags); + off += shnum * entsize; + } + else { + off = max(off, ehdr->e_shoff + shnum * entsize); + } + } + else { + entsize = 0; + if (layout) { + rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags); + } + } + if (shnum >= SHN_LORESERVE) { + Elf_Scn *scn = elf->e_scn_1; + Elf64_Shdr *shdr = &scn->s_shdr64; + + elf_assert(scn->s_index == 0); + rewrite(shdr->sh_size, shnum, scn->s_shdr_flags); + *flag |= scn->s_shdr_flags; + shnum = 0; + } + rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags); + rewrite(ehdr->e_shentsize, entsize, 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], ELFCLASS64, 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; +} + +#endif /* __LIBELF64 */ + +#define ptrinside(p,a,l) ((p)>=(a)&&(p)<(a)+(l)) +#define newptr(p,o,n) ((p)=((p)-(o))+(n)) + +static int +_elf_update_pointers(Elf *elf, char *outbuf, size_t len) { + Elf_Scn *scn; + 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; + /* cooked data is stored outside the raw image */ + 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 */ + 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 ((sd = scn->s_data_1)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + if (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)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + if (sd->sd_memdata && sd->sd_free_data) { + size_t off, len; + + if (elf->e_class == ELFCLASS32) { + off = scn->s_shdr32.sh_offset; + len = scn->s_shdr32.sh_size; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + off = scn->s_shdr64.sh_offset; + len = scn->s_shdr64.sh_size; + } +#endif /* __LIBELF64 */ + else { + seterr(ERROR_UNIMPLEMENTED); + return -1; + } + if (!(rawdata = (char*)realloc(sd->sd_memdata, len))) { + seterr(ERROR_IO_2BIG); + return -1; + } + memcpy(rawdata, outbuf + off, len); + 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; +} + +#undef ptrinside +#undef newptr + +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; + + elf_assert(len); + elf_assert(elf->e_ehdr); + ehdr = (Elf32_Ehdr*)elf->e_ehdr; + encode = ehdr->e_ident[EI_DATA]; + + src.d_buf = ehdr; + src.d_type = ELF_T_EHDR; + src.d_size = _msize(ELFCLASS32, _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 (elf->e_phnum) { + src.d_buf = elf->e_phdr; + src.d_type = ELF_T_PHDR; + src.d_size = elf->e_phnum * _msize(ELFCLASS32, _elf_version, ELF_T_PHDR); + src.d_version = _elf_version; + dst.d_buf = outbuf + ehdr->e_phoff; + dst.d_size = elf->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) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf == elf); + + src.d_buf = &scn->s_uhdr; + src.d_type = ELF_T_SHDR; + src.d_size = _msize(ELFCLASS32, EV_CURRENT, ELF_T_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; + } + shdr = &scn->s_shdr32; + if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) { + continue; + } + /* XXX: this is probably no longer necessary */ + if (scn->s_data_1 && !elf_getdata(scn, NULL)) { + return -1; + } + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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)) { + size_t tmp; + + tmp = _elf32_xltsize(&src, dst.d_version, ELFDATA2LSB, 1); + if (tmp == (size_t)-1) { + return -1; + } + dst.d_size = tmp; + } + else { + src.d_type = ELF_T_BYTE; + } + if (!elf32_xlatetof(&dst, &src, encode)) { + return -1; + } + } + } + + /* cleanup */ + if (elf->e_readable && _elf_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; +} + +#if __LIBELF64 + +static off_t +_elf64_write(Elf *elf, char *outbuf, size_t len) { + Elf64_Ehdr *ehdr; + Elf64_Shdr *shdr; + Elf_Scn *scn; + Scn_Data *sd; + Elf_Data src; + Elf_Data dst; + unsigned encode; + + elf_assert(len); + elf_assert(elf->e_ehdr); + ehdr = (Elf64_Ehdr*)elf->e_ehdr; + encode = ehdr->e_ident[EI_DATA]; + + src.d_buf = ehdr; + src.d_type = ELF_T_EHDR; + src.d_size = _msize(ELFCLASS64, _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 (!elf64_xlatetof(&dst, &src, encode)) { + return -1; + } + + if (elf->e_phnum) { + src.d_buf = elf->e_phdr; + src.d_type = ELF_T_PHDR; + src.d_size = elf->e_phnum * _msize(ELFCLASS64, _elf_version, ELF_T_PHDR); + src.d_version = _elf_version; + dst.d_buf = outbuf + ehdr->e_phoff; + dst.d_size = elf->e_phnum * ehdr->e_phentsize; + dst.d_version = ehdr->e_version; + if (!elf64_xlatetof(&dst, &src, encode)) { + return -1; + } + } + + for (scn = elf->e_scn_1; scn; scn = scn->s_link) { + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(scn->s_elf == elf); + + src.d_buf = &scn->s_uhdr; + src.d_type = ELF_T_SHDR; + src.d_size = _msize(ELFCLASS64, EV_CURRENT, ELF_T_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 (!elf64_xlatetof(&dst, &src, encode)) { + return -1; + } + + if (scn->s_index == SHN_UNDEF) { + continue; + } + shdr = &scn->s_shdr64; + if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) { + continue; + } + /* XXX: this is probably no longer necessary */ + if (scn->s_data_1 && !elf_getdata(scn, NULL)) { + return -1; + } + for (sd = scn->s_data_1; sd; sd = sd->sd_link) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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)) { + size_t tmp; + + tmp = _elf64_xltsize(&src, dst.d_version, ELFDATA2LSB, 1); + if (tmp == (size_t)-1) { + return -1; + } + dst.d_size = tmp; + } + else { + src.d_type = ELF_T_BYTE; + } + if (!elf64_xlatetof(&dst, &src, encode)) { + return -1; + } + } + } + + /* cleanup */ + if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) { + return -1; + } + /* NOTE: ehdr is no longer valid! */ + ehdr = (Elf64_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_shdr64; + scn->s_type = shdr->sh_type; + scn->s_size = shdr->sh_size; + scn->s_offset = shdr->sh_offset; + } + } + elf->e_size = len; + return len; +} + +#endif /* __LIBELF64 */ + +static int +xwrite(int fd, char *buffer, size_t len) { + size_t done = 0; + size_t n; + + while (done < len) { + n = write(fd, buffer + done, len - done); + if (n == 0) { + /* file system full */ + return -1; + } + else if (n != (size_t)-1) { + /* some bytes written, continue */ + done += n; + } + else if (errno != EAGAIN && errno != EINTR) { + /* real error */ + return -1; + } + } + return 0; +} + +static off_t +_elf_output(Elf *elf, int fd, size_t len, off_t (*_elf_write)(Elf*, char*, size_t)) { + char *buf; + off_t err; + + elf_assert(len); +#if HAVE_FTRUNCATE + ftruncate(fd, 0); +#endif /* HAVE_FTRUNCATE */ +#if HAVE_MMAP + /* + * Make sure the file is (at least) len bytes long + */ +#if HAVE_FTRUNCATE + lseek(fd, (off_t)len, SEEK_SET); + if (ftruncate(fd, len)) { +#else /* HAVE_FTRUNCATE */ + { +#endif /* HAVE_FTRUNCATE */ + if (lseek(fd, (off_t)len - 1, SEEK_SET) != (off_t)len - 1) { + seterr(ERROR_IO_SEEK); + return -1; + } + if (xwrite(fd, "", 1)) { + seterr(ERROR_IO_WRITE); + return -1; + } + } + buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (buf != (char*)-1) { + if ((char)_elf_fill && !(elf->e_elf_flags & ELF_F_LAYOUT)) { + memset(buf, _elf_fill, len); + } + err = _elf_write(elf, buf, len); + munmap(buf, len); + return err; + } +#endif /* HAVE_MMAP */ + if (!(buf = (char*)malloc(len))) { + seterr(ERROR_MEM_OUTBUF); + return -1; + } + memset(buf, _elf_fill, len); + err = _elf_write(elf, buf, len); + if (err != -1 && (size_t)err == len) { + if (lseek(fd, (off_t)0, SEEK_SET)) { + seterr(ERROR_IO_SEEK); + err = -1; + } + else if (xwrite(fd, buf, len)) { + seterr(ERROR_IO_WRITE); + err = -1; + } + } + free(buf); + return err; +} + +off_t +elf_update(Elf *elf, Elf_Cmd cmd) { + unsigned flag; + off_t len; + + 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)) { + len = _elf_output(elf, elf->e_fd, (size_t)len, _elf32_write); + } + return len; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + len = _elf64_layout(elf, &flag); + if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) { + len = _elf_output(elf, elf->e_fd, (size_t)len, _elf64_write); + } + return len; + } +#endif /* __LIBELF64 */ + else if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return -1; +} diff --git a/lib/verdef.h b/lib/verdef.h new file mode 100644 index 0000000..e17f682 --- /dev/null +++ b/lib/verdef.h @@ -0,0 +1,241 @@ +/* + * verdef.h - copy versioning information. + * Copyright (C) 2001 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef lint +static const char verdef_h_rcsid[] = "@(#) $Id: verdef.h,v 1.13 2008/05/23 08:15:35 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 _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 _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 off; + + if (sizeof(verdef_stype) != sizeof(verdef_dtype) + || sizeof(verdaux_stype) != sizeof(verdaux_dtype)) { + /* never happens for ELF v1 and Verneed v1 */ + seterr(ERROR_UNIMPLEMENTED); + return (size_t)-1; + } + /* size translation shortcut */ + if (dst == NULL) { + return n; + } + if (src == NULL) { + seterr(ERROR_NULLBUF); + return (size_t)-1; + } + off = 0; + while (off + sizeof(verdef_stype) <= n) { + const verdef_stype *svd; + verdef_dtype *dvd; + verdef_mtype vd; + size_t acount; + size_t aoff; + + /* + * check for proper alignment + */ + if (off % sizeof(verdef_atype)) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + /* + * copy and check src + */ + svd = (verdef_stype*)(src + off); + dvd = (verdef_dtype*)(dst + off); + 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) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + copy_verdef_tmptodst(dvd, &vd, enc); + /* + * copy aux array + */ + aoff = off + vd.vd_aux; + for (acount = 0; acount < vd.vd_cnt; acount++) { + const verdaux_stype *svda; + verdaux_dtype *dvda; + verdaux_mtype vda; + + /* + * are we still inside the buffer limits? + */ + if (aoff + sizeof(verdaux_stype) > n) { + break; + } + /* + * check for proper alignment + */ + if (aoff % sizeof(verdef_atype)) { + seterr(ERROR_VERDEF_FORMAT); + return (size_t)-1; + } + /* + * copy and check src + */ + svda = (verdaux_stype*)(src + aoff); + dvda = (verdaux_dtype*)(dst + aoff); + copy_verdaux_srctotmp(&vda, svda, enc); + copy_verdaux_tmptodst(dvda, &vda, enc); + /* + * advance to next verdaux + */ + if (vda.vda_next == 0) { + /* end of list */ + break; + } + aoff += vda.vda_next; + } + /* + * advance to next verdef + */ + if (vd.vd_next == 0) { + /* end of list */ + break; + } + off += vd.vd_next; + } + return n; +} + +size_t +translator(verdef,L11)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verdef(dst, src, n, ELFDATA2LSB); +} + +size_t +translator(verdef,M11)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verdef(dst, src, n, ELFDATA2MSB); +} diff --git a/lib/verdef_32_tof.c b/lib/verdef_32_tof.c new file mode 100644 index 0000000..efca6ee --- /dev/null +++ b/lib/verdef_32_tof.c @@ -0,0 +1,53 @@ +/* +verdef_32_tof.c - copy 32-bit versioning information. +Copyright (C) 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.5 2008/05/23 08:15:35 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/lib/verdef_32_tom.c b/lib/verdef_32_tom.c new file mode 100644 index 0000000..f0efd0f --- /dev/null +++ b/lib/verdef_32_tom.c @@ -0,0 +1,53 @@ +/* +verdef_32_tom.c - copy 32-bit versioning information. +Copyright (C) 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.5 2008/05/23 08:15:35 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/lib/verdef_64_tof.c b/lib/verdef_64_tof.c new file mode 100644 index 0000000..16b903e --- /dev/null +++ b/lib/verdef_64_tof.c @@ -0,0 +1,53 @@ +/* +verdef_64_tof.c - copy 64-bit versioning information. +Copyright (C) 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.5 2008/05/23 08:15:35 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/lib/verdef_64_tom.c b/lib/verdef_64_tom.c new file mode 100644 index 0000000..183524e --- /dev/null +++ b/lib/verdef_64_tom.c @@ -0,0 +1,53 @@ +/* +verdef_64_tom.c - copy 64-bit versioning information. +Copyright (C) 2001 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.5 2008/05/23 08:15:35 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/lib/verneed.h b/lib/verneed.h new file mode 100644 index 0000000..54f0f06 --- /dev/null +++ b/lib/verneed.h @@ -0,0 +1,245 @@ +/* + * verneed.h - copy versioning information. + * Copyright (C) 2001 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef lint +static const char verneed_h_rcsid[] = "@(#) $Id: verneed.h,v 1.13 2008/05/23 08:15:35 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 _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 _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 off; + + if (sizeof(verneed_stype) != sizeof(verneed_dtype) + || sizeof(vernaux_stype) != sizeof(vernaux_dtype)) { + /* never happens for ELF v1 and Verneed v1 */ + seterr(ERROR_UNIMPLEMENTED); + return (size_t)-1; + } + /* size translation shortcut */ + if (dst == NULL) { + return n; + } + if (src == NULL) { + seterr(ERROR_NULLBUF); + return (size_t)-1; + } + off = 0; + while (off + sizeof(verneed_stype) <= n) { + const verneed_stype *svn; + verneed_dtype *dvn; + verneed_mtype vn; + size_t acount; + size_t aoff; + + /* + * check for proper alignment + */ + if (off % sizeof(verneed_atype)) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + /* + * copy and check src + */ + svn = (verneed_stype*)(src + off); + dvn = (verneed_dtype*)(dst + off); + 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) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + copy_verneed_tmptodst(dvn, &vn, enc); + /* + * copy aux array + */ + aoff = off + vn.vn_aux; + for (acount = 0; acount < vn.vn_cnt; acount++) { + const vernaux_stype *svna; + vernaux_dtype *dvna; + vernaux_mtype vna; + + /* + * are we still inside the buffer limits? + */ + if (aoff + sizeof(vernaux_stype) > n) { + break; + } + /* + * check for proper alignment + */ + if (aoff % sizeof(verneed_atype)) { + seterr(ERROR_VERNEED_FORMAT); + return (size_t)-1; + } + /* + * copy and check src + */ + svna = (vernaux_stype*)(src + aoff); + dvna = (vernaux_dtype*)(dst + aoff); + copy_vernaux_srctotmp(&vna, svna, enc); + copy_vernaux_tmptodst(dvna, &vna, enc); + /* + * advance to next vernaux + */ + if (vna.vna_next == 0) { + /* end of list */ + break; + } + aoff += vna.vna_next; + } + /* + * advance to next verneed + */ + if (vn.vn_next == 0) { + /* end of list */ + break; + } + off += vn.vn_next; + } + return n; +} + +size_t +translator(verneed,L11)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verneed(dst, src, n, ELFDATA2LSB); +} + +size_t +translator(verneed,M11)(unsigned char *dst, const unsigned char *src, size_t n) { + return xlt_verneed(dst, src, n, ELFDATA2MSB); +} diff --git a/lib/version.c b/lib/version.c new file mode 100644 index 0000000..7a901d3 --- /dev/null +++ b/lib/version.c @@ -0,0 +1,44 @@ +/* + * version.c - implementation of the elf_version(3) function. + * Copyright (C) 1995 - 1998, 2007 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: version.c,v 1.8 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +unsigned +elf_version(unsigned ver) { + const char *s; + unsigned tmp; + + if ((s = getenv("LIBELF_SANITY_CHECKS"))) { + _elf_sanity_checks = (int)strtol(s, (char**)NULL, 0); + } + 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; +} diff --git a/lib/x.elfext.c b/lib/x.elfext.c new file mode 100644 index 0000000..cbd3539 --- /dev/null +++ b/lib/x.elfext.c @@ -0,0 +1,190 @@ +/* + * x.elfext.c -- handle ELF format extensions + * Copyright (C) 2002 - 2006 Michael Riepe + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: x.elfext.c,v 1.5 2009/07/07 17:57:43 michael Exp $"; +#endif /* lint */ + +int +elf_getphdrnum(Elf *elf, size_t *resultp) { + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return -1; + } + if (!elf->e_ehdr && !_elf_cook(elf)) { + return -1; + } + if (resultp) { + *resultp = elf->e_phnum; + } + return 0; +} + +int +elf_getshdrnum(Elf *elf, size_t *resultp) { + size_t num = 0; + Elf_Scn *scn; + + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return -1; + } + if (!elf->e_ehdr && !_elf_cook(elf)) { + return -1; + } + if ((scn = elf->e_scn_n)) { + num = scn->s_index + 1; + } + if (resultp) { + *resultp = num; + } + return 0; +} + +int +elf_getshdrstrndx(Elf *elf, size_t *resultp) { + size_t num = 0; + size_t dummy; + Elf_Scn *scn; + + if (!elf) { + return -1; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (resultp == NULL) { + resultp = &dummy; /* handle NULL pointer gracefully */ + } + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return -1; + } + if (!elf->e_ehdr && !_elf_cook(elf)) { + return -1; + } + if (elf->e_class == ELFCLASS32) { + num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx; + } +#endif /* __LIBELF64 */ + else { + if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return -1; + } + if (num != SHN_XINDEX) { + *resultp = num; + return 0; + } + /* + * look at first section header + */ + if (!(scn = elf->e_scn_1)) { + seterr(ERROR_NOSUCHSCN); + return -1; + } + elf_assert(scn->s_magic == SCN_MAGIC); +#if __LIBELF64 + if (elf->e_class == ELFCLASS64) { + *resultp = scn->s_shdr64.sh_link; + return 0; + } +#endif /* __LIBELF64 */ + *resultp = scn->s_shdr32.sh_link; + return 0; +} + +int +elf_getphnum(Elf *elf, size_t *resultp) { + return elf_getphdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS; +} + +int +elf_getshnum(Elf *elf, size_t *resultp) { + return elf_getshdrnum(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS; +} + +int +elf_getshstrndx(Elf *elf, size_t *resultp) { + return elf_getshdrstrndx(elf, resultp) ? LIBELF_FAILURE : LIBELF_SUCCESS; +} + +int +elfx_update_shstrndx(Elf *elf, size_t value) { + size_t extvalue = 0; + Elf_Scn *scn; + + if (!elf) { + return LIBELF_FAILURE; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (value >= SHN_LORESERVE) { + extvalue = value; + value = SHN_XINDEX; + } + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return LIBELF_FAILURE; + } + if (!elf->e_ehdr && !_elf_cook(elf)) { + return LIBELF_FAILURE; + } + if (!(scn = _elf_first_scn(elf))) { + return LIBELF_FAILURE; + } + elf_assert(scn->s_magic == SCN_MAGIC); + if (elf->e_class == ELFCLASS32) { + ((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx = value; + scn->s_shdr32.sh_link = extvalue; + } +#if __LIBELF64 + else if (elf->e_class == ELFCLASS64) { + ((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx = value; + scn->s_shdr64.sh_link = extvalue; + } +#endif /* __LIBELF64 */ + else { + if (valid_class(elf->e_class)) { + seterr(ERROR_UNIMPLEMENTED); + } + else { + seterr(ERROR_UNKNOWN_CLASS); + } + return LIBELF_FAILURE; + } + elf->e_ehdr_flags |= ELF_F_DIRTY; + scn->s_shdr_flags |= ELF_F_DIRTY; + return LIBELF_SUCCESS; +} diff --git a/lib/x.movscn.c b/lib/x.movscn.c new file mode 100644 index 0000000..4f3d9d2 --- /dev/null +++ b/lib/x.movscn.c @@ -0,0 +1,112 @@ +/* +x.movscn.c - implementation of the elfx_movscn(3) function. +Copyright (C) 1995 - 2001, 2003 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: x.movscn.c,v 1.14 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +size_t +elfx_movscn(Elf *elf, Elf_Scn *scn, Elf_Scn *after) { + Elf_Scn *prev; + Elf_Scn *tmp; + int off; + + if (!elf || !scn || !after) { + return SHN_UNDEF; + } + elf_assert(elf->e_magic == ELF_MAGIC); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return SHN_UNDEF; + } + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(after->s_magic == SCN_MAGIC); + if (scn->s_elf != elf || after->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; + } + if (scn == after || scn == after->s_link) { + /* nothing to do */ + return scn->s_index; + } + + /* + * Find previous section. + */ + prev = NULL; + for (tmp = elf->e_scn_1; tmp->s_link; tmp = tmp->s_link) { + if (tmp->s_link == scn) { + prev = tmp; + break; + } + } + elf_assert(prev != NULL); + + /* + * Update section indices + */ + off = 0; + for (tmp = elf->e_scn_1; tmp; tmp = tmp->s_link) { + if (off) { + tmp->s_index += off; + } + if (tmp == after) { + off++; + } + else if (tmp == scn) { + off--; + } + } + elf_assert(off == 0); + + /* + * Move section. + */ + prev->s_link = scn->s_link; + scn->s_link = after->s_link; + after->s_link = scn; + scn->s_index = after->s_index + 1; + if (elf->e_scn_n == scn) { + elf->e_scn_n = prev; + } + else if (elf->e_scn_n == after) { + elf->e_scn_n = scn; + } + +#if ENABLE_DEBUG + /* + * Check section indices + */ + tmp = elf->e_scn_1; + elf_assert(tmp->s_index == 0); + while (tmp->s_link) { + elf_assert(tmp->s_link->s_index == tmp->s_index + 1); + tmp = tmp->s_link; + } +#endif /* ENABLE_DEBUG */ + + return scn->s_index; +} diff --git a/lib/x.remscn.c b/lib/x.remscn.c new file mode 100644 index 0000000..d04816e --- /dev/null +++ b/lib/x.remscn.c @@ -0,0 +1,119 @@ +/* +x.remscn.c - implementation of the elfx_remscn(3) function. +Copyright (C) 1995 - 2001, 2003 Michael Riepe + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include <private.h> + +#ifndef lint +static const char rcsid[] = "@(#) $Id: x.remscn.c,v 1.15 2008/05/23 08:15:35 michael Exp $"; +#endif /* lint */ + +size_t +elfx_remscn(Elf *elf, Elf_Scn *scn) { + 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); + if (elf->e_kind != ELF_K_ELF) { + seterr(ERROR_NOTELF); + return SHN_UNDEF; + } + elf_assert(scn->s_magic == SCN_MAGIC); + elf_assert(elf->e_ehdr); + 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; + } + + /* + * Find previous section. + */ + 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; + } + + /* + * Unlink section. + */ + if (elf->e_scn_n == scn) { + elf->e_scn_n = pscn; + } + pscn->s_link = scn->s_link; + index = scn->s_index; + + /* + * Free section descriptor and data. + */ + for (sd = scn->s_data_1; sd; sd = tmp) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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)) { + elf_assert(sd->sd_magic == DATA_MAGIC); + elf_assert(sd->sd_scn == scn); + 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 section count in ELF header + */ + if (_elf_update_shnum(elf, elf->e_scn_n->s_index + 1)) { + return SHN_UNDEF; + } + return index; +} |