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 */ | |
33 #define R_DEBUG_TEMPLATE_PREFIX "--r_debug=0x" | |
34 #define R_DEBUG_TEMPLATE_DIGITS "XXXXXXXXXXXXXXXX" | |
35 static const char kRDebugTemplate[] = | |
36 R_DEBUG_TEMPLATE_PREFIX R_DEBUG_TEMPLATE_DIGITS; | |
37 static const size_t kRDebugPrefixLen = sizeof R_DEBUG_TEMPLATE_PREFIX - 1; | |
Mark Seaborn
2011/11/14 20:15:41
consistency: elsewhere you use sizeof() (i.e. with
| |
38 | |
30 | 39 |
31 /* | 40 /* |
32 * We're not using <string.h> functions here, to avoid dependencies. | 41 * We're not using <string.h> functions here, to avoid dependencies. |
33 * In the x86 libc, even "simple" functions like memset and strlen can | 42 * In the x86 libc, even "simple" functions like memset and strlen can |
34 * depend on complex startup code, because in newer libc | 43 * depend on complex startup code, because in newer libc |
35 * implementations they are defined using STT_GNU_IFUNC. | 44 * implementations they are defined using STT_GNU_IFUNC. |
36 */ | 45 */ |
37 | 46 |
38 static void my_bzero(void *buf, size_t n) { | 47 static void my_bzero(void *buf, size_t n) { |
39 char *p = buf; | 48 char *p = buf; |
40 while (n-- > 0) | 49 while (n-- > 0) |
41 *p++ = 0; | 50 *p++ = 0; |
42 } | 51 } |
43 | 52 |
44 static size_t my_strlen(const char *s) { | 53 static size_t my_strlen(const char *s) { |
45 size_t n = 0; | 54 size_t n = 0; |
46 while (*s++ != '\0') | 55 while (*s++ != '\0') |
47 ++n; | 56 ++n; |
48 return n; | 57 return n; |
49 } | 58 } |
50 | 59 |
60 static int my_strcmp(const char *a, const char *b) { | |
61 while (*a == *b) { | |
62 if (*a == '\0') | |
63 return 0; | |
64 ++a; | |
65 ++b; | |
66 } | |
67 return (int) (unsigned char) *a - (int) (unsigned char) *b; | |
68 } | |
69 | |
51 | 70 |
52 /* | 71 /* |
53 * Get inline functions for system calls. | 72 * Get inline functions for system calls. |
54 */ | 73 */ |
55 static int my_errno; | 74 static int my_errno; |
56 #define SYS_ERRNO my_errno | 75 #define SYS_ERRNO my_errno |
57 #include "third_party/lss/linux_syscall_support.h" | 76 #include "third_party/lss/linux_syscall_support.h" |
58 | 77 |
59 | 78 |
60 /* | 79 /* |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 | 359 |
341 if (out_phdr != NULL) | 360 if (out_phdr != NULL) |
342 *out_phdr = (ehdr.e_phoff - first_load->p_offset + | 361 *out_phdr = (ehdr.e_phoff - first_load->p_offset + |
343 first_load->p_vaddr + load_bias); | 362 first_load->p_vaddr + load_bias); |
344 if (out_phnum != NULL) | 363 if (out_phnum != NULL) |
345 *out_phnum = ehdr.e_phnum; | 364 *out_phnum = ehdr.e_phnum; |
346 | 365 |
347 return ehdr.e_entry + load_bias; | 366 return ehdr.e_entry + load_bias; |
348 } | 367 } |
349 | 368 |
369 | |
370 /* | |
371 * GDB looks for this symbol name when it cannot find PT_DYNAMIC->DT_DEBUG. | |
372 * We don't have a PT_DYNAMIC, so it will find this. Now all we have to do | |
373 * is arrange for this space to be filled in with the dynamic linker's | |
374 * _r_debug contents after they're initialized. That way, attaching GDB to | |
375 * this process or examining its core file will find the PIE we loaded, the | |
376 * dynamic linker, and all the shared libraries, making debugging pleasant. | |
377 */ | |
378 struct r_debug _r_debug __attribute__((nocommon, section(".r_debug"))); | |
379 | |
380 /* | |
381 * If the argument matches the kRDebugTemplate string, then replace | |
382 * the 16 Xs with the hexadecimal address of our _r_debug variable. | |
383 */ | |
384 static int check_r_debug_arg(char *arg) { | |
385 if (!my_strcmp(arg, kRDebugTemplate)) { | |
Mark Seaborn
2011/11/14 20:15:41
prefer "strcmp(x,y) == 0" since strcmp()'s result
| |
386 uintptr_t addr = (uintptr_t) &_r_debug; | |
387 size_t i = 16; | |
388 while (i-- > 0) { | |
389 arg[kRDebugPrefixLen + i] = "0123456789abcdef"[addr & 0xf]; | |
390 addr >>= 4; | |
391 } | |
392 return 1; | |
393 } | |
394 return 0; | |
395 } | |
396 | |
397 | |
350 /* | 398 /* |
351 * This is the main loading code. It's called with the starting stack pointer. | 399 * This is the main loading code. It's called with the starting stack pointer. |
352 * This points to a sequence of pointer-size words: | 400 * This points to a sequence of pointer-size words: |
353 * [0] argc | 401 * [0] argc |
354 * [1..argc] argv[0..argc-1] | 402 * [1..argc] argv[0..argc-1] |
355 * [1+argc] NULL | 403 * [1+argc] NULL |
356 * [2+argc..] envp[0..] | 404 * [2+argc..] envp[0..] |
357 * NULL | 405 * NULL |
358 * auxv[0].a_type | 406 * auxv[0].a_type |
359 * auxv[1].a_un.a_val | 407 * 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. | 443 * that, envp and auxv will start one word back from where they were. |
396 */ | 444 */ |
397 --argc; | 445 --argc; |
398 --envp; | 446 --envp; |
399 auxv = (ElfW(auxv_t) *) ep; | 447 auxv = (ElfW(auxv_t) *) ep; |
400 stack[0] = argc; | 448 stack[0] = argc; |
401 for (i = 1; i < stack_words; ++i) | 449 for (i = 1; i < stack_words; ++i) |
402 stack[i] = stack[i + 1]; | 450 stack[i] = stack[i + 1]; |
403 | 451 |
404 /* | 452 /* |
453 * If one of our arguments is the kRDebugTemplate string, then | |
454 * we'll modify that argument string in place to specify the | |
455 * address of our _r_debug structure. | |
456 */ | |
457 for (i = 1; i < argc; ++i) { | |
458 if (check_r_debug_arg(argv[i])) | |
459 break; | |
460 } | |
461 | |
462 /* | |
405 * Record the auxv entries that are specific to the file loaded. | 463 * Record the auxv entries that are specific to the file loaded. |
406 * The incoming entries point to our own static executable. | 464 * The incoming entries point to our own static executable. |
407 */ | 465 */ |
408 ElfW(auxv_t) *av_entry = NULL; | 466 ElfW(auxv_t) *av_entry = NULL; |
409 ElfW(auxv_t) *av_phdr = NULL; | 467 ElfW(auxv_t) *av_phdr = NULL; |
410 ElfW(auxv_t) *av_phnum = NULL; | 468 ElfW(auxv_t) *av_phnum = NULL; |
411 size_t pagesize = 0; | 469 size_t pagesize = 0; |
412 | 470 |
413 for (av = auxv; | 471 for (av = auxv; |
414 av_entry == NULL || av_phdr == NULL || av_phnum == NULL || pagesize == 0; | 472 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. */ | 563 "mov r4, sp\n" /* Save starting SP in r4. */ |
506 "mov r0, sp\n" /* Argument: stack block. */ | 564 "mov r0, sp\n" /* Argument: stack block. */ |
507 "bl do_load\n" | 565 "bl do_load\n" |
508 "mov sp, r4\n" /* Restore the saved SP. */ | 566 "mov sp, r4\n" /* Restore the saved SP. */ |
509 "blx r0\n" /* Jump to the entry point. */ | 567 "blx r0\n" /* Jump to the entry point. */ |
510 ".popsection" | 568 ".popsection" |
511 ); | 569 ); |
512 #else | 570 #else |
513 # error "Need stack-preserving _start code for this architecture!" | 571 # error "Need stack-preserving _start code for this architecture!" |
514 #endif | 572 #endif |
OLD | NEW |