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