Home | History | Annotate | Download | only in libelf
      1 /* Conversion functions for versioning information.
      2    Copyright (C) 1998, 1999, 2000, 2002, 2003 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   do
     59     {
     60       size_t aux_offset;
     61       GElf_Verdaux *asrc;
     62 
     63       /* Test for correct offset.  */
     64       if (def_offset > len || len - def_offset < sizeof (GElf_Verdef))
     65 	return;
     66 
     67       /* Work the tree from the first record.  */
     68       ddest = (GElf_Verdef *) ((char *) dest + def_offset);
     69       dsrc = (GElf_Verdef *) ((char *) src + def_offset);
     70 
     71       /* Decode first if necessary.  */
     72       if (! encode)
     73 	{
     74 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
     75 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
     76 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
     77 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
     78 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
     79 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
     80 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
     81 
     82 	  aux_offset = def_offset + ddest->vd_aux;
     83 	}
     84       else
     85 	aux_offset = def_offset + dsrc->vd_aux;
     86 
     87       /* Handle all the auxiliary records belonging to this definition.  */
     88       do
     89 	{
     90 	  GElf_Verdaux *adest;
     91 
     92 	  /* Test for correct offset.  */
     93 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Verdaux))
     94 	    return;
     95 
     96 	  adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
     97 	  asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
     98 
     99 	  if (encode)
    100 	    aux_offset += asrc->vda_next;
    101 
    102 	  adest->vda_name = bswap_32 (asrc->vda_name);
    103 	  adest->vda_next = bswap_32 (asrc->vda_next);
    104 
    105 	  if (! encode)
    106 	    aux_offset += adest->vda_next;
    107 	}
    108       while (asrc->vda_next != 0);
    109 
    110       /* Encode now if necessary.  */
    111       if (encode)
    112 	{
    113 	  def_offset += dsrc->vd_next;
    114 
    115 	  ddest->vd_version = bswap_16 (dsrc->vd_version);
    116 	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
    117 	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
    118 	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
    119 	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
    120 	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
    121 	  ddest->vd_next = bswap_32 (dsrc->vd_next);
    122 	}
    123       else
    124 	def_offset += ddest->vd_next;
    125     }
    126   while (dsrc->vd_next != 0);
    127 }
    128 
    129 
    130 static void
    131 elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
    132 {
    133   /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
    134      To recognize them we have to walk the data structure and convert
    135      them one after the other.  The ENCODE parameter specifies whether
    136      we are encoding or decoding.  When we are encoding we can immediately
    137      use the data in the buffer; if not, we have to decode the data before
    138      using it.  */
    139   size_t need_offset = 0;
    140   GElf_Verneed *ndest;
    141   GElf_Verneed *nsrc;
    142 
    143   /* We rely on the types being all the same size.  */
    144   assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
    145   assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
    146   assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
    147   assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
    148 
    149   if (len == 0)
    150     return;
    151 
    152   do
    153     {
    154       size_t aux_offset;
    155       GElf_Vernaux *asrc;
    156 
    157       /* Test for correct offset.  */
    158       if (need_offset > len || len - need_offset < sizeof (GElf_Verneed))
    159 	return;
    160 
    161       /* Work the tree from the first record.  */
    162       ndest = (GElf_Verneed *) ((char *) dest + need_offset);
    163       nsrc = (GElf_Verneed *) ((char *) src + need_offset);
    164 
    165       /* Decode first if necessary.  */
    166       if (! encode)
    167 	{
    168 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
    169 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
    170 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
    171 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
    172 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
    173 
    174 	  aux_offset = need_offset + ndest->vn_aux;
    175 	}
    176       else
    177 	aux_offset = need_offset + nsrc->vn_aux;
    178 
    179       /* Handle all the auxiliary records belonging to this requirement.  */
    180       do
    181 	{
    182 	  GElf_Vernaux *adest;
    183 
    184 	  /* Test for correct offset.  */
    185 	  if (aux_offset > len || len - aux_offset < sizeof (GElf_Vernaux))
    186 	    return;
    187 
    188 	  adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
    189 	  asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
    190 
    191 	  if (encode)
    192 	    aux_offset += asrc->vna_next;
    193 
    194 	  adest->vna_hash = bswap_32 (asrc->vna_hash);
    195 	  adest->vna_flags = bswap_16 (asrc->vna_flags);
    196 	  adest->vna_other = bswap_16 (asrc->vna_other);
    197 	  adest->vna_name = bswap_32 (asrc->vna_name);
    198 	  adest->vna_next = bswap_32 (asrc->vna_next);
    199 
    200 	  if (! encode)
    201 	    aux_offset += adest->vna_next;
    202 	}
    203       while (asrc->vna_next != 0);
    204 
    205       /* Encode now if necessary.  */
    206       if (encode)
    207 	{
    208 	  need_offset += nsrc->vn_next;
    209 
    210 	  ndest->vn_version = bswap_16 (nsrc->vn_version);
    211 	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
    212 	  ndest->vn_file = bswap_32 (nsrc->vn_file);
    213 	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
    214 	  ndest->vn_next = bswap_32 (nsrc->vn_next);
    215 	}
    216       else
    217 	need_offset += ndest->vn_next;
    218     }
    219   while (nsrc->vn_next != 0);
    220 }
    221