Git init
[external/libelf.git] / lib / cook.c
1 /*
2  * cook.c - read and translate ELF files.
3  * Copyright (C) 1995 - 2006 Michael Riepe
4  * 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * 
10  * This library 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 GNU
13  * Library General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <private.h>
21
22 #ifndef lint
23 static const char rcsid[] = "@(#) $Id: cook.c,v 1.29 2008/05/23 08:15:34 michael Exp $";
24 #endif /* lint */
25
26 const Elf_Scn _elf_scn_init = INIT_SCN;
27 const Scn_Data _elf_data_init = INIT_DATA;
28
29 Elf_Type
30 _elf_scn_type(unsigned t) {
31     switch (t) {
32         case SHT_DYNAMIC:       return ELF_T_DYN;
33         case SHT_DYNSYM:        return ELF_T_SYM;
34         case SHT_HASH:          return ELF_T_WORD;
35         case SHT_REL:           return ELF_T_REL;
36         case SHT_RELA:          return ELF_T_RELA;
37         case SHT_SYMTAB:        return ELF_T_SYM;
38         case SHT_SYMTAB_SHNDX:  return ELF_T_WORD;      /* XXX: really? */
39 #if __LIBELF_SYMBOL_VERSIONS
40 #if __LIBELF_SUN_SYMBOL_VERSIONS
41         case SHT_SUNW_verdef:   return ELF_T_VDEF;
42         case SHT_SUNW_verneed:  return ELF_T_VNEED;
43         case SHT_SUNW_versym:   return ELF_T_HALF;
44 #else /* __LIBELF_SUN_SYMBOL_VERSIONS */
45         case SHT_GNU_verdef:    return ELF_T_VDEF;
46         case SHT_GNU_verneed:   return ELF_T_VNEED;
47         case SHT_GNU_versym:    return ELF_T_HALF;
48 #endif /* __LIBELF_SUN_SYMBOL_VERSIONS */
49 #endif /* __LIBELF_SYMBOL_VERSIONS */
50     }
51     return ELF_T_BYTE;
52 }
53
54 /*
55  * Check for overflow on 32-bit systems
56  */
57 #define overflow(a,b,t) (sizeof(a) < sizeof(t) && (t)(a) != (b))
58
59 #define truncerr(t) ((t)==ELF_T_EHDR?ERROR_TRUNC_EHDR:  \
60                     ((t)==ELF_T_PHDR?ERROR_TRUNC_PHDR:  \
61                     ERROR_INTERNAL))
62 #define memerr(t)   ((t)==ELF_T_EHDR?ERROR_MEM_EHDR:    \
63                     ((t)==ELF_T_PHDR?ERROR_MEM_PHDR:    \
64                     ERROR_INTERNAL))
65
66 Elf_Data*
67 _elf_xlatetom(const Elf *elf, Elf_Data *dst, const Elf_Data *src) {
68     if (elf->e_class == ELFCLASS32) {
69         return elf32_xlatetom(dst, src, elf->e_encoding);
70     }
71 #if __LIBELF64
72     else if (elf->e_class == ELFCLASS64) {
73         return elf64_xlatetom(dst, src, elf->e_encoding);
74     }
75 #endif /* __LIBELF64 */
76     seterr(ERROR_UNIMPLEMENTED);
77     return NULL;
78 }
79
80 static char*
81 _elf_item(void *buf, Elf *elf, Elf_Type type, size_t off) {
82     Elf_Data src, dst;
83
84     elf_assert(valid_type(type));
85     if (off < 0 || off > elf->e_size) {
86         seterr(ERROR_OUTSIDE);
87         return NULL;
88     }
89
90     src.d_type = type;
91     src.d_version = elf->e_version;
92     src.d_size = _fsize(elf->e_class, src.d_version, type);
93     elf_assert(src.d_size);
94     if ((elf->e_size - off) < src.d_size) {
95         seterr(truncerr(type));
96         return NULL;
97     }
98
99     dst.d_version = _elf_version;
100     dst.d_size = _msize(elf->e_class, dst.d_version, type);
101     elf_assert(dst.d_size);
102
103     if (!(dst.d_buf = buf) && !(dst.d_buf = malloc(dst.d_size))) {
104         seterr(memerr(type));
105         return NULL;
106     }
107
108     elf_assert(elf->e_data);
109     if (elf->e_rawdata) {
110         src.d_buf = elf->e_rawdata + off;
111     }
112     else {
113         src.d_buf = elf->e_data + off;
114     }
115
116     if (_elf_xlatetom(elf, &dst, &src)) {
117         return (char*)dst.d_buf;
118     }
119     if (dst.d_buf != buf) {
120         free(dst.d_buf);
121     }
122     return NULL;
123 }
124
125 static int
126 _elf_cook_phdr(Elf *elf) {
127     size_t num, off, entsz;
128
129     if (elf->e_class == ELFCLASS32) {
130         num = ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum;
131         off = ((Elf32_Ehdr*)elf->e_ehdr)->e_phoff;
132         entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_phentsize;
133     }
134 #if __LIBELF64
135     else if (elf->e_class == ELFCLASS64) {
136         num = ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum;
137         off = ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff;
138         entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_phentsize;
139         /*
140          * Check for overflow on 32-bit systems
141          */
142         if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff, Elf64_Off)) {
143             seterr(ERROR_OUTSIDE);
144             return 0;
145         }
146     }
147 #endif /* __LIBELF64 */
148     else {
149         seterr(ERROR_UNIMPLEMENTED);
150         return 0;
151     }
152     if (off) {
153         Elf_Scn *scn;
154         size_t size;
155         unsigned i;
156         char *p;
157
158         if (num == PN_XNUM) {
159             /*
160              * Overflow in ehdr->e_phnum.
161              * Get real value from first SHDR.
162              */
163             if (!(scn = elf->e_scn_1)) {
164                 seterr(ERROR_NOSUCHSCN);
165                 return 0;
166             }
167             if (elf->e_class == ELFCLASS32) {
168                 num = scn->s_shdr32.sh_info;
169             }
170 #if __LIBELF64
171             else if (elf->e_class == ELFCLASS64) {
172                 num = scn->s_shdr64.sh_info;
173             }
174 #endif /* __LIBELF64 */
175             /* we already had this
176             else {
177                 seterr(ERROR_UNIMPLEMENTED);
178                 return 0;
179             }
180             */
181         }
182
183         size = _fsize(elf->e_class, elf->e_version, ELF_T_PHDR);
184         elf_assert(size);
185 #if ENABLE_EXTENDED_FORMAT
186         if (entsz < size) {
187 #else /* ENABLE_EXTENDED_FORMAT */
188         if (entsz != size) {
189 #endif /* ENABLE_EXTENDED_FORMAT */
190             seterr(ERROR_EHDR_PHENTSIZE);
191             return 0;
192         }
193         size = _msize(elf->e_class, _elf_version, ELF_T_PHDR);
194         elf_assert(size);
195         if (!(p = malloc(num * size))) {
196             seterr(memerr(ELF_T_PHDR));
197             return 0;
198         }
199         for (i = 0; i < num; i++) {
200             if (!_elf_item(p + i * size, elf, ELF_T_PHDR, off + i * entsz)) {
201                 free(p);
202                 return 0;
203             }
204         }
205         elf->e_phdr = p;
206         elf->e_phnum = num;
207     }
208     return 1;
209 }
210
211 static int
212 _elf_cook_shdr(Elf *elf) {
213     size_t num, off, entsz;
214
215     if (elf->e_class == ELFCLASS32) {
216         num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum;
217         off = ((Elf32_Ehdr*)elf->e_ehdr)->e_shoff;
218         entsz = ((Elf32_Ehdr*)elf->e_ehdr)->e_shentsize;
219     }
220 #if __LIBELF64
221     else if (elf->e_class == ELFCLASS64) {
222         num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum;
223         off = ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff;
224         entsz = ((Elf64_Ehdr*)elf->e_ehdr)->e_shentsize;
225         /*
226          * Check for overflow on 32-bit systems
227          */
228         if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff, Elf64_Off)) {
229             seterr(ERROR_OUTSIDE);
230             return 0;
231         }
232     }
233 #endif /* __LIBELF64 */
234     else {
235         seterr(ERROR_UNIMPLEMENTED);
236         return 0;
237     }
238     if (off) {
239         struct tmp {
240             Elf_Scn     scn;
241             Scn_Data    data;
242         } *head;
243         Elf_Data src, dst;
244         Elf_Scn *scn;
245         Scn_Data *sd;
246         unsigned i;
247
248         if (off < 0 || off > elf->e_size) {
249             seterr(ERROR_OUTSIDE);
250             return 0;
251         }
252
253         src.d_type = ELF_T_SHDR;
254         src.d_version = elf->e_version;
255         src.d_size = _fsize(elf->e_class, src.d_version, ELF_T_SHDR);
256         elf_assert(src.d_size);
257 #if ENABLE_EXTENDED_FORMAT
258         if (entsz < src.d_size) {
259 #else /* ENABLE_EXTENDED_FORMAT */
260         if (entsz != src.d_size) {
261 #endif /* ENABLE_EXTENDED_FORMAT */
262             seterr(ERROR_EHDR_SHENTSIZE);
263             return 0;
264         }
265         dst.d_version = EV_CURRENT;
266
267         if (num == 0) {
268             union {
269                 Elf32_Shdr sh32;
270 #if __LIBELF64
271                 Elf64_Shdr sh64;
272 #endif /* __LIBELF64 */
273             } u;
274
275             /*
276              * Overflow in ehdr->e_shnum.
277              * Get real value from first SHDR.
278              */
279             if (elf->e_size - off < entsz) {
280                 seterr(ERROR_TRUNC_SHDR);
281                 return 0;
282             }
283             if (elf->e_rawdata) {
284                 src.d_buf = elf->e_rawdata + off;
285             }
286             else {
287                 src.d_buf = elf->e_data + off;
288             }
289             dst.d_buf = &u;
290             dst.d_size = sizeof(u);
291             if (!_elf_xlatetom(elf, &dst, &src)) {
292                 return 0;
293             }
294             elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR));
295             elf_assert(dst.d_type == ELF_T_SHDR);
296             if (elf->e_class == ELFCLASS32) {
297                 num = u.sh32.sh_size;
298             }
299 #if __LIBELF64
300             else if (elf->e_class == ELFCLASS64) {
301                 num = u.sh64.sh_size;
302                 /*
303                  * Check for overflow on 32-bit systems
304                  */
305                 if (overflow(num, u.sh64.sh_size, Elf64_Xword)) {
306                     seterr(ERROR_OUTSIDE);
307                     return 0;
308                 }
309             }
310 #endif /* __LIBELF64 */
311         }
312
313         if ((elf->e_size - off) / entsz < num) {
314             seterr(ERROR_TRUNC_SHDR);
315             return 0;
316         }
317
318         if (!(head = (struct tmp*)malloc(num * sizeof(struct tmp)))) {
319             seterr(ERROR_MEM_SCN);
320             return 0;
321         }
322         for (scn = NULL, i = num; i-- > 0; ) {
323             head[i].scn = _elf_scn_init;
324             head[i].data = _elf_data_init;
325             head[i].scn.s_link = scn;
326             if (!scn) {
327                 elf->e_scn_n = &head[i].scn;
328             }
329             scn = &head[i].scn;
330             sd = &head[i].data;
331
332             if (elf->e_rawdata) {
333                 src.d_buf = elf->e_rawdata + off + i * entsz;
334             }
335             else {
336                 src.d_buf = elf->e_data + off + i * entsz;
337             }
338             dst.d_buf = &scn->s_uhdr;
339             dst.d_size = sizeof(scn->s_uhdr);
340             if (!_elf_xlatetom(elf, &dst, &src)) {
341                 elf->e_scn_n = NULL;
342                 free(head);
343                 return 0;
344             }
345             elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR));
346             elf_assert(dst.d_type == ELF_T_SHDR);
347
348             scn->s_elf = elf;
349             scn->s_index = i;
350             scn->s_data_1 = sd;
351             scn->s_data_n = sd;
352
353             sd->sd_scn = scn;
354
355             if (elf->e_class == ELFCLASS32) {
356                 Elf32_Shdr *shdr = &scn->s_shdr32;
357
358                 scn->s_type = shdr->sh_type;
359                 scn->s_size = shdr->sh_size;
360                 scn->s_offset = shdr->sh_offset;
361                 sd->sd_data.d_align = shdr->sh_addralign;
362                 sd->sd_data.d_type = _elf_scn_type(scn->s_type);
363             }
364 #if __LIBELF64
365             else if (elf->e_class == ELFCLASS64) {
366                 Elf64_Shdr *shdr = &scn->s_shdr64;
367
368                 scn->s_type = shdr->sh_type;
369                 scn->s_size = shdr->sh_size;
370                 scn->s_offset = shdr->sh_offset;
371                 sd->sd_data.d_align = shdr->sh_addralign;
372                 /*
373                  * Check for overflow on 32-bit systems
374                  */
375                 if (overflow(scn->s_size, shdr->sh_size, Elf64_Xword)
376                  || overflow(scn->s_offset, shdr->sh_offset, Elf64_Off)
377                  || overflow(sd->sd_data.d_align, shdr->sh_addralign, Elf64_Xword)) {
378                     seterr(ERROR_OUTSIDE);
379                     return 0;
380                 }
381                 sd->sd_data.d_type = _elf_scn_type(scn->s_type);
382                 /*
383                  * QUIRKS MODE:
384                  *
385                  * Some 64-bit architectures use 64-bit entries in the
386                  * .hash section. This violates the ELF standard, and
387                  * should be fixed. It's mostly harmless as long as the
388                  * binary and the machine running your program have the
389                  * same byte order, but you're in trouble if they don't,
390                  * and if the entry size is wrong.
391                  *
392                  * As a workaround, I let libelf guess the right size
393                  * for the binary. This relies pretty much on the fact
394                  * that the binary provides correct data in the section
395                  * headers. If it doesn't, it's probably broken anyway.
396                  * Therefore, libelf uses a standard conforming value
397                  * when it's not absolutely sure.
398                  */
399                 if (scn->s_type == SHT_HASH) {
400                     int override = 0;
401
402                     /*
403                      * sh_entsize must reflect the entry size
404                      */
405                     if (shdr->sh_entsize == ELF64_FSZ_ADDR) {
406                         override++;
407                     }
408                     /*
409                      * sh_size must be a multiple of sh_entsize
410                      */
411                     if (shdr->sh_size % ELF64_FSZ_ADDR == 0) {
412                         override++;
413                     }
414                     /*
415                      * There must be room for at least 2 entries
416                      */
417                     if (shdr->sh_size >= 2 * ELF64_FSZ_ADDR) {
418                         override++;
419                     }
420                     /*
421                      * sh_addralign must be correctly set
422                      */
423                     if (shdr->sh_addralign == ELF64_FSZ_ADDR) {
424                         override++;
425                     }
426                     /*
427                      * The section must be properly aligned
428                      */
429                     if (shdr->sh_offset % ELF64_FSZ_ADDR == 0) {
430                         override++;
431                     }
432                     /* XXX: also look at the data? */
433                     /*
434                      * Make a conservative decision...
435                      */
436                     if (override >= 5) {
437                         sd->sd_data.d_type = ELF_T_ADDR;
438                     }
439                 }
440                 /*
441                  * END QUIRKS MODE.
442                  */
443             }
444 #endif /* __LIBELF64 */
445             /* we already had this
446             else {
447                 seterr(ERROR_UNIMPLEMENTED);
448                 return 0;
449             }
450             */
451
452             sd->sd_data.d_size = scn->s_size;
453             sd->sd_data.d_version = _elf_version;
454         }
455         elf_assert(scn == &head[0].scn);
456         elf->e_scn_1 = &head[0].scn;
457         head[0].scn.s_freeme = 1;
458     }
459     return 1;
460 }
461
462 static int
463 _elf_cook_file(Elf *elf) {
464     elf->e_ehdr = _elf_item(NULL, elf, ELF_T_EHDR, 0);
465     if (!elf->e_ehdr) {
466         return 0;
467     }
468     /*
469      * Note: _elf_cook_phdr may require the first section header!
470      */
471     if (!_elf_cook_shdr(elf)) {
472         return 0;
473     }
474     if (!_elf_cook_phdr(elf)) {
475         return 0;
476     }
477     return 1;
478 }
479
480 int
481 _elf_cook(Elf *elf) {
482     elf_assert(_elf_scn_init.s_magic == SCN_MAGIC);
483     elf_assert(_elf_data_init.sd_magic == DATA_MAGIC);
484     elf_assert(elf);
485     elf_assert(elf->e_magic == ELF_MAGIC);
486     elf_assert(elf->e_kind == ELF_K_ELF);
487     elf_assert(!elf->e_ehdr);
488     if (!valid_version(elf->e_version)) {
489         seterr(ERROR_UNKNOWN_VERSION);
490     }
491     else if (!valid_encoding(elf->e_encoding)) {
492         seterr(ERROR_UNKNOWN_ENCODING);
493     }
494     else if (valid_class(elf->e_class)) {
495         return _elf_cook_file(elf);
496     }
497     else {
498         seterr(ERROR_UNKNOWN_CLASS);
499     }
500     return 0;
501 }