f3a1541f0b2fd04374a77eba3fdfca93058f0cb5
[barrelfish] / lib / elf / elf32.c
1 /**
2  * \file
3  * \brief Rudimentary ELF32 loader and handling routines.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <assert.h>
16 #include <stdio.h>
17 #include <stdint.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <barrelfish_kpi/paging_arch.h>
21 #include <barrelfish_kpi/types.h>
22 #include <errors/errno.h>
23 #include <elf/elf.h>
24
25 /**
26  * \brief Calculates the base of the loadable portion of the elf image in
27  * virtual memory.
28  */
29 genvaddr_t elf_virtual_base32(struct Elf32_Ehdr *ehead)
30 {
31     struct Elf32_Phdr *phead =
32         (struct Elf32_Phdr *)((uintptr_t)ehead + (uintptr_t)ehead->e_phoff);
33
34     genvaddr_t retval = 0;
35     int i;
36
37     for (i = 0; i < ehead->e_phnum; i++) {
38         struct Elf32_Phdr *p = &phead[i];
39         if (p->p_type == PT_LOAD) {
40             if(retval == 0) {
41                 retval = p->p_vaddr;
42             }
43             retval = p->p_vaddr < retval ? p->p_vaddr : retval;
44         }
45     }
46
47     return retval;
48 }
49
50 /**
51  * \brief Return pointer to relocation section ELF header.
52  *
53  * This function finds and returns a pointer to the first ELF section
54  * header of type 'type'.
55  *
56  * \param shdr          Pointer to head of ELF section header table.
57  * \param entries       Number of entries in the ELF section header table.
58  * \param type          ELF section header type to look for.
59  *
60  * \return Pointer to first ELF section header of type 'type', or NULL.
61  */
62 struct Elf32_Shdr *
63 elf32_find_section_header_type(struct Elf32_Shdr *shdr,
64                                uint32_t entries, uint32_t type)
65 {
66     int i;
67
68     for(i = 0; i < entries; i++) {
69         struct Elf32_Shdr *s = &shdr[i];
70
71         if(s->sh_type == type) {
72             return s;
73         }
74     }
75     return NULL;
76 }
77
78 /**
79  * \brief Return pointer to section header with given name.
80  *
81  * @param elf_base      Address of ELF header
82  * @param elf_bytes     Size of ELF file.
83  * @param section_name  Named section to look for.
84  *
85  * @return Pointer to ELF section header with name, or NULL.
86  */
87 struct Elf32_Shdr *
88 elf32_find_section_header_name(genvaddr_t  elf_base,
89                                size_t      elf_bytes,
90                                const char* section_name)
91 {
92     lvaddr_t elf_lbase = (lvaddr_t)elf_base;
93     struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elf_lbase;
94
95     if (elf_bytes < sizeof(struct Elf32_Ehdr) || !IS_ELF(*head) ||
96         head->e_ident[EI_CLASS] != ELFCLASS32) {
97         return NULL;
98     }
99
100     struct Elf32_Shdr *shead =
101         (struct Elf32_Shdr *)(elf_lbase + (uintptr_t)head->e_shoff);
102
103     struct Elf32_Shdr *strtab =
104         elf32_find_section_header_type(shead, head->e_shnum, SHT_STRTAB);
105
106     if (strtab == NULL)
107     {
108         return NULL;
109     }
110
111     for (uint32_t i = 0; i < head->e_shnum; i++)
112     {
113         const char* strings = (const char*)(elf_lbase +
114                                             (size_t)strtab->sh_offset);
115         if (!strcmp(section_name, strings + shead[i].sh_name)) {
116             return &shead[i];
117         }
118     }
119     return NULL;
120 }
121
122 /**
123  * \brief Return pointer to relocation section ELF header.
124  *
125  * This function finds and returns a pointer to the first ELF section
126  * header at virtual address 'addr'.
127  *
128  * \param shdr          Pointer to head of ELF section header table.
129  * \param entries       Number of entries in the ELF section header table.
130  * \param addr          Virtual address to look for
131  *
132  * \return Pointer to first ELF section header loaded at 'addr', or NULL.
133  */
134 static struct Elf32_Shdr *
135 elf32_find_section_header_vaddr(struct Elf32_Shdr *shdr,
136                                 uint32_t entries, genvaddr_t addr)
137 {
138     int i;
139
140     for(i = 0; i < entries; i++) {
141         struct Elf32_Shdr *s = &shdr[i];
142
143         if(s->sh_addr == addr) {
144             return s;
145         }
146     }
147
148     return NULL;
149 }
150
151 /**
152  * \brief finds the symbol by name
153  *
154  * \param elf_base  virtual address where the elf image is mapped
155  * \param elf_bytes size of the mapped elf image
156  * \param name      name of the symbol to look for
157  * \param contains  if non zero, search for containing rather than exact match
158  * \param type      type of the symbol STT_*
159  * \param sindex     index where to start and returns the index of the symbol
160  *
161  * \returns pointer to the symbol
162  *          NULL if there is none
163  */
164 struct Elf32_Sym *
165 elf32_find_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
166                           const char *name,
167                           uint8_t contains, uint8_t type,
168                           uintptr_t *sindex)
169 {
170     struct Elf32_Sym *sym = NULL;
171     struct Elf32_Shdr *shead;
172     struct Elf32_Shdr *symtab;
173     const char *symname;
174
175     lvaddr_t elfbase = (lvaddr_t)elf_base;
176     struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;
177
178     // just a sanity check
179     if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
180         return NULL;
181     }
182
183     shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
184
185     symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
186
187     uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;
188
189     uintptr_t start = 0, idx = 0;
190     if (sindex) {
191         idx = *sindex;
192         start = idx * sizeof(struct Elf32_Sym);
193     }
194
195     for (uintptr_t i = start; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
196         idx++;
197
198         // getting the symbol
199         sym = (struct Elf32_Sym *)(symbase + i);
200
201         // check for matching type
202         if ((sym->st_info & 0x0F) != type) {
203             continue;
204         }
205
206         // find the section of the associacted string table
207         struct Elf32_Shdr *strtab = shead+symtab->sh_link;
208
209         // get the pointer to the symbol name from string table + string index
210         symname = (const char *)elfbase + strtab->sh_offset + sym->st_name;
211
212         if (!contains) {
213             if (strcmp(symname, name)==0) {
214                 /* we have a match */
215                 break;
216             }
217         } else {
218             if (strstr(symname,name) != 0) {
219                 break;
220             }
221         }
222     }
223
224     if (sym != NULL) {
225         if (sindex) {
226             *sindex = idx;
227         }
228     }
229     return sym;
230 }
231
232 uint32_t
233 elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
234                           const char *name, uint8_t contains, uint8_t type,
235                           size_t *ret_bytes)
236 {
237     struct Elf32_Sym *sym = NULL;
238     struct Elf32_Shdr *shead;
239     struct Elf32_Shdr *symtab;
240     const char *symname;
241
242     lvaddr_t elfbase = (lvaddr_t)elf_base;
243     struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;
244
245     // just a sanity check
246     if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
247         return 0;
248     }
249
250     uint32_t count = 0;
251     size_t bytes = 0;
252
253     shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
254
255     symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
256
257     uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;
258
259     for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
260         // getting the symbol
261         sym = (struct Elf32_Sym *)(symbase + i);
262
263         // check for matching type
264         if ((sym->st_info & 0x0F) != type) {
265             continue;
266         }
267
268         // find the section of the associacted string table
269         struct Elf32_Shdr *strtab = shead+symtab->sh_link;
270
271         // get the pointer to the symbol name from string table + string index
272         symname = (const char *)elfbase + strtab->sh_offset + sym->st_name;
273
274         if (!contains) {
275             if (strcmp(symname, name)==0) {
276                 /* we have a match */
277                 count++;
278                 bytes += strlen(symname)+1;
279             }
280         } else {
281             if (strstr(symname,name) != 0) {
282                 count++;
283                 bytes += strlen(symname)+1;
284             }
285         }
286     }
287
288     if (ret_bytes) {
289         *ret_bytes = bytes;
290     }
291
292     return count;
293 }
294
295 /**
296  * \brief finds the symbol by its address
297  *
298  * \param elf_base  virtual address where the elf image is mapped
299  * \param elf_bytes size of the mapped elf image
300  * \param addr      virtual address of the symbol
301  * \param index     returns the index of the symbol
302  *
303  * \returns pointer to the symbol
304  *          NULL if there is none
305  */
306 struct Elf32_Sym *
307 elf32_find_symbol_by_addr(genvaddr_t elf_base, size_t elf_bytes,
308                           lvaddr_t addr, uintptr_t *sindex)
309 {
310     struct Elf32_Sym *sym = NULL;
311     struct Elf32_Shdr *shead;
312     struct Elf32_Shdr *symtab;
313
314     lvaddr_t elfbase = (lvaddr_t)elf_base;
315     struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;
316
317     // just a sanity check
318     if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS32) {
319         return NULL;
320     }
321
322     shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
323
324     symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
325
326     uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;
327
328     uintptr_t idx = 0;
329     for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
330         // getting the symbol
331         sym = (struct Elf32_Sym *)(symbase + i);
332
333         /* XXX: not handling relocatable symbols */
334         if (sym->st_value == addr) {
335             break;
336         }
337
338         idx++;
339     }
340
341     if (sym != NULL) {
342         if (sindex) {
343             *sindex = idx;
344         }
345     }
346     return sym;
347 }
348
349 const char *
350 elf32_get_symbolname(struct Elf32_Ehdr *head,
351                      struct Elf32_Sym *sym)
352 {
353     struct Elf32_Shdr *shead;
354     struct Elf32_Shdr *symtab;
355
356     // just a sanity check
357     if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
358         return NULL;
359     }
360
361     uintptr_t elfbase = (uintptr_t)head;
362
363     shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
364
365     symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
366
367     // find the section of the associacted string table
368     struct Elf32_Shdr *strtab = shead+symtab->sh_link;
369
370     // get the pointer to the symbol name from string table + string index
371     return (const char *)elfbase + strtab->sh_offset + sym->st_name;
372 }
373
374
375 /**
376  * \brief Relocates the ELF image from src to dst.
377  *
378  * This function processes the ELF relocation section 'rela' of size 'size' of
379  * the ELF image, formerly located at 'src', to the new location 'dst'.
380  * Relocation is necessary for certain variables that cannot be coded as
381  * position-independent code.
382  *
383  * \param dst           Address to relocate to.
384  * \param src           Former base address of the ELF image.
385  * \param rela          Pointer to relocation section of the ELF image.
386  * \param size          Size in bytes of the ELF relocation section.
387  * \param symtab        Pointer to ELF symbol table.
388  * \param symsize       Size in bytes of the ELF symbol table.
389  * \param start         Original base address of the ELF image.
390  * \param vbase         Pointer to ELF image in virtual memory.
391  */
392 void elf32_relocate(genvaddr_t dst, genvaddr_t src,
393                     struct Elf32_Rel * SAFE NONNULL rel, size_t size,
394                     struct Elf32_Sym * SAFE NONNULL symtab, size_t symsize,
395                     genvaddr_t start, void *vbase)
396 {
397     genvaddr_t base = dst - src, abase = dst - start;
398
399     for(int i = 0; i < size / sizeof(struct Elf32_Rel); i++) {
400         struct Elf32_Rel *r = &rel[i];
401         uint32_t type = ELF32_R_TYPE(r->r_info);
402         uint32_t *addr = (uint32_t *)((char *)vbase + r->r_offset - start);
403
404         switch(type) {
405         case R_ARM_ABS32: //fall through
406         case R_386_32:
407             {
408                 uint32_t sym = ELF32_R_SYM(r->r_info);
409                 assert(sym < symsize / sizeof(struct Elf32_Sym));
410                 /* assert(symtab[sym].st_value != 0); */
411                 *addr = abase + symtab[sym].st_value;
412             }
413             break;
414         case R_ARM_RELATIVE: //fall through
415         case R_386_RELATIVE:
416             *addr += base;
417             break;
418
419         default:
420             printf("elf_relocate: relocation %d type %"PRIu32"\n", i, type);
421             assert(!"Unimplemented: Cannot handle relocation type");
422             break;
423         }
424     }
425 }
426
427 // Return if machine is big endian.
428 // TODO: move to appropriate place
429 static bool is_big_endian(void)
430 {
431     int i = 1;
432     char c[sizeof(int)];
433     memcpy(c, &i, sizeof(int));
434     return !(c[0] & 1);
435 }
436
437 /**
438  * \brief Load ELF32 binary image into memory
439  *
440  * This function loads an ELF32 binary image, based at 'base' and of size
441  * 'size' into the memory provided by 'allocate'
442  *
443  * \param em_machine    ELF machine type.
444  * \param allocate      Memory allocation function.
445  * \param state         Pointer to state for allocation function.
446  * \param base          Base address of ELF32 binary image in memory.
447  * \param size          Size of ELF32 binary image in bytes.
448  * \param retentry      Used to return entry point address
449  * \param ret_tlsbase   Used to return TLS block base address
450  * \param ret_tlsinitlen Used to return length of initialised TLS data block
451  * \param ret_tlstotallen Used to return total length of TLS data
452  */
453 errval_t elf32_load(uint16_t em_machine, elf_allocator_fn allocate_func,
454                     void *state, lvaddr_t base, size_t size,
455                     genvaddr_t *retentry,
456                     genvaddr_t *ret_tlsbase, size_t *ret_tlsinitlen,
457                     size_t *ret_tlstotallen)
458 {
459     struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)base;
460     errval_t err;
461     int i;
462
463     // Check for valid file size
464     if (size < sizeof(struct Elf32_Ehdr)) {
465         return ELF_ERR_FILESZ;
466     }
467
468     // Stage 1: Check for compatible ELF32 header: check endianess
469     if(is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2MSB){
470         return ELF_ERR_HEADER;
471     } else if(!is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2LSB){
472         return ELF_ERR_HEADER;
473     }
474
475     // Stage 2: Check for compatible ELF32 header
476     if (!IS_ELF(*head)
477         || head->e_ident[EI_CLASS] != ELFCLASS32
478 //        || head->e_ident[EI_DATA] != ELFDATA2MSB   //Enhanced with a function to check machine endianess
479         || head->e_ident[EI_VERSION] != EV_CURRENT
480         || head->e_ident[EI_OSABI] != ELFOSABI_SYSV
481         || head->e_ident[EI_ABIVERSION] != 0
482         || (head->e_type != ET_EXEC && head->e_type != ET_DYN)
483         || head->e_machine != em_machine
484         || head->e_version != EV_CURRENT) {
485         return ELF_ERR_HEADER;
486     }
487
488     // More sanity checks
489     if (head->e_phoff + head->e_phentsize * head->e_phnum > size
490         || head->e_phentsize != sizeof(struct Elf32_Phdr)) {
491         return ELF_ERR_PROGHDR;
492     }
493
494     struct Elf32_Shdr *shead =
495         (struct Elf32_Shdr *)(base + (uintptr_t)head->e_shoff);
496     struct Elf32_Shdr *rela =
497         elf32_find_section_header_type(shead, head->e_shnum, SHT_REL);
498     struct Elf32_Shdr *symtab =
499         elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
500
501     size_t rela_size = rela ? rela->sh_size : 0, new_rela_size = 0;
502     struct Elf32_Shdr *new_rela = NULL;
503
504     // Find dynamic program header, if any
505     struct Elf32_Phdr *phead =
506         (struct Elf32_Phdr *)(base + (uintptr_t)head->e_phoff);
507     for (i = 0; i < head->e_phnum; i++) {
508         struct Elf32_Phdr *p = &phead[i];
509
510         if (p->p_type == PT_DYNAMIC) {
511             struct Elf32_Dyn *dynamic = (void *)(base + (uintptr_t)p->p_offset);
512             int n_dynamic = p->p_filesz / sizeof(struct Elf32_Dyn);
513             for (int j = 0; j < n_dynamic; j++) {
514                 switch (dynamic[j].d_tag) {
515                 case DT_RELA:
516                     // virtual address of relocations, look for matching section
517                     new_rela =
518                         elf32_find_section_header_vaddr(shead, head->e_shnum,
519                                                         dynamic[j].d_un.d_val);
520                     break;
521
522                 case DT_RELASZ:
523                     // store size of relocations, as they may cover more than
524                     // one section
525                     new_rela_size = dynamic[j].d_un.d_val;
526                     break;
527
528                 case DT_SYMTAB:
529                     // virtual address of symtab, look for matching section
530                     symtab =
531                         elf32_find_section_header_vaddr(shead, head->e_shnum,
532                                                         dynamic[j].d_un.d_val);
533                     break;
534
535                 case DT_SYMENT:
536                     assert(dynamic[j].d_un.d_val == sizeof(struct Elf32_Sym));
537                     break;
538                 }
539             }
540
541             if (new_rela != NULL) {
542                 assert(new_rela_size != 0);
543                 rela = new_rela;
544                 rela_size = new_rela_size;
545             }
546             break;
547         }
548     }
549
550     genvaddr_t tls_base = 0;
551     size_t tls_init_len = 0, tls_total_len = 0;
552
553     // Process program headers to load file
554     for (i = 0; i < head->e_phnum; i++) {
555         struct Elf32_Phdr *p = &phead[i];
556
557         if (p->p_type == PT_LOAD) {
558             // Map segment in user-space memory
559             void *dest = NULL;
560             err = allocate_func(state, p->p_vaddr, p->p_memsz, p->p_flags, &dest);
561             if (err_is_fail(err)) {
562                 return err_push(err, ELF_ERR_ALLOCATE);
563             }
564             assert(dest != NULL);
565
566             // Copy file segment into memory
567             memcpy(dest, (void *)(base + (uintptr_t)p->p_offset), p->p_filesz);
568
569             // Initialize rest of memory segment (ie. BSS) with all zeroes
570             memset((char *)dest + p->p_filesz, 0, p->p_memsz - p->p_filesz);
571
572             // Apply relocations
573             if (rela != NULL && symtab != NULL) {
574                 elf32_relocate(p->p_vaddr, p->p_vaddr,
575                                (struct Elf32_Rel *)
576                                (base + (uintptr_t)rela->sh_offset),
577                                rela_size,
578                                (struct Elf32_Sym *)
579                                (base + (uintptr_t)symtab->sh_offset),
580                                symtab->sh_size, p->p_vaddr, dest);
581             }
582         } else if (p->p_type == PT_TLS) {
583             assert(p->p_vaddr != 0);
584             assert(tls_base == 0); // if not we have multiple TLS sections!
585             tls_base = p->p_vaddr;
586             tls_init_len = p->p_filesz;
587             tls_total_len = p->p_memsz;
588         }
589     }
590
591     if (retentry != NULL) {
592         *retentry = head->e_entry;
593     }
594
595     if (ret_tlsbase != NULL) {
596         *ret_tlsbase = tls_base;
597     }
598
599     if (ret_tlsinitlen != NULL) {
600         *ret_tlsinitlen = tls_init_len;
601     }
602
603     if (ret_tlstotallen != NULL) {
604         *ret_tlstotallen = tls_total_len;
605     }
606
607     return SYS_ERR_OK;
608 }