• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
elf_cvt_Verdef(void * dest,const void * src,size_t len,int encode)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
elf_cvt_Verneed(void * dest,const void * src,size_t len,int encode)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