Splint annotations and spec file.
authorjbj <devnull@localhost>
Tue, 18 Jun 2002 17:00:30 +0000 (17:00 +0000)
committerjbj <devnull@localhost>
Tue, 18 Jun 2002 17:00:30 +0000 (17:00 +0000)
CVS patchset: 5507
CVS date: 2002/06/18 17:00:30

29 files changed:
libelf/lib/.lclintrc [new file with mode: 0755]
libelf/lib/32.fsize.c
libelf/lib/32.newehdr.c
libelf/lib/32.newphdr.c
libelf/lib/32.xlatetof.c
libelf/lib/64.xlatetof.c
libelf/lib/assert.c
libelf/lib/begin.c
libelf/lib/byteswap.h
libelf/lib/checksum.c
libelf/lib/cook.c
libelf/lib/end.c
libelf/lib/errmsg.c
libelf/lib/flag.c
libelf/lib/gelf.h
libelf/lib/gelftrans.c
libelf/lib/getarsym.c
libelf/lib/getdata.c
libelf/lib/input.c
libelf/lib/libelf.h
libelf/lib/newscn.c
libelf/lib/nlist.c
libelf/lib/nlist.h
libelf/lib/opt.delscn.c
libelf/lib/private.h
libelf/lib/update.c
libelf/lib/verdef.h
libelf/lib/verneed.h
libelf/libelf.spec [new file with mode: 0755]

diff --git a/libelf/lib/.lclintrc b/libelf/lib/.lclintrc
new file mode 100755 (executable)
index 0000000..8dcf673
--- /dev/null
@@ -0,0 +1,81 @@
+-DHAVE_CONFIG_H -I.. -I.
+
++partial
++forcehints
+
+-warnunixlib
+-warnposix
+
++unixlib
+
+-unrecogcomments       # XXX ignore doxygen markings
+
++strict                        # lclint level
+
+# --- in progress
+#+bounds               # 675
+#+boundswrite          # 94
+
+-branchstate           # 77
+-compdef               # 85
+-compmempass           # 79
+-globstate             # 93
+-incondefs             # 4
+-matchfields           # 24
+-mods                  # 259
+-nullderef             # 10
+-redef                 # 42
+-retalias              # 21
+-retvalint             # 9
+-shadow                        # 9
+-shiftimplementation   # 35
+-sizeoftype            # 325
+-unsignedcompare       # 11
+-usereleased           # 50
+
+-immediatetrans                # 19
+-kepttrans             # 15
+-temptrans             # 15
+
+# --- +partial artifacts
+-declundef
+-exportheadervar
+-exportlocal
+
+-enummemuse
+-fcnuse
+-typeuse
+-varuse
+
+# --- not-yet at strict level
+-bitwisesigned
+-elseifcomplete
+-exportconst
+-exportfcn
+-exporttype
+-exportvar
+-fielduse
+-forblock              # tedious
+-ifblock               # tedious
+-namechecks            # tedious ANSI compliance checks
+-ptrarith
+
+-compdestroy
+-mustdefine
+-sys-dir-errors
+
+-strictops
+-whileblock            # tedious
+
+# --- not-yet at checks level
++enumint
+-mustfree
+-predboolptr
+-usedef
+
+# --- not-yet at standard level
+-boolops
++boolint
++charint
++ignorequals
++matchanyintegral
index 2d972f5..25bb4b4 100755 (executable)
@@ -1,6 +1,6 @@
 /*
-32.fsize.c - implementation of the elf32_fsize(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+32.fsize.c - implementation of the elf{32,64}_fsize(3) functions.
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -20,28 +20,72 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include <private.h>
 #include <ext_types.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: 32.fsize.c,v 1.9 2001/10/05 19:05:25 michael Exp ";
+#endif /* lint */
+
+/*@-initsize@*/
 const size_t
-_elf32_fmsize[EV_CURRENT - EV_NONE][ELF_T_NUM][2] = {
+_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 */
     {
-       { 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)    },
+       /* 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 */
 };
+/*@=initsize@*/
 
-size_t
-elf32_fsize(Elf_Type type, size_t count, unsigned ver) {
-    size_t n;
+static size_t
+_elf_fsize(unsigned cls, Elf_Type type, unsigned ver)
+       /*@globals _elf_errno @*/
+       /*@modifies _elf_errno @*/
+{
+    size_t n = 0;
 
     if (!valid_version(ver)) {
        seterr(ERROR_UNKNOWN_VERSION);
@@ -49,11 +93,68 @@ elf32_fsize(Elf_Type type, size_t count, unsigned ver) {
     else if (!valid_type(type)) {
        seterr(ERROR_UNKNOWN_TYPE);
     }
-    else if (!(n = _fsize32(ver, type))) {
+    else if (!(n = _fsize(cls, ver, type))) {
        seterr(ERROR_UNKNOWN_TYPE);
     }
-    else if (count) {
-       return count * n;
+    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 */
index 403a387..ecfcc54 100755 (executable)
@@ -1,6 +1,6 @@
 /*
-32.newehdr.c - implementation of the elf32_newehdr(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+32.newehdr.c - implementation of the elf{32,64}_newehdr(3) functions.
+Copyright (C) 1995 - 2000 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,9 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
-Elf32_Ehdr*
-elf32_newehdr(Elf *elf) {
-    Elf32_Ehdr *ehdr;
+#ifndef lint
+static const char rcsid[] = "@(#) Id: 32.newehdr.c,v 1.9 2000/03/31 12:42:32 michael Exp ";
+#endif /* lint */
+
+/*@null@*/
+static char*
+_elf_newehdr(Elf *elf, unsigned cls)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
     size_t size;
 
     if (!elf) {
@@ -29,28 +36,53 @@ elf32_newehdr(Elf *elf) {
     }
     elf_assert(elf->e_magic == ELF_MAGIC);
     if (elf->e_readable) {
-       return elf32_getehdr(elf);
+       return _elf_getehdr(elf, cls);
     }
     else if (!elf->e_ehdr) {
-       size = _msize32(_elf_version, ELF_T_EHDR);
+       size = _msize(cls, _elf_version, ELF_T_EHDR);
        elf_assert(size);
-       if ((ehdr = (Elf32_Ehdr*)malloc(size))) {
-           memset(ehdr, 0, size);
-           elf->e_ehdr = (char*)ehdr;
+       if ((elf->e_ehdr = (char*)malloc(size))) {
+           memset(elf->e_ehdr, 0, size);
            elf->e_free_ehdr = 1;
            elf->e_ehdr_flags |= ELF_F_DIRTY;
            elf->e_kind = ELF_K_ELF;
-           elf->e_class = ELFCLASS32;
-           return ehdr;
+           elf->e_class = cls;
+           return elf->e_ehdr;
        }
        seterr(ERROR_MEM_EHDR);
     }
-    else if (elf->e_class != ELFCLASS32) {
+    else if (elf->e_class != cls) {
        seterr(ERROR_CLASSMISMATCH);
     }
     else {
        elf_assert(elf->e_kind == ELF_K_ELF);
-       return (Elf32_Ehdr*)elf->e_ehdr;
+       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;
+    }
+    if (!_elf_newehdr(elf, cls)) {
+       return 0;
+    }
+    return 1;  /* really? */
+}
+
+#endif /* __LIBELF64 */
index 79ca622..e5ede14 100755 (executable)
@@ -1,6 +1,6 @@
 /*
-32.newphdr.c - implementation of the elf32_newphdr(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+32.newphdr.c - implementation of the elf{32,64}_newphdr(3) functions.
+Copyright (C) 1995 - 2000 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,10 +19,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
-Elf32_Phdr*
-elf32_newphdr(Elf *elf, size_t count) {
-    Elf32_Phdr *phdr = NULL;
-    Elf32_Ehdr *ehdr;
+#ifndef lint
+static const char rcsid[] = "@(#) Id: 32.newphdr.c,v 1.9 2000/03/31 12:42:32 michael Exp ";
+#endif /* lint */
+
+/*@null@*/
+static char*
+_elf_newphdr(Elf *elf, size_t count, unsigned cls)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
+    char *phdr = NULL;
     size_t size;
 
     if (!elf) {
@@ -35,30 +42,70 @@ elf32_newphdr(Elf *elf, size_t count) {
     else if (elf->e_kind != ELF_K_ELF) {
        seterr(ERROR_NOTELF);
     }
-    else if (elf->e_class != ELFCLASS32) {
+    else if (elf->e_class != cls) {
        seterr(ERROR_CLASSMISMATCH);
     }
     else if (elf->e_ehdr || _elf_cook(elf)) {
-       ehdr = (Elf32_Ehdr*)elf->e_ehdr;
+       size = _msize(cls, _elf_version, ELF_T_PHDR);
+       elf_assert(size);
        if (count) {
-           size = _msize32(_elf_version, ELF_T_PHDR);
-           elf_assert(size);
-           if (!(phdr = (Elf32_Phdr*)malloc(count * size))) {
+           if (!(phdr = (char*)malloc(count * size))) {
                seterr(ERROR_MEM_PHDR);
                return NULL;
            }
            memset(phdr, 0, count * size);
        }
+       elf_assert(elf->e_ehdr);
+       if (cls == ELFCLASS32) {
+           ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum = elf->e_phnum = count;
+       }
+#if __LIBELF64
+       else if (cls == ELFCLASS64) {
+           ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum = elf->e_phnum = count;
+       }
+#endif /* __LIBELF64 */
+       else {
+           seterr(ERROR_UNIMPLEMENTED);
+           if (phdr) {
+               free(phdr);
+           }
+           return NULL;
+       }
        if (elf->e_free_phdr) {
            elf_assert(elf->e_phdr);
            free(elf->e_phdr);
        }
-       elf->e_phdr = (char*)phdr;
+       elf->e_phdr = phdr;
        elf->e_free_phdr = phdr ? 1 : 0;
        elf->e_phdr_flags |= ELF_F_DIRTY;
-       elf->e_phnum = ehdr->e_phnum = count;
        elf->e_ehdr_flags |= ELF_F_DIRTY;
        return phdr;
     }
     return NULL;
 }
+
+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;
+    }
+    if (!_elf_newphdr(elf, phnum, elf->e_class)) {
+       return 0;
+    }
+    return 1;  /* really? */
+}
+
+#endif /* __LIBELF64 */
index 0220a82..32a4c2c 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 32.xlatetof.c - implementation of the elf32_xlateto[fm](3) functions.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2002 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -21,23 +21,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include <ext_types.h>
 #include <byteswap.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: 32.xlatetof.c,v 1.14 2002/06/11 18:53:22 michael Exp ";
+#endif /* lint */
+
 /*
  * Ugly, ugly
  */
+#if defined(__LCLINT__)
+# 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 x
 #if defined/**/x
 # define Cat2(a,b)a##b
 # define Cat3(a,b,c)a##b##c
-# define Exn(m1,m2,args)m1##m2##args
 # define Ex1(m1,m2,a,b)m1##m2(a##b)
 # define Ex2(m1,m2,a,b,c)m1##m2(a,b##c)
 #else
 # define Cat2(a,b)a/**/b
 # define Cat3(a,b,c)a/**/b/**/c
-# define Exn(m1,m2,args)m1/**/m2/**/args
 # define Ex1(m1,m2,a,b)m1/**/m2(a/**/b)
 # define Ex2(m1,m2,a,b,c)m1/**/m2(a,b/**/c)
 #endif
+#endif
 #undef x
 
 /*
@@ -50,27 +59,37 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  * function instantiator
  */
 #define copy_type_e_io(name,e,io,tfrom,tto,copy)               \
-    static void                                                        \
-    Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) {  \
-       const tfrom *from = (const tfrom*)src;                  \
-       tto *to = (tto*)dst;                                    \
-       if (sizeof(tfrom) < sizeof(tto)) {                      \
-           from += n;                                          \
-           to += n;                                            \
-           while (n-- > 0) {                                   \
-               --from;                                         \
-               --to;                                           \
-               copy(e,io,seq_back)                             \
+    /*@-mustmod@*/                                             \
+    static size_t                                              \
+    Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) \
+       /*@modifies *dst @*/                                    \
+    {                                                          \
+       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 {                                                  \
-           while (n-- > 0) {                                   \
-               copy(e,io,seq_forw)                             \
-               from++;                                         \
-               to++;                                           \
+           else {                                              \
+               for (i = 0; i < n; i++) {                       \
+                   copy(e,io,seq_forw)                         \
+                   from++;                                     \
+                   to++;                                       \
+               }                                               \
            }                                                   \
        }                                                       \
-    }
+       return n * sizeof(tto);                                 \
+    }                                                          \
+    /*@=mustmod@*/
 
 #define copy_type_e(name,e,type,copy)                          \
     copy_type_e_io(name,e,tom,Cat2(__ext_,type),type,copy)     \
@@ -86,14 +105,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 /*
  * scalar copying
  */
-#define copy_scalar_tom(type)  *to = Exn(__load_,type,(*from));
-#define copy_scalar_tof(type)  Exn(__store_,type,(*to, *from));
+#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 = Exn(__load_,type,(from->mb));
-#define copy_tof(mb,type)      Exn(__store_,type,(to->mb, from->mb));
+#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)
@@ -181,32 +200,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     seq(copy_half(e,io,st_shndx),      \
     /**/))))))
 
-static void
-byte_copy(unsigned char *dst, const unsigned char *src, size_t n) {
-    if (dst == src || !n) {
-       return;
-    }
+static size_t
+byte_copy(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
+    if (n && dst && dst != src) {
 #if HAVE_BROKEN_MEMMOVE
-    while (dst > src && dst < &src[n]) {
-       if (n <= 16) {
-           /* copy `manually' */
-           while (n--) {
-               dst[n] = src[n];
+       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];
            }
-           return;
        }
-       /* copy upper half */
-       byte_copy(&dst[n / 2], &src[n / 2], n - n / 2);
-       /* continue with lower half */
-       n /= 2;
+       else {
+           for (i = n; --i; ) {
+               dst[i] = src[i];
+           }
+       }
+#else /* HAVE_BROKEN_MEMMOVE */
+       memmove(dst, src, n);
+#endif /* HAVE_BROKEN_MEMMOVE */
     }
-#endif
-    memmove(dst, src, n);
+    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);
+array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t slen)
+       /*@modifies *dst @*/
+{
+    (void) byte_copy(dst, src, dlen < slen ? dlen : slen);
     if (dlen > slen) {
        memset(dst + slen, 0, dlen - slen);
     }
@@ -215,11 +241,11 @@ array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t sle
 /*
  * 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(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)
@@ -228,50 +254,81 @@ copy_type(rel_32,11,Elf32_Rel,copy_rel_11)
 copy_type(shdr_32,11,Elf32_Shdr,copy_shdr_11)
 copy_type(sym_32,11,Elf32_Sym,copy_sym_11)
 
-typedef void (*xlator)(unsigned char*, const unsigned char*, size_t);
+typedef size_t (*xlator)(unsigned char* dst, const unsigned char* src, size_t n)
+       /*@modifies *dst @*/;
 typedef xlator xltab[ELF_T_NUM][2];
 
 /*
  * translation table (32-bit, version 1 -> version 1)
  */
+/*@-initsize -nullassign @*/
+/*@unchecked@*/ /*@observer@*/
+#if PIC
+static xltab
+#else /* PIC */
 static const xltab
+#endif /* PIC */
 xlate32_11[/*encoding*/] = {
     {
-       { byte_copy,        byte_copy       },
-       { addr_32L_tom,     addr_32L_tof    },
+       { 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     },
+       { 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   },
+       { sword_32L__tom,   sword_32L__tof  },
        { sym_32L11_tom,    sym_32L11_tof   },
-       { word_32L_tom,     word_32L_tof    },
+       { word_32L__tom,    word_32L__tof   },
+       { NULL,             NULL            },  /* there is no Sxword */
+       { NULL,             NULL            },  /* 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 */
+       { NULL,             NULL            },
+       { NULL,             NULL            },
+#endif /* __LIBELF_SYMBOL_VERSIONS */
     },
     {
-       { byte_copy,        byte_copy       },
-       { addr_32M_tom,     addr_32M_tof    },
+       { byte_copy,        byte_copy       },
+       { addr_32M__tom,    addr_32M__tof   },
        { dyn_32M11_tom,    dyn_32M11_tof   },
        { ehdr_32M11_tom,   ehdr_32M11_tof  },
-       { half_32M_tom,     half_32M_tof    },
-       { off_32M_tom,      off_32M_tof     },
+       { 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   },
+       { sword_32M__tom,   sword_32M__tof  },
        { sym_32M11_tom,    sym_32M11_tof   },
-       { word_32M_tom,     word_32M_tof    },
+       { word_32M__tom,    word_32M__tof   },
+       { NULL,             NULL            },  /* there is no Sxword */
+       { NULL,             NULL            },  /* 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 */
+       { NULL,             NULL            },
+       { NULL,             NULL            },
+#endif /* __LIBELF_SYMBOL_VERSIONS */
     },
 };
+/*@=initsize =nullassign @*/
 
 /*
  * main translation table (32-bit)
  */
+/*@unchecked@*/ /*@observer@*/
+#if PIC
+static xltab*
+#else /* PIC */
 static const xltab *const
+#endif /* PIC */
 xlate32[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = {
     { xlate32_11, },
 };
@@ -284,13 +341,54 @@ xlate32[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = {
            [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
  */
+/*@null@*/
 static Elf_Data*
-elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
-    size_t ssize, dsize, count;
+elf32_xlate(/*@returned@*/ Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof)
+       /*@modifies *dst @*/
+{
     Elf_Type type;
-    int sv, dv;
+    int dv;
+    int sv;
+    size_t dsize;
+    size_t tmp;
     xlator op;
 
     if (!src || !dst) {
@@ -315,22 +413,21 @@ elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
        seterr(ERROR_UNKNOWN_TYPE);
        return NULL;
     }
-    ssize = _fmsize32(sv, type, 1 - tof);
-    dsize = _fmsize32(dv, type, tof);
     op = translator(sv, dv, encode, type, tof);
-    if (!ssize || !dsize || !op) {
+    if (!op) {
        seterr(ERROR_UNKNOWN_TYPE);
        return NULL;
     }
-    count = src->d_size / ssize;
-    if (dst->d_size < count * dsize) {
+    dsize = (*op)(NULL, src->d_buf, src->d_size);
+    if (dst->d_size < dsize) {
        seterr(ERROR_DST2SMALL);
        return NULL;
     }
-    if (count) {
-       (*op)(dst->d_buf, src->d_buf, count);
+    if (dsize) {
+       tmp = (*op)(dst->d_buf, src->d_buf, src->d_size);
+       elf_assert(tmp == dsize);
     }
-    dst->d_size = count * dsize;
+    dst->d_size = dsize;
     dst->d_type = type;
     return dst;
 }
index aa2d71c..77cdeba 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 64.xlatetof.c - implementation of the elf64_xlateto[fm](3) functions.
-Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2002 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -21,61 +21,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include <ext_types.h>
 #include <byteswap.h>
 
+#if __LIBELF64
+
 #ifndef lint
-static const char rcsid[] = "@(#) Id: 64.xlatetof.c,v 1.3 1998/08/25 15:22:24 michael Exp ";
+static const char rcsid[] = "@(#) Id: 64.xlatetof.c,v 1.14 2002/06/11 18:53:22 michael Exp ";
 #endif /* lint */
 
-static __libelf_u64_t
-__load_u64L(const unsigned char *from) {
-    return ((__libelf_u64_t)__load_u32L(from + 4) << 32) | (__libelf_u64_t)__load_u32L(from);
-}
-
-static __libelf_u64_t
-__load_u64M(const unsigned char *from) {
-    return ((__libelf_u64_t)__load_u32M(from) << 32) | (__libelf_u64_t)__load_u32M(from + 4);
-}
-
-static __libelf_i64_t
-__load_i64L(const unsigned char *from) {
-    return ((__libelf_i64_t)__load_i32L(from + 4) << 32) | (__libelf_u64_t)__load_u32L(from);
-}
-
-static __libelf_i64_t
-__load_i64M(const unsigned char *from) {
-    return ((__libelf_u64_t)__load_u32M(from) << 32) | (__libelf_i64_t)__load_i32M(from + 4);
-}
-
-static void
-__store_u64L(unsigned char *to, __libelf_u64_t v) {
-    __store_u32L(to, (unsigned long)v);
-    v >>= 32;
-    __store_u32L(to + 4, (unsigned long)v);
-}
-
-static void
-__store_u64M(unsigned char *to, __libelf_u64_t v) {
-    __store_u32M(to + 4, (unsigned long)v);
-    v >>= 32;
-    __store_u32M(to, (unsigned long)v);
-}
-
-static void
-__store_i64L(unsigned char *to, __libelf_u64_t v) {
-    __store_u32L(to, (unsigned long)v);
-    v >>= 32;
-    __store_i32L(to + 4, (unsigned long)v);
-}
-
-static void
-__store_i64M(unsigned char *to, __libelf_u64_t v) {
-    __store_u32M(to + 4, (unsigned long)v);
-    v >>= 32;
-    __store_i32M(to, (unsigned long)v);
-}
-
 /*
  * Ugly, ugly
  */
+#if defined(__LCLINT__)
+# 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 x
 #if defined/**/x
 # define Cat2(a,b)a##b
@@ -89,6 +49,7 @@ __store_i64M(unsigned char *to, __libelf_u64_t v) {
 # define Ex2(m1,m2,a,b,c)m1/**/m2(a,b/**/c)
 #endif
 #undef x
+#endif
 
 /*
  * auxiliary macros for execution order reversal
@@ -100,27 +61,37 @@ __store_i64M(unsigned char *to, __libelf_u64_t v) {
  * function instantiator
  */
 #define copy_type_e_io(name,e,io,tfrom,tto,copy)               \
-    static void                                                        \
-    Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) {  \
-       const tfrom *from = (const tfrom*)src;                  \
-       tto *to = (tto*)dst;                                    \
-       if (sizeof(tfrom) < sizeof(tto)) {                      \
-           from += n;                                          \
-           to += n;                                            \
-           while (n-- > 0) {                                   \
-               --from;                                         \
-               --to;                                           \
-               copy(e,io,seq_back)                             \
+    /*@-mustmod@*/                                             \
+    static size_t                                              \
+    Cat3(name,_,io)(unsigned char *dst, const unsigned char *src, size_t n) \
+       /*@modifies *dst @*/                                    \
+    {                                                          \
+       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 {                                                  \
-           while (n-- > 0) {                                   \
-               copy(e,io,seq_forw)                             \
-               from++;                                         \
-               to++;                                           \
+           else {                                              \
+               for (i = 0; i < n; i++) {                       \
+                   copy(e,io,seq_forw)                         \
+                   from++;                                     \
+                   to++;                                       \
+               }                                               \
            }                                                   \
        }                                                       \
-    }
+       return n * sizeof(tto);                                 \
+    }                                                          \
+    /*@=mustmod@*/
 
 #define copy_type_e(name,e,type,copy)                          \
     copy_type_e_io(name,e,tom,Cat2(__ext_,type),type,copy)     \
@@ -153,8 +124,8 @@ __store_i64M(unsigned char *to, __libelf_u64_t v) {
 #define copy_half(e,io,mb)     Ex2(copy_,io,mb,u16,e)
 #define copy_off(e,io,mb)      Ex2(copy_,io,mb,u64,e)
 #define copy_sword(e,io,mb)    Ex2(copy_,io,mb,i32,e)
-#define copy_sxword(e,io,mb)   Ex2(copy_,io,mb,i64,e)
 #define copy_word(e,io,mb)     Ex2(copy_,io,mb,u32,e)
+#define copy_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));
@@ -167,8 +138,8 @@ __store_i64M(unsigned char *to, __libelf_u64_t v) {
 #define copy_half_11(e,io,seq) Ex1(copy_scalar_,io,u16,e)
 #define copy_off_11(e,io,seq)  Ex1(copy_scalar_,io,u64,e)
 #define copy_sword_11(e,io,seq)        Ex1(copy_scalar_,io,i32,e)
-#define copy_sxword_11(e,io,seq)Ex1(copy_scalar_,io,i64,e)
 #define copy_word_11(e,io,seq) Ex1(copy_scalar_,io,u32,e)
+#define copy_sxword_11(e,io,seq)Ex1(copy_scalar_,io,i64,e)
 #define copy_xword_11(e,io,seq)        Ex1(copy_scalar_,io,u64,e)
 
 /*
@@ -255,32 +226,39 @@ __store_i64M(unsigned char *to, __libelf_u64_t v) {
     seq(copy_xword(e,io,st_size),      \
     /**/))))))
 
-static void
-byte_copy(unsigned char *dst, const unsigned char *src, size_t n) {
-    if (dst == src || !n) {
-       return;
-    }
+static size_t
+byte_copy(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
+    if (n && dst && dst != src) {
 #if HAVE_BROKEN_MEMMOVE
-    while (dst > src && dst < &src[n]) {
-       if (n <= 16) {
-           /* copy `manually' */
-           while (n--) {
-               dst[n] = src[n];
+       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];
            }
-           return;
        }
-       /* copy upper half */
-       byte_copy(&dst[n / 2], &src[n / 2], n - n / 2);
-       /* continue with lower half */
-       n /= 2;
+#else /* HAVE_BROKEN_MEMMOVE */
+       memmove(dst, src, n);
+#endif /* HAVE_BROKEN_MEMMOVE */
     }
-#endif
-    memmove(dst, src, n);
+    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);
+array_copy(unsigned char *dst, size_t dlen, const unsigned char *src, size_t slen)
+       /*@modifies *dst @*/
+{
+    (void) byte_copy(dst, src, dlen < slen ? dlen : slen);
     if (dlen > slen) {
        memset(dst + slen, 0, dlen - slen);
     }
@@ -293,8 +271,8 @@ copy_type(addr_64,_,Elf64_Addr,copy_addr_11)
 copy_type(half_64,_,Elf64_Half,copy_half_11)
 copy_type(off_64,_,Elf64_Off,copy_off_11)
 copy_type(sword_64,_,Elf64_Sword,copy_sword_11)
-copy_type(sxword_64,_,Elf64_Sxword,copy_sxword_11)
 copy_type(word_64,_,Elf64_Word,copy_word_11)
+copy_type(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)
@@ -304,21 +282,28 @@ copy_type(rel_64,11,Elf64_Rel,copy_rel_11)
 copy_type(shdr_64,11,Elf64_Shdr,copy_shdr_11)
 copy_type(sym_64,11,Elf64_Sym,copy_sym_11)
 
-typedef void (*xlator)(unsigned char*, const unsigned char*, size_t);
+typedef size_t (*xlator)(unsigned char* dst, const unsigned char* src, size_t n)
+       /*@modifies *dst @*/;
 typedef xlator xltab[ELF_T_NUM][2];
 
 /*
  * translation table (64-bit, version 1 -> version 1)
  */
+/*@-initsize@*/
+/*@unchecked@*/ /*@observer@*/
+#if PIC
+static xltab
+#else /* PIC */
 static const xltab
+#endif /* PIC */
 xlate64_11[/*encoding*/] = {
     {
-       { byte_copy,        byte_copy       },
+       { 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    },
+       { off_64L__tom,     off_64L__tof    },
        { phdr_64L11_tom,   phdr_64L11_tof  },
        { rela_64L11_tom,   rela_64L11_tof  },
        { rel_64L11_tom,    rel_64L11_tof   },
@@ -328,14 +313,21 @@ xlate64_11[/*encoding*/] = {
        { 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 */
+       { NULL,             NULL            },
+       { NULL,             NULL            },
+#endif /* __LIBELF_SYMBOL_VERSIONS */
     },
     {
-       { byte_copy,        byte_copy       },
+       { 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    },
+       { off_64M__tom,     off_64M__tof    },
        { phdr_64M11_tom,   phdr_64M11_tof  },
        { rela_64M11_tom,   rela_64M11_tof  },
        { rel_64M11_tom,    rel_64M11_tof   },
@@ -345,13 +337,26 @@ xlate64_11[/*encoding*/] = {
        { 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 */
+       { NULL,             NULL            },
+       { NULL,             NULL            },
+#endif /* __LIBELF_SYMBOL_VERSIONS */
     },
 };
+/*@=initsize@*/
 
 /*
  * main translation table (64-bit)
  */
+/*@unchecked@*/ /*@observer@*/
+#if PIC
+static xltab*
+#else /* PIC */
 static const xltab *const
+#endif /* PIC */
 xlate64[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = {
     { xlate64_11, },
 };
@@ -364,13 +369,54 @@ xlate64[EV_CURRENT - EV_NONE][EV_CURRENT - EV_NONE] = {
            [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
  */
+/*@null@*/
 static Elf_Data*
-elf64_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
-    size_t ssize, dsize, count;
+elf64_xlate(/*@returned@*/ Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof)
+       /*@modifies *dst @*/
+{
     Elf_Type type;
-    int sv, dv;
+    int dv;
+    int sv;
+    size_t dsize;
+    size_t tmp;
     xlator op;
 
     if (!src || !dst) {
@@ -395,22 +441,21 @@ elf64_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
        seterr(ERROR_UNKNOWN_TYPE);
        return NULL;
     }
-    ssize = _fmsize(ELFCLASS64, sv, type, 1 - tof);
-    dsize = _fmsize(ELFCLASS64, dv, type, tof);
     op = translator(sv, dv, encode, type, tof);
-    if (!ssize || !dsize || !op) {
+    if (!op) {
        seterr(ERROR_UNKNOWN_TYPE);
        return NULL;
     }
-    count = src->d_size / ssize;
-    if (dst->d_size < count * dsize) {
+    dsize = (*op)(NULL, src->d_buf, src->d_size);
+    if (dst->d_size < dsize) {
        seterr(ERROR_DST2SMALL);
        return NULL;
     }
-    if (count) {
-       (*op)(dst->d_buf, src->d_buf, count);
+    if (dsize) {
+       tmp = (*op)(dst->d_buf, src->d_buf, src->d_size);
+       elf_assert(tmp == dsize);
     }
-    dst->d_size = count * dsize;
+    dst->d_size = dsize;
     dst->d_type = type;
     return dst;
 }
@@ -428,3 +473,48 @@ 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__ */
index 9e76bed..a35cbcd 100755 (executable)
@@ -25,9 +25,11 @@ static const char rcsid[] = "@(#) Id: assert.c,v 1.1 1999/11/04 19:16:36 michael
 
 #include <stdio.h>
 
+/*@-internalglobs@*/
 void
 __elf_assert(const char *file, unsigned line, const char *cond) {
     fprintf(stderr, "%s:%u: libelf assertion failure: %s\n",
            file, line, cond);
     abort();
 }
+/*@=internalglobs@*/
index 57f803e..07a9e7b 100755 (executable)
@@ -1,6 +1,6 @@
 /*
-begin.c - implementation of the elf_begin(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+begin.c - implementation of the elf_begin(3) and elf_memory(3) functions.
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -18,13 +18,41 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
 #include <private.h>
+
+#ifndef lint
+static const char rcsid[] = "@(#) Id: begin.c,v 1.12 2001/10/15 21:38:29 michael Exp ";
+#endif /* lint */
+
+#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 */
+
+/*@unchecked@*/
 static const Elf _elf_init = INIT_ELF;
+/*@unchecked@*/ /*@observer@*/
 static const char fmag[] = ARFMAG;
 
 static unsigned long
-getnum(const char *str, size_t len, int base, int *err) {
+getnum(const char *str, size_t len, int base, int *err)
+       /*@modifies *err @*/
+{
     unsigned long result = 0;
 
     while (len && *str == ' ') {
@@ -43,7 +71,9 @@ getnum(const char *str, size_t len, int base, int *err) {
 }
 
 static void
-_elf_init_ar(Elf *elf) {
+_elf_init_ar(Elf *elf)
+       /*@modifies *elf @*/
+{
     struct ar_hdr *hdr;
     size_t offset;
     size_t size;
@@ -52,7 +82,6 @@ _elf_init_ar(Elf *elf) {
     elf->e_kind = ELF_K_AR;
     elf->e_idlen = SARMAG;
     elf->e_off = SARMAG;
-    elf->e_cooked = 1;     /* do not freeze archives! */
 
     /* process special members */
     offset = SARMAG;
@@ -86,8 +115,12 @@ _elf_init_ar(Elf *elf) {
     }
 }
 
+/*@null@*/
 static Elf_Arhdr*
-_elf_arhdr(Elf *arf) {
+_elf_arhdr(Elf *arf)
+       /*@globals _elf_errno @*/
+       /*@modifies _elf_errno @*/
+{
     struct ar_hdr *hdr;
     Elf_Arhdr *arhdr;
     size_t namelen;
@@ -155,9 +188,11 @@ _elf_arhdr(Elf *arf) {
     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))) {
@@ -177,6 +212,11 @@ _elf_arhdr(Elf *arf) {
        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';
@@ -190,6 +230,23 @@ _elf_arhdr(Elf *arf) {
     return arhdr;
 }
 
+static void
+_elf_check_type(Elf *elf, size_t size)
+       /*@modifies *elf @*/
+{
+    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;
@@ -225,7 +282,10 @@ elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
            seterr(ERROR_MEMBERWRITE);
            return NULL;
        }
-       if (fd != ref->e_fd) {
+       if (ref->e_memory) {
+           fd = ref->e_fd;
+       }
+       else if (fd != ref->e_fd) {
            seterr(ERROR_FDMISMATCH);
            return NULL;
        }
@@ -234,7 +294,7 @@ elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
        }
        size = arhdr->ar_size;
     }
-    else if ((size = lseek(fd, 0L, 2)) == (size_t)-1L) {
+    else if ((off_t)(size = lseek(fd, (off_t)0, SEEK_END)) == (off_t)-1) {
        seterr(ERROR_IO_GETSIZE);
        return NULL;
     }
@@ -276,31 +336,47 @@ elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
        for (xelf = ref->e_members; xelf; xelf = xelf->e_link) {
            elf_assert(xelf->e_parent == ref);
            if (xelf->e_base == elf->e_base) {
+/*@-nullpass@*/
                free(arhdr);
+/*@=nullpass@*/
                free(elf);
                xelf->e_count++;
                return xelf;
            }
        }
-       /*
-        * The member's memory image may have been modified if
-        * the member has been processed before. Since we need the
-        * original image, we have to re-read the archive file.
-        * Will fail if the archive's file descriptor is disabled.
-        */
-       if (size) {
-           elf->e_data = _elf_read(ref, ref->e_data + offset, offset, size);
-           if (!elf->e_data) {
+       if (size == 0) {
+           elf->e_data = NULL;
+       }
+       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)) {
+/*@-nullpass@*/
                free(arhdr);
+/*@=nullpass@*/
                free(elf);
                return NULL;
            }
        }
-       else {
-           elf->e_data = NULL;
-       }
        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;
@@ -317,24 +393,54 @@ elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
            elf->e_unmap_data = 1;
        }
        else
-#endif
+#endif /* HAVE_MMAP */
        if (!(elf->e_data = _elf_read(elf, NULL, 0, size))) {
            free(elf);
            return NULL;
        }
     }
 
-    elf->e_idlen = size;
-    if (size >= EI_NIDENT && !memcmp(elf->e_data, ELFMAG, SELFMAG)) {
-       elf->e_kind = ELF_K_ELF;
-       elf->e_idlen = EI_NIDENT;
-       elf->e_class = elf->e_data[EI_CLASS];
-       elf->e_encoding = elf->e_data[EI_DATA];
-       elf->e_version = elf->e_data[EI_VERSION];
+    _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 >= SARMAG && !memcmp(elf->e_data, ARMAG, SARMAG)) {
-       _elf_init_ar(elf);
+    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 */
index af7b1d6..94871cb 100755 (executable)
@@ -1,6 +1,6 @@
 /*
-byteswap.h - C preprocessor macros for byte swapping.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+byteswap.h - functions and macros for byte swapping.
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -17,57 +17,87 @@ 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: byteswap.h,v 1.3 2001/10/03 20:48:16 michael Exp  */
+
 #ifndef _BYTESWAP_H
 #define _BYTESWAP_H
 
-#define lu(from,i,s)           (((long)((unsigned char*)(from))[i])<<(s))
-#define li(from,i,s)           (((long)((signed char*)(from))[i])<<(s))
-
-#define __load_u16L(from)      ((unsigned long)(lu(from,1,8)|lu(from,0,0)))
-#define __load_u16M(from)      ((unsigned long)(lu(from,0,8)|lu(from,1,0)))
-#define __load_i16L(from)      ((long)(li(from,1,8)|lu(from,0,0)))
-#define __load_i16M(from)      ((long)(li(from,0,8)|lu(from,1,0)))
-
-#define __load_u32L(from)      ((unsigned long)(lu(from,3,24)| \
-                                                lu(from,2,16)| \
-                                                lu(from,1,8)|  \
-                                                lu(from,0,0)))
-#define __load_u32M(from)      ((unsigned long)(lu(from,0,24)| \
-                                                lu(from,1,16)| \
-                                                lu(from,2,8)|  \
-                                                lu(from,3,0)))
-#define __load_i32L(from)      ((long)(li(from,3,24)|  \
-                                       lu(from,2,16)|  \
-                                       lu(from,1,8)|   \
-                                       lu(from,0,0)))
-#define __load_i32M(from)      ((long)(li(from,0,24)|  \
-                                       lu(from,1,16)|  \
-                                       lu(from,2,8)|   \
-                                       lu(from,3,0)))
-
-#define su(to,i,v,s)           (((char*)(to))[i]=((unsigned long)(v)>>(s)))
-#define si(to,i,v,s)           (((char*)(to))[i]=((long)(v)>>(s)))
-
-#define __store_u16L(to,v)     (su(to,1,v,8),su(to,0,v,0))
-#define __store_u16M(to,v)     (su(to,0,v,8),su(to,1,v,0))
-#define __store_i16L(to,v)     (si(to,1,v,8),si(to,0,v,0))
-#define __store_i16M(to,v)     (si(to,0,v,8),si(to,1,v,0))
-
-#define __store_u32L(to,v)     (su(to,3,v,24), \
-                                su(to,2,v,16), \
-                                su(to,1,v,8),  \
-                                su(to,0,v,0))
-#define __store_u32M(to,v)     (su(to,0,v,24), \
-                                su(to,1,v,16), \
-                                su(to,2,v,8),  \
-                                su(to,3,v,0))
-#define __store_i32L(to,v)     (si(to,3,v,24), \
-                                si(to,2,v,16), \
-                                si(to,1,v,8),  \
-                                si(to,0,v,0))
-#define __store_i32M(to,v)     (si(to,0,v,24), \
-                                si(to,1,v,16), \
-                                si(to,2,v,8),  \
-                                si(to,3,v,0))
+#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)
+       /*@modifies *to @*/;
+extern void _elf_store_u64M(unsigned char *to, __libelf_u64_t v)
+       /*@modifies *to @*/;
+extern void _elf_store_i64L(unsigned char *to, __libelf_u64_t v)
+       /*@modifies *to @*/;
+extern void _elf_store_i64M(unsigned char *to, __libelf_u64_t v)
+       /*@modifies *to @*/;
+
+/*
+ * 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 */
index 48ae094..5c0f241 100755 (executable)
@@ -40,7 +40,10 @@ static const char rcsid[] = "@(#) Id: checksum.c,v 1.2 2001/10/01 22:30:10 micha
  */
 
 static int
-skip_section(Elf_Scn *scn, unsigned cls) {
+skip_section(Elf_Scn *scn, unsigned cls)
+       /*@globals _elf_errno @*/
+       /*@modifies _elf_errno @*/
+{
     if (cls == ELFCLASS32) {
        Elf32_Shdr *shdr = &scn->s_shdr32;
 
@@ -80,7 +83,9 @@ skip_section(Elf_Scn *scn, unsigned cls) {
 }
 
 static long
-add_bytes(unsigned char *ptr, size_t len) {
+add_bytes(unsigned char *ptr, size_t len)
+       /*@*/
+{
     long csum = 0;
 
     while (len--) {
@@ -90,7 +95,10 @@ add_bytes(unsigned char *ptr, size_t len) {
 }
 
 static long
-_elf_csum(Elf *elf) {
+_elf_csum(Elf *elf)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
     long csum = 0;
     Elf_Data *data;
     Elf_Scn *scn;
index c61d8d4..89c371c 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 cook.c - read and translate ELF files.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,23 +19,43 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: cook.c,v 1.17 2001/10/07 19:36:02 michael Exp ";
+#endif /* lint */
+
+/*@-fullinitblock@*/
 const Elf_Scn _elf_scn_init = INIT_SCN;
 const Scn_Data _elf_data_init = INIT_DATA;
+/*@=fullinitblock@*/
 
-const Elf_Type _elf_scn_types[SHT_NUM] = {
-    /* SHT_NULL */     ELF_T_BYTE,
-    /* SHT_PROGBITS */ ELF_T_BYTE,
-    /* SHT_SYMTAB */   ELF_T_SYM,
-    /* SHT_STRTAB */   ELF_T_BYTE,
-    /* SHT_RELA */     ELF_T_RELA,
-    /* SHT_HASH */     ELF_T_WORD,
-    /* SHT_DYNAMIC */  ELF_T_DYN,
-    /* SHT_NOTE */     ELF_T_BYTE,
-    /* SHT_NOBITS */   ELF_T_BYTE,
-    /* SHT_REL */      ELF_T_REL,
-    /* SHT_SHLIB */    ELF_T_BYTE,
-    /* SHT_DYNSYM */   ELF_T_SYM
-};
+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;
+#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:  \
@@ -44,8 +64,26 @@ const Elf_Type _elf_scn_types[SHT_NUM] = {
                    ((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;
+}
+
+/*@null@*/
 static char*
-_elf32_item(Elf *elf, Elf_Type type, unsigned n, size_t off, int *flag) {
+_elf_item(Elf *elf, Elf_Type type, size_t n, size_t off, int *flag)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, *flag, _elf_errno @*/
+{
     Elf_Data src, dst;
 
     *flag = 0;
@@ -58,15 +96,16 @@ _elf32_item(Elf *elf, Elf_Type type, unsigned n, size_t off, int *flag) {
 
     src.d_type = type;
     src.d_version = elf->e_version;
-    src.d_size = n * _fsize32(src.d_version, type);
+    src.d_size = n * _fsize(elf->e_class, src.d_version, type);
     elf_assert(src.d_size);
-    if (off + src.d_size > elf->e_size) {
+    if (off + src.d_size < off /* modulo overflow */
+     || off + src.d_size > elf->e_size) {
        seterr(truncerr(type));
        return NULL;
     }
 
     dst.d_version = _elf_version;
-    dst.d_size = n * _msize32(dst.d_version, type);
+    dst.d_size = n * _msize(elf->e_class, dst.d_version, type);
     elf_assert(dst.d_size);
 
     elf_assert(elf->e_data);
@@ -88,7 +127,7 @@ _elf32_item(Elf *elf, Elf_Type type, unsigned n, size_t off, int *flag) {
        src.d_buf = elf->e_data + off;
     }
 
-    if (elf32_xlatetom(&dst, &src, elf->e_encoding)) {
+    if (_elf_xlatetom(elf, &dst, &src)) {
        if (!*flag) {
            elf->e_cooked = 1;
        }
@@ -105,59 +144,118 @@ _elf32_item(Elf *elf, Elf_Type type, unsigned n, size_t off, int *flag) {
 #undef truncerr
 #undef memerr
 
+/*@-uniondef@*/
 static int
-_elf32_cook(Elf *elf) {
-    Elf_Scn *scn;
-    Elf32_Ehdr *ehdr;
-    Elf32_Shdr *shdr;
-    Scn_Data *sd;
-    unsigned i;
+_elf_cook_file(Elf *elf)
+       /*@globals _elf_errno, _elf_data_init, _elf_scn_init @*/
+       /*@modifies *elf, _elf_errno, _elf_data_init, _elf_scn_init @*/
+{
+    size_t num, off, align_addr;
     int flag;
 
-    elf->e_ehdr = _elf32_item(elf, ELF_T_EHDR, 1, 0, &flag);
-    if (!(ehdr = (Elf32_Ehdr*)elf->e_ehdr)) {
+    elf->e_ehdr = _elf_item(elf, ELF_T_EHDR, 1, 0, &flag);
+    if (!elf->e_ehdr) {
        return 0;
     }
     if (flag) {
        elf->e_free_ehdr = 1;
     }
-    if (ehdr->e_phnum && ehdr->e_phoff) {
-       elf->e_phdr = _elf32_item(elf, ELF_T_PHDR, ehdr->e_phnum, ehdr->e_phoff, &flag);
+    align_addr = _fsize(elf->e_class, elf->e_version, ELF_T_ADDR);
+    elf_assert(align_addr);
+    if (elf->e_class == ELFCLASS32) {
+       num = ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum;
+       off = ((Elf32_Ehdr*)elf->e_ehdr)->e_phoff;
+    }
+#if __LIBELF64
+    else if (elf->e_class == ELFCLASS64) {
+       num = ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum;
+       off = ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff;
+       /*
+        * 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 (num && off) {
+       if (off % align_addr) {
+           seterr(ERROR_ALIGN_PHDR);
+           return 0;
+       }
+       elf->e_phdr = _elf_item(elf, ELF_T_PHDR, num, off, &flag);
        if (!elf->e_phdr) {
            return 0;
        }
        if (flag) {
            elf->e_free_phdr = 1;
        }
-       elf->e_phnum = ehdr->e_phnum;
+       elf->e_phnum = num;
     }
-    if (ehdr->e_shnum && ehdr->e_shoff) {
-       Elf_Data src, dst;
+    if (elf->e_class == ELFCLASS32) {
+       num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum;
+       off = ((Elf32_Ehdr*)elf->e_ehdr)->e_shoff;
+    }
+#if __LIBELF64
+    else if (elf->e_class == ELFCLASS64) {
+       num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum;
+       off = ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff;
+       /*
+        * 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 */
+    /* we already had this
+    else {
+       seterr(ERROR_UNIMPLEMENTED);
+       return 0;
+    }
+    */
+    if (num && off) {
        struct tmp {
            Elf_Scn     scn;
            Scn_Data    data;
        } *head;
+       Elf_Data src, dst;
+       Elf_Scn *scn;
+       Scn_Data *sd;
+       unsigned i;
+
+       if (off % align_addr) {
+           seterr(ERROR_ALIGN_SHDR);
+           return 0;
+       }
+       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 = _fsize32(src.d_version, ELF_T_SHDR);
+       src.d_size = _fsize(elf->e_class, src.d_version, ELF_T_SHDR);
        elf_assert(src.d_size);
        dst.d_version = EV_CURRENT;
 
-       if (ehdr->e_shoff < 0 || ehdr->e_shoff > elf->e_size) {
-           seterr(ERROR_OUTSIDE);
-           return 0;
-       }
-       if (ehdr->e_shoff + ehdr->e_shnum * src.d_size > elf->e_size) {
+       if (off + num * src.d_size < off /* modulo overflow */
+        || off + num * src.d_size > elf->e_size) {
            seterr(ERROR_TRUNC_SHDR);
            return 0;
        }
 
-       if (!(head = (struct tmp*)malloc(ehdr->e_shnum * sizeof(*head)))) {
+       if (!(head = (struct tmp*)malloc(num * sizeof(struct tmp)))) {
            seterr(ERROR_MEM_SCN);
            return 0;
        }
-       for (scn = NULL, i = ehdr->e_shnum; i-- > 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;
@@ -168,38 +266,64 @@ _elf32_cook(Elf *elf) {
            sd = &head[i].data;
 
            if (elf->e_rawdata) {
-               src.d_buf = elf->e_rawdata + ehdr->e_shoff + i * src.d_size;
+               src.d_buf = elf->e_rawdata + off + i * src.d_size;
            }
            else {
-               src.d_buf = elf->e_data + ehdr->e_shoff + i * src.d_size;
+               src.d_buf = elf->e_data + off + i * src.d_size;
            }
-           dst.d_buf = shdr = &scn->s_shdr32;
-           dst.d_size = sizeof(Elf32_Shdr);
-           if (!(elf32_xlatetom(&dst, &src, elf->e_encoding))) {
+           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 == sizeof(Elf32_Shdr));
+           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;
-           scn->s_type = shdr->sh_type;
-           scn->s_size = shdr->sh_size;
-           scn->s_offset = shdr->sh_offset;
 
            sd->sd_scn = scn;
-           if (valid_scntype(shdr->sh_type)) {
-               sd->sd_data.d_type = _elf_scn_types[shdr->sh_type];
+
+           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;
            }
+#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;
+               }
+           }
+#endif /* __LIBELF64 */
+           /* we already had this
            else {
-               sd->sd_data.d_type = ELF_T_BYTE;
+               seterr(ERROR_UNIMPLEMENTED);
+               return 0;
            }
-           sd->sd_data.d_size = shdr->sh_size;
-           sd->sd_data.d_align = shdr->sh_addralign;
+           */
+
+           sd->sd_data.d_type = _elf_scn_type(scn->s_type);
+           sd->sd_data.d_size = scn->s_size;
            sd->sd_data.d_version = _elf_version;
        }
        elf_assert(scn == &head[0].scn);
@@ -208,6 +332,7 @@ _elf32_cook(Elf *elf) {
     }
     return 1;
 }
+/*@=uniondef@*/
 
 int
 _elf_cook(Elf *elf) {
@@ -223,11 +348,8 @@ _elf_cook(Elf *elf) {
     else if (!valid_encoding(elf->e_encoding)) {
        seterr(ERROR_UNKNOWN_ENCODING);
     }
-    else if (elf->e_class == ELFCLASS32) {
-       return _elf32_cook(elf);
-    }
     else if (valid_class(elf->e_class)) {
-       seterr(ERROR_UNIMPLEMENTED);
+       return _elf_cook_file(elf);
     }
     else {
        seterr(ERROR_UNKNOWN_CLASS);
index 5771fd3..951978c 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 end.c - implementation of the elf_end(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2000 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,19 +19,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: end.c,v 1.7 2000/03/26 03:00:20 michael Exp ";
+#endif /* lint */
+
 #if HAVE_MMAP
 #include <sys/mman.h>
-#endif
+#endif /* HAVE_MMAP */
 
 static void
-_elf_free(void *ptr) {
+_elf_free(/*@only@*/ /*@null@*/ void *ptr)
+       /*@modifies *ptr @*/
+{
     if (ptr) {
        free(ptr);
     }
 }
 
 static void
-_elf_free_scns(Elf *elf, Elf_Scn *scn) {
+_elf_free_scns(/*@unused@*/ Elf *elf, Elf_Scn *scn)
+       /*@modifies *scn @*/
+{
     Scn_Data *sd, *tmp;
     Elf_Scn *freescn;
 
@@ -39,6 +47,8 @@ _elf_free_scns(Elf *elf, Elf_Scn *scn) {
        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);
@@ -48,6 +58,8 @@ _elf_free_scns(Elf *elf, Elf_Scn *scn) {
            }
        }
        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);
            }
@@ -92,8 +104,8 @@ elf_end(Elf *elf) {
     else if (elf->e_unmap_data) {
        munmap(elf->e_data, elf->e_size);
     }
-#endif
-    else {
+#endif /* HAVE_MMAP */
+    else if (!elf->e_memory) {
        _elf_free(elf->e_data);
     }
     _elf_free_scns(elf, elf->e_scn_1);
index 2414a08..e922af7 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 errmsg.c - implementation of the elf_errmsg(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 1999 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,28 +19,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: errmsg.c,v 1.6 2000/03/31 18:02:55 michael Exp ";
+#endif /* lint */
+
 #if HAVE_GETTEXT
 # undef HAVE_CATGETS
 # include <libintl.h>
-#else
+#else /* HAVE_GETTEXT */
 # define dgettext(dom, str) str
-#endif
+#endif /* HAVE_GETTEXT */
 
 #if HAVE_CATGETS
 # include <nl_types.h>
+/*@unchecked@*/
 static nl_catd _libelf_cat = (nl_catd)0;
-#endif
+#endif /* HAVE_CATGETS */
 
 #if HAVE_GETTEXT || HAVE_CATGETS
+/*@unchecked@*/ /*@observer@*/
 static const char domain[] = "libelf";
-#endif
+#endif /* HAVE_GETTEXT || HAVE_CATGETS */
 
+/*@unchecked@*/ /*@observer@*/
+#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__
 };
 
+/*@-moduncon@*/
 const char*
 elf_errmsg(int err) {
     if (err == 0) {
@@ -64,6 +76,9 @@ elf_errmsg(int err) {
     if (_libelf_cat != (nl_catd)-1) {
        return catgets(_libelf_cat, 1, err + 1, _messages[err]);
     }
-#endif
+#endif /* HAVE_CATGETS */
+/*@-nullpass@*/
     return dgettext(domain, _messages[err]);
+/*@=nullpass@*/
 }
+/*@=moduncon@*/
index 5811799..f647438 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 flag.c - implementation of the elf_flag*(3) functions.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,8 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: flag.c,v 1.3 1998/06/12 19:42:23 michael Exp ";
+#endif /* lint */
+
 static unsigned
-_elf_flag(unsigned *f, Elf_Cmd cmd, unsigned flags) {
+_elf_flag(unsigned *f, Elf_Cmd cmd, unsigned flags)
+       /*@globals _elf_errno @*/
+       /*@modifies *f, _elf_errno @*/
+{
     if (cmd == ELF_C_SET) {
        return *f |= flags;
     }
index a1494a1..018da7b 100755 (executable)
@@ -97,52 +97,89 @@ typedef Elf64_Syminfo GElf_Syminfo;
 /*
  * 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));
+extern int             gelf_getclass __P((Elf *elf))
+       /*@*/;
+
+extern size_t             gelf_fsize __P((Elf *elf, Elf_Type type, size_t count, unsigned ver))
+       /*@*/;
+
+/*@null@*/
+extern Elf_Data       *gelf_xlatetof __P((Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode))
+       /*@modifies *dst @*/;
+/*@null@*/
+extern Elf_Data       *gelf_xlatetom __P((Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode))
+       /*@modifies *dst @*/;
+
+/*@null@*/
+extern GElf_Ehdr       *gelf_getehdr __P((Elf *elf, /*@returned@*/ GElf_Ehdr *dst))
+       /*@modifies *elf, dst @*/;
+extern int          gelf_update_ehdr __P((Elf *elf, GElf_Ehdr *src))
+       /*@modifies *elf @*/;
+extern unsigned long    gelf_newehdr __P((Elf *elf, int cls))
+       /*@modifies *elf @*/;
+
+/*@null@*/
+extern GElf_Phdr       *gelf_getphdr __P((Elf *elf, int ndx, /*@returned@*/ GElf_Phdr *dst))
+       /*@modifies *elf, dst @*/;
+extern int          gelf_update_phdr __P((Elf *elf, int ndx, GElf_Phdr *src))
+       /*@modifies *elf @*/;
+extern unsigned long    gelf_newphdr __P((Elf *elf, size_t phnum))
+       /*@modifies *elf @*/;
+
+/*@null@*/
+extern GElf_Shdr       *gelf_getshdr __P((Elf_Scn *scn, /*@returned@*/ GElf_Shdr *dst))
+       /*@modifies dst @*/;
+extern int          gelf_update_shdr __P((Elf_Scn *scn, GElf_Shdr *src))
+       /*@modifies scn @*/;
+
+/*@null@*/
+extern GElf_Dyn         *gelf_getdyn __P((Elf_Data *src, int ndx, /*@returned@*/ GElf_Dyn *dst))
+       /*@modifies *dst @*/;
+extern int           gelf_update_dyn __P((Elf_Data *dst, int ndx, GElf_Dyn *src))
+       /*@modifies *dst @*/;
+
+/*@null@*/
+extern GElf_Rel         *gelf_getrel __P((Elf_Data *src, int ndx, /*@returned@*/ GElf_Rel *dst))
+       /*@modifies *dst @*/;
+extern int           gelf_update_rel __P((Elf_Data *dst, int ndx, GElf_Rel *src))
+       /*@modifies *dst @*/;
+
+/*@null@*/
+extern GElf_Rela       *gelf_getrela __P((Elf_Data *src, int ndx, /*@returned@*/ GElf_Rela *dst))
+       /*@modifies *dst @*/;
+extern int          gelf_update_rela __P((Elf_Data *dst, int ndx, GElf_Rela *src))
+       /*@modifies *dst @*/;
+
+/*@null@*/
+extern GElf_Sym         *gelf_getsym __P((Elf_Data *src, int ndx, /*@returned@*/ GElf_Sym *dst))
+       /*@modifies *dst @*/;
+extern int           gelf_update_sym __P((Elf_Data *dst, int ndx, GElf_Sym *src))
+       /*@modifies *dst @*/;
+
+extern long            gelf_checksum __P((Elf *elf))
+       /*@modifies *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));
  */
+#if 0
+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))
+       /*@modifies *dst @*/;
+
+extern GElf_Syminfo* gelf_getsyminfo __P((Elf_Data *src, int ndx, GElf_Syminfo *dst))
+       /*@modifies *dst @*/;
+extern int       gelf_update_syminfo __P((Elf_Data *dst, int ndx, GElf_Syminfo *src))
+       /*@modifies *dst @*/;
+#endif
 
 /*
  * Extensions (not available in other versions of libelf)
  */
-extern size_t             gelf_msize __P((Elf *__elf, Elf_Type __type, size_t __count, unsigned __ver));
+extern size_t             gelf_msize __P((Elf *elf, Elf_Type type, size_t count, unsigned ver))
+       /*@*/;
 
 #endif /* __LIBELF64 */
 
index 7a265b9..3724aa6 100755 (executable)
@@ -56,8 +56,12 @@ static const char rcsid[] = "@(#) Id: gelftrans.c,v 1.6 2001/10/07 19:33:03 mich
 # define ELF64_R_INFO(s,t)     (((Elf64_Xword)(s)<<32)+((t)&0xffffffffL))
 #endif /* !defined(...) */
 
+/*@dependent@*/ /*@null@*/
 static char*
-get_addr_and_class(const Elf_Data *data, int ndx, Elf_Type type, unsigned *cls) {
+get_addr_and_class(const Elf_Data *data, int ndx, Elf_Type type, unsigned *cls)
+       /*@globals _elf_errno @*/
+       /*@modifies *cls, _elf_errno @*/
+{
     Scn_Data *sd = (Scn_Data*)data;
     Elf_Scn *scn;
     Elf *elf;
index f492b97..6b2f6f3 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 getarsym.c - implementation of the elf_getarsym(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -20,6 +20,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #include <private.h>
 #include <byteswap.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: getarsym.c,v 1.3 1998/06/12 19:42:24 michael Exp ";
+#endif /* lint */
+
+/*@-bounds@*/
 Elf_Arsym*
 elf_getarsym(Elf *elf, size_t *ptr) {
     Elf_Arsym *syms;
@@ -81,3 +86,4 @@ elf_getarsym(Elf *elf, size_t *ptr) {
     *ptr = elf->e_symlen;
     return (Elf_Arsym*)elf->e_symtab;
 }
+/*@=bounds@*/
index fb6be91..324bc05 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 getdata.c - implementation of the elf_getdata(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,23 +19,56 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: getdata.c,v 1.9 2001/10/07 04:39:50 michael Exp ";
+#endif /* lint */
+
+/*@null@*/
 static Elf_Data*
-_elf32_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) {
-    Elf_Data src, dst;
-    size_t fsize, msize;
+_elf_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, *sd, _elf_errno @*/
+{
+    Elf_Data dst;
+    Elf_Data src;
     int flag = 0;
+    size_t dlen;
+
+    elf_assert(elf->e_data);
 
-    src = dst = sd->sd_data;
+    /*
+     * Prepare source
+     */
+    src = sd->sd_data;
     src.d_version = elf->e_version;
-    fsize = _fsize32(src.d_version, src.d_type);
-    elf_assert(fsize);
-    msize = _msize32(dst.d_version, src.d_type);
-    elf_assert(msize);
-    if (fsize != msize) {
-       dst.d_size = (dst.d_size / fsize) * msize;
+    if (elf->e_rawdata) {
+       src.d_buf = elf->e_rawdata + scn->s_offset;
+    }
+    else {
+       src.d_buf = elf->e_data + scn->s_offset;
     }
 
-    elf_assert(elf->e_data);
+    /*
+     * 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;
     }
@@ -47,20 +80,16 @@ _elf32_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) {
        flag = 1;
     }
 
-    if (elf->e_rawdata) {
-       src.d_buf = elf->e_rawdata + scn->s_offset;
-    }
-    else {
-       src.d_buf = elf->e_data + scn->s_offset;
-    }
-
-    if (elf32_xlatetom(&dst, &src, elf->e_encoding)) {
+    /*
+     * 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 (Elf_Data*)sd;
+       return &sd->sd_data;
     }
 
     if (flag) {
@@ -71,7 +100,7 @@ _elf32_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) {
 
 Elf_Data*
 elf_getdata(Elf_Scn *scn, Elf_Data *data) {
-    Scn_Data *sd = (Scn_Data*)data;
+    Scn_Data *sd;
     Elf *elf;
 
     if (!scn) {
@@ -81,45 +110,48 @@ elf_getdata(Elf_Scn *scn, Elf_Data *data) {
     if (scn->s_index == SHN_UNDEF) {
        seterr(ERROR_NULLSCN);
     }
-    else if (sd) {
-       if (sd->sd_scn == scn) {
-           /*
-            * sd_link allocated by elf_newdata().
-            */
-           return (Elf_Data*)sd->sd_link;
+    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 (Elf_Data*)sd;
+           return &sd->sd_data;
        }
        else if (scn->s_type == SHT_NULL) {
            seterr(ERROR_NULLSCN);
        }
        else if (sd->sd_memdata) {
            /* already cooked */
-           return (Elf_Data*)sd;
+           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 (Elf_Data*)sd;
+           return &sd->sd_data;
        }
        else if (scn->s_offset + scn->s_size > elf->e_size) {
            seterr(ERROR_TRUNC_SCN);
        }
-       else if (elf->e_class == ELFCLASS32) {
-           return _elf32_cook_scn(elf, scn, sd);
-       }
        else if (valid_class(elf->e_class)) {
-           seterr(ERROR_UNIMPLEMENTED);
+           return _elf_cook_scn(elf, scn, sd);
        }
        else {
            seterr(ERROR_UNKNOWN_CLASS);
index ed8b40d..986e03a 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 input.c - low-level input for libelf.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,9 +19,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: input.c,v 1.6 2001/10/15 21:38:29 michael Exp ";
+#endif /* lint */
+
 #if HAVE_MMAP
 #include <sys/mman.h>
-#endif
+#endif /* HAVE_MMAP */
 
 void*
 _elf_read(Elf *elf, void *buffer, size_t off, size_t len) {
@@ -35,7 +39,7 @@ _elf_read(Elf *elf, void *buffer, size_t off, size_t len) {
     }
     else if (len) {
        off += elf->e_base;
-       if (lseek(elf->e_fd, off, 0) != (off_t)off) {
+       if (lseek(elf->e_fd, (off_t)off, SEEK_SET) != (off_t)off) {
            seterr(ERROR_IO_SEEK);
        }
        else if (!(tmp = buffer) && !(tmp = malloc(len))) {
@@ -43,9 +47,11 @@ _elf_read(Elf *elf, void *buffer, size_t off, size_t len) {
        }
        else if (read(elf->e_fd, tmp, len) != (int)len) {
            seterr(ERROR_IO_READ);
+/*@-temptrans@*/
            if (tmp != buffer) {
                free(tmp);
            }
+/*@=temptrans@*/
        }
        else {
            return tmp;
@@ -72,6 +78,6 @@ _elf_mmap(Elf *elf) {
            return tmp;
        }
     }
-#endif
+#endif /* HAVE_MMAP */
     return NULL;
 }
index 7d09150..73436c1 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 libelf.h - public header file for libelf.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -17,6 +17,8 @@ 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: libelf.h,v 1.10 2001/10/05 19:05:25 michael Exp  */
+
 #ifndef _LIBELF_H
 #define _LIBELF_H
 
@@ -24,21 +26,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #if __LIBELF_INTERNAL__
 #include <sys_elf.h>
-#else
+#else /* __LIBELF_INTERNAL__ */
 #include <libelf/sys_elf.h>
-#endif
+#endif /* __LIBELF_INTERNAL__ */
 
 #ifdef __cplusplus
 extern "C" {
-#endif
+#endif /* __cplusplus */
 
 #ifndef __P
 # if __STDC__ || defined(__cplusplus)
 #  define __P(args) args
-# else
+# else /* __STDC__ || defined(__cplusplus) */
 #  define __P(args) ()
-# endif
-#endif
+# endif /* __STDC__ || defined(__cplusplus) */
+#endif /* __P */
 
 /*
  * Commands
@@ -58,8 +60,8 @@ typedef enum {
 /*
  * Flags
  */
-#define        ELF_F_DIRTY     0x1
-#define        ELF_F_LAYOUT    0x4
+#define ELF_F_DIRTY    0x1
+#define ELF_F_LAYOUT   0x4
 
 /*
  * File types
@@ -89,6 +91,21 @@ typedef enum {
     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;
 
@@ -106,12 +123,14 @@ typedef struct Elf_Scn    Elf_Scn;
  * Archive member header
  */
 typedef struct {
+/*@dependent@*/
     char*              ar_name;
     time_t             ar_date;
     long               ar_uid;
     long               ar_gid;
     unsigned long      ar_mode;
     off_t              ar_size;
+/*@dependent@*/
     char*              ar_rawname;
 } Elf_Arhdr;
 
@@ -119,6 +138,7 @@ typedef struct {
  * Archive symbol table
  */
 typedef struct {
+/*@dependent@*/
     char*              as_name;
     size_t             as_off;
     unsigned long      as_hash;
@@ -128,6 +148,7 @@ typedef struct {
  * Data descriptor
  */
 typedef struct {
+/*@relnull@*/
     void*              d_buf;
     Elf_Type           d_type;
     size_t             d_size;
@@ -139,64 +160,175 @@ typedef struct {
 /*
  * Function declarations
  */
-extern Elf *elf_begin __P((int __fd, Elf_Cmd __cmd, Elf *__ref));
-extern int elf_cntl __P((Elf *__elf, Elf_Cmd __cmd));
-extern int elf_end __P((Elf *__elf));
-extern const char *elf_errmsg __P((int __err));
-extern int elf_errno __P((void));
-extern void elf_fill __P((int __fill));
-extern unsigned elf_flagdata __P((Elf_Data *__data, Elf_Cmd __cmd,
-       unsigned __flags));
-extern unsigned elf_flagehdr __P((Elf *__elf, Elf_Cmd __cmd,
-       unsigned __flags));
-extern unsigned elf_flagelf __P((Elf *__elf, Elf_Cmd __cmd,
-       unsigned __flags));
-extern unsigned elf_flagphdr __P((Elf *__elf, Elf_Cmd __cmd,
-       unsigned __flags));
-extern unsigned elf_flagscn __P((Elf_Scn *__scn, Elf_Cmd __cmd,
-       unsigned __flags));
-extern unsigned elf_flagshdr __P((Elf_Scn *__scn, Elf_Cmd __cmd,
-       unsigned __flags));
-extern size_t elf32_fsize __P((Elf_Type __type, size_t __count,
-       unsigned __ver));
-extern Elf_Arhdr *elf_getarhdr __P((Elf *__elf));
-extern Elf_Arsym *elf_getarsym __P((Elf *__elf, size_t *__ptr));
-extern off_t elf_getbase __P((Elf *__elf));
-extern Elf_Data *elf_getdata __P((Elf_Scn *__scn, Elf_Data *__data));
-extern Elf32_Ehdr *elf32_getehdr __P((Elf *__elf));
-extern char *elf_getident __P((Elf *__elf, size_t *__ptr));
-extern Elf32_Phdr *elf32_getphdr __P((Elf *__elf));
-extern Elf_Scn *elf_getscn __P((Elf *__elf, size_t __index));
-extern Elf32_Shdr *elf32_getshdr __P((Elf_Scn *__scn));
-extern unsigned long elf_hash __P((const char *__name));
-extern Elf_Kind elf_kind __P((Elf *__elf));
-extern size_t elf_ndxscn __P((Elf_Scn *__scn));
-extern Elf_Data *elf_newdata __P((Elf_Scn *__scn));
-extern Elf32_Ehdr *elf32_newehdr __P((Elf *__elf));
-extern Elf32_Phdr *elf32_newphdr __P((Elf *__elf, size_t __count));
-extern Elf_Scn *elf_newscn __P((Elf *__elf));
-extern Elf_Cmd elf_next __P((Elf *__elf));
-extern Elf_Scn *elf_nextscn __P((Elf *__elf, Elf_Scn *__scn));
-extern size_t elf_rand __P((Elf *__elf, size_t __offset));
-extern Elf_Data *elf_rawdata __P((Elf_Scn *__scn, Elf_Data *__data));
-extern char *elf_rawfile __P((Elf *__elf, size_t *__ptr));
-extern char *elf_strptr __P((Elf *__elf, size_t __section, size_t __offset));
-extern off_t elf_update __P((Elf *__elf, Elf_Cmd __cmd));
-extern unsigned elf_version __P((unsigned __ver));
-extern Elf_Data *elf32_xlatetof __P((Elf_Data *__dst, const Elf_Data *__src,
-       unsigned __encode));
-extern Elf_Data *elf32_xlatetom __P((Elf_Data *__dst, const Elf_Data *__src,
-       unsigned __encode));
+/*@only@*/ /*@null@*/
+extern Elf *elf_begin __P((int fd, Elf_Cmd cmd, /*@returned@*/ /*@null@*/ Elf *ref))
+       /*@modifies *ref @*/;
+/*@null@*/
+extern Elf *elf_memory __P((char *image, size_t size))
+       /*@*/;
+extern int elf_cntl __P((/*@null@*/ Elf *elf, Elf_Cmd cmd))
+       /*@modifies *elf @*/;
+extern int elf_end __P((/*@only@*/ /*@null@*/ Elf *elf))
+       /*@globals fileSystem @*/
+       /*@modifies elf, fileSystem @*/;
+/*@null@*/
+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))
+       /*@modifies *elf @*/;
+extern unsigned elf_flagelf __P((Elf *elf, Elf_Cmd cmd,
+       unsigned flags))
+       /*@modifies *elf @*/;
+extern unsigned elf_flagphdr __P((Elf *elf, Elf_Cmd cmd,
+       unsigned flags))
+       /*@modifies *elf @*/;
+extern unsigned elf_flagscn __P((Elf_Scn *scn, Elf_Cmd cmd,
+       unsigned flags))
+       /*@modifies *scn @*/;
+extern unsigned elf_flagshdr __P((Elf_Scn *scn, Elf_Cmd cmd,
+       unsigned flags))
+       /*@modifies *scn @*/;
+extern size_t elf32_fsize __P((Elf_Type type, size_t count,
+       unsigned ver))
+       /*@*/;
+/*@null@*/
+extern Elf_Arhdr *elf_getarhdr __P((Elf *elf))
+       /*@*/;
+/*@null@*/
+extern Elf_Arsym *elf_getarsym __P((Elf *elf, size_t *ptr))
+       /*@modifies *elf, *ptr @*/;
+extern off_t elf_getbase __P((Elf *elf))
+       /*@*/;
+/*@null@*/
+extern Elf_Data *elf_getdata __P((Elf_Scn *scn, /*@null@*/ Elf_Data *data))
+       /*@modifies *scn @*/;
+/*@null@*/
+extern Elf32_Ehdr *elf32_getehdr __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern char *elf_getident __P((Elf *elf, size_t *ptr))
+       /*@modifies *elf, *ptr @*/;
+/*@null@*/
+extern Elf32_Phdr *elf32_getphdr __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf_Scn *elf_getscn __P((Elf *elf, size_t index))
+       /*@modifies *elf @*/;
+/*@null@*/
+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))
+       /*@*/;
+/*@null@*/
+extern Elf_Data *elf_newdata __P((Elf_Scn *scn))
+       /*@modifies *scn @*/;
+/*@null@*/
+extern Elf32_Ehdr *elf32_newehdr __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf32_Phdr *elf32_newphdr __P((Elf *elf, size_t count))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf_Scn *elf_newscn __P((Elf *elf))
+       /*@modifies *elf @*/;
+extern Elf_Cmd elf_next __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf_Scn *elf_nextscn __P((Elf *elf, Elf_Scn *scn))
+       /*@modifies *elf @*/;
+extern size_t elf_rand __P((Elf *elf, size_t offset))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf_Data *elf_rawdata __P((Elf_Scn *scn, Elf_Data *data))
+       /*@modifies *scn @*/;
+/*@null@*/
+extern char *elf_rawfile __P((Elf *elf, size_t *ptr))
+       /*@modifies *elf, *ptr @*/;
+/*@dependent@*/ /*@null@*/
+extern char *elf_strptr __P((Elf *elf, size_t section, size_t offset))
+       /*@modifies elf @*/;
+extern off_t elf_update __P((Elf *elf, Elf_Cmd cmd))
+       /*@globals fileSystem @*/
+       /*@modifies elf, fileSystem @*/;
+extern unsigned elf_version __P((unsigned ver))
+       /*@globals internalState @*/
+       /*@modifies internalState @*/;
+/*@null@*/
+extern Elf_Data *elf32_xlatetof __P((/*@returned@*/ Elf_Data *dst, const Elf_Data *src,
+       unsigned encode))
+       /*@modifies *dst @*/;
+/*@null@*/
+extern Elf_Data *elf32_xlatetom __P((/*@returned@*/ Elf_Data *dst, const Elf_Data *src,
+       unsigned encode))
+       /*@modifies *dst @*/;
+
+/*
+ * Additional functions found on Solaris
+ */
+extern long elf32_checksum __P((Elf *elf))
+       /*@modifies *elf @*/;
+
+#if __LIBELF64
+/*
+ * 64-bit ELF functions
+ * Not available on all platforms
+ */
+/*@null@*/
+extern Elf64_Ehdr *elf64_getehdr __P((Elf *elf))
+       /*@*/;
+/*@null@*/
+extern Elf64_Ehdr *elf64_newehdr __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf64_Phdr *elf64_getphdr __P((Elf *elf))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf64_Phdr *elf64_newphdr __P((Elf *elf, size_t count))
+       /*@modifies *elf @*/;
+/*@null@*/
+extern Elf64_Shdr *elf64_getshdr __P((Elf_Scn *scn))
+       /*@*/;
+extern size_t elf64_fsize __P((Elf_Type type, size_t count,
+       unsigned ver))
+       /*@*/;
+/*@null@*/
+extern Elf_Data *elf64_xlatetof __P((/*@returned@*/ Elf_Data *dst, const Elf_Data *src,
+       unsigned encode))
+       /*@modifies *dst @*/;
+/*@null@*/
+extern Elf_Data *elf64_xlatetom __P((/*@returned@*/ Elf_Data *dst, const Elf_Data *src,
+       unsigned encode))
+       /*@modifies *dst @*/;
+
+/*
+ * Additional functions found on Solaris
+ */
+extern long elf64_checksum __P((Elf *elf))
+       /*@modifies *elf @*/;
+
+#endif /* __LIBELF64 */
 
 /*
- * More function declarations
- * These functions are NOT available
- * in the SYSV version of libelf!
+ * More function declarations.  These functions are NOT available in
+ * the SYSV/Solaris versions of libelf!
  */
-extern size_t elf_delscn __P((Elf *__elf, Elf_Scn *__scn));
+extern size_t elf_delscn __P((Elf *elf, /*@only@*/ Elf_Scn *scn))
+       /*@modifies *elf, scn @*/;
 
 #ifdef __cplusplus
 }
-#endif
+#endif /* __cplusplus */
 
 #endif /* _LIBELF_H */
index 8963e02..5ab1b64 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 newscn.c - implementation of the elf_newscn(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,8 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: newscn.c,v 1.5 1998/06/12 19:42:32 michael Exp ";
+#endif /* lint */
+
+/*@null@*/
 static Elf_Scn*
-_buildscn(Elf *elf) {
+_buildscn(Elf *elf)
+       /*@globals _elf_errno, _elf_scn_init @*/
+       /*@modifies *elf, _elf_errno, _elf_scn_init @*/
+{
     Elf_Scn *scn;
 
     elf_assert(elf);
@@ -46,7 +54,10 @@ _buildscn(Elf *elf) {
 }
 
 Elf_Scn*
-elf_newscn(Elf *elf) {
+elf_newscn(Elf *elf)
+       /*@globals _elf_errno, _elf_scn_init @*/
+       /*@modifies _elf_errno, _elf_scn_init @*/
+{
     Elf_Scn *scn;
 
     if (!elf) {
@@ -70,6 +81,16 @@ elf_newscn(Elf *elf) {
        elf->e_ehdr_flags |= ELF_F_DIRTY;
        return scn;
     }
+#if __LIBELF64
+    else if (elf->e_class == ELFCLASS64) {
+       if (!(scn = _buildscn(elf))) {
+           return NULL;
+       }
+       ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum = scn->s_index + 1;
+       elf->e_ehdr_flags |= ELF_F_DIRTY;
+       return scn;
+    }
+#endif /* __LIBELF64 */
     else if (valid_class(elf->e_class)) {
        seterr(ERROR_UNIMPLEMENTED);
     }
index 49bedb3..fc7f58c 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 nlist.c - implementation of the nlist(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2002 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,125 +19,211 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 #include <nlist.h>
+
+#ifndef lint
+static const char rcsid[] = "@(#) Id: nlist.c,v 1.7 2002/06/11 18:53:55 michael Exp ";
+#endif /* lint */
+
+#if HAVE_FCNTL_H
 #include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
+
+#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;
-    Elf32_Sym*         sym;
+    unsigned           next;
 };
 
+/*@null@*/
+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)
+       /*@modifies *np @*/
+{
+    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) {
+_elf_nlist(Elf *elf, struct nlist *nl)
+       /*@modifies *elf, *nl @*/
+{
+    unsigned first[PRIME];
     Elf_Scn *symtab = NULL;
     Elf_Scn *strtab = NULL;
     Elf_Data *symdata;
     Elf_Data *strdata;
-    Elf32_Ehdr *ehdr;
-    Elf32_Shdr *shdr;
-    Elf_Scn *scn;
-    Elf32_Sym *symbols;
-    const char *strings;
-    unsigned nsymbols;
-    unsigned nstrings;
-    unsigned i;
+    size_t symsize;
+    size_t nsymbols;
     const char *name;
     struct hash *table;
-    unsigned nhash;
     unsigned long hash;
-    unsigned long j;
+    unsigned i;
+    struct nlist *np;
 
-    if (!(ehdr = elf32_getehdr(elf))) {
+    /*
+     * 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;
     }
-    scn = NULL;
-    elf_errno();
-    while ((scn = elf_nextscn(elf, scn))) {
-       if (!(shdr = elf32_getshdr(scn))) {
-           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 (shdr->sh_type != SHT_SYMTAB && shdr->sh_type != SHT_DYNSYM) {
-           continue;
+       if (symtab->s_type == SHT_DYNSYM) {
+           strtab = symtab;
        }
-       symtab = scn;
-       strtab = elf_getscn(elf, shdr->sh_link);
-       if (shdr->sh_type == SHT_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 (elf_errno()) {
+    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;
     }
-    symbols = (Elf32_Sym*)symdata->d_buf;
-    strings = (const char*)strdata->d_buf;
-    nsymbols = symdata->d_size / sizeof(Elf32_Sym);
-    nstrings = strdata->d_size;
-    if (!symbols || !strings || !nsymbols || !nstrings) {
+    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
+     * Build a simple hash table.
      */
-    nhash = 3 * nsymbols - 4;
-    if (!(table = (struct hash*)malloc(nhash * sizeof(*table)))) {
+    if (!(table = (struct hash*)malloc(nsymbols * sizeof(*table)))) {
        return -1;
     }
-    for (i = 0; i < nhash; i++) {
+    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++) {
-       if (symbols[i].st_name < 0 || symbols[i].st_name >= nstrings) {
+       name = symbol_name(elf, symdata->d_buf, strdata->d_buf,
+                          strdata->d_size, i);
+       if (name == NULL) {
            free(table);
            return -1;
        }
-       if (symbols[i].st_name == 0) {
-           continue;
-       }
-       name = strings + symbols[i].st_name;
-       hash = elf_hash(name);
-       for (j = hash; table[j %= nhash].name; j += 3) {
-           if (table[j].hash != hash) {
-               continue;
-           }
-           if (table[j].name == name || !strcmp(table[j].name, name)) {
-               break;
-           }
+       if (*name != '\0') {
+           table[i].name = name;
+           table[i].hash = elf_hash(name);
+           hash = table[i].hash % PRIME;
+           table[i].next = first[hash];
+           first[hash] = i;
        }
-       table[j].hash = hash;
-       table[j].name = name;
-       table[j].sym = &symbols[i];
     }
 
     /*
-     * symbol lookup
+     * Lookup symbols, one by one.
      */
-    for (i = 0; (name = nl[i].n_name) && *name; i++) {
+    for (np = nl; (name = np->n_name) && *name; np++) {
        hash = elf_hash(name);
-       for (j = hash; table[j %= nhash].name; j += 3) {
-           if (table[j].hash == hash && !strcmp(table[j].name, name)) {
-               break;
+       for (i = first[hash % PRIME]; i; i = table[i].next) {
+           if (table[i].hash == hash && !strcmp(table[i].name, name)) {
+               /*@innerbreak@*/ break;
            }
        }
-       if (table[j].name) {
-           nl[i].n_value = table[j].sym->st_value;
-           nl[i].n_scnum = table[j].sym->st_shndx;
+       if (i) {
+           copy_symbol(elf, np, symdata->d_buf, i);
        }
        else {
-           nl[i].n_value = 0;
-           nl[i].n_scnum = 0;
+           np->n_value = 0;
+           np->n_scnum = 0;
+           np->n_type = 0;
+           np->n_sclass = 0;
+           np->n_numaux = 0;
        }
-       /*
-        * this needs more work
-        */
-       nl[i].n_type = 0;
-       nl[i].n_sclass = 0;
-       nl[i].n_numaux = 0;
     }
     free(table);
     return 0;
@@ -151,7 +237,7 @@ nlist(const char *filename, struct nlist *nl) {
     int fd;
 
     if ((oldver = elf_version(EV_CURRENT)) != EV_NONE) {
-       if ((fd = open(filename, O_RDONLY)) != -1) {
+       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);
index 8514f90..1317b7e 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 nlist.h - public header file for nlist(3).
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 1998 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -17,12 +17,14 @@ 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: nlist.h,v 1.3 1998/06/01 19:47:24 michael Exp  */
+
 #ifndef _NLIST_H
 #define _NLIST_H
 
 #ifdef __cplusplus
 extern "C" {
-#endif
+#endif /* __cplusplus */
 
 struct nlist {
     char*              n_name;
@@ -33,14 +35,16 @@ struct nlist {
     char               n_numaux;
 };
 
-#if __STDC__ || defined(__cplusplus)
-extern int nlist(const char *__filename, struct nlist *__nl);
-#else
+#if __STDC__ || defined(__cplusplus) || defined(__LCLINT__)
+extern int nlist(const char *filename, struct nlist *nl)
+       /*@globals fileSystem, internalState @*/
+       /*@modifies *nl, fileSystem, internalState @*/;
+#else /* __STDC__ || defined(__cplusplus) */
 extern int nlist();
-#endif
+#endif /* __STDC__ || defined(__cplusplus) */
 
 #ifdef __cplusplus
 }
-#endif
+#endif /* __cplusplus */
 
 #endif /* _NLIST_H */
index 718df6a..17afbc4 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 opt.delscn.c - implementation of the elf_delscn(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,9 +19,99 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: opt.delscn.c,v 1.8 2001/10/08 15:57:10 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)
+       /*@modifies *elf @*/
+{
+    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);
+               /*@fallthrough@*/
+           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);
+               /*@fallthrough@*/
+           default:
+               /*@switchbreak@*/ break;
+       }
+    }
+}
+
+#if __LIBELF64
+
+static void
+_elf64_update_shdr(Elf *elf, size_t index)
+       /*@modifies *elf @*/
+{
+    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);
+               /*@fallthrough@*/
+           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);
+               /*@fallthrough@*/
+           default:
+               /*@switchbreak@*/ break;
+       }
+    }
+}
+
+#endif /* __LIBELF64 */
+
 size_t
 elf_delscn(Elf *elf, Elf_Scn *scn) {
-    Elf32_Shdr *shdr;
     Elf_Scn *pscn;
     Scn_Data *sd;
     Scn_Data *tmp;
@@ -32,6 +122,7 @@ elf_delscn(Elf *elf, Elf_Scn *scn) {
     }
     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;
@@ -41,6 +132,10 @@ elf_delscn(Elf *elf, Elf_Scn *scn) {
        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;
@@ -50,15 +145,20 @@ elf_delscn(Elf *elf, Elf_Scn *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
+     * 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);
@@ -68,6 +168,8 @@ elf_delscn(Elf *elf, Elf_Scn *scn) {
        }
     }
     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);
        }
@@ -80,47 +182,25 @@ elf_delscn(Elf *elf, Elf_Scn *scn) {
        free(scn);
     }
     /*
-     * adjust section indices
+     * Adjust section indices.
      */
     for (scn = pscn->s_link; scn; scn = scn->s_link) {
        elf_assert(scn->s_index > index);
        scn->s_index--;
     }
     /*
-     * adjust header and well-known section headers
+     * Adjust ELF header and well-known section headers.
      */
     if (elf->e_class == ELFCLASS32) {
-       elf_assert(elf->e_ehdr);
-       ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = elf->e_scn_n->s_index + 1;
-       for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
-           shdr = &scn->s_shdr32;
-           switch (shdr->sh_type) {
-               case SHT_REL:
-               case SHT_RELA:
-                   if (shdr->sh_info == index) {
-                       shdr->sh_info = SHN_UNDEF;
-                   }
-                   else if (shdr->sh_info > index) {
-                       shdr->sh_info--;
-                   }
-                   /* fall through */
-               case SHT_DYNSYM:
-               case SHT_DYNAMIC:
-               case SHT_HASH:
-               case SHT_SYMTAB:
-                   if (shdr->sh_link == index) {
-                       shdr->sh_link = SHN_UNDEF;
-                   }
-                   else if (shdr->sh_link > index) {
-                       shdr->sh_link--;
-                   }
-                   /* fall through */
-               default:
-                   break;
-           }
-       }
+       _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);
     }
index 211843d..bff5f60 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 private.h - private definitions for libelf.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -17,6 +17,8 @@ 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: private.h,v 1.23 2001/10/15 21:39:02 michael Exp  */
+
 #ifndef _PRIVATE_H
 #define _PRIVATE_H
 
@@ -24,58 +26,72 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #if HAVE_CONFIG_H
 # include <config.h>
-#endif
+#endif /* HAVE_CONFIG_H */
 
 #include <sys/types.h>
 
 #if STDC_HEADERS
 # include <stdlib.h>
 # include <string.h>
-#else
-extern char *malloc();
-extern void free(), bcopy(), bzero();
+#else /* STDC_HEADERS */
+extern void *malloc(), *realloc();
+extern void free(), bcopy(), abort();
 extern int strcmp(), strncmp(), memcmp();
 extern void *memcpy(), *memmove(), *memset();
-#endif
+#endif /* STDC_HEADERS */
 
 #if HAVE_UNISTD_H
 # include <unistd.h>
-#else
-extern int read(), write();
+#else /* HAVE_UNISTD_H */
+extern int read(), write(), close();
 extern off_t lseek();
-#endif
+#if HAVE_FTRUNCATE
+extern int ftruncate();
+#endif /* HAVE_FTRUNCATE */
+#endif /* HAVE_UNISTD_H */
+
+#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
+#endif /* !HAVE_MEMCMP */
 #if !HAVE_MEMCPY
 # define memcpy(d,s,n) bcopy(s,d,n)
-#endif
+#endif /* !HAVE_MEMCPY */
 #if !HAVE_MEMMOVE
 # define memmove(d,s,n)        bcopy(s,d,n)
-#endif
+#endif /* !HAVE_MEMMOVE */
 
-/*
- * if c is 0, replace slow memset() substitute with bzero().
- */
 #if !HAVE_MEMSET
-# define memset(d,c,n) ((char)(c)?(void)__memset(d,c,n):bzero(d,n))
-extern void *__memset();
-#endif
+# define memset _elf_memset
+extern void *_elf_memset();
+#endif /* !HAVE_MEMSET */
 
 #if HAVE_STRUCT_NLIST_DECLARATION
 # define nlist __override_nlist_declaration
-#endif
+#endif /* HAVE_STRUCT_NLIST_DECLARATION */
 
-#if NEED_LINK_H
+#if __LIBELF_NEED_LINK_H
 # include <link.h>
-#endif
+#endif /* __LIBELF_NEED_LINK_H */
 
 #include <libelf.h>
 
 #if HAVE_STRUCT_NLIST_DECLARATION
 # undef nlist
-#endif
+#endif /* HAVE_STRUCT_NLIST_DECLARATION */
+
+#if __LIBELF64
+#include <gelf.h>
+#endif /* __LIBELF64 */
 
 typedef struct Scn_Data Scn_Data;
 
@@ -87,32 +103,44 @@ struct Elf {
     size_t     e_size;                 /* file/member size */
     size_t     e_dsize;                /* size of memory image */
     Elf_Kind   e_kind;                 /* kind of file */
+/*@owned@*/ /*@relnull@*/
     char*      e_data;                 /* file/member data */
+/*@owned@*/ /*@relnull@*/
     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) */
+/*@null@*/
     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 */
+/*@null@*/
     Elf*       e_link;                 /* next archive member or NULL */
+/*@null@*/
     Elf_Arhdr* e_arhdr;                /* archive member header or NULL */
     /* archives */
     size_t     e_off;                  /* current member offset (for elf_begin) */
+/*@null@*/
     Elf*       e_members;              /* linked list of active archive members */
+/*@owned@*/ /*@null@*/
     char*      e_symtab;               /* archive symbol table */
     size_t     e_symlen;               /* length of archive symbol table */
+/*@null@*/
     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 */
+/*@relnull@*/
     char*      e_ehdr;                 /* ELF header */
+/*@relnull@*/
     char*      e_phdr;                 /* ELF program header table */
     size_t     e_phnum;                /* size of program header table */
+/*@relnull@*/
     Elf_Scn*   e_scn_1;                /* first section */
+/*@relnull@*/
     Elf_Scn*   e_scn_n;                /* last section */
     unsigned   e_elf_flags;            /* elf flags (ELF_F_*) */
     unsigned   e_ehdr_flags;           /* ehdr flags (ELF_F_*) */
@@ -126,6 +154,7 @@ struct Elf {
     unsigned   e_free_ehdr : 1;        /* e_ehdr is malloc'ed */
     unsigned   e_free_phdr : 1;        /* e_phdr is malloc'ed */
     unsigned   e_unmap_data : 1;       /* e_data is mmap'ed */
+    unsigned   e_memory : 1;           /* created by elf_memory() */
     /* magic number for debugging */
     long       e_magic;
 };
@@ -171,6 +200,7 @@ struct Elf {
     /* e_free_ehdr */  0,\
     /* e_free_phdr */  0,\
     /* e_unmap_data */ 0,\
+    /* e_memory */     0,\
     /* e_magic */      ELF_MAGIC\
 }
 
@@ -178,13 +208,18 @@ struct Elf {
  * Section descriptor
  */
 struct Elf_Scn {
+/*@relnull@*/
     Elf_Scn*   s_link;                 /* pointer to next Elf_Scn */
+/*@null@*/
     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_*) */
+/*@null@*/
     Scn_Data*  s_data_1;               /* first data buffer */
+/*@null@*/
     Scn_Data*  s_data_n;               /* last data buffer */
+/*@null@*/
     Scn_Data*  s_rawdata;              /* raw data buffer */
     /* data copied from shdr */
     unsigned   s_type;                 /* section type */
@@ -194,12 +229,16 @@ struct Elf_Scn {
     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
 
@@ -225,8 +264,11 @@ struct Elf_Scn {
  */
 struct Scn_Data {
     Elf_Data   sd_data;                /* must be first! */
+/*@null@*/
     Scn_Data*  sd_link;                /* pointer to next Scn_Data */
+/*@null@*/
     Elf_Scn*   sd_scn;                 /* pointer to section */
+/*@relnull@*/
     char*      sd_memdata;             /* memory image of section */
     unsigned   sd_data_flags;          /* data flags (ELF_F_*) */
     /* misc flags */
@@ -259,31 +301,99 @@ struct Scn_Data {
 /*
  * Private status variables
  */
+/*@unchecked@*/
 extern unsigned _elf_version;
+/*@unchecked@*/
 extern int _elf_errno;
+/*@unchecked@*/
 extern int _elf_fill;
 
 /*
  * Private functions
  */
-extern void *_elf_read __P((Elf*, void*, size_t, size_t));
-extern void *_elf_mmap __P((Elf*));
-extern int _elf_cook __P((Elf*));
+/*@null@*/
+extern void *_elf_read __P((Elf* elf, /*@returned@*/ /*@null@*/ void* buffer, size_t off, size_t len))
+       /*@globals _elf_errno @*/
+       /*@modifies *buffer, _elf_errno @*/;
+/*@null@*/
+extern void *_elf_mmap __P((Elf* elf))
+       /*@globals _elf_errno @*/
+       /*@modifies _elf_errno @*/;
+extern int _elf_cook __P((Elf* elf))
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/;
+/*@null@*/
+extern char *_elf_getehdr __P((Elf* elf, unsigned cls))
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/;
+/*@null@*/
+extern char *_elf_getphdr __P((Elf* elf, unsigned cls))
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/;
+/*@null@*/
+extern Elf_Data *_elf_xlatetom __P((const Elf* elf, Elf_Data* dst, const Elf_Data* src))
+       /*@globals _elf_errno @*/
+       /*@modifies *dst, _elf_errno @*/;
+extern Elf_Type _elf_scn_type __P((unsigned t))
+       /*@*/;
+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))
+       /*@*/;
+
+/*
+ * Special translators
+ */
+extern size_t _elf_verdef_32L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_32L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_32M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_32M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_64L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_64L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_64M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verdef_64M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_32L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_32L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_32M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_32M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_64L11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_64L11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_64M11_tof __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
+extern size_t _elf_verneed_64M11_tom __P((unsigned char *dst, const unsigned char *src, size_t n))
+       /*@modifies *dst @*/;
 
 /*
  * Private data
  */
+/*@unchecked@*/
 extern const Elf_Scn _elf_scn_init;
+/*@unchecked@*/
 extern const Scn_Data _elf_data_init;
-extern const Elf_Type _elf_scn_types[SHT_NUM];
-extern const size_t _elf32_fmsize[EV_CURRENT - EV_NONE][ELF_T_NUM][2];
+/*@unchecked@*/
+extern const size_t _elf_fmsize[2][EV_CURRENT - EV_NONE][ELF_T_NUM][2];
 
 /*
- * Access macros for _elf32_fmsize
+ * Access macros for _elf_fmsize[]
  */
-#define _fmsize32(v,t,w)       (_elf32_fmsize[(v)-EV_NONE-1][(t)-ELF_T_BYTE][(w)])
-#define _fsize32(v,t)          _fmsize32((v),(t),1)
-#define _msize32(v,t)          _fmsize32((v),(t),0)
+#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
@@ -292,7 +402,6 @@ extern const size_t _elf32_fmsize[EV_CURRENT - EV_NONE][ELF_T_NUM][2];
 #define valid_encoding(e)      ((e) >= ELFDATA2LSB && (e) <= ELFDATA2MSB)
 #define valid_version(v)       ((v) > EV_NONE && (v) <= EV_CURRENT)
 #define valid_type(t)          ((t) >= ELF_T_BYTE && (t) < ELF_T_NUM)
-#define valid_scntype(s)       ((s) >= SHT_NULL && (s) < SHT_NUM)
 
 /*
  * Error codes
@@ -308,32 +417,39 @@ ERROR_NUM
 
 /*
  * Sizes of data types (external representation)
- */
-#ifndef ELF32_FSZ_ADDR
-/*
  * 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
+#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 */
 
 /*
  * Debugging
  */
-#if ENABLE_DEBUG
-# include <stdio.h>
+#if ENABLE_DEBUG || defined(__LCLINT__)
+/*@exits@*/
+extern void __elf_assert __P((const char*, unsigned, const char*))
+       /*@*/;
 # if __STDC__
-#  define elf_assert(x)        ((void)((x)||__elf_assert(__FILE__,__LINE__,#x)))
-# else
-#  define elf_assert(x)        ((void)((x)||__elf_assert(__FILE__,__LINE__,"x")))
-# endif
-# define __elf_assert(f,l,x)   (fprintf(stderr,\
-       "%s:%u: libelf assertion failure: %s\n",(f),(l),(x)),abort(),0)
-#else
-# define elf_assert(x) ((void)0)
-#endif
+#  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 */
 
 #endif /* _PRIVATE_H */
index 40d998b..9c3f792 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 update.c - implementation of the elf_update(3) function.
-Copyright (C) 1995, 1996 Michael Riepe <michael@stud.uni-hannover.de>
+Copyright (C) 1995 - 2001 Michael Riepe <michael@stud.uni-hannover.de>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
@@ -19,10 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include <private.h>
 
+#ifndef lint
+static const char rcsid[] = "@(#) Id: update.c,v 1.18 2001/11/17 21:02:51 michael Exp ";
+#endif /* lint */
+
 #if HAVE_MMAP
 #include <sys/mman.h>
-#endif
+#endif /* HAVE_MMAP */
 
+/*@unchecked@*/
 static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);
 #define native_encoding (*(unsigned char*)&__encoding)
 
@@ -35,12 +40,89 @@ static const unsigned short __encoding = ELFDATA2LSB + (ELFDATA2MSB << 8);
 #define max(a,b)               ((a)>(b)?(a):(b))
 
 static off_t
-_elf32_layout(Elf *elf, unsigned *flag) {
+scn_data_layout(Elf_Scn *scn, unsigned v, unsigned type, size_t *algn, unsigned *flag)
+       /*@globals _elf_errno @*/
+       /*@modifies *scn, *algn, *flag, _elf_errno @*/
+{
+    Elf *elf = scn->s_elf;
+    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;
+
+    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 (!valid_version(sd->sd_data.d_version)) {
+           return (off_t)-1;
+       }
+
+       fsize = sd->sd_data.d_size;
+       if (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)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, *flag, _elf_errno @*/
+{
     int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
     Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf->e_ehdr;
     size_t off = 0;
     unsigned version;
     unsigned encoding;
+    size_t align_addr;
     size_t entsize;
     unsigned shnum;
     Elf_Scn *scn;
@@ -61,16 +143,19 @@ _elf32_layout(Elf *elf, unsigned *flag) {
        seterr(ERROR_UNKNOWN_ENCODING);
        return -1;
     }
-    entsize = _fsize32(version, ELF_T_EHDR); elf_assert(entsize);
+    entsize = _fsize(ELFCLASS32, version, ELF_T_EHDR);
+    elf_assert(entsize);
     rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
     off = entsize;
 
-    rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags);
+    align_addr = _fsize(ELFCLASS32, version, ELF_T_ADDR);
+    elf_assert(align_addr);
+
     if (elf->e_phnum) {
-       entsize = _fsize32(version, ELF_T_PHDR); elf_assert(entsize);
-       rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);
+       entsize = _fsize(ELFCLASS32, version, ELF_T_PHDR);
+       elf_assert(entsize);
        if (layout) {
-           align(off, 4);
+           align(off, align_addr);
            rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
            off += elf->e_phnum * entsize;
        }
@@ -79,17 +164,18 @@ _elf32_layout(Elf *elf, unsigned *flag) {
        }
     }
     else {
-       rewrite(ehdr->e_phentsize, 0, elf->e_ehdr_flags);
+       entsize = 0;
        if (layout) {
            rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
        }
     }
+    rewrite(ehdr->e_phnum, elf->e_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;
-       size_t len = 0;
-       Scn_Data *sd;
+       off_t len;
 
        elf_assert(scn->s_index == shnum);
 
@@ -104,82 +190,251 @@ _elf32_layout(Elf *elf, unsigned *flag) {
            }
            continue;
        }
-#if 1
        if (shdr->sh_type == SHT_NULL) {
            continue;
        }
-#endif
-       for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
-           size_t fsize, msize;
 
-           if (shdr->sh_type == SHT_NOBITS) {
-               fsize = sd->sd_data.d_size;
-           }
-           else if (!valid_type(sd->sd_data.d_type)) {
-               /* can't translate */
-               fsize = sd->sd_data.d_size;
-           }
-           else {
-               msize = _msize32(sd->sd_data.d_version, sd->sd_data.d_type);
-               elf_assert(msize);
-               fsize = _fsize32(version, sd->sd_data.d_type);
-               elf_assert(fsize);
-               fsize = (sd->sd_data.d_size / msize) * fsize;
+       len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
+       if (len == -1) {
+           return -1;
+       }
+
+       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;
 
-           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;
+           end1 = shdr->sh_offset;
+           if (shdr->sh_type != SHT_NOBITS) {
+               end1 += shdr->sh_size;
            }
-           else {
-               len = max(len, sd->sd_data.d_off + fsize);
+           if (shdr->sh_offset < off) {
+               /*
+                * check for overlapping sections
+                */
+               for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
+                   if (scn2 == scn) {
+                       /*@innerbreak@*/ 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 |= sd->sd_data_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);
+       }
+    }
+    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);
 
-       if (valid_scntype(shdr->sh_type)) {
-           Elf_Type type = _elf_scn_types[shdr->sh_type];
-           size_t fsize;
+    *flag |= elf->e_ehdr_flags;
 
-           elf_assert(valid_type(type));
-           if (type != ELF_T_BYTE) {
-               fsize = _fsize32(version, type);
-               elf_assert(fsize);
-               rewrite(shdr->sh_entsize, fsize, scn->s_shdr_flags);
+    return off;
+}
+
+#if __LIBELF64
+
+static off_t
+_elf64_layout(Elf *elf, unsigned *flag)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, *flag, _elf_errno @*/
+{
+    int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 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 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 (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 += elf->e_phnum * entsize;
+       }
+       else {
+           off = max(off, ehdr->e_phoff + elf->e_phnum * entsize);
+       }
+    }
+    else {
+       entsize = 0;
+       if (layout) {
+           rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
+       }
+    }
+    rewrite(ehdr->e_phnum, elf->e_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 | scn->s_shdr_flags;
+
+       if (scn->s_index == SHN_UNDEF) {
+           rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
+           if (layout) {
+               rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
+               rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
+               rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
            }
+           continue;
+       }
+       if (shdr->sh_type == SHT_NULL) {
+           continue;
+       }
+
+       len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
+       if (len == -1) {
+           return -1;
+       }
+
+       entsize = scn_entsize(elf, version, shdr->sh_type);
+       if (entsize > 1) {
+           /* Some architectures use 64-bit hash entries.  */
+           if (shdr->sh_type != SHT_HASH
+               || shdr->sh_entsize != _fsize(elf->e_class, version, ELF_T_ADDR))
+               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, len, 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 += len;
+               off += (size_t)len;
            }
        }
-       else if (len > shdr->sh_size) {
+       else if ((size_t)len > shdr->sh_size) {
            seterr(ERROR_SCN2SMALL);
            return -1;
        }
-       else if (shdr->sh_type != SHT_NOBITS) {
-           off = max(off, shdr->sh_offset + shdr->sh_size);
-       }
        else {
-           off = max(off, shdr->sh_offset);
+           Elf_Scn *scn2;
+           size_t end1, end2;
+
+           end1 = shdr->sh_offset;
+           if (shdr->sh_type != SHT_NOBITS) {
+               end1 += shdr->sh_size;
+           }
+           if (shdr->sh_offset < off) {
+               /*
+                * check for overlapping sections
+                */
+               for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
+                   if (scn2 == scn) {
+                       /*@innerbreak@*/ 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;
+           }
        }
     }
 
-    rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
     if (shnum) {
-       entsize = _fsize32(version, ELF_T_SHDR); elf_assert(entsize);
-       rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);
+       entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR);
+       elf_assert(entsize);
        if (layout) {
-           align(off, 4);
+           align(off, align_addr);
            rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
            off += shnum * entsize;
        }
@@ -188,17 +443,19 @@ _elf32_layout(Elf *elf, unsigned *flag) {
        }
     }
     else {
-       rewrite(ehdr->e_shentsize, 0, elf->e_ehdr_flags);
+       entsize = 0;
        if (layout) {
            rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
        }
     }
+    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_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);
@@ -208,13 +465,17 @@ _elf32_layout(Elf *elf, unsigned *flag) {
     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
-_elf32_update_pointers(Elf *elf, char *outbuf, size_t len) {
+_elf_update_pointers(Elf *elf, char *outbuf, size_t len)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
     Elf_Scn *scn;
-    Elf32_Shdr *shdr;
     Scn_Data *sd;
     char *data, *rawdata;
 
@@ -241,6 +502,7 @@ _elf32_update_pointers(Elf *elf, char *outbuf, size_t len) {
        /* 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) {
@@ -266,35 +528,66 @@ _elf32_update_pointers(Elf *elf, char *outbuf, size_t len) {
        newptr(elf->e_phdr, elf->e_data, data);
     }
     for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
-       if ((sd = scn->s_data_1) && sd->sd_memdata && !sd->sd_free_data) {
-           elf_assert(ptrinside(sd->sd_memdata, elf->e_data, elf->e_dsize));
-           if (sd->sd_data.d_buf == sd->sd_memdata) {
-               newptr(sd->sd_memdata, elf->e_data, data);
-               sd->sd_data.d_buf = sd->sd_memdata;
-           }
-           else {
-               newptr(sd->sd_memdata, elf->e_data, data);
+       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) && sd->sd_memdata && sd->sd_free_data) {
-           shdr = &scn->s_shdr32;
-           if (!(rawdata = (char*)realloc(sd->sd_memdata, shdr->sh_size))) {
-               seterr(ERROR_IO_2BIG);
-               return -1;
-           }
-           memcpy(rawdata, outbuf + shdr->sh_offset, shdr->sh_size);
-           if (sd->sd_data.d_buf == sd->sd_memdata) {
-               sd->sd_data.d_buf = rawdata;
+       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;
            }
-           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_write(Elf *elf, char *outbuf, size_t len)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
     Elf32_Ehdr *ehdr;
     Elf32_Shdr *shdr;
     Elf_Scn *scn;
@@ -302,19 +595,15 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
     Elf_Data src;
     Elf_Data dst;
     unsigned encode;
-    size_t fsize;
-    size_t msize;
 
-    if (!len) {
-       return len;
-    }
-
-    ehdr = (Elf32_Ehdr*)elf->e_ehdr; elf_assert(ehdr);
+    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 = _msize32(_elf_version, 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;
@@ -326,7 +615,7 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
     if (ehdr->e_phnum) {
        src.d_buf = elf->e_phdr;
        src.d_type = ELF_T_PHDR;
-       src.d_size = ehdr->e_phnum * _msize32(_elf_version, ELF_T_PHDR);
+       src.d_size = ehdr->e_phnum * _msize(ELFCLASS32, _elf_version, ELF_T_PHDR);
        src.d_version = _elf_version;
        dst.d_buf = outbuf + ehdr->e_phoff;
        dst.d_size = ehdr->e_phnum * ehdr->e_phentsize;
@@ -337,10 +626,12 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
     }
 
     for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
-       shdr = &scn->s_shdr32;
-       src.d_buf = shdr;
+       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 = sizeof(*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;
@@ -352,6 +643,7 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
        if (scn->s_index == SHN_UNDEF) {
            continue;
        }
+       shdr = &scn->s_shdr32;
        if (shdr->sh_type == SHT_NULL || shdr->sh_type == SHT_NOBITS) {
            continue;
        }
@@ -359,9 +651,11 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
            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;
+               /*@innercontinue@*/ continue;
            }
            if (!src.d_buf) {
                seterr(ERROR_NULLBUF);
@@ -371,13 +665,13 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
            dst.d_size = src.d_size;
            dst.d_version = ehdr->e_version;
            if (valid_type(src.d_type)) {
-               msize = _msize32(src.d_version, src.d_type);
-               elf_assert(msize);
-               fsize = _fsize32(dst.d_version, src.d_type);
-               elf_assert(fsize);
-               if (msize != fsize) {
-                   dst.d_size = (src.d_size / msize) * fsize;
+               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;
@@ -389,7 +683,7 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
     }
 
     /* cleanup */
-    if (elf->e_readable && _elf32_update_pointers(elf, outbuf, len)) {
+    if (elf->e_readable && _elf_update_pointers(elf, outbuf, len)) {
        return -1;
     }
     /* NOTE: ehdr is no longer valid! */
@@ -416,12 +710,203 @@ _elf32_write(Elf *elf, char *outbuf, size_t len) {
     return len;
 }
 
+#if __LIBELF64
+
+static off_t
+_elf64_write(Elf *elf, char *outbuf, size_t len)
+       /*@globals _elf_errno @*/
+       /*@modifies *elf, _elf_errno @*/
+{
+    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 (ehdr->e_phnum) {
+       src.d_buf = elf->e_phdr;
+       src.d_type = ELF_T_PHDR;
+       src.d_size = ehdr->e_phnum * _msize(ELFCLASS64, _elf_version, ELF_T_PHDR);
+       src.d_version = _elf_version;
+       dst.d_buf = outbuf + ehdr->e_phoff;
+       dst.d_size = ehdr->e_phnum * ehdr->e_phentsize;
+       dst.d_version = ehdr->e_version;
+       if (!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;
+       }
+       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) {
+               /*@innercontinue@*/ 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 off_t
+_elf_output(Elf *elf, int fd, size_t len, off_t (*_elf_write)(Elf*, char*, size_t))
+       /*@globals _elf_errno, fileSystem @*/
+       /*@modifies _elf_errno, fileSystem @*/
+{
+    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
+    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 (write(fd, "", 1) != 1) {
+           seterr(ERROR_IO_WRITE);
+           return -1;
+       }
+    }
+    buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (buf != (char*)-1) {
+/*@-nullpass@*/
+       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);
+/*@=nullpass@*/
+       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 (write(fd, buf, len) != 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;
-    char *buf;
-    int err;
 
     if (!elf) {
        return -1;
@@ -450,64 +935,20 @@ elf_update(Elf *elf, Elf_Cmd cmd) {
     }
     else if (elf->e_class == ELFCLASS32) {
        len = _elf32_layout(elf, &flag);
-       if (len == -1 || cmd != ELF_C_WRITE || !(flag & ELF_F_DIRTY)) {
-           return len;
-       }
-       if (!len) {
-           /* can this happen at all??? */
-           return len;
-       }
-#if HAVE_FTRUNCATE
-       ftruncate(elf->e_fd, 0);
-#endif
-#if HAVE_MMAP
-       /*
-        * Make sure the file is (at least) len bytes long
-        */
-#if HAVE_FTRUNCATE
-       if (ftruncate(elf->e_fd, len)) {
-#else
-       {
-#endif
-           if (lseek(elf->e_fd, (long)len - 1, 0) != (long)len - 1) {
-               seterr(ERROR_IO_SEEK);
-               return -1;
-           }
-           if (write(elf->e_fd, "", 1) != 1) {
-               seterr(ERROR_IO_WRITE);
-               return -1;
-           }
+       if (len != -1 && cmd == ELF_C_WRITE && (flag & ELF_F_DIRTY)) {
+           len = _elf_output(elf, elf->e_fd, (size_t)len, _elf32_write);
        }
-       buf = (void*)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
-                         elf->e_fd, 0);
-       if (buf != (char*)-1) {
-           if ((char)_elf_fill) {
-               memset(buf, _elf_fill, len);
-           }
-           err = _elf32_write(elf, buf, len);
-           munmap(buf, len);
-           return err;
-       }
-#endif
-       if (!(buf = (char*)malloc(len))) {
-           seterr(ERROR_MEM_OUTBUF);
-           return -1;
-       }
-       memset(buf, _elf_fill, len);
-       err = _elf32_write(elf, buf, len);
-       if (err == len) {
-           if (lseek(elf->e_fd, 0L, 0)) {
-               seterr(ERROR_IO_SEEK);
-               err = -1;
-           }
-           else if (write(elf->e_fd, buf, len) != len) {
-               seterr(ERROR_IO_WRITE);
-               err = -1;
-           }
+       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);
        }
-       free(buf);
-       return err;
+       return len;
     }
+#endif /* __LIBELF64 */
     else if (valid_class(elf->e_class)) {
        seterr(ERROR_UNIMPLEMENTED);
     }
index 66da492..abfe0f4 100755 (executable)
@@ -28,7 +28,9 @@ static const char verdef_h_rcsid[] = "@(#) Id: verdef.h,v 1.1 2001/10/07 20:03:0
 #if TOFILE
 
 static void
-__store_verdaux(verdaux_ftype *dst, const verdaux_mtype *src, unsigned enc) {
+__store_verdaux(verdaux_ftype *dst, const verdaux_mtype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        __store_u32L(dst->vda_name, src->vda_name);
        __store_u32L(dst->vda_next, src->vda_next);
@@ -40,7 +42,9 @@ __store_verdaux(verdaux_ftype *dst, const verdaux_mtype *src, unsigned enc) {
 }
 
 static void
-__store_verdef(verdef_ftype *dst, const verdef_mtype *src, unsigned enc) {
+__store_verdef(verdef_ftype *dst, const verdef_mtype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        __store_u16L(dst->vd_version, src->vd_version);
        __store_u16L(dst->vd_flags,   src->vd_flags);
@@ -77,7 +81,9 @@ typedef align_mtype           verdef_atype;
 #else /* TOFILE */
 
 static void
-__load_verdaux(verdaux_mtype *dst, const verdaux_ftype *src, unsigned enc) {
+__load_verdaux(verdaux_mtype *dst, const verdaux_ftype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        dst->vda_name = __load_u32L(src->vda_name);
        dst->vda_next = __load_u32L(src->vda_next);
@@ -89,7 +95,9 @@ __load_verdaux(verdaux_mtype *dst, const verdaux_ftype *src, unsigned enc) {
 }
 
 static void
-__load_verdef(verdef_mtype *dst, const verdef_ftype *src, unsigned enc) {
+__load_verdef(verdef_mtype *dst, const verdef_ftype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        dst->vd_version = __load_u16L(src->vd_version);
        dst->vd_flags   = __load_u16L(src->vd_flags);
@@ -131,7 +139,10 @@ typedef align_ftype                verdef_atype;
 #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) {
+xlt_verdef(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc)
+       /*@globals _elf_errno @*/
+       /*@modifies *dst, _elf_errno @*/
+{
     size_t doff;
     size_t soff;
 
@@ -229,7 +240,7 @@ xlt_verdef(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc)
             * end check
             */
            if (vda.vda_next == 0) {
-               break;
+               /*@innerbreak@*/ break;
            }
        }
        /*
@@ -259,11 +270,15 @@ xlt_verdef(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc)
 }
 
 size_t
-translator(verdef,L)(unsigned char *dst, const unsigned char *src, size_t n) {
+translator(verdef,L)(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
     return xlt_verdef(dst, src, n, ELFDATA2LSB);
 }
 
 size_t
-translator(verdef,M)(unsigned char *dst, const unsigned char *src, size_t n) {
+translator(verdef,M)(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
     return xlt_verdef(dst, src, n, ELFDATA2MSB);
 }
index 9af8389..e110573 100755 (executable)
@@ -28,7 +28,9 @@ static const char verneed_h_rcsid[] = "@(#) Id: verneed.h,v 1.1 2001/10/07 20:03
 #if TOFILE
 
 static void
-__store_vernaux(vernaux_ftype *dst, const vernaux_mtype *src, unsigned enc) {
+__store_vernaux(vernaux_ftype *dst, const vernaux_mtype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        __store_u32L(dst->vna_hash,  src->vna_hash);
        __store_u16L(dst->vna_flags, src->vna_flags);
@@ -46,7 +48,9 @@ __store_vernaux(vernaux_ftype *dst, const vernaux_mtype *src, unsigned enc) {
 }
 
 static void
-__store_verneed(verneed_ftype *dst, const verneed_mtype *src, unsigned enc) {
+__store_verneed(verneed_ftype *dst, const verneed_mtype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        __store_u16L(dst->vn_version, src->vn_version);
        __store_u16L(dst->vn_cnt,     src->vn_cnt);
@@ -79,7 +83,9 @@ typedef align_mtype           verneed_atype;
 #else /* TOFILE */
 
 static void
-__load_vernaux(vernaux_mtype *dst, const vernaux_ftype *src, unsigned enc) {
+__load_vernaux(vernaux_mtype *dst, const vernaux_ftype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        dst->vna_hash  = __load_u32L(src->vna_hash);
        dst->vna_flags = __load_u16L(src->vna_flags);
@@ -97,7 +103,9 @@ __load_vernaux(vernaux_mtype *dst, const vernaux_ftype *src, unsigned enc) {
 }
 
 static void
-__load_verneed(verneed_mtype *dst, const verneed_ftype *src, unsigned enc) {
+__load_verneed(verneed_mtype *dst, const verneed_ftype *src, unsigned enc)
+       /*@modifies *dst @*/
+{
     if (enc == ELFDATA2LSB) {
        dst->vn_version = __load_u16L(src->vn_version);
        dst->vn_cnt     = __load_u16L(src->vn_cnt);
@@ -135,7 +143,10 @@ typedef align_ftype                verneed_atype;
 #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) {
+xlt_verneed(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc)
+       /*@globals _elf_errno @*/
+       /*@modifies *dst, _elf_errno @*/
+{
     size_t doff;
     size_t soff;
 
@@ -233,7 +244,7 @@ xlt_verneed(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc
             * end check
             */
            if (vna.vna_next == 0) {
-               break;
+               /*@innerbreak@*/ break;
            }
        }
        /*
@@ -263,11 +274,15 @@ xlt_verneed(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc
 }
 
 size_t
-translator(verneed,L)(unsigned char *dst, const unsigned char *src, size_t n) {
+translator(verneed,L)(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
     return xlt_verneed(dst, src, n, ELFDATA2LSB);
 }
 
 size_t
-translator(verneed,M)(unsigned char *dst, const unsigned char *src, size_t n) {
+translator(verneed,M)(unsigned char *dst, const unsigned char *src, size_t n)
+       /*@modifies *dst @*/
+{
     return xlt_verneed(dst, src, n, ELFDATA2MSB);
 }
diff --git a/libelf/libelf.spec b/libelf/libelf.spec
new file mode 100755 (executable)
index 0000000..03322a0
--- /dev/null
@@ -0,0 +1,94 @@
+Summary: An ELF object file access shared library.
+Name: libelf
+Version: 0.7.0
+Release: 5
+Copyright: distributable
+Group: System Environment/Libraries
+Source: ftp://www.ibiblio.org/pub/Linux/libs/libelf-0.7.0.tar.gz
+Patch: libelf-0.7.0.patch
+Patch2: libelf-0.7.0-hash.patch
+Buildroot: /var/tmp/libelf-root
+
+%description
+The libelf package contains a shared library for accessing ELF object files.
+You need to install it if you use any tools linked against it dynamically.
+
+%package devel
+Summary: An ELF object file access library.
+Group: Development/Libraries
+Requires: libelf = %{version}-%{release}
+
+%description devel
+The libelf-devel package contains a library for accessing ELF object
+files. Libelf allows you to access the internals of the ELF object file
+format, so you can see the different sections of an ELF file.
+
+%prep
+%setup
+%patch -p1
+%patch2 -p1
+
+%build
+%{__libtoolize} --copy --force
+%configure --enable-shared
+make
+
+%install
+%makeinstall
+
+%files
+%defattr(-,root,root)
+%doc README
+%{_prefix}/%{_lib}/libelf.so.*
+
+%files devel
+%defattr(-,root,root)
+%{_prefix}/%{_lib}/libelf.so
+%{_prefix}/%{_lib}/libelf.a
+%{_prefix}/include/libelf
+
+%changelog
+* Mon Jun 17 2002 Jakub Jelinek <jakub@redhat.com> 0.7.0-5
+- build libelf shared and split into libelf and libelf-devel
+  subpackages (#66184)
+- don't override SHT_HASH's sh_entsize for 64-bit ELF,
+  some platforms like Alpha use 64-bit hash entries
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Wed Sep 26 2001 Jakub Jelinek <jakub@redhat.com> 0.7.0-2
+- fix Elf64_Sxword conversion
+
+* Tue Jul  3 2001 Jakub Jelinek <jakub@redhat.com> 0.7.0-1
+- update to 0.7.0 to support 64bit elf
+
+* Sun Jun 24 2001 Elliot Lee <sopwith@redhat.com>
+- Bump release + rebuild.
+
+* Tue Jul 18 2000 Nalin Dahyabhai <nalin@redhat.com>
+- add %%defattr (release 7)
+
+* Thu Jul 13 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Sun Jun 18 2000 Matt Wilson <msw@redhat.com>
+- rebuilt for next release
+- don't build on ia64 (libelf don't grok 64bit elf)
+
+* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com> 
+- auto rebuild in the new build environment (release 4)
+
+* Thu Jan 14 1999 Cristian Gafton <gafton@redhat.com>
+- build for glibc 2.1
+
+* Fri May 01 1998 Prospector System <bugs@redhat.com>
+- translations modified for de, fr, tr
+
+* Fri Oct 31 1997 Michael K. Johnson <johnsonm@redhat.com>
+- upgraded to 0.6.4
+- buildroot
+