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