OLD | NEW |
1 /* Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * This is a standalone program that loads and runs the dynamic linker. | 5 * This is a standalone program that loads and runs the dynamic linker. |
6 * This program itself must be linked statically. To keep it small, it's | 6 * This program itself must be linked statically. To keep it small, it's |
7 * written to avoid all dependencies on libc and standard startup code. | 7 * written to avoid all dependencies on libc and standard startup code. |
8 * Hence, this should be linked using -nostartfiles. It must be compiled | 8 * Hence, this should be linked using -nostartfiles. It must be compiled |
9 * with -fno-stack-protector to ensure the compiler won't emit code that | 9 * with -fno-stack-protector to ensure the compiler won't emit code that |
10 * presumes some special setup has been done. | 10 * presumes some special setup has been done. |
11 * | 11 * |
12 * On ARM, the compiler will emit calls to some libc functions, so we | 12 * On ARM, the compiler will emit calls to some libc functions, so we |
13 * cannot link with -nostdlib. The functions it does use (memset and | 13 * cannot link with -nostdlib. The functions it does use (memset and |
14 * __aeabi_* functions for integer division) are sufficiently small and | 14 * __aeabi_* functions for integer division) are sufficiently small and |
15 * self-contained in ARM's libc.a that we don't have any problem using | 15 * self-contained in ARM's libc.a that we don't have any problem using |
16 * the libc definitions though we aren't using the rest of libc or doing | 16 * the libc definitions though we aren't using the rest of libc or doing |
17 * any of the setup it might expect. | 17 * any of the setup it might expect. |
18 */ | 18 */ |
19 | 19 |
20 #include <elf.h> | 20 #include <elf.h> |
21 #include <fcntl.h> | 21 #include <fcntl.h> |
22 #include <limits.h> | 22 #include <limits.h> |
23 #include <link.h> | 23 #include <link.h> |
24 #include <stddef.h> | 24 #include <stddef.h> |
25 #include <stdint.h> | 25 #include <stdint.h> |
26 #include <sys/mman.h> | 26 #include <sys/mman.h> |
27 | 27 |
28 #define MAX_PHNUM 12 | 28 #define MAX_PHNUM 12 |
29 | 29 |
| 30 /* |
| 31 * This exact magic argument string is recognized in check_r_debug_arg, below. |
| 32 * Requiring the argument to have those Xs as a template both simplifies |
| 33 * our argument matching code and saves us from having to reformat the |
| 34 * whole stack to find space for a string longer than the original argument. |
| 35 */ |
| 36 #define R_DEBUG_TEMPLATE_PREFIX "--r_debug=0x" |
| 37 #define R_DEBUG_TEMPLATE_DIGITS "XXXXXXXXXXXXXXXX" |
| 38 static const char kRDebugTemplate[] = |
| 39 R_DEBUG_TEMPLATE_PREFIX R_DEBUG_TEMPLATE_DIGITS; |
| 40 static const size_t kRDebugPrefixLen = sizeof(R_DEBUG_TEMPLATE_PREFIX) - 1; |
| 41 |
30 | 42 |
31 /* | 43 /* |
32 * We're not using <string.h> functions here, to avoid dependencies. | 44 * We're not using <string.h> functions here, to avoid dependencies. |
33 * In the x86 libc, even "simple" functions like memset and strlen can | 45 * In the x86 libc, even "simple" functions like memset and strlen can |
34 * depend on complex startup code, because in newer libc | 46 * depend on complex startup code, because in newer libc |
35 * implementations they are defined using STT_GNU_IFUNC. | 47 * implementations they are defined using STT_GNU_IFUNC. |
36 */ | 48 */ |
37 | 49 |
38 static void my_bzero(void *buf, size_t n) { | 50 static void my_bzero(void *buf, size_t n) { |
39 char *p = buf; | 51 char *p = buf; |
40 while (n-- > 0) | 52 while (n-- > 0) |
41 *p++ = 0; | 53 *p++ = 0; |
42 } | 54 } |
43 | 55 |
44 static size_t my_strlen(const char *s) { | 56 static size_t my_strlen(const char *s) { |
45 size_t n = 0; | 57 size_t n = 0; |
46 while (*s++ != '\0') | 58 while (*s++ != '\0') |
47 ++n; | 59 ++n; |
48 return n; | 60 return n; |
49 } | 61 } |
50 | 62 |
| 63 static int my_strcmp(const char *a, const char *b) { |
| 64 while (*a == *b) { |
| 65 if (*a == '\0') |
| 66 return 0; |
| 67 ++a; |
| 68 ++b; |
| 69 } |
| 70 return (int) (unsigned char) *a - (int) (unsigned char) *b; |
| 71 } |
| 72 |
51 | 73 |
52 /* | 74 /* |
53 * Get inline functions for system calls. | 75 * Get inline functions for system calls. |
54 */ | 76 */ |
55 static int my_errno; | 77 static int my_errno; |
56 #define SYS_ERRNO my_errno | 78 #define SYS_ERRNO my_errno |
57 #include "third_party/lss/linux_syscall_support.h" | 79 #include "third_party/lss/linux_syscall_support.h" |
58 | 80 |
59 | 81 |
60 /* | 82 /* |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 362 |
341 if (out_phdr != NULL) | 363 if (out_phdr != NULL) |
342 *out_phdr = (ehdr.e_phoff - first_load->p_offset + | 364 *out_phdr = (ehdr.e_phoff - first_load->p_offset + |
343 first_load->p_vaddr + load_bias); | 365 first_load->p_vaddr + load_bias); |
344 if (out_phnum != NULL) | 366 if (out_phnum != NULL) |
345 *out_phnum = ehdr.e_phnum; | 367 *out_phnum = ehdr.e_phnum; |
346 | 368 |
347 return ehdr.e_entry + load_bias; | 369 return ehdr.e_entry + load_bias; |
348 } | 370 } |
349 | 371 |
| 372 |
| 373 /* |
| 374 * GDB looks for this symbol name when it cannot find PT_DYNAMIC->DT_DEBUG. |
| 375 * We don't have a PT_DYNAMIC, so it will find this. Now all we have to do |
| 376 * is arrange for this space to be filled in with the dynamic linker's |
| 377 * _r_debug contents after they're initialized. That way, attaching GDB to |
| 378 * this process or examining its core file will find the PIE we loaded, the |
| 379 * dynamic linker, and all the shared libraries, making debugging pleasant. |
| 380 */ |
| 381 struct r_debug _r_debug __attribute__((nocommon, section(".r_debug"))); |
| 382 |
| 383 /* |
| 384 * If the argument matches the kRDebugTemplate string, then replace |
| 385 * the 16 Xs with the hexadecimal address of our _r_debug variable. |
| 386 */ |
| 387 static int check_r_debug_arg(char *arg) { |
| 388 if (my_strcmp(arg, kRDebugTemplate) == 0) { |
| 389 uintptr_t addr = (uintptr_t) &_r_debug; |
| 390 size_t i = 16; |
| 391 while (i-- > 0) { |
| 392 arg[kRDebugPrefixLen + i] = "0123456789abcdef"[addr & 0xf]; |
| 393 addr >>= 4; |
| 394 } |
| 395 return 1; |
| 396 } |
| 397 return 0; |
| 398 } |
| 399 |
| 400 |
350 /* | 401 /* |
351 * This is the main loading code. It's called with the starting stack pointer. | 402 * This is the main loading code. It's called with the starting stack pointer. |
352 * This points to a sequence of pointer-size words: | 403 * This points to a sequence of pointer-size words: |
353 * [0] argc | 404 * [0] argc |
354 * [1..argc] argv[0..argc-1] | 405 * [1..argc] argv[0..argc-1] |
355 * [1+argc] NULL | 406 * [1+argc] NULL |
356 * [2+argc..] envp[0..] | 407 * [2+argc..] envp[0..] |
357 * NULL | 408 * NULL |
358 * auxv[0].a_type | 409 * auxv[0].a_type |
359 * auxv[1].a_un.a_val | 410 * auxv[1].a_un.a_val |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 * that, envp and auxv will start one word back from where they were. | 446 * that, envp and auxv will start one word back from where they were. |
396 */ | 447 */ |
397 --argc; | 448 --argc; |
398 --envp; | 449 --envp; |
399 auxv = (ElfW(auxv_t) *) ep; | 450 auxv = (ElfW(auxv_t) *) ep; |
400 stack[0] = argc; | 451 stack[0] = argc; |
401 for (i = 1; i < stack_words; ++i) | 452 for (i = 1; i < stack_words; ++i) |
402 stack[i] = stack[i + 1]; | 453 stack[i] = stack[i + 1]; |
403 | 454 |
404 /* | 455 /* |
| 456 * If one of our arguments is the kRDebugTemplate string, then |
| 457 * we'll modify that argument string in place to specify the |
| 458 * address of our _r_debug structure. |
| 459 */ |
| 460 for (i = 1; i < argc; ++i) { |
| 461 if (check_r_debug_arg(argv[i])) |
| 462 break; |
| 463 } |
| 464 |
| 465 /* |
405 * Record the auxv entries that are specific to the file loaded. | 466 * Record the auxv entries that are specific to the file loaded. |
406 * The incoming entries point to our own static executable. | 467 * The incoming entries point to our own static executable. |
407 */ | 468 */ |
408 ElfW(auxv_t) *av_entry = NULL; | 469 ElfW(auxv_t) *av_entry = NULL; |
409 ElfW(auxv_t) *av_phdr = NULL; | 470 ElfW(auxv_t) *av_phdr = NULL; |
410 ElfW(auxv_t) *av_phnum = NULL; | 471 ElfW(auxv_t) *av_phnum = NULL; |
411 size_t pagesize = 0; | 472 size_t pagesize = 0; |
412 | 473 |
413 for (av = auxv; | 474 for (av = auxv; |
414 av_entry == NULL || av_phdr == NULL || av_phnum == NULL || pagesize == 0; | 475 av_entry == NULL || av_phdr == NULL || av_phnum == NULL || pagesize == 0; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 "mov r4, sp\n" /* Save starting SP in r4. */ | 566 "mov r4, sp\n" /* Save starting SP in r4. */ |
506 "mov r0, sp\n" /* Argument: stack block. */ | 567 "mov r0, sp\n" /* Argument: stack block. */ |
507 "bl do_load\n" | 568 "bl do_load\n" |
508 "mov sp, r4\n" /* Restore the saved SP. */ | 569 "mov sp, r4\n" /* Restore the saved SP. */ |
509 "blx r0\n" /* Jump to the entry point. */ | 570 "blx r0\n" /* Jump to the entry point. */ |
510 ".popsection" | 571 ".popsection" |
511 ); | 572 ); |
512 #else | 573 #else |
513 # error "Need stack-preserving _start code for this architecture!" | 574 # error "Need stack-preserving _start code for this architecture!" |
514 #endif | 575 #endif |
OLD | NEW |