From: jbj Date: Tue, 18 Jun 2002 17:00:30 +0000 (+0000) Subject: Splint annotations and spec file. X-Git-Tag: tznext/4.11.0.1.tizen20130304~7356 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7de7470228c6d8adc42872554b5de7b8dee3f261;p=tools%2Flibrpm-tizen.git Splint annotations and spec file. CVS patchset: 5507 CVS date: 2002/06/18 17:00:30 --- diff --git a/libelf/lib/.lclintrc b/libelf/lib/.lclintrc new file mode 100755 index 0000000..8dcf673 --- /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 2d972f5..25bb4b4 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 +32.fsize.c - implementation of the elf{32,64}_fsize(3) functions. +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -20,28 +20,72 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +#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 403a387..ecfcc54 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 +32.newehdr.c - implementation of the elf{32,64}_newehdr(3) functions. +Copyright (C) 1995 - 2000 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,9 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -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 79ca622..e5ede14 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 +32.newphdr.c - implementation of the elf{32,64}_newphdr(3) functions. +Copyright (C) 1995 - 2000 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,10 +19,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -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 0220a82..32a4c2c 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 +Copyright (C) 1995 - 2002 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,23 +21,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +#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 aa2d71c..77cdeba 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 +Copyright (C) 1995 - 2002 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -21,61 +21,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +#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 9e76bed..a35cbcd 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 +/*@-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 57f803e..07a9e7b 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 +begin.c - implementation of the elf_begin(3) and elf_memory(3) functions. +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -18,13 +18,41 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include + +#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 +#else /* HAVE_AR_H */ + +#define ARMAG "!\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 af7b1d6..94871cb 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 +byteswap.h - functions and macros for byte swapping. +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -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 48ae094..5c0f241 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 c61d8d4..89c371c 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,23 +19,43 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 5771fd3..951978c 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 +Copyright (C) 1995 - 2000 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,19 +19,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 -#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 2414a08..e922af7 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 +Copyright (C) 1995 - 1999 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,28 +19,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 -#else +#else /* HAVE_GETTEXT */ # define dgettext(dom, str) str -#endif +#endif /* HAVE_GETTEXT */ #if HAVE_CATGETS # include +/*@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 /* 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 5811799..f647438 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 +Copyright (C) 1995 - 1998 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,8 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 a1494a1..018da7b 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 7a265b9..3724aa6 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 f492b97..6b2f6f3 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 +Copyright (C) 1995 - 1998 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -20,6 +20,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +#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 fb6be91..324bc05 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,23 +19,56 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 ed8b40d..986e03a 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,9 +19,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 -#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 7d09150..73436c1 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -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 -#else +#else /* __LIBELF_INTERNAL__ */ #include -#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 8963e02..5ab1b64 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 +Copyright (C) 1995 - 1998 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,8 +19,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 49bedb3..fc7f58c 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 +Copyright (C) 1995 - 2002 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,125 +19,211 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include + +#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 +#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 8514f90..1317b7e 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 +Copyright (C) 1995 - 1998 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -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 718df6a..17afbc4 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,9 +19,99 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 211843d..bff5f60 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -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 -#endif +#endif /* HAVE_CONFIG_H */ #include #if STDC_HEADERS # include # include -#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 -#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 -#endif +#endif /* __LIBELF_NEED_LINK_H */ #include #if HAVE_STRUCT_NLIST_DECLARATION # undef nlist -#endif +#endif /* HAVE_STRUCT_NLIST_DECLARATION */ + +#if __LIBELF64 +#include +#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 , 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 +#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 40d998b..9c3f792 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 +Copyright (C) 1995 - 2001 Michael Riepe This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -19,10 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#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 -#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 66da492..abfe0f4 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 9af8389..e110573 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 0000000..03322a0 --- /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 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 +- automated rebuild + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Wed Sep 26 2001 Jakub Jelinek 0.7.0-2 +- fix Elf64_Sxword conversion + +* Tue Jul 3 2001 Jakub Jelinek 0.7.0-1 +- update to 0.7.0 to support 64bit elf + +* Sun Jun 24 2001 Elliot Lee +- Bump release + rebuild. + +* Tue Jul 18 2000 Nalin Dahyabhai +- add %%defattr (release 7) + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Sun Jun 18 2000 Matt Wilson +- rebuilt for next release +- don't build on ia64 (libelf don't grok 64bit elf) + +* Sun Mar 21 1999 Cristian Gafton +- auto rebuild in the new build environment (release 4) + +* Thu Jan 14 1999 Cristian Gafton +- build for glibc 2.1 + +* Fri May 01 1998 Prospector System +- translations modified for de, fr, tr + +* Fri Oct 31 1997 Michael K. Johnson +- upgraded to 0.6.4 +- buildroot +