blob: 20e8e624ba2b6cf4341a92b922bc38d79534e73b [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return the next data element from the section after possibly converting it.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 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
45static 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. */
111static void
112convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
113 int data, 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[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. */
178int
179internal_function_def
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 (INTUSE(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
302 = (SH_ENTSIZE_HASH (INTUSE(gelf_getehdr) (elf, &ehdr_mem))
303 == 4 ? ELF_T_WORD : ELF_T_XWORD);
304 }
305 else
306 {
307#if EV_NUM != 2
308 scn->rawdata.d.d_type =
309 shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type;
310#else
311 scn->rawdata.d.d_type =
312 shtype_map[0][elf->class - 1][TYPEIDX (type)].type;
313#endif
314 }
315 scn->rawdata.d.d_off = 0;
316 scn->rawdata.d.d_align = align;
317 if (elf->class == ELFCLASS32
318 || (offsetof (struct Elf, state.elf32.ehdr)
319 == offsetof (struct Elf, state.elf64.ehdr)))
320 scn->rawdata.d.d_version =
321 elf->state.elf32.ehdr->e_ident[EI_VERSION];
322 else
323 scn->rawdata.d.d_version =
324 elf->state.elf64.ehdr->e_ident[EI_VERSION];
325
326 scn->rawdata.s = scn;
327
328 scn->data_read = 1;
329
330 /* We actually read data from the file. At least we tried. */
331 scn->flags |= ELF_F_FILEDATA;
332
333 return 0;
334}
335
336
337Elf_Data *
338elf_getdata (scn, data)
339 Elf_Scn *scn;
340 Elf_Data *data;
341{
342 Elf_Data *result = NULL;
343 Elf *elf;
344
345 if (scn == NULL)
346 return NULL;
347
348 if (unlikely (scn->elf->kind != ELF_K_ELF))
349 {
350 __libelf_seterrno (ELF_E_INVALID_HANDLE);
351 return NULL;
352 }
353
354 /* We will need this multiple times later on. */
355 elf = scn->elf;
356
357 rwlock_rdlock (elf->lock);
358
359 /* If `data' is not NULL this means we are not addressing the initial
360 data in the file. But this also means this data is already read
361 (since otherwise it is not possible to have a valid `data' pointer)
362 and all the data structures are initialized as well. In this case
363 we can simply walk the list of data records. */
364 if (data != NULL)
365 {
366 Elf_Data_List *runp;
367
368 /* It is not possible that if DATA is not NULL the first entry is
369 returned. But this also means that there must be a first data
370 entry. */
371 if (scn->data_list_rear == NULL
372 /* The section the reference data is for must match the section
373 parameter. */
374 || unlikely (((Elf_Data_Scn *) data)->s != scn))
375 {
376 __libelf_seterrno (ELF_E_DATA_MISMATCH);
377 goto out;
378 }
379
380 /* We start searching with the first entry. */
381 runp = &scn->data_list;
382
383 while (1)
384 {
385 /* If `data' does not match any known record punt. */
386 if (runp == NULL)
387 {
388 __libelf_seterrno (ELF_E_DATA_MISMATCH);
389 goto out;
390 }
391
392 if (&runp->data.d == data)
393 /* Found the entry. */
394 break;
395
396 runp = runp->next;
397 }
398
399 /* Return the data for the next data record. */
400 result = runp->next ? &runp->next->data.d : NULL;
401 goto out;
402 }
403
404 /* If the data for this section was not yet initialized do it now. */
405 if (scn->data_read == 0)
406 {
407 /* We cannot acquire a write lock while we are holding a read
408 lock. Therefore give up the read lock and then get the write
409 lock. But this means that the data could meanwhile be
410 modified, therefore start the tests again. */
411 rwlock_unlock (elf->lock);
412 rwlock_wrlock (elf->lock);
413
414 /* Read the data from the file. There is always a file (or
415 memory region) associated with this descriptor since
416 otherwise the `data_read' flag would be set. */
417 if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0)
418 /* Something went wrong. The error value is already set. */
419 goto out;
420 }
421
422 /* At this point we know the raw data is available. But it might be
423 empty in case the section has size zero (for whatever reason).
424 Now create the converted data in case this is necessary. */
425 if (scn->data_list_rear == NULL)
426 {
427 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
428 /* Convert according to the version and the type. */
429 convert_data (scn, __libelf_version, elf->class,
430 (elf->class == ELFCLASS32
431 || (offsetof (struct Elf, state.elf32.ehdr)
432 == offsetof (struct Elf, state.elf64.ehdr))
433 ? elf->state.elf32.ehdr->e_ident[EI_DATA]
434 : elf->state.elf64.ehdr->e_ident[EI_DATA]),
435 scn->rawdata.d.d_size, 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}
454INTDEF(elf_getdata)