/* * verdef.h - copy versioning information. * Copyright (C) 2001 - 2006 Michael Riepe * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef lint static const char verdef_h_rcsid[] = "@(#) $Id: verdef.h,v 1.13 2008/05/23 08:15:35 michael Exp $"; #endif /* lint */ #if VER_DEF_CURRENT != 1 #error libelf currently does not support VER_DEF_CURRENT != 1 #endif /* VER_DEF_CURRENT != 1 */ #if TOFILE static void __store_verdaux(verdaux_ftype *dst, const verdaux_mtype *src, unsigned enc) { if (enc == ELFDATA2LSB) { __store_u32L(dst->vda_name, src->vda_name); __store_u32L(dst->vda_next, src->vda_next); } else { __store_u32M(dst->vda_name, src->vda_name); __store_u32M(dst->vda_next, src->vda_next); } } static void __store_verdef(verdef_ftype *dst, const verdef_mtype *src, unsigned enc) { if (enc == ELFDATA2LSB) { __store_u16L(dst->vd_version, src->vd_version); __store_u16L(dst->vd_flags, src->vd_flags); __store_u16L(dst->vd_ndx, src->vd_ndx); __store_u16L(dst->vd_cnt, src->vd_cnt); __store_u32L(dst->vd_hash, src->vd_hash); __store_u32L(dst->vd_aux, src->vd_aux); __store_u32L(dst->vd_next, src->vd_next); } else { __store_u16M(dst->vd_version, src->vd_version); __store_u16M(dst->vd_flags, src->vd_flags); __store_u16M(dst->vd_ndx, src->vd_ndx); __store_u16M(dst->vd_cnt, src->vd_cnt); __store_u32M(dst->vd_hash, src->vd_hash); __store_u32M(dst->vd_aux, src->vd_aux); __store_u32M(dst->vd_next, src->vd_next); } } typedef verdaux_mtype verdaux_stype; typedef verdaux_ftype verdaux_dtype; typedef verdef_mtype verdef_stype; typedef verdef_ftype verdef_dtype; typedef align_mtype verdef_atype; #define copy_verdaux_srctotmp(d, s, e) (*(d) = *(s)) #define copy_verdaux_tmptodst(d, s, e) __store_verdaux((d), (s), (e)) #define copy_verdef_srctotmp(d, s, e) (*(d) = *(s)) #define copy_verdef_tmptodst(d, s, e) __store_verdef((d), (s), (e)) #define translator_suffix _tof #else /* TOFILE */ static void __load_verdaux(verdaux_mtype *dst, const verdaux_ftype *src, unsigned enc) { if (enc == ELFDATA2LSB) { dst->vda_name = __load_u32L(src->vda_name); dst->vda_next = __load_u32L(src->vda_next); } else { dst->vda_name = __load_u32M(src->vda_name); dst->vda_next = __load_u32M(src->vda_next); } } static void __load_verdef(verdef_mtype *dst, const verdef_ftype *src, unsigned enc) { if (enc == ELFDATA2LSB) { dst->vd_version = __load_u16L(src->vd_version); dst->vd_flags = __load_u16L(src->vd_flags); dst->vd_ndx = __load_u16L(src->vd_ndx); dst->vd_cnt = __load_u16L(src->vd_cnt); dst->vd_hash = __load_u32L(src->vd_hash); dst->vd_aux = __load_u32L(src->vd_aux); dst->vd_next = __load_u32L(src->vd_next); } else { dst->vd_version = __load_u16M(src->vd_version); dst->vd_flags = __load_u16M(src->vd_flags); dst->vd_ndx = __load_u16M(src->vd_ndx); dst->vd_cnt = __load_u16M(src->vd_cnt); dst->vd_hash = __load_u32M(src->vd_hash); dst->vd_aux = __load_u32M(src->vd_aux); dst->vd_next = __load_u32M(src->vd_next); } } typedef verdaux_ftype verdaux_stype; typedef verdaux_mtype verdaux_dtype; typedef verdef_ftype verdef_stype; typedef verdef_mtype verdef_dtype; typedef align_ftype verdef_atype; #define copy_verdaux_srctotmp(d, s, e) __load_verdaux((d), (s), (e)) #define copy_verdaux_tmptodst(d, s, e) (*(d) = *(s)) #define copy_verdef_srctotmp(d, s, e) __load_verdef((d), (s), (e)) #define copy_verdef_tmptodst(d, s, e) (*(d) = *(s)) #define translator_suffix _tom #endif /* TOFILE */ #define cat3(a,b,c) a##b##c #define xlt3(p,e,s) cat3(p,e,s) #define xltprefix(x) xlt3(x,_,class_suffix) #define translator(x,e) xlt3(xltprefix(_elf_##x),e,translator_suffix) static size_t xlt_verdef(unsigned char *dst, const unsigned char *src, size_t n, unsigned enc) { size_t off; if (sizeof(verdef_stype) != sizeof(verdef_dtype) || sizeof(verdaux_stype) != sizeof(verdaux_dtype)) { /* never happens for ELF v1 and Verneed v1 */ seterr(ERROR_UNIMPLEMENTED); return (size_t)-1; } /* size translation shortcut */ if (dst == NULL) { return n; } if (src == NULL) { seterr(ERROR_NULLBUF); return (size_t)-1; } off = 0; while (off + sizeof(verdef_stype) <= n) { const verdef_stype *svd; verdef_dtype *dvd; verdef_mtype vd; size_t acount; size_t aoff; /* * check for proper alignment */ if (off % sizeof(verdef_atype)) { seterr(ERROR_VERDEF_FORMAT); return (size_t)-1; } /* * copy and check src */ svd = (verdef_stype*)(src + off); dvd = (verdef_dtype*)(dst + off); copy_verdef_srctotmp(&vd, svd, enc); if (vd.vd_version < 1 || vd.vd_version > VER_DEF_CURRENT) { seterr(ERROR_VERDEF_VERSION); return (size_t)-1; } if (vd.vd_cnt < 1 || vd.vd_aux == 0) { seterr(ERROR_VERDEF_FORMAT); return (size_t)-1; } copy_verdef_tmptodst(dvd, &vd, enc); /* * copy aux array */ aoff = off + vd.vd_aux; for (acount = 0; acount < vd.vd_cnt; acount++) { const verdaux_stype *svda; verdaux_dtype *dvda; verdaux_mtype vda; /* * are we still inside the buffer limits? */ if (aoff + sizeof(verdaux_stype) > n) { break; } /* * check for proper alignment */ if (aoff % sizeof(verdef_atype)) { seterr(ERROR_VERDEF_FORMAT); return (size_t)-1; } /* * copy and check src */ svda = (verdaux_stype*)(src + aoff); dvda = (verdaux_dtype*)(dst + aoff); copy_verdaux_srctotmp(&vda, svda, enc); copy_verdaux_tmptodst(dvda, &vda, enc); /* * advance to next verdaux */ if (vda.vda_next == 0) { /* end of list */ break; } aoff += vda.vda_next; } /* * advance to next verdef */ if (vd.vd_next == 0) { /* end of list */ break; } off += vd.vd_next; } return n; } size_t translator(verdef,L11)(unsigned char *dst, const unsigned char *src, size_t n) { return xlt_verdef(dst, src, n, ELFDATA2LSB); } size_t translator(verdef,M11)(unsigned char *dst, const unsigned char *src, size_t n) { return xlt_verdef(dst, src, n, ELFDATA2MSB); }