summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2002-06-18 17:00:30 +0000
committerjbj <devnull@localhost>2002-06-18 17:00:30 +0000
commit7de7470228c6d8adc42872554b5de7b8dee3f261 (patch)
tree164de5964296a88a5752f94e5c0c3a5a3097c58a
parentcd8a7dcf4e0b6a45fcb06ce1555504f3bcd4f6ee (diff)
downloadrpm-7de7470228c6d8adc42872554b5de7b8dee3f261.tar.gz
rpm-7de7470228c6d8adc42872554b5de7b8dee3f261.tar.bz2
rpm-7de7470228c6d8adc42872554b5de7b8dee3f261.zip
Splint annotations and spec file.
CVS patchset: 5507 CVS date: 2002/06/18 17:00:30
-rwxr-xr-xlibelf/lib/.lclintrc81
-rwxr-xr-xlibelf/lib/32.fsize.c145
-rwxr-xr-xlibelf/lib/32.newehdr.c60
-rwxr-xr-xlibelf/lib/32.newphdr.c73
-rwxr-xr-xlibelf/lib/32.xlatetof.c243
-rwxr-xr-xlibelf/lib/64.xlatetof.c302
-rwxr-xr-xlibelf/lib/assert.c2
-rwxr-xr-xlibelf/lib/begin.c166
-rwxr-xr-xlibelf/lib/byteswap.h132
-rwxr-xr-xlibelf/lib/checksum.c14
-rwxr-xr-xlibelf/lib/cook.c240
-rwxr-xr-xlibelf/lib/end.c24
-rwxr-xr-xlibelf/lib/errmsg.c27
-rwxr-xr-xlibelf/lib/flag.c11
-rwxr-xr-xlibelf/lib/gelf.h111
-rwxr-xr-xlibelf/lib/gelftrans.c6
-rwxr-xr-xlibelf/lib/getarsym.c8
-rwxr-xr-xlibelf/lib/getdata.c102
-rwxr-xr-xlibelf/lib/input.c14
-rwxr-xr-xlibelf/lib/libelf.h256
-rwxr-xr-xlibelf/lib/newscn.c27
-rwxr-xr-xlibelf/lib/nlist.c220
-rwxr-xr-xlibelf/lib/nlist.h18
-rwxr-xr-xlibelf/lib/opt.delscn.c148
-rwxr-xr-xlibelf/lib/private.h210
-rwxr-xr-xlibelf/lib/update.c751
-rwxr-xr-xlibelf/lib/verdef.h31
-rwxr-xr-xlibelf/lib/verneed.h31
-rwxr-xr-xlibelf/libelf.spec94
29 files changed, 2693 insertions, 854 deletions
diff --git a/libelf/lib/.lclintrc b/libelf/lib/.lclintrc
new file mode 100755
index 000000000..8dcf67302
--- /dev/null
+++ b/libelf/lib/.lclintrc
@@ -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
diff --git a/libelf/lib/32.fsize.c b/libelf/lib/32.fsize.c
index 2d972f5c9..25bb4b49b 100755
--- a/libelf/lib/32.fsize.c
+++ b/libelf/lib/32.fsize.c
@@ -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 */
diff --git a/libelf/lib/32.newehdr.c b/libelf/lib/32.newehdr.c
index 403a3873b..ecfcc54b1 100755
--- a/libelf/lib/32.newehdr.c
+++ b/libelf/lib/32.newehdr.c
@@ -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 */
diff --git a/libelf/lib/32.newphdr.c b/libelf/lib/32.newphdr.c
index 79ca6228f..e5ede143d 100755
--- a/libelf/lib/32.newphdr.c
+++ b/libelf/lib/32.newphdr.c
@@ -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 */
diff --git a/libelf/lib/32.xlatetof.c b/libelf/lib/32.xlatetof.c
index 0220a8209..32a4c2c75 100755
--- a/libelf/lib/32.xlatetof.c
+++ b/libelf/lib/32.xlatetof.c
@@ -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;
}
diff --git a/libelf/lib/64.xlatetof.c b/libelf/lib/64.xlatetof.c
index aa2d71c2c..77cdeba7c 100755
--- a/libelf/lib/64.xlatetof.c
+++ b/libelf/lib/64.xlatetof.c
@@ -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__ */
diff --git a/libelf/lib/assert.c b/libelf/lib/assert.c
index 9e76bed8e..a35cbcd08 100755
--- a/libelf/lib/assert.c
+++ b/libelf/lib/assert.c
@@ -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@*/
diff --git a/libelf/lib/begin.c b/libelf/lib/begin.c
index 57f803ee1..07a9e7b09 100755
--- a/libelf/lib/begin.c
+++ b/libelf/lib/begin.c
@@ -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 */
diff --git a/libelf/lib/byteswap.h b/libelf/lib/byteswap.h
index af7b1d66c..94871cb1f 100755
--- a/libelf/lib/byteswap.h
+++ b/libelf/lib/byteswap.h
@@ -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 */
diff --git a/libelf/lib/checksum.c b/libelf/lib/checksum.c
index 48ae0948f..5c0f24101 100755
--- a/libelf/lib/checksum.c
+++ b/libelf/lib/checksum.c
@@ -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;
diff --git a/libelf/lib/cook.c b/libelf/lib/cook.c
index c61d8d49d..89c371c00 100755
--- a/libelf/lib/cook.c
+++ b/libelf/lib/cook.c
@@ -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);
diff --git a/libelf/lib/end.c b/libelf/lib/end.c
index 5771fd3a9..951978c2d 100755
--- a/libelf/lib/end.c
+++ b/libelf/lib/end.c
@@ -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);
diff --git a/libelf/lib/errmsg.c b/libelf/lib/errmsg.c
index 2414a088d..e922af79d 100755
--- a/libelf/lib/errmsg.c
+++ b/libelf/lib/errmsg.c
@@ -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@*/
diff --git a/libelf/lib/flag.c b/libelf/lib/flag.c
index 58117998a..f64743801 100755
--- a/libelf/lib/flag.c
+++ b/libelf/lib/flag.c
@@ -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;
}
diff --git a/libelf/lib/gelf.h b/libelf/lib/gelf.h
index a1494a1b5..018da7b9d 100755
--- a/libelf/lib/gelf.h
+++ b/libelf/lib/gelf.h
@@ -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 */
diff --git a/libelf/lib/gelftrans.c b/libelf/lib/gelftrans.c
index 7a265b90c..3724aa6fa 100755
--- a/libelf/lib/gelftrans.c
+++ b/libelf/lib/gelftrans.c
@@ -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;
diff --git a/libelf/lib/getarsym.c b/libelf/lib/getarsym.c
index f492b974f..6b2f6f320 100755
--- a/libelf/lib/getarsym.c
+++ b/libelf/lib/getarsym.c
@@ -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@*/
diff --git a/libelf/lib/getdata.c b/libelf/lib/getdata.c
index fb6be910b..324bc0570 100755
--- a/libelf/lib/getdata.c
+++ b/libelf/lib/getdata.c
@@ -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);
diff --git a/libelf/lib/input.c b/libelf/lib/input.c
index ed8b40d98..986e03a9f 100755
--- a/libelf/lib/input.c
+++ b/libelf/lib/input.c
@@ -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;
}
diff --git a/libelf/lib/libelf.h b/libelf/lib/libelf.h
index 7d09150e5..73436c1f0 100755
--- a/libelf/lib/libelf.h
+++ b/libelf/lib/libelf.h
@@ -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 */
diff --git a/libelf/lib/newscn.c b/libelf/lib/newscn.c
index 8963e02a8..5ab1b640c 100755
--- a/libelf/lib/newscn.c
+++ b/libelf/lib/newscn.c
@@ -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);
}
diff --git a/libelf/lib/nlist.c b/libelf/lib/nlist.c
index 49bedb326..fc7f58c9a 100755
--- a/libelf/lib/nlist.c
+++ b/libelf/lib/nlist.c
@@ -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);
diff --git a/libelf/lib/nlist.h b/libelf/lib/nlist.h
index 8514f9008..1317b7ea5 100755
--- a/libelf/lib/nlist.h
+++ b/libelf/lib/nlist.h
@@ -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 */
diff --git a/libelf/lib/opt.delscn.c b/libelf/lib/opt.delscn.c
index 718df6a60..17afbc4ce 100755
--- a/libelf/lib/opt.delscn.c
+++ b/libelf/lib/opt.delscn.c
@@ -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);
}
diff --git a/libelf/lib/private.h b/libelf/lib/private.h
index 211843dc9..bff5f60ae 100755
--- a/libelf/lib/private.h
+++ b/libelf/lib/private.h
@@ -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 */
diff --git a/libelf/lib/update.c b/libelf/lib/update.c
index 40d998b57..9c3f792d9 100755
--- a/libelf/lib/update.c
+++ b/libelf/lib/update.c
@@ -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);
}
diff --git a/libelf/lib/verdef.h b/libelf/lib/verdef.h
index 66da492bf..abfe0f429 100755
--- a/libelf/lib/verdef.h
+++ b/libelf/lib/verdef.h
@@ -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);
}
diff --git a/libelf/lib/verneed.h b/libelf/lib/verneed.h
index 9af8389fd..e110573d2 100755
--- a/libelf/lib/verneed.h
+++ b/libelf/lib/verneed.h
@@ -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
index 000000000..03322a04c
--- /dev/null
+++ b/libelf/libelf.spec
@@ -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
+