Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / linux / nacl_bootstrap.c
1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  *
6  * This is a standalone program that loads and runs the dynamic linker.
7  * This program itself must be linked statically.  To keep it small, it's
8  * written to avoid all dependencies on libc and standard startup code.
9  * Hence, this should be linked using -nostartfiles.  It must be compiled
10  * with -fno-stack-protector to ensure the compiler won't emit code that
11  * presumes some special setup has been done.
12  *
13  * On ARM, the compiler will emit calls to some libc functions, so we
14  * cannot link with -nostdlib.  The functions it does use (memset and
15  * __aeabi_* functions for integer division) are sufficiently small and
16  * self-contained in ARM's libc.a that we don't have any problem using
17  * the libc definitions though we aren't using the rest of libc or doing
18  * any of the setup it might expect.
19  */
20 #include <elf.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <link.h>
24 #include <stddef.h>
25 #include <stdint.h>
26 #include <sys/mman.h>
27
28 /*
29  * Get inline functions for system calls.
30  */
31 static int my_errno;
32 #define SYS_ERRNO my_errno
33 #include "third_party/lss/linux_syscall_support.h"
34
35 #define MAX_PHNUM               12
36
37 typedef uintptr_t __attribute__((may_alias)) stack_val_t;
38
39 /*
40  * These exact magic argument strings are recognized in check_r_debug_arg
41  * and check_reserved_at_zero_arg, below. Requiring the arguments to have
42  * those Xs as a template both simplifies our argument matching code and saves
43  * us from having to reformat the whole stack to find space for a string longer
44  * than the original argument.
45  */
46 #define TEMPLATE_DIGITS "XXXXXXXXXXXXXXXX"
47 #define R_DEBUG_TEMPLATE_PREFIX "--r_debug=0x"
48 static const char kRDebugTemplate[] = R_DEBUG_TEMPLATE_PREFIX TEMPLATE_DIGITS;
49 static const size_t kRDebugPrefixLen = sizeof(R_DEBUG_TEMPLATE_PREFIX) - 1;
50
51 #define RESERVED_AT_ZERO_TEMPLATE_PREFIX "--reserved_at_zero=0x"
52 static const char kReservedAtZeroTemplate[] =
53     RESERVED_AT_ZERO_TEMPLATE_PREFIX TEMPLATE_DIGITS;
54 static const size_t kReservedAtZeroPrefixLen =
55     sizeof(RESERVED_AT_ZERO_TEMPLATE_PREFIX) - 1;
56 extern char RESERVE_TOP[];
57
58 extern char TEXT_START[];
59
60 /*
61  * We're not using <string.h> functions here, to avoid dependencies.
62  * In the x86 libc, even "simple" functions like memset and strlen can
63  * depend on complex startup code, because in newer libc
64  * implementations they are defined using STT_GNU_IFUNC.
65  */
66
67 /*
68  * Some GCC versions are so clever that they recognize these simple loops
69  * as having the semantics of standard library functions and replace them
70  * with calls.  That defeats the whole purpose, which is to avoid requiring
71  * any C library at all.  Fortunately, this optimization can be disabled
72  * for all (following) functions in the file via #pragma.
73  */
74 #if (defined(__GNUC__) && !defined(__clang__) && \
75      (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
76 # pragma GCC optimize("-fno-tree-loop-distribute-patterns")
77 #endif
78
79 static void my_bzero(void *buf, size_t n) {
80   char *p = buf;
81   while (n-- > 0)
82     *p++ = 0;
83 }
84
85 static size_t my_strlen(const char *s) {
86   size_t n = 0;
87   while (*s++ != '\0')
88     ++n;
89   return n;
90 }
91
92 static int my_strcmp(const char *a, const char *b) {
93   while (*a == *b) {
94     if (*a == '\0')
95       return 0;
96     ++a;
97     ++b;
98   }
99   return (int) (unsigned char) *a - (int) (unsigned char) *b;
100 }
101
102
103 /*
104  * We're avoiding libc, so no printf.  The only nontrivial thing we need
105  * is rendering numbers, which is, in fact, pretty trivial.
106  * bufsz of course must be enough to hold INT_MIN in decimal.
107  */
108 static void iov_int_string(int value, struct kernel_iovec *iov,
109                            char *buf, size_t bufsz) {
110   char *p = &buf[bufsz];
111   int negative = value < 0;
112   if (negative)
113     value = -value;
114   do {
115     --p;
116     *p = "0123456789"[value % 10];
117     value /= 10;
118   } while (value != 0);
119   if (negative)
120     *--p = '-';
121   iov->iov_base = p;
122   iov->iov_len = &buf[bufsz] - p;
123 }
124
125 #define STRING_IOV(string_constant, cond) \
126   { (void *) string_constant, cond ? (sizeof(string_constant) - 1) : 0 }
127
128 __attribute__((noreturn)) static void fail(const char *filename,
129                                            const char *message,
130                                            const char *item1, int value1,
131                                            const char *item2, int value2) {
132   char valbuf1[32];
133   char valbuf2[32];
134   struct kernel_iovec iov[] = {
135     STRING_IOV("bootstrap_helper: ", 1),
136     { (void *) filename, my_strlen(filename) },
137     STRING_IOV(": ", 1),
138     { (void *) message, my_strlen(message) },
139     { (void *) item1, item1 == NULL ? 0 : my_strlen(item1) },
140     STRING_IOV("=", item1 != NULL),
141     { NULL, 0 },                        /* iov[6] */
142     STRING_IOV(", ", item1 != NULL && item2 != NULL),
143     { (void *) item2, item2 == NULL ? 0 : my_strlen(item2) },
144     STRING_IOV("=", item2 != NULL),
145     { NULL, 0 },                        /* iov[10] */
146     { "\n", 1 },
147   };
148   const int niov = sizeof(iov) / sizeof(iov[0]);
149
150   if (item1 != NULL)
151     iov_int_string(value1, &iov[6], valbuf1, sizeof(valbuf1));
152   if (item2 != NULL)
153     iov_int_string(value2, &iov[10], valbuf2, sizeof(valbuf2));
154
155   sys_writev(2, iov, niov);
156   sys_exit_group(2);
157   while (1) *(volatile int *) 0 = 0;  /* Crash.  */
158 }
159
160
161 static int my_open(const char *file, int oflag) {
162   int result = sys_open(file, oflag, 0);
163   if (result < 0)
164     fail(file, "Cannot open ELF file!  ", "errno", my_errno, NULL, 0);
165   return result;
166 }
167
168 static void my_pread(const char *file, const char *fail_message,
169                      int fd, void *buf, size_t bufsz, uintptr_t pos) {
170   ssize_t result = sys_pread64(fd, buf, bufsz, pos);
171   if (result < 0)
172     fail(file, fail_message, "errno", my_errno, NULL, 0);
173   if ((size_t) result != bufsz)
174     fail(file, fail_message, "read count", result, NULL, 0);
175 }
176
177 static uintptr_t my_mmap_simple(uintptr_t address, size_t size,
178                                 int prot, int flags, int fd, uintptr_t pos) {
179 #if defined(__NR_mmap2)
180   void *result = sys_mmap2((void *) address, size, prot, flags, fd, pos >> 12);
181 #else
182   void *result = sys_mmap((void *) address, size, prot, flags, fd, pos);
183 #endif
184   return (uintptr_t) result;
185 }
186
187 static uintptr_t my_mmap(const char *file,
188                          const char *segment_type, unsigned int segnum,
189                          uintptr_t address, size_t size,
190                          int prot, int flags, int fd, uintptr_t pos) {
191   uintptr_t result = my_mmap_simple(address, size, prot, flags, fd, pos);
192   if ((void *) result == MAP_FAILED)
193     fail(file, "Failed to map segment!  ",
194          segment_type, segnum, "errno", my_errno);
195   return result;
196 }
197
198 static void my_mprotect(const char *file, unsigned int segnum,
199                         uintptr_t address, size_t size, int prot) {
200   if (sys_mprotect((void *) address, size, prot) < 0)
201     fail(file, "Failed to mprotect segment hole!  ",
202          "segment", segnum, "errno", my_errno);
203 }
204
205
206 static int prot_from_phdr(const ElfW(Phdr) *phdr) {
207   int prot = 0;
208   if (phdr->p_flags & PF_R)
209     prot |= PROT_READ;
210   if (phdr->p_flags & PF_W)
211     prot |= PROT_WRITE;
212   if (phdr->p_flags & PF_X)
213     prot |= PROT_EXEC;
214   return prot;
215 }
216
217 static uintptr_t round_up(uintptr_t value, uintptr_t size) {
218   return (value + size - 1) & -size;
219 }
220
221 static uintptr_t round_down(uintptr_t value, uintptr_t size) {
222   return value & -size;
223 }
224
225 /*
226  * Handle the "bss" portion of a segment, where the memory size
227  * exceeds the file size and we zero-fill the difference.  For any
228  * whole pages in this region, we over-map anonymous pages.  For the
229  * sub-page remainder, we zero-fill bytes directly.
230  */
231 static void handle_bss(const char *file,
232                        unsigned int segnum, const ElfW(Phdr) *ph,
233                        ElfW(Addr) load_bias, size_t pagesize) {
234   if (ph->p_memsz > ph->p_filesz) {
235     ElfW(Addr) file_end = ph->p_vaddr + load_bias + ph->p_filesz;
236     ElfW(Addr) file_page_end = round_up(file_end, pagesize);
237     ElfW(Addr) page_end = round_up(ph->p_vaddr + load_bias +
238                                    ph->p_memsz, pagesize);
239     if (page_end > file_page_end)
240       my_mmap(file, "bss segment", segnum,
241               file_page_end, page_end - file_page_end,
242               prot_from_phdr(ph), MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
243     if (file_page_end > file_end && (ph->p_flags & PF_W))
244       my_bzero((void *) file_end, file_page_end - file_end);
245   }
246 }
247
248 /*
249  * Open an ELF file and load it into memory.
250  */
251 static ElfW(Addr) load_elf_file(const char *filename,
252                                 size_t pagesize,
253                                 ElfW(Addr) *out_phdr,
254                                 ElfW(Addr) *out_phnum,
255                                 const char **out_interp) {
256   int fd = my_open(filename, O_RDONLY);
257
258   ElfW(Ehdr) ehdr;
259   my_pread(filename, "Failed to read ELF header from file!  ",
260            fd, &ehdr, sizeof(ehdr), 0);
261
262   if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
263       ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
264       ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
265       ehdr.e_ident[EI_MAG3] != ELFMAG3 ||
266       ehdr.e_version != EV_CURRENT ||
267       ehdr.e_ehsize != sizeof(ehdr) ||
268       ehdr.e_phentsize != sizeof(ElfW(Phdr)))
269     fail(filename, "File has no valid ELF header!", NULL, 0, NULL, 0);
270
271   switch (ehdr.e_machine) {
272 #if defined(__i386__)
273     case EM_386:
274 #elif defined(__x86_64__)
275     case EM_X86_64:
276 #elif defined(__arm__)
277     case EM_ARM:
278 #elif defined(__mips__)
279     case EM_MIPS:
280 #else
281 # error "Don't know the e_machine value for this architecture!"
282 #endif
283       break;
284     default:
285       fail(filename, "ELF file has wrong architecture!  ",
286            "e_machine", ehdr.e_machine, NULL, 0);
287       break;
288   }
289
290   ElfW(Phdr) phdr[MAX_PHNUM];
291   if (ehdr.e_phnum > sizeof(phdr) / sizeof(phdr[0]) || ehdr.e_phnum < 1)
292     fail(filename, "ELF file has unreasonable ",
293          "e_phnum", ehdr.e_phnum, NULL, 0);
294
295   if (ehdr.e_type != ET_DYN)
296     fail(filename, "ELF file not ET_DYN!  ",
297          "e_type", ehdr.e_type, NULL, 0);
298
299   my_pread(filename, "Failed to read program headers from ELF file!  ",
300            fd, phdr, sizeof(phdr[0]) * ehdr.e_phnum, ehdr.e_phoff);
301
302   size_t i = 0;
303   while (i < ehdr.e_phnum && phdr[i].p_type != PT_LOAD)
304     ++i;
305   if (i == ehdr.e_phnum)
306     fail(filename, "ELF file has no PT_LOAD header!",
307          NULL, 0, NULL, 0);
308
309   /*
310    * ELF requires that PT_LOAD segments be in ascending order of p_vaddr.
311    * Find the last one to calculate the whole address span of the image.
312    */
313   const ElfW(Phdr) *first_load = &phdr[i];
314   const ElfW(Phdr) *last_load = &phdr[ehdr.e_phnum - 1];
315   while (last_load > first_load && last_load->p_type != PT_LOAD)
316     --last_load;
317
318   size_t span = last_load->p_vaddr + last_load->p_memsz - first_load->p_vaddr;
319
320   /*
321    * Map the first segment and reserve the space used for the rest and
322    * for holes between segments.
323    */
324   const uintptr_t mapping = my_mmap(filename, "segment", first_load - phdr,
325                                     round_down(first_load->p_vaddr, pagesize),
326                                     span, prot_from_phdr(first_load),
327                                     MAP_PRIVATE, fd,
328                                     round_down(first_load->p_offset, pagesize));
329
330   const ElfW(Addr) load_bias = mapping - round_down(first_load->p_vaddr,
331                                                     pagesize);
332
333   if (first_load->p_offset > ehdr.e_phoff ||
334       first_load->p_filesz < ehdr.e_phoff + (ehdr.e_phnum * sizeof(ElfW(Phdr))))
335     fail(filename, "First load segment of ELF file does not contain phdrs!",
336          NULL, 0, NULL, 0);
337
338   handle_bss(filename, first_load - phdr, first_load, load_bias, pagesize);
339
340   ElfW(Addr) last_end = first_load->p_vaddr + load_bias + first_load->p_memsz;
341
342   /*
343    * Map the remaining segments, and protect any holes between them.
344    */
345   const ElfW(Phdr) *ph;
346   for (ph = first_load + 1; ph <= last_load; ++ph) {
347     if (ph->p_type == PT_LOAD) {
348       ElfW(Addr) last_page_end = round_up(last_end, pagesize);
349
350       last_end = ph->p_vaddr + load_bias + ph->p_memsz;
351       ElfW(Addr) start = round_down(ph->p_vaddr + load_bias, pagesize);
352       ElfW(Addr) end = round_up(last_end, pagesize);
353
354       if (start > last_page_end)
355         my_mprotect(filename,
356                     ph - phdr, last_page_end, start - last_page_end, PROT_NONE);
357
358       my_mmap(filename, "segment", ph - phdr,
359               start, end - start,
360               prot_from_phdr(ph), MAP_PRIVATE | MAP_FIXED, fd,
361               round_down(ph->p_offset, pagesize));
362
363       handle_bss(filename, ph - phdr, ph, load_bias, pagesize);
364     }
365   }
366
367   if (out_interp != NULL) {
368     /*
369      * Find the PT_INTERP header, if there is one.
370      */
371     for (i = 0; i < ehdr.e_phnum; ++i) {
372       if (phdr[i].p_type == PT_INTERP) {
373         /*
374          * The PT_INTERP isn't really required to sit inside the first
375          * (or any) load segment, though it normally does.  So we can
376          * easily avoid an extra read in that case.
377          */
378         if (phdr[i].p_offset >= first_load->p_offset &&
379             phdr[i].p_filesz <= first_load->p_filesz) {
380           *out_interp = (const char *) (phdr[i].p_vaddr + load_bias);
381         } else {
382           static char interp_buffer[PATH_MAX + 1];
383           if (phdr[i].p_filesz >= sizeof(interp_buffer)) {
384             fail(filename, "ELF file has unreasonable PT_INTERP size!  ",
385                  "segment", i, "p_filesz", phdr[i].p_filesz);
386           }
387           my_pread(filename, "Cannot read PT_INTERP segment contents!",
388                    fd, interp_buffer, phdr[i].p_filesz, phdr[i].p_offset);
389           *out_interp = interp_buffer;
390         }
391         break;
392       }
393     }
394   }
395
396   sys_close(fd);
397
398   if (out_phdr != NULL)
399     *out_phdr = (ehdr.e_phoff - first_load->p_offset +
400                  first_load->p_vaddr + load_bias);
401   if (out_phnum != NULL)
402     *out_phnum = ehdr.e_phnum;
403
404   return ehdr.e_entry + load_bias;
405 }
406
407 /*
408  * Replace template digits with a fill value.  This function places the
409  * bottom num_digits of the hex representation of fill into the string
410  * pointed to by start.
411  */
412 static void fill_in_template_digits(char *start, size_t num_digits,
413                                     uintptr_t fill) {
414   while (num_digits-- > 0) {
415     start[num_digits] = "0123456789abcdef"[fill & 0xf];
416     fill >>= 4;
417   }
418   if (fill != 0)
419     fail("fill_in_template_digits",
420          "fill has significant digits beyond num_digits", NULL, 0, NULL, 0);
421 }
422
423 /*
424  * GDB looks for this symbol name when it cannot find PT_DYNAMIC->DT_DEBUG.
425  * We don't have a PT_DYNAMIC, so it will find this.  Now all we have to do
426  * is arrange for this space to be filled in with the dynamic linker's
427  * _r_debug contents after they're initialized.  That way, attaching GDB to
428  * this process or examining its core file will find the PIE we loaded, the
429  * dynamic linker, and all the shared libraries, making debugging pleasant.
430  */
431 struct r_debug _r_debug __attribute__((nocommon, section(".r_debug")));
432
433 /*
434  * If the argument matches the kRDebugTemplate string, then replace
435  * the 16 Xs with the hexadecimal address of our _r_debug variable.
436  */
437 static int check_r_debug_arg(char *arg) {
438   if (my_strcmp(arg, kRDebugTemplate) == 0) {
439     fill_in_template_digits(arg + kRDebugPrefixLen,
440                             sizeof(TEMPLATE_DIGITS) - 1,
441                             (uintptr_t) &_r_debug);
442     return 1;
443   }
444   return 0;
445 }
446
447 /*
448  * If the argument matches the kReservedAtZeroTemplate string, then replace
449  * the 8 Xs with the hexadecimal representation of the amount of
450  * prereserved memory.
451  */
452 static int check_reserved_at_zero_arg(char *arg) {
453   if (my_strcmp(arg, kReservedAtZeroTemplate) == 0) {
454     fill_in_template_digits(arg + kReservedAtZeroPrefixLen,
455                             sizeof(TEMPLATE_DIGITS) - 1,
456                             (uintptr_t) RESERVE_TOP);
457     return 1;
458   }
459   return 0;
460 }
461
462
463 static void ReserveBottomPages(size_t pagesize) {
464   uintptr_t page_addr;
465   uintptr_t mmap_rval;
466
467   /*
468    * Attempt to protect low memory from zero to the code start address.
469    *
470    * It is normal for mmap() calls to fail with EPERM if the indicated
471    * page is less than vm.mmap_min_addr (see /proc/sys/vm/mmap_min_addr),
472    * or with EACCES under SELinux if less than CONFIG_LSM_MMAP_MIN_ADDR
473    * (64k).  Sometimes, mmap() calls may fail with EINVAL if the
474    * starting address is 0.  Hence, we adaptively move the bottom of the
475    * region up a page at a time until we succeed in getting a reservation.
476    */
477   for (page_addr = 0;
478        page_addr < (uintptr_t) TEXT_START;
479        page_addr += pagesize) {
480     mmap_rval = my_mmap_simple(page_addr,
481                                (uintptr_t) TEXT_START - page_addr,
482                                PROT_NONE,
483                                MAP_PRIVATE | MAP_FIXED |
484                                MAP_ANONYMOUS | MAP_NORESERVE,
485                                -1, 0);
486     if (page_addr == mmap_rval) {
487       /* Success; the pages are now protected. */
488       break;
489     } else if (MAP_FAILED == (void *) mmap_rval &&
490                (EPERM == my_errno || EACCES == my_errno ||
491                 (EINVAL == my_errno && 0 == page_addr))) {
492       /*
493        * Normal; this is an invalid page for this process and
494        * doesn't need to be protected. Continue with next page.
495        */
496     } else {
497       fail("ReserveBottomPages", "NULL pointer guard page ",
498            "errno", my_errno, NULL, 0);
499     }
500   }
501 }
502
503
504 /*
505  * This is the main loading code.  It's called with the starting stack pointer.
506  * This points to a sequence of pointer-size words:
507  *      [0]             argc
508  *      [1..argc]       argv[0..argc-1]
509  *      [1+argc]        NULL
510  *      [2+argc..]      envp[0..]
511  *                      NULL
512  *                      auxv[0].a_type
513  *                      auxv[1].a_un.a_val
514  *                      ...
515  * It returns the dynamic linker's runtime entry point address, where
516  * we should jump to.  This is called by the machine-dependent _start
517  * code (below).  On return, it restores the original stack pointer
518  * and jumps to this entry point.
519  *
520  * argv[0] is the uninteresting name of this bootstrap program.  argv[1] is
521  * the real program file name we'll open, and also the argv[0] for that
522  * program.  We need to modify argc, move argv[1..] back to the argv[0..]
523  * position, and also examine and modify the auxiliary vector on the stack.
524  */
525 ElfW(Addr) do_load(stack_val_t *stack) {
526   size_t i;
527   int argn;
528
529   /*
530    * First find the end of the auxiliary vector.
531    */
532   int argc = stack[0];
533   char **argv = (char **) &stack[1];
534   const char *program = argv[1];
535   char **envp = &argv[argc + 1];
536   char **ep = envp;
537   while (*ep != NULL)
538     ++ep;
539   ElfW(auxv_t) *auxv = (ElfW(auxv_t) *) (ep + 1);
540   ElfW(auxv_t) *av = auxv;
541   while (av->a_type != AT_NULL)
542     ++av;
543   size_t stack_words = (stack_val_t *) (av + 1) - &stack[1];
544
545   if (argc < 2)
546     fail("Usage", "PROGRAM ARGS...", NULL, 0, NULL, 0);
547
548   /*
549    * Now move everything back to eat our original argv[0].  When we've done
550    * that, envp and auxv will start one word back from where they were.
551    */
552   --argc;
553   --envp;
554   auxv = (ElfW(auxv_t) *) ep;
555   stack[0] = argc;
556   for (i = 1; i < stack_words; ++i)
557     stack[i] = stack[i + 1];
558
559   /*
560    * If an argument is the kRDebugTemplate or kReservedAtZeroTemplate
561    * string, then we'll modify that argument string in place to specify
562    * the address of our _r_debug structure (for kRDebugTemplate) or the
563    * amount of prereserved address space (for kReservedAtZeroTemplate).
564    * We expect that the arguments matching the templates are the first
565    * arguments provided.
566    */
567   for (argn = 1; argn < argc; ++argn) {
568     if (!check_r_debug_arg(argv[argn]) &&
569         !check_reserved_at_zero_arg(argv[argn]))
570      break;
571   }
572
573   /*
574    * Record the auxv entries that are specific to the file loaded.
575    * The incoming entries point to our own static executable.
576    */
577   ElfW(auxv_t) *av_entry = NULL;
578   ElfW(auxv_t) *av_phdr = NULL;
579   ElfW(auxv_t) *av_phnum = NULL;
580   size_t pagesize = 0;
581
582   for (av = auxv;
583        av_entry == NULL || av_phdr == NULL || av_phnum == NULL || pagesize == 0;
584        ++av) {
585     switch (av->a_type) {
586       case AT_NULL:
587         fail("startup",
588              "Failed to find AT_ENTRY, AT_PHDR, AT_PHNUM, or AT_PAGESZ!",
589              NULL, 0, NULL, 0);
590         /*NOTREACHED*/
591         break;
592       case AT_ENTRY:
593         av_entry = av;
594         break;
595       case AT_PAGESZ:
596         pagesize = av->a_un.a_val;
597         break;
598       case AT_PHDR:
599         av_phdr = av;
600         break;
601       case AT_PHNUM:
602         av_phnum = av;
603         break;
604     }
605   }
606
607   ReserveBottomPages(pagesize);
608
609   /* Load the program and point the auxv elements at its phdrs and entry.  */
610   const char *interp = NULL;
611   av_entry->a_un.a_val = load_elf_file(program,
612                                        pagesize,
613                                        &av_phdr->a_un.a_val,
614                                        &av_phnum->a_un.a_val,
615                                        &interp);
616
617   ElfW(Addr) entry = av_entry->a_un.a_val;
618
619   if (interp != NULL) {
620     /*
621      * There was a PT_INTERP, so we have a dynamic linker to load.
622      */
623     entry = load_elf_file(interp, pagesize, NULL, NULL, NULL);
624   }
625
626   return entry;
627 }
628
629 /*
630  * We have to define the actual entry point code (_start) in assembly for
631  * each machine.  The kernel startup protocol is not compatible with the
632  * normal C function calling convention.  Here, we call do_load (above)
633  * using the normal C convention as per the ABI, with the starting stack
634  * pointer as its argument; restore the original starting stack; and
635  * finally, jump to the dynamic linker's entry point address.
636  */
637 #if defined(__i386__)
638 asm(".pushsection \".text\",\"ax\",@progbits\n"
639     ".globl _start\n"
640     ".type _start,@function\n"
641     "_start:\n"
642     "xorl %ebp, %ebp\n"
643     "movl %esp, %ebx\n"         /* Save starting SP in %ebx.  */
644     "andl $-16, %esp\n"         /* Align the stack as per ABI.  */
645     "pushl %ebx\n"              /* Argument: stack block.  */
646     "call do_load\n"
647     "movl %ebx, %esp\n"         /* Restore the saved SP.  */
648     "jmp *%eax\n"               /* Jump to the entry point.  */
649     ".popsection"
650     );
651 #elif defined(__x86_64__)
652 asm(".pushsection \".text\",\"ax\",@progbits\n"
653     ".globl _start\n"
654     ".type _start,@function\n"
655     "_start:\n"
656     "xorq %rbp, %rbp\n"
657     "movq %rsp, %rbx\n"         /* Save starting SP in %rbx.  */
658     "andq $-16, %rsp\n"         /* Align the stack as per ABI.  */
659     "movq %rbx, %rdi\n"         /* Argument: stack block.  */
660     "call do_load\n"
661     "movq %rbx, %rsp\n"         /* Restore the saved SP.  */
662     "jmp *%rax\n"               /* Jump to the entry point.  */
663     ".popsection"
664     );
665 #elif defined(__arm__)
666 asm(".pushsection \".text\",\"ax\",%progbits\n"
667     ".globl _start\n"
668     ".type _start,#function\n"
669     "_start:\n"
670 #if defined(__thumb2__)
671     ".thumb\n"
672     ".syntax unified\n"
673 #endif
674     "mov fp, #0\n"
675     "mov lr, #0\n"
676     "mov r4, sp\n"              /* Save starting SP in r4.  */
677     "mov r0, sp\n"              /* Argument: stack block.  */
678     "bl do_load\n"
679     "mov sp, r4\n"              /* Restore the saved SP.  */
680     "blx r0\n"                  /* Jump to the entry point.  */
681     ".popsection"
682     );
683 #elif defined(__mips__)
684 asm(".pushsection \".text\",\"ax\",@progbits\n"
685     ".globl _start\n"
686     ".type _start,@function\n"
687     "_start:\n"
688     ".set noreorder\n"
689     "addiu $fp, $zero, 0\n"
690     "addiu $ra, $zero, 0\n"
691     "addiu $s8, $sp,   0\n"     /* Save starting SP in s8.  */
692     "addiu $a0, $sp,   0\n"
693     "addiu $sp, $sp, -16\n"
694     "jal   do_load\n"
695     "nop\n"
696     "addiu $sp, $s8,  0\n"      /* Restore the saved SP.  */
697     "jr    $v0\n"               /* Jump to the entry point.  */
698     "nop\n"
699     ".popsection"
700     );
701 #else
702 # error "Need stack-preserving _start code for this architecture!"
703 #endif
704
705 #if defined(__arm__)
706 /*
707  * We may bring in __aeabi_* functions from libgcc that in turn
708  * want to call raise.
709  */
710 int raise(int sig) {
711   return sys_kill(sys_getpid(), sig);
712 }
713 #endif