1 /* Return the next data element from the section after possibly converting it.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@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 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stddef.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "libelfP.h"
27 #include "common.h"
28 #include "elf-knowledge.h"
29
30
31 #if _STRING_ARCH_unaligned
32 # define ALLOW_ALIGNED 1
33 #else
34 # define ALLOW_ALIGNED 0
35 #endif
36
37
38 #define TYPEIDX(Sh_Type) \
39 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
40 ? Sh_Type \
41 : (Sh_Type >= SHT_GNU_LIBLIST && Sh_Type <= SHT_HISUNW \
42 ? SHT_NUM + Sh_Type - SHT_GNU_LIBLIST \
43 : 0))
44
45 static const struct
46 {
47 Elf_Type type;
48 size_t size;
49 #if ALLOW_ALIGNED
50 # define AL(val)
51 #else
52 size_t align;
53 # define AL(val), val
54 #endif
55 } shtype_map[EV_NUM - 1][ELFCLASSNUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
56 {
57 [EV_CURRENT - 1] =
58 {
59 [ELFCLASS32 - 1] =
60 {
61 /* Associate section types with libelf types, their sizes and
62 alignment. SHT_GNU_verdef is special since the section does
63 not contain entries of only one size. */
64 #define DEFINE(Bits) \
65 [SHT_SYMTAB] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \
66 AL (__alignof__ (ElfW2(Bits,Sym))) }, \
67 [SHT_RELA] = { ELF_T_RELA, sizeof (ElfW2(Bits,Rela)) \
68 AL (__alignof__ (ElfW2(Bits,Rela))) }, \
69 [SHT_HASH] = { ELF_T_WORD, sizeof (ElfW2(Bits,Word)) \
70 AL (__alignof__ (ElfW2(Bits,Word))) }, \
71 [SHT_DYNAMIC] = { ELF_T_DYN, sizeof (ElfW2(Bits,Dyn)) \
72 AL (__alignof__ (ElfW2(Bits,Dyn))) }, \
73 [SHT_REL] = { ELF_T_REL, sizeof (ElfW2(Bits,Rel)) \
74 AL (__alignof__ (ElfW2(Bits,Rel))) }, \
75 [SHT_DYNSYM] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \
76 AL (__alignof__ (ElfW2(Bits,Sym))) }, \
77 [SHT_INIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
78 AL (__alignof__ (ElfW2(Bits,Addr))) }, \
79 [SHT_FINI_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
80 AL (__alignof__ (ElfW2(Bits,Addr))) }, \
81 [SHT_PREINIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
82 AL (__alignof__ (ElfW2(Bits,Addr))) }, \
83 [SHT_GROUP] = { ELF_T_WORD, sizeof (Elf32_Word) \
84 AL (__alignof__ (Elf32_Word)) }, \
85 [SHT_SYMTAB_SHNDX] = { ELF_T_WORD, sizeof (Elf32_Word) \
86 AL (__alignof__ (Elf32_Word)) }, \
87 [TYPEIDX (SHT_GNU_verdef)] = { ELF_T_VDEF, 1 AL (1) }, \
88 [TYPEIDX (SHT_GNU_verneed)] = { ELF_T_VNEED, \
89 sizeof (ElfW2(Bits,Verneed)) \
90 AL (__alignof__ (ElfW2(Bits,Verneed)))},\
91 [TYPEIDX (SHT_GNU_versym)] = { ELF_T_HALF, sizeof (ElfW2(Bits,Versym)) \
92 AL (__alignof__ (ElfW2(Bits,Versym))) }, \
93 [TYPEIDX (SHT_SUNW_syminfo)] = { ELF_T_SYMINFO, \
94 sizeof (ElfW2(Bits,Syminfo)) \
95 AL(__alignof__ (ElfW2(Bits,Syminfo)))},\
96 [TYPEIDX (SHT_SUNW_move)] = { ELF_T_MOVE, sizeof (ElfW2(Bits,Move)) \
97 AL (__alignof__ (ElfW2(Bits,Move))) }, \
98 [TYPEIDX (SHT_GNU_LIBLIST)] = { ELF_T_LIB, sizeof (ElfW2(Bits,Lib)) \
99 AL (__alignof__ (ElfW2(Bits,Lib))) }
100 DEFINE (32)
101 },
102 [ELFCLASS64 - 1] =
103 {
104 DEFINE (64)
105 }
106 }
107 };
108
109
110 /* Convert the data in the current section. */
111 static void
convert_data(Elf_Scn * scn,int version,int eclass,int data,size_t size,size_t type)112 convert_data (Elf_Scn *scn, int version, int eclass, int data,
113 size_t size, size_t type)
114 {
115 #if ALLOW_ALIGNED
116 /* No need to compute the alignment requirement of the host. */
117 const size_t align = 1;
118 #else
119 # if EV_NUM != 2
120 size_t align = shtype_map[__libelf_version - 1][eclass - 1][type].align;
121 # else
122 size_t align = shtype_map[0][eclass - 1][type].align;
123 # endif
124 #endif
125
126 if (data == MY_ELFDATA)
127 {
128 if (ALLOW_ALIGNED
129 || (((size_t) ((char *) scn->rawdata_base)) & (align - 1)) == 0)
130 /* No need to copy, we can use the raw data. */
131 scn->data_base = scn->rawdata_base;
132 else
133 {
134 scn->data_base = (char *) malloc (size);
135 if (scn->data_base == NULL)
136 {
137 __libelf_seterrno (ELF_E_NOMEM);
138 return;
139 }
140
141 /* The copy will be appropriately aligned for direct access. */
142 memcpy (scn->data_base, scn->rawdata_base, size);
143 }
144 }
145 else
146 {
147 xfct_t fp;
148
149 scn->data_base = (char *) malloc (size);
150 if (scn->data_base == NULL)
151 {
152 __libelf_seterrno (ELF_E_NOMEM);
153 return;
154 }
155
156 /* Get the conversion function. */
157 #if EV_NUM != 2
158 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
159 #else
160 fp = __elf_xfctstom[0][0][eclass - 1][type];
161 #endif
162
163 fp (scn->data_base, scn->rawdata_base, size, 0);
164 }
165
166 scn->data_list.data.d.d_buf = scn->data_base;
167 scn->data_list.data.d.d_size = size;
168 scn->data_list.data.d.d_type = type;
169 scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
170 scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
171 scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
172
173 scn->data_list.data.s = scn;
174 }
175
176
177 /* Store the information for the raw data in the `rawdata' element. */
178 int
179 internal_function_def
__libelf_set_rawdata(Elf_Scn * scn)180 __libelf_set_rawdata (Elf_Scn *scn)
181 {
182 size_t offset;
183 size_t size;
184 size_t align;
185 int type;
186 Elf *elf = scn->elf;
187
188 if (elf->class == ELFCLASS32)
189 {
190 Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn);
191
192 if (shdr == NULL)
193 /* Something went terribly wrong. */
194 return 1;
195
196 offset = shdr->sh_offset;
197 size = shdr->sh_size;
198 type = shdr->sh_type;
199 align = shdr->sh_addralign;
200 }
201 else
202 {
203 Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (scn);
204
205 if (shdr == NULL)
206 /* Something went terribly wrong. */
207 return 1;
208
209 offset = shdr->sh_offset;
210 size = shdr->sh_size;
211 type = shdr->sh_type;
212 align = shdr->sh_addralign;
213 }
214
215 /* If the section has no data (for whatever reason), leave the `d_buf'
216 pointer NULL. */
217 if (size != 0 && type != SHT_NOBITS)
218 {
219 /* First a test whether the section is valid at all. */
220 size_t entsize;
221
222 if (type == SHT_HASH)
223 {
224 GElf_Ehdr ehdr_mem;
225
226 entsize = SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem));
227 }
228 else
229 {
230 #if EV_NUM != 2
231 entsize = shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].size;
232 #else
233 entsize = shtype_map[0][elf->class - 1][TYPEIDX (type)].size;
234 #endif
235 }
236
237 /* We assume it is an array of bytes if it is none of the structured
238 sections we know of. */
239 if (entsize == 0)
240 entsize = 1;
241
242 if (size % entsize != 0)
243 {
244 __libelf_seterrno (ELF_E_INVALID_DATA);
245 return 1;
246 }
247
248 /* We can use the mapped or loaded data if available. */
249 if (elf->map_address != NULL)
250 {
251 /* First see whether the information in the section header is
252 valid and it does not ask for too much. */
253 if (offset + size > elf->maximum_size)
254 {
255 /* Something is wrong. */
256 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
257 return 1;
258 }
259
260 scn->rawdata_base = scn->rawdata.d.d_buf
261 = (char *) elf->map_address + elf->start_offset + offset;
262 }
263 else if (elf->fildes != -1)
264 {
265 /* We have to read the data from the file. Allocate the needed
266 memory. */
267 scn->rawdata_base = scn->rawdata.d.d_buf
268 = (char *) malloc (size);
269 if (scn->rawdata.d.d_buf == NULL)
270 {
271 __libelf_seterrno (ELF_E_NOMEM);
272 return 1;
273 }
274
275 if ((size_t) pread (elf->fildes, scn->rawdata.d.d_buf, size,
276 elf->start_offset + offset) != size)
277 {
278 /* Cannot read the data. */
279 free (scn->rawdata.d.d_buf);
280 scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
281 __libelf_seterrno (ELF_E_READ_ERROR);
282 return 1;
283 }
284 }
285 else
286 {
287 /* The file descriptor is already closed, we cannot get the data
288 anymore. */
289 __libelf_seterrno (ELF_E_FD_DISABLED);
290 return 1;
291 }
292 }
293
294 scn->rawdata.d.d_size = size;
295 /* Some broken ELF ABI for 64-bit machines use the wrong hash table
296 entry size. See elf-knowledge.h for more information. */
297 if (type == SHT_HASH && elf->class == ELFCLASS64)
298 {
299 GElf_Ehdr ehdr_mem;
300
301 scn->rawdata.d.d_type = (SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem))
302 == 4 ? ELF_T_WORD : ELF_T_XWORD);
303 }
304 else
305 {
306 #if EV_NUM != 2
307 scn->rawdata.d.d_type =
308 shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type;
309 #else
310 scn->rawdata.d.d_type =
311 shtype_map[0][elf->class - 1][TYPEIDX (type)].type;
312 #endif
313 }
314 scn->rawdata.d.d_off = 0;
315 scn->rawdata.d.d_align = align;
316 if (elf->class == ELFCLASS32
317 || (offsetof (struct Elf, state.elf32.ehdr)
318 == offsetof (struct Elf, state.elf64.ehdr)))
319 scn->rawdata.d.d_version =
320 elf->state.elf32.ehdr->e_ident[EI_VERSION];
321 else
322 scn->rawdata.d.d_version =
323 elf->state.elf64.ehdr->e_ident[EI_VERSION];
324
325 scn->rawdata.s = scn;
326
327 scn->data_read = 1;
328
329 /* We actually read data from the file. At least we tried. */
330 scn->flags |= ELF_F_FILEDATA;
331
332 return 0;
333 }
334
335
336 Elf_Data *
elf_getdata(scn,data)337 elf_getdata (scn, data)
338 Elf_Scn *scn;
339 Elf_Data *data;
340 {
341 Elf_Data *result = NULL;
342 Elf *elf;
343
344 if (scn == NULL)
345 return NULL;
346
347 if (unlikely (scn->elf->kind != ELF_K_ELF))
348 {
349 __libelf_seterrno (ELF_E_INVALID_HANDLE);
350 return NULL;
351 }
352
353 /* We will need this multiple times later on. */
354 elf = scn->elf;
355
356 rwlock_rdlock (elf->lock);
357
358 /* If `data' is not NULL this means we are not addressing the initial
359 data in the file. But this also means this data is already read
360 (since otherwise it is not possible to have a valid `data' pointer)
361 and all the data structures are initialized as well. In this case
362 we can simply walk the list of data records. */
363 if (data != NULL)
364 {
365 Elf_Data_List *runp;
366
367 /* It is not possible that if DATA is not NULL the first entry is
368 returned. But this also means that there must be a first data
369 entry. */
370 if (scn->data_list_rear == NULL
371 /* The section the reference data is for must match the section
372 parameter. */
373 || unlikely (((Elf_Data_Scn *) data)->s != scn))
374 {
375 __libelf_seterrno (ELF_E_DATA_MISMATCH);
376 goto out;
377 }
378
379 /* We start searching with the first entry. */
380 runp = &scn->data_list;
381
382 while (1)
383 {
384 /* If `data' does not match any known record punt. */
385 if (runp == NULL)
386 {
387 __libelf_seterrno (ELF_E_DATA_MISMATCH);
388 goto out;
389 }
390
391 if (&runp->data.d == data)
392 /* Found the entry. */
393 break;
394
395 runp = runp->next;
396 }
397
398 /* Return the data for the next data record. */
399 result = runp->next ? &runp->next->data.d : NULL;
400 goto out;
401 }
402
403 /* If the data for this section was not yet initialized do it now. */
404 if (scn->data_read == 0)
405 {
406 /* We cannot acquire a write lock while we are holding a read
407 lock. Therefore give up the read lock and then get the write
408 lock. But this means that the data could meanwhile be
409 modified, therefore start the tests again. */
410 rwlock_unlock (elf->lock);
411 rwlock_wrlock (elf->lock);
412
413 /* Read the data from the file. There is always a file (or
414 memory region) associated with this descriptor since
415 otherwise the `data_read' flag would be set. */
416 if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0)
417 /* Something went wrong. The error value is already set. */
418 goto out;
419 }
420
421 /* At this point we know the raw data is available. But it might be
422 empty in case the section has size zero (for whatever reason).
423 Now create the converted data in case this is necessary. */
424 if (scn->data_list_rear == NULL)
425 {
426 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
427 /* Convert according to the version and the type. */
428 convert_data (scn, __libelf_version, elf->class,
429 (elf->class == ELFCLASS32
430 || (offsetof (struct Elf, state.elf32.ehdr)
431 == offsetof (struct Elf, state.elf64.ehdr))
432 ? elf->state.elf32.ehdr->e_ident[EI_DATA]
433 : elf->state.elf64.ehdr->e_ident[EI_DATA]),
434 scn->rawdata.d.d_size,
435 scn->rawdata.d.d_type);
436 else
437 /* This is an empty or NOBITS section. There is no buffer but
438 the size information etc is important. */
439 scn->data_list.data.d = scn->rawdata.d;
440
441 scn->data_list_rear = &scn->data_list;
442 }
443
444 /* If no data is present we cannot return any. */
445 if (scn->data_list_rear != NULL)
446 /* Return the first data element in the list. */
447 result = &scn->data_list.data.d;
448
449 out:
450 rwlock_unlock (elf->lock);
451
452 return result;
453 }
454 INTDEF(elf_getdata)
455