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