Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: chrome/nacl/nacl_helper_bootstrap_linux.c

Issue 8491060: Make nacl_helper easily debuggable (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698