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