Initialize Tizen 2.3
[external/prelink.git] / src / data.c
1 /* Copyright (C) 2001, 2002 Red Hat, Inc.
2    Written by Jakub Jelinek <jakub@redhat.com>, 2001.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
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 <config.h>
19 #include "prelink.h"
20
21 #define UREAD(le,nn)                                            \
22 uint##nn##_t                                                    \
23 read_u##le##nn (DSO *dso, GElf_Addr addr)                       \
24 {                                                               \
25   unsigned char *data = get_data (dso, addr, NULL);             \
26                                                                 \
27   if (data == NULL)                                             \
28     return 0;                                                   \
29                                                                 \
30   return buf_read_u##le##nn (data);                             \
31 }
32
33 #define WRITE(le,nn)                                            \
34 int                                                             \
35 write_##le##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val)     \
36 {                                                               \
37   int sec;                                                      \
38   unsigned char *data = get_data (dso, addr, &sec);             \
39                                                                 \
40   if (data == NULL)                                             \
41     return -1;                                                  \
42                                                                 \
43   buf_write_##le##nn (data, val);                               \
44   elf_flagscn (dso->scn[sec], ELF_C_SET, ELF_F_DIRTY);          \
45   return 0;                                                     \
46 }
47
48 #define BUFREADUNE(nn)                                          \
49 uint##nn##_t                                                    \
50 buf_read_une##nn (DSO *dso, unsigned char *buf)                 \
51 {                                                               \
52   if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)                \
53     return buf_read_ule32 (buf);                                \
54   else                                                          \
55     return buf_read_ube32 (buf);                                \
56 }
57
58 #define READUNE(nn)                                             \
59 uint##nn##_t                                                    \
60 read_une##nn (DSO *dso, GElf_Addr addr)                         \
61 {                                                               \
62   if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)                \
63     return read_ule##nn (dso, addr);                            \
64   else                                                          \
65     return read_ube##nn (dso, addr);                            \
66 }
67
68 #define WRITENE(nn)                                             \
69 void                                                            \
70 write_ne##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val)       \
71 {                                                               \
72   if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)                \
73     write_le##nn (dso, addr, val);                              \
74   else                                                          \
75     write_be##nn (dso, addr, val);                              \
76 }
77
78 #define BUFWRITENE(nn)                                          \
79 void                                                            \
80 buf_write_ne##nn (DSO *dso, unsigned char *buf,                 \
81                   uint##nn##_t val)                             \
82 {                                                               \
83   if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)                \
84     buf_write_le##nn (buf, val);                                \
85   else                                                          \
86     buf_write_be##nn (buf, val);                                \
87 }
88
89 #define READWRITE(le,nn) UREAD(le,nn) WRITE(le,nn)
90 #define READWRITESIZE(nn) \
91   READWRITE(le,nn) READWRITE(be,nn) \
92   BUFREADUNE(nn) READUNE(nn) \
93   WRITENE(nn) BUFWRITENE(nn)
94
95 unsigned char *
96 get_data (DSO *dso, GElf_Addr addr, int *secp)
97 {
98   int sec = addr_to_sec (dso, addr);
99   Elf_Data *data = NULL;
100
101   if (sec == -1)
102     return NULL;
103
104   if (secp)
105     *secp = sec;
106
107   addr -= dso->shdr[sec].sh_addr;
108   while ((data = elf_getdata (dso->scn[sec], data)) != NULL)
109     if (data->d_off <= addr && data->d_off + data->d_size > addr)
110       return (unsigned char *) data->d_buf + (addr - data->d_off);
111
112   return NULL;
113 }
114
115 /* Initialize IT so that the first byte it provides is address ADDR
116    of DSO.  */
117
118 void
119 init_data_iterator (struct data_iterator *it, DSO *dso, GElf_Addr addr)
120 {
121   it->dso = dso;
122   it->data = NULL;
123   it->addr = addr;
124 }
125
126 /* Return a pointer to the next SIZE bytes pointed to by IT, and move
127    IT to the end of the returned block.  Return null if the data could
128    not be read for some reason.  */
129
130 unsigned char *
131 get_data_from_iterator (struct data_iterator *it, GElf_Addr size)
132 {
133   unsigned char *ptr;
134
135   /* If we're at the end of a data block, move onto the next.  */
136   if (it->data && it->data->d_off + it->data->d_size == it->sec_offset)
137     it->data = elf_getdata (it->dso->scn[it->sec], it->data);
138
139   if (it->data == NULL)
140     {
141       /* Find out which section contains the next byte.  */
142       it->sec = addr_to_sec (it->dso, it->addr);
143       if (it->sec < 0)
144         return NULL;
145
146       /* Fast-forward to the block that contains ADDR, if any.  */
147       it->sec_offset = it->addr - it->dso->shdr[it->sec].sh_addr;
148       do
149         it->data = elf_getdata (it->dso->scn[it->sec], it->data);
150       while (it->data && it->data->d_off + it->data->d_size <= it->sec_offset);
151     }
152
153   /* Make sure that all the data we want is included in this block.  */
154   if (it->data == NULL
155       || it->data->d_off > it->sec_offset
156       || it->data->d_off + it->data->d_size < it->sec_offset + size)
157     return NULL;
158
159   ptr = (unsigned char *) it->data->d_buf + (it->sec_offset - it->data->d_off);
160   it->sec_offset += size;
161   it->addr += size;
162   return ptr;
163 }
164
165 /* Read the symbol pointed to by IT into SYM and move IT onto the
166    next symbol.  Return true on success.  */
167
168 int
169 get_sym_from_iterator (struct data_iterator *it, GElf_Sym *sym)
170 {
171   GElf_Addr offset, size;
172   unsigned char *ptr;
173
174   size = gelf_fsize (it->dso->elf, ELF_T_SYM, 1, EV_CURRENT);
175   ptr = get_data_from_iterator (it, size);
176   if (ptr != NULL)
177     {
178       offset = ptr - (unsigned char *) it->data->d_buf;
179       if (offset % size == 0)
180         {
181           gelfx_getsym (it->dso->elf, it->data, offset / size, sym);
182           return 1;
183         }
184     }
185   return 0;
186 }
187
188 inline uint8_t
189 buf_read_u8 (unsigned char *data)
190 {
191   return *data;
192 }
193
194 inline uint16_t
195 buf_read_ule16 (unsigned char *data)
196 {
197   return data[0] | (data[1] << 8);
198 }
199
200 inline uint16_t
201 buf_read_ube16 (unsigned char *data)
202 {
203   return data[1] | (data[0] << 8);
204 }
205
206 inline uint32_t
207 buf_read_ule32 (unsigned char *data)
208 {
209   return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
210 }
211
212 inline uint32_t
213 buf_read_ube32 (unsigned char *data)
214 {
215   return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
216 }
217
218 inline uint64_t
219 buf_read_ule64 (unsigned char *data)
220 {
221   return (data[0] | (data[1] << 8) | (data[2] << 16))
222          | (((uint64_t)data[3]) << 24)
223          | (((uint64_t)data[4]) << 32)
224          | (((uint64_t)data[5]) << 40)
225          | (((uint64_t)data[6]) << 48)
226          | (((uint64_t)data[7]) << 56);
227 }
228
229 inline uint64_t
230 buf_read_ube64 (unsigned char *data)
231 {
232   return (data[7] | (data[6] << 8) | (data[5] << 16))
233          | (((uint64_t)data[4]) << 24)
234          | (((uint64_t)data[3]) << 32)
235          | (((uint64_t)data[2]) << 40)
236          | (((uint64_t)data[1]) << 48)
237          | (((uint64_t)data[0]) << 56);
238 }
239
240 inline void
241 buf_write_8 (unsigned char *data, uint8_t val)
242 {
243   *data = val;
244 }
245
246 inline void
247 buf_write_le16 (unsigned char *data, uint16_t val)
248 {
249   data[0] = val;
250   data[1] = val >> 8;
251 }
252
253 inline void
254 buf_write_be16 (unsigned char *data, uint16_t val)
255 {
256   data[1] = val;
257   data[0] = val >> 8;
258 }
259
260 inline void
261 buf_write_le32 (unsigned char *data, uint32_t val)
262 {
263   data[0] = val;
264   data[1] = val >> 8;
265   data[2] = val >> 16;
266   data[3] = val >> 24;
267 }
268
269 inline void
270 buf_write_be32 (unsigned char *data, uint32_t val)
271 {
272   data[3] = val;
273   data[2] = val >> 8;
274   data[1] = val >> 16;
275   data[0] = val >> 24;
276 }
277
278 inline void
279 buf_write_le64 (unsigned char *data, uint64_t val)
280 {
281   data[0] = val;
282   data[1] = val >> 8;
283   data[2] = val >> 16;
284   data[3] = val >> 24;
285   data[4] = val >> 32;
286   data[5] = val >> 40;
287   data[6] = val >> 48;
288   data[7] = val >> 56;
289 }
290
291 inline void
292 buf_write_be64 (unsigned char *data, uint64_t val)
293 {
294   data[7] = val;
295   data[6] = val >> 8;
296   data[5] = val >> 16;
297   data[4] = val >> 24;
298   data[3] = val >> 32;
299   data[2] = val >> 40;
300   data[1] = val >> 48;
301   data[0] = val >> 56;
302 }
303
304 READWRITE(,8)
305 READWRITESIZE(16)
306 READWRITESIZE(32)
307 READWRITESIZE(64)
308
309 const char *
310 strptr (DSO *dso, int sec, off_t offset)
311 {
312   Elf_Scn *scn;
313   Elf_Data *data;
314
315   scn = dso->scn[sec];
316   if (offset >= 0 && offset < dso->shdr[sec].sh_size)
317     {
318       data = NULL;
319       while ((data = elf_getdata (scn, data)) != NULL)
320         {
321           if (data->d_buf
322               && offset >= data->d_off
323               && offset < data->d_off + data->d_size)
324             return (const char *) data->d_buf + (offset - data->d_off);
325         }
326     }
327
328   return NULL;
329 }