Home | History | Annotate | Download | only in libelf
      1 /* Conversion functions for versioning information.
      2    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #include <assert.h>
     31 #include <gelf.h>
     32 
     33 #include "libelfP.h"
     34 
     35 
     36 static void
     37 elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
     38 {
     39   /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
     40      To recognize them we have to walk the data structure and convert
     41      them one after the other.  The ENCODE parameter specifies whether
     42      we are encoding or decoding.  When we are encoding we can immediately
     43      use the data in the buffer; if not, we have to decode the data before
     44      using it.  */
     45   size_t def_offset = 0;
     46   GElf_Verdef *ddest;
     47   GElf_Verdef *dsrc;
     48 
     49   /* We rely on the types being all the same size.  */
     50   assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
     51   assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
     52   assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
     53   assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
     54 
     55   if (len == 0)
     56     return;
     57 
     58   /* Below we rely on the next field offsets to be correct, start by
     59      copying over all data as is in case some data isn't translated.
     60      We don't want to leave (undefined) garbage in the dest buffer.  */
     61   memmove (dest, src, len);
     62 
     63   do
     64     {
     65       size_t aux_offset;
     66       GElf_Verdaux *asrc;
     67 
     68       /* Test for correct offset.  */
     69       if (def_offset > len || len - def_offset < sizeof (GElf_Verdef))
     70 	return;
     71 
     72       /* Work the tree from the first record.  */
     73       ddest = (GElf_Verdef *) ((char *) dest + def_offset);
     74       dsrc = (GElf_Verdef *) ((char *) src + def_offset);
     75 
     76       /* Decode first if necessary.  */
     77       if (! encode)
     78 	{
     79 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
     80 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
     81 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
     82 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
     83 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
     84 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
     85 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
     86 
     87 	  aux_offset = def_offset + ddest->vd_aux;
     88 	}
     89       else
     90 	aux_offset = def_offset + dsrc->vd_aux;
     91 
     92       /* Handle all the auxiliary records belonging to this definition.  */
     93       do
     94 	{
     95 	  GElf_Verdaux *adest;
     96 
     97 	  /* Test for correct offset.  */
     98 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Verdaux))
     99 	    return;
    100 
    101 	  adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
    102 	  asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
    103 
    104 	  if (encode)
    105 	    aux_offset += asrc->vda_next;
    106 
    107 	  adest->vda_name = bswap_32 (asrc->vda_name);
    108 	  adest->vda_next = bswap_32 (asrc->vda_next);
    109 
    110 	  if (! encode)
    111 	    aux_offset += adest->vda_next;
    112 	}
    113       while (asrc->vda_next != 0);
    114 
    115       /* Encode now if necessary.  */
    116       if (encode)
    117 	{
    118 	  def_offset += dsrc->vd_next;
    119 
    120 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
    121 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
    122 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
    123 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
    124 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
    125 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
    126 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
    127 	}
    128       else
    129 	def_offset += ddest->vd_next;
    130     }
    131   while (dsrc->vd_next != 0);
    132 }
    133 
    134 
    135 static void
    136 elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
    137 {
    138   /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
    139      To recognize them we have to walk the data structure and convert
    140      them one after the other.  The ENCODE parameter specifies whether
    141      we are encoding or decoding.  When we are encoding we can immediately
    142      use the data in the buffer; if not, we have to decode the data before
    143      using it.  */
    144   size_t need_offset = 0;
    145   GElf_Verneed *ndest;
    146   GElf_Verneed *nsrc;
    147 
    148   /* We rely on the types being all the same size.  */
    149   assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
    150   assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
    151   assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
    152   assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
    153 
    154   if (len == 0)
    155     return;
    156 
    157   /* Below we rely on the next field offsets to be correct, start by
    158      copying over all data as is in case some data isn't translated.
    159      We don't want to leave (undefined) garbage in the dest buffer.  */
    160   memmove (dest, src, len);
    161 
    162   do
    163     {
    164       size_t aux_offset;
    165       GElf_Vernaux *asrc;
    166 
    167       /* Test for correct offset.  */
    168       if (need_offset > len || len - need_offset < sizeof (GElf_Verneed))
    169 	return;
    170 
    171       /* Work the tree from the first record.  */
    172       ndest = (GElf_Verneed *) ((char *) dest + need_offset);
    173       nsrc = (GElf_Verneed *) ((char *) src + need_offset);
    174 
    175       /* Decode first if necessary.  */
    176       if (! encode)
    177 	{
    178 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
    179 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
    180 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
    181 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
    182 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
    183 
    184 	  aux_offset = need_offset + ndest->vn_aux;
    185 	}
    186       else
    187 	aux_offset = need_offset + nsrc->vn_aux;
    188 
    189       /* Handle all the auxiliary records belonging to this requirement.  */
    190       do
    191 	{
    192 	  GElf_Vernaux *adest;
    193 
    194 	  /* Test for correct offset.  */
    195 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Vernaux))
    196 	    return;
    197 
    198 	  adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
    199 	  asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
    200 
    201 	  if (encode)
    202 	    aux_offset += asrc->vna_next;
    203 
    204 	  adest->vna_hash = bswap_32 (asrc->vna_hash);
    205 	  adest->vna_flags = bswap_16 (asrc->vna_flags);
    206 	  adest->vna_other = bswap_16 (asrc->vna_other);
    207 	  adest->vna_name = bswap_32 (asrc->vna_name);
    208 	  adest->vna_next = bswap_32 (asrc->vna_next);
    209 
    210 	  if (! encode)
    211 	    aux_offset += adest->vna_next;
    212 	}
    213       while (asrc->vna_next != 0);
    214 
    215       /* Encode now if necessary.  */
    216       if (encode)
    217 	{
    218 	  need_offset += nsrc->vn_next;
    219 
    220 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
    221 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
    222 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
    223 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
    224 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
    225 	}
    226       else
    227 	need_offset += ndest->vn_next;
    228     }
    229   while (nsrc->vn_next != 0);
    230 }
    231