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

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: cosmetic trivia per review 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
« no previous file with comments | « chrome/app/nacl_fork_delegate_linux.cc ('k') | chrome/nacl/nacl_helper_bootstrap_linux.x » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 * 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
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
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
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
OLDNEW
« no previous file with comments | « chrome/app/nacl_fork_delegate_linux.cc ('k') | chrome/nacl/nacl_helper_bootstrap_linux.x » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698