Initialize Tizen 2.3
[external/prelink.git] / gelf / gelf.c
1 /* Generic ELF wrapper for libelf which does not support gelf_ API.
2    Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
3    Written by Jakub Jelinek <jakub@redhat.com>, 2001.
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; either version 2, or (at your option)
8    any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software Foundation,
17    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 #include <config.h>
20 #include <elf.h>
21 #include <libelf.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include "gelf.h"
26
27 inline int
28 gelf_getclass (Elf *elf)
29 {
30   size_t size;
31   char *e_ident = elf_getident (elf, &size);
32
33   if (e_ident == NULL)
34     return ELFCLASSNONE;
35   switch (e_ident [EI_CLASS])
36     {
37     case ELFCLASS32:
38     case ELFCLASS64:
39       return e_ident [EI_CLASS];
40     default:
41       return ELFCLASSNONE;
42     }
43 }
44
45 size_t
46 gelf_fsize (Elf *elf, Elf_Type type, size_t count, unsigned int ver)
47 {
48   switch (gelf_getclass (elf))
49     {
50     case ELFCLASS32:
51       return elf32_fsize (type, count, ver);
52     case ELFCLASS64:
53       return elf64_fsize (type, count, ver);
54     default:
55       return 0;
56     }
57 }
58
59 GElf_Ehdr *
60 gelf_getehdr (Elf *elf, GElf_Ehdr *dst)
61 {
62   Elf32_Ehdr *ehdr32;
63   Elf64_Ehdr *ehdr64;
64
65   switch (gelf_getclass (elf))
66     {
67     case ELFCLASS32:
68       ehdr32 = elf32_getehdr (elf);
69       if (ehdr32 != NULL)
70         {
71           memcpy (dst->e_ident, ehdr32->e_ident, EI_NIDENT);
72           dst->e_type = ehdr32->e_type;
73           dst->e_machine = ehdr32->e_machine;
74           dst->e_version = ehdr32->e_version;
75           dst->e_entry = ehdr32->e_entry;
76           dst->e_phoff = ehdr32->e_phoff;
77           dst->e_shoff = ehdr32->e_shoff;
78           dst->e_flags = ehdr32->e_flags;
79           dst->e_ehsize = ehdr32->e_ehsize;
80           dst->e_phentsize = ehdr32->e_phentsize;
81           dst->e_phnum = ehdr32->e_phnum;
82           dst->e_shentsize = ehdr32->e_shentsize;
83           dst->e_shnum = ehdr32->e_shnum;
84           dst->e_shstrndx = ehdr32->e_shstrndx;
85           return dst;
86         }
87       break;
88     case ELFCLASS64:
89       ehdr64 = elf64_getehdr (elf);
90       if (ehdr64 != NULL)
91         {
92           memcpy (dst, ehdr64, sizeof (Elf64_Ehdr));
93           return dst;
94         }
95     }
96   return NULL;
97 }
98
99 int
100 gelf_update_ehdr (Elf *elf, GElf_Ehdr *src)
101 {
102   Elf32_Ehdr *ehdr32;
103   Elf64_Ehdr *ehdr64;
104
105   switch (gelf_getclass (elf))
106     {
107     case ELFCLASS32:
108       ehdr32 = elf32_getehdr (elf);
109       if (ehdr32 == NULL)
110         return 0;
111       memcpy (ehdr32->e_ident, src->e_ident, EI_NIDENT);
112       ehdr32->e_type = src->e_type;
113       ehdr32->e_machine = src->e_machine;
114       ehdr32->e_version = src->e_version;
115       ehdr32->e_entry = src->e_entry;
116       ehdr32->e_phoff = src->e_phoff;
117       ehdr32->e_shoff = src->e_shoff;
118       ehdr32->e_flags = src->e_flags;
119       ehdr32->e_ehsize = src->e_ehsize;
120       ehdr32->e_phentsize = src->e_phentsize;
121       ehdr32->e_phnum = src->e_phnum;
122       ehdr32->e_shentsize = src->e_shentsize;
123       ehdr32->e_shnum = src->e_shnum;
124       ehdr32->e_shstrndx = src->e_shstrndx;
125       return 1;
126     case ELFCLASS64:
127       ehdr64 = elf64_getehdr (elf);
128       if (ehdr64 != NULL)
129         {
130           memcpy (ehdr64, src, sizeof (Elf64_Ehdr));
131           return 1;
132         }
133     default:
134       break;
135     }
136   return 0;
137 }
138
139 unsigned long
140 gelf_newehdr (Elf *elf, int class)
141 {
142   switch (class)
143     {
144     case ELFCLASS32:
145       return (unsigned long) elf32_newehdr (elf);
146     case ELFCLASS64:
147       return (unsigned long) elf64_newehdr (elf);
148     default:
149       return 0;
150     }
151 }
152
153 GElf_Phdr *
154 gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst)
155 {
156   Elf32_Ehdr *ehdr32;
157   Elf64_Ehdr *ehdr64;
158   Elf32_Phdr *phdr32;
159   Elf64_Phdr *phdr64;
160
161   switch (gelf_getclass (elf))
162     {
163     case ELFCLASS32:
164       phdr32 = elf32_getphdr (elf);
165       if (phdr32 == NULL)
166         return NULL;
167       ehdr32 = elf32_getehdr (elf);
168       if (ehdr32 == NULL)
169         return NULL;
170       if (ndx >= ehdr32->e_phnum)
171         return NULL;
172       phdr32 += ndx;
173       dst->p_type = phdr32->p_type;
174       dst->p_offset = phdr32->p_offset;
175       dst->p_vaddr = phdr32->p_vaddr;
176       dst->p_paddr = phdr32->p_paddr;
177       dst->p_filesz = phdr32->p_filesz;
178       dst->p_memsz = phdr32->p_memsz;
179       dst->p_flags = phdr32->p_flags;
180       dst->p_align = phdr32->p_align;
181       return dst;
182     case ELFCLASS64:
183       phdr64 = elf64_getphdr (elf);
184       if (phdr64 == NULL)
185         return NULL;
186       ehdr64 = elf64_getehdr (elf);
187       if (ehdr64 == NULL)
188         return NULL;
189       if (ndx >= ehdr64->e_phnum)
190         return NULL;
191       memcpy (dst, phdr64 + ndx, sizeof (Elf64_Phdr));
192       return dst;
193     default:
194       return NULL;
195     }
196 }
197
198 int
199 gelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src)
200 {
201   Elf32_Ehdr *ehdr32;
202   Elf64_Ehdr *ehdr64;
203   Elf32_Phdr *phdr32;
204   Elf64_Phdr *phdr64;
205
206   switch (gelf_getclass (elf))
207     {
208     case ELFCLASS32:
209       phdr32 = elf32_getphdr (elf);
210       if (phdr32 == NULL)
211         return 0;
212       ehdr32 = elf32_getehdr (elf);
213       if (ehdr32 == NULL)
214         return 0;
215       if (ndx >= ehdr32->e_phnum)
216         return 0;
217       phdr32 += ndx;
218       phdr32->p_type = src->p_type;
219       phdr32->p_offset = src->p_offset;
220       phdr32->p_vaddr = src->p_vaddr;
221       phdr32->p_paddr = src->p_paddr;
222       phdr32->p_filesz = src->p_filesz;
223       phdr32->p_memsz = src->p_memsz;
224       phdr32->p_flags = src->p_flags;
225       phdr32->p_align = src->p_align;
226       return 1;
227     case ELFCLASS64:
228       phdr64 = elf64_getphdr (elf);
229       if (phdr64 == NULL)
230         return 0;
231       ehdr64 = elf64_getehdr (elf);
232       if (ehdr64 == NULL)
233         return 0;
234       if (ndx >= ehdr64->e_phnum)
235         return 0;
236       memcpy (phdr64 + ndx, src, sizeof (Elf64_Phdr));
237       return 1;
238     default:
239       return 0;
240     }
241 }
242
243 unsigned long
244 gelf_newphdr (Elf *elf, size_t phnum)
245 {
246   switch (gelf_getclass (elf))
247     {
248     case ELFCLASS32:
249       return (unsigned long) elf32_newphdr (elf, phnum);
250     case ELFCLASS64:
251       return (unsigned long) elf64_newphdr (elf, phnum);
252     default:
253       return 0;
254     }
255 }
256
257 GElf_Shdr *
258 gelfx_getshdr (Elf *elf, Elf_Scn *scn, GElf_Shdr *dst)
259 {
260   Elf32_Shdr *shdr32;
261   Elf64_Shdr *shdr64;
262
263   switch (gelf_getclass (elf))
264     {
265     case ELFCLASS32:
266       shdr32 = elf32_getshdr (scn);
267       if (shdr32 == NULL)
268         return NULL;
269       dst->sh_name = shdr32->sh_name;
270       dst->sh_type = shdr32->sh_type;
271       dst->sh_flags = shdr32->sh_flags;
272       dst->sh_addr = shdr32->sh_addr;
273       dst->sh_offset = shdr32->sh_offset;
274       dst->sh_size = shdr32->sh_size;
275       dst->sh_link = shdr32->sh_link;
276       dst->sh_info = shdr32->sh_info;
277       dst->sh_addralign = shdr32->sh_addralign;
278       dst->sh_entsize = shdr32->sh_entsize;
279       return dst;
280     case ELFCLASS64:
281       shdr64 = elf64_getshdr (scn);
282       if (shdr64 == NULL)
283         return NULL;
284       memcpy (dst, shdr64, sizeof (Elf64_Shdr));
285       return dst;
286     default:
287       return NULL;
288     }
289 }
290
291 int
292 gelfx_update_shdr (Elf *elf, Elf_Scn *scn, GElf_Shdr *src)
293 {
294   Elf32_Shdr *shdr32;
295   Elf64_Shdr *shdr64;
296
297   switch (gelf_getclass (elf))
298     {
299     case ELFCLASS32:
300       shdr32 = elf32_getshdr (scn);
301       if (shdr32 == NULL)
302         return 0;
303       shdr32->sh_name = src->sh_name;
304       shdr32->sh_type = src->sh_type;
305       shdr32->sh_flags = src->sh_flags;
306       shdr32->sh_addr = src->sh_addr;
307       shdr32->sh_offset = src->sh_offset;
308       shdr32->sh_size = src->sh_size;
309       shdr32->sh_link = src->sh_link;
310       shdr32->sh_info = src->sh_info;
311       shdr32->sh_addralign = src->sh_addralign;
312       shdr32->sh_entsize = src->sh_entsize;
313       return 1;
314     case ELFCLASS64:
315       shdr64 = elf64_getshdr (scn);
316       if (shdr64 == NULL)
317         return 0;
318       memcpy (shdr64, src, sizeof (Elf64_Shdr));
319       return 1;
320     default:
321       return 0;
322     }
323 }
324
325 Elf_Data *
326 gelf_xlatetom (Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
327 {
328   switch (gelf_getclass (elf))
329     {
330     case ELFCLASS32:
331       return elf32_xlatetom (dst, src, encode);
332     case ELFCLASS64:
333       return elf64_xlatetom (dst, src, encode);
334     default:
335       return NULL;
336     }
337 }
338
339 Elf_Data *
340 gelf_xlatetof (Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
341 {
342   switch (gelf_getclass (elf))
343     {
344     case ELFCLASS32:
345       return elf32_xlatetof (dst, src, encode);
346     case ELFCLASS64:
347       return elf64_xlatetof (dst, src, encode);
348     default:
349       return NULL;
350     }
351 }
352
353 GElf_Sym *gelfx_getsym (Elf *elf, Elf_Data *data, int ndx, GElf_Sym *dst)
354 {
355   Elf32_Sym *sym32;
356
357   if (data->d_type != ELF_T_SYM)
358     return NULL;
359
360   switch (gelf_getclass (elf))
361     {
362     case ELFCLASS32:
363       if ((ndx + 1) * sizeof (Elf32_Sym) > data->d_size)
364         return NULL;
365       sym32 = &((Elf32_Sym *) data->d_buf)[ndx];
366       dst->st_name = sym32->st_name;
367       dst->st_info = sym32->st_info;
368       dst->st_other = sym32->st_other;
369       dst->st_shndx = sym32->st_shndx;
370       dst->st_value = sym32->st_value;
371       dst->st_size = sym32->st_size;
372       return dst;
373     case ELFCLASS64:
374       if ((ndx + 1) * sizeof (Elf64_Sym) > data->d_size)
375         return NULL;
376       *dst = ((GElf_Sym *) data->d_buf)[ndx];
377       return dst;
378     default:
379       return NULL;
380     }
381 }
382
383 int gelfx_update_sym (Elf *elf, Elf_Data *data, int ndx, GElf_Sym *src)
384 {
385   Elf32_Sym *sym32;
386
387   if (data->d_type != ELF_T_SYM)
388     return 0;
389
390   switch (gelf_getclass (elf))
391     {
392     case ELFCLASS32:
393       if ((ndx + 1) * sizeof (Elf32_Sym) > data->d_size)
394         return 0;
395       sym32 = &((Elf32_Sym *) data->d_buf)[ndx];
396       sym32->st_name = src->st_name;
397       sym32->st_info = src->st_info;
398       sym32->st_other = src->st_other;
399       sym32->st_shndx = src->st_shndx;
400       sym32->st_value = src->st_value;
401       sym32->st_size = src->st_size;
402       return 1;
403     case ELFCLASS64:
404       if ((ndx + 1) * sizeof (Elf64_Sym) > data->d_size)
405         return 0;
406       ((GElf_Sym *) data->d_buf)[ndx] = *src;
407       return 1;
408     default:
409       return 0;
410     }
411 }
412
413 GElf_Dyn *gelfx_getdyn (Elf *elf, Elf_Data *data, int ndx, GElf_Dyn *dst)
414 {
415   Elf32_Dyn *dyn32;
416
417   if (data->d_type != ELF_T_DYN)
418     return NULL;
419
420   switch (gelf_getclass (elf))
421     {
422     case ELFCLASS32:
423       if ((ndx + 1) * sizeof (Elf32_Dyn) > data->d_size)
424         return NULL;
425       dyn32 = &((Elf32_Dyn *) data->d_buf)[ndx];
426       dst->d_tag = dyn32->d_tag;
427       dst->d_un.d_val = dyn32->d_un.d_val;
428       return dst;
429     case ELFCLASS64:
430       if ((ndx + 1) * sizeof (Elf64_Dyn) > data->d_size)
431         return NULL;
432       *dst = ((GElf_Dyn *) data->d_buf)[ndx];
433       return dst;
434     default:
435       return NULL;
436     }
437 }
438
439 int gelfx_update_dyn (Elf *elf, Elf_Data *data, int ndx, GElf_Dyn *src)
440 {
441   Elf32_Dyn *dyn32;
442
443   if (data->d_type != ELF_T_DYN)
444     return 0;
445
446   switch (gelf_getclass (elf))
447     {
448     case ELFCLASS32:
449       if ((ndx + 1) * sizeof (Elf32_Dyn) > data->d_size)
450         return 0;
451       dyn32 = &((Elf32_Dyn *) data->d_buf)[ndx];
452       dyn32->d_tag = src->d_tag;
453       dyn32->d_un.d_val = src->d_un.d_val;
454       return 1;
455     case ELFCLASS64:
456       if ((ndx + 1) * sizeof (Elf64_Dyn) > data->d_size)
457         return 0;
458       ((GElf_Dyn *) data->d_buf)[ndx] = *src;
459       return 1;
460     default:
461       return 0;
462     }
463 }
464
465 GElf_Rel *gelfx_getrel (Elf *elf, Elf_Data *data, int ndx, GElf_Rel *dst)
466 {
467   Elf32_Rel *rel32;
468
469   if (data->d_type != ELF_T_REL)
470     return NULL;
471
472   switch (gelf_getclass (elf))
473     {
474     case ELFCLASS32:
475       if ((ndx + 1) * sizeof (Elf32_Rel) > data->d_size)
476         return NULL;
477       rel32 = &((Elf32_Rel *) data->d_buf)[ndx];
478       dst->r_offset = rel32->r_offset;
479       dst->r_info = GELF_R_INFO (ELF32_R_SYM (rel32->r_info),
480                                  ELF32_R_TYPE (rel32->r_info));
481       return dst;
482     case ELFCLASS64:
483       if ((ndx + 1) * sizeof (Elf64_Rel) > data->d_size)
484         return NULL;
485       *dst = ((GElf_Rel *) data->d_buf)[ndx];
486       return dst;
487     default:
488       return NULL;
489     }
490 }
491
492 int gelfx_update_rel (Elf *elf, Elf_Data *data, int ndx, GElf_Rel *src)
493 {
494   Elf32_Rel *rel32;
495
496   if (data->d_type != ELF_T_REL)
497     return 0;
498
499   switch (gelf_getclass (elf))
500     {
501     case ELFCLASS32:
502       if ((ndx + 1) * sizeof (Elf32_Rel) > data->d_size)
503         return 0;
504       rel32 = &((Elf32_Rel *) data->d_buf)[ndx];
505       rel32->r_offset = src->r_offset;
506       rel32->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info),
507                                      GELF_R_TYPE (src->r_info));
508       return 1;
509     case ELFCLASS64:
510       if ((ndx + 1) * sizeof (Elf64_Rel) > data->d_size)
511         return 0;
512       ((GElf_Rel *) data->d_buf)[ndx] = *src;
513       return 1;
514     default:
515       return 0;
516     }
517 }
518
519 GElf_Rela *gelfx_getrela (Elf *elf, Elf_Data *data, int ndx, GElf_Rela *dst)
520 {
521   Elf32_Rela *rela32;
522
523   if (data->d_type != ELF_T_RELA)
524     return NULL;
525
526   switch (gelf_getclass (elf))
527     {
528     case ELFCLASS32:
529       if ((ndx + 1) * sizeof (Elf32_Rela) > data->d_size)
530         return NULL;
531       rela32 = &((Elf32_Rela *) data->d_buf)[ndx];
532       dst->r_offset = rela32->r_offset;
533       dst->r_info = GELF_R_INFO (ELF32_R_SYM (rela32->r_info),
534                                  ELF32_R_TYPE (rela32->r_info));
535       dst->r_addend = rela32->r_addend;
536       return dst;
537     case ELFCLASS64:
538       if ((ndx + 1) * sizeof (Elf64_Rela) > data->d_size)
539         return NULL;
540       *dst = ((GElf_Rela *) data->d_buf)[ndx];
541       return dst;
542     default:
543       return NULL;
544     }
545 }
546
547 int gelfx_update_rela (Elf *elf, Elf_Data *data, int ndx, GElf_Rela *src)
548 {
549   Elf32_Rela *rela32;
550
551   if (data->d_type != ELF_T_RELA)
552     return 0;
553
554   switch (gelf_getclass (elf))
555     {
556     case ELFCLASS32:
557       if ((ndx + 1) * sizeof (Elf32_Rela) > data->d_size)
558         return 0;
559       rela32 = &((Elf32_Rela *) data->d_buf)[ndx];
560       rela32->r_offset = src->r_offset;
561       rela32->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info),
562                                      GELF_R_TYPE (src->r_info));
563       rela32->r_addend = src->r_addend;
564       return 1;
565     case ELFCLASS64:
566       if ((ndx + 1) * sizeof (Elf64_Rela) > data->d_size)
567         return 0;
568       ((GElf_Rela *) data->d_buf)[ndx] = *src;
569       return 1;
570     default:
571       return 0;
572     }
573 }