diff options
-rw-r--r-- | DEPS | 4 | ||||
-rw-r--r-- | chrome/chrome_exe.gypi | 2 | ||||
-rw-r--r-- | chrome/nacl.gypi | 160 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_bootstrap_linux.c | 575 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_bootstrap_linux.x | 133 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_bootstrap_munge_phdr.c | 66 | ||||
-rwxr-xr-x | chrome/nacl/nacl_helper_bootstrap_munge_phdr.py | 39 | ||||
-rwxr-xr-x | tools/ld_bfd/ld | 50 |
8 files changed, 4 insertions, 1025 deletions
@@ -33,6 +33,7 @@ vars = { "libjingle_revision": "95", "libphonenumber_revision": "407", "libvpx_revision": "109236", + "lss_revision": "9", "ffmpeg_revision": "112050", "sfntly_revision": "111", "skia_revision": "2785", @@ -402,7 +403,8 @@ deps_os = { "/trunk/deps/third_party/swig/linux@" + Var("swig_revision"), "src/third_party/lss": - (Var("googlecode_url") % "linux-syscall-support") + "/trunk/lss@8", + ((Var("googlecode_url") % "linux-syscall-support") + "/trunk/lss@" + + Var("lss_revision")), "src/third_party/openssl": "/trunk/deps/third_party/openssl@105093", diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index 9d7819c..4f7edcc 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi @@ -418,7 +418,7 @@ # For now, do not build nacl_helper when disable_nacl=1 ['disable_nacl!=1', { 'dependencies': [ - 'nacl_helper_bootstrap', + '../native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap', 'nacl_helper', ], }], diff --git a/chrome/nacl.gypi b/chrome/nacl.gypi index 337d13e..f391ca1 100644 --- a/chrome/nacl.gypi +++ b/chrome/nacl.gypi @@ -187,166 +187,6 @@ 'ldflags': ['-pie'], }, }, - { - 'target_name': 'nacl_helper_bootstrap_munge_phdr', - 'type': 'executable', - 'toolsets': ['host'], - 'sources': [ - 'nacl/nacl_helper_bootstrap_munge_phdr.c', - ], - 'libraries': [ - '-lelf', - ], - # This is an ugly kludge because gyp doesn't actually treat - # host_arch=x64 target_arch=ia32 as proper cross compilation. - # It still wants to compile the "host" program with -m32 et - # al. Though a program built that way can indeed run on the - # x86-64 host, we cannot reliably build this program on such a - # host because Ubuntu does not provide the full suite of - # x86-32 libraries in packages that can be installed on an - # x86-64 host; in particular, libelf is missing. So here we - # use the hack of eliding all the -m* flags from the - # compilation lines, getting the command close to what they - # would be if gyp were to really build properly for the host. - # TODO(bradnelson): Clean up with proper cross support. - 'conditions': [ - ['host_arch=="x64"', { - 'cflags/': [['exclude', '-m.*']], - 'ldflags/': [['exclude', '-m.*']], - }], - ], - }, - { - 'target_name': 'nacl_helper_bootstrap_lib', - 'type': 'static_library', - 'product_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome', - 'hard_depencency': 1, - 'include_dirs': [ - '..', - ], - 'sources': [ - 'nacl/nacl_helper_bootstrap_linux.c', - ], - 'cflags': [ - # The tiny standalone bootstrap program is incompatible with - # -fstack-protector, which might be on by default. That switch - # requires using the standard libc startup code, which we do not. - '-fno-stack-protector', - # We don't want to compile it PIC (or its cousin PIE), because - # it goes at an absolute address anyway, and because any kind - # of PIC complicates life for the x86-32 assembly code. We - # append -fno-* flags here instead of using a 'cflags!' stanza - # to remove -f* flags, just in case some system's compiler - # defaults to using PIC for everything. - '-fno-pic', '-fno-PIC', - '-fno-pie', '-fno-PIE', - ], - 'cflags!': [ - # TODO(glider): -fasan is deprecated. - '-fasan', - '-faddress-sanitizer', - '-w', - ], - 'conditions': [ - ['clang==1', { - 'cflags': [ - # Prevent llvm-opt from replacing my_bzero with a call - # to memset - '-ffreestanding', - # But make its <limits.h> still work! - '-U__STDC_HOSTED__', '-D__STDC_HOSTED__=1', - ], - }], - ], - }, - { - 'target_name': 'nacl_helper_bootstrap_raw', - 'type': 'none', - 'dependencies': [ - 'nacl_helper_bootstrap_lib', - ], - 'actions': [ - { - 'action_name': 'link_with_ld_bfd', - 'variables': { - 'bootstrap_lib': '<(SHARED_INTERMEDIATE_DIR)/chrome/<(STATIC_LIB_PREFIX)nacl_helper_bootstrap_lib<(STATIC_LIB_SUFFIX)', - 'linker_script': 'nacl/nacl_helper_bootstrap_linux.x', - }, - 'inputs': [ - '<(linker_script)', - '<(bootstrap_lib)', - '../tools/ld_bfd/ld', - ], - 'outputs': [ - '<(PRODUCT_DIR)/nacl_helper_bootstrap_raw', - ], - 'message': 'Linking nacl_helper_bootstrap_raw', - 'conditions': [ - ['target_arch=="x64"', { - 'variables': { - 'linker_emulation': 'elf_x86_64', - 'bootstrap_extra_lib': '', - } - }], - ['target_arch=="ia32"', { - 'variables': { - 'linker_emulation': 'elf_i386', - 'bootstrap_extra_lib': '', - } - }], - ['target_arch=="arm"', { - 'variables': { - 'linker_emulation': 'armelf_linux_eabi', - # ARM requires linking against libc due to ABI - # dependencies on memset. - 'bootstrap_extra_lib' : "${SYSROOT}/usr/lib/libc.a", - } - }], - ], - 'action': ['../tools/ld_bfd/ld', - '-m', '<(linker_emulation)', - '--build-id', - # This program is (almost) entirely - # standalone. It has its own startup code, so - # no crt1.o for it. It is statically linked, - # and on x86 it does not use libc at all. - # However, on ARM it needs a few (safe) things - # from libc. - '-static', - # Link with custom linker script for special - # layout. The script uses the symbol RESERVE_TOP. - '<@(nacl_reserve_top)', - '--script=<(linker_script)', - '-o', '<@(_outputs)', - # On x86-64, the default page size with some - # linkers is 2M rather than the real Linux page - # size of 4K. A larger page size is incompatible - # with our custom linker script's special layout. - '-z', 'max-page-size=0x1000', - '--whole-archive', '<(bootstrap_lib)', - '--no-whole-archive', - '<@(bootstrap_extra_lib)', - ], - } - ], - }, - { - 'target_name': 'nacl_helper_bootstrap', - 'dependencies': [ - 'nacl_helper_bootstrap_raw', - 'nacl_helper_bootstrap_munge_phdr#host', - ], - 'type': 'none', - 'actions': [{ - 'action_name': 'munge_phdr', - 'inputs': ['nacl/nacl_helper_bootstrap_munge_phdr.py', - '<(PRODUCT_DIR)/nacl_helper_bootstrap_munge_phdr', - '<(PRODUCT_DIR)/nacl_helper_bootstrap_raw'], - 'outputs': ['<(PRODUCT_DIR)/nacl_helper_bootstrap'], - 'message': 'Munging ELF program header', - 'action': ['python', '<@(_inputs)', '<@(_outputs)'] - }], - }, ], }], ], diff --git a/chrome/nacl/nacl_helper_bootstrap_linux.c b/chrome/nacl/nacl_helper_bootstrap_linux.c deleted file mode 100644 index 61e8a1f..0000000 --- a/chrome/nacl/nacl_helper_bootstrap_linux.c +++ /dev/null @@ -1,575 +0,0 @@ -/* Copyright (c) 2011 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * This is a standalone program that loads and runs the dynamic linker. - * This program itself must be linked statically. To keep it small, it's - * written to avoid all dependencies on libc and standard startup code. - * Hence, this should be linked using -nostartfiles. It must be compiled - * with -fno-stack-protector to ensure the compiler won't emit code that - * presumes some special setup has been done. - * - * On ARM, the compiler will emit calls to some libc functions, so we - * cannot link with -nostdlib. The functions it does use (memset and - * __aeabi_* functions for integer division) are sufficiently small and - * self-contained in ARM's libc.a that we don't have any problem using - * the libc definitions though we aren't using the rest of libc or doing - * any of the setup it might expect. - */ - -#include <elf.h> -#include <fcntl.h> -#include <limits.h> -#include <link.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/mman.h> - -#define MAX_PHNUM 12 - -/* - * This exact magic argument string is recognized in check_r_debug_arg, below. - * Requiring the argument to have those Xs as a template both simplifies - * our argument matching code and saves us from having to reformat the - * whole stack to find space for a string longer than the original argument. - */ -#define R_DEBUG_TEMPLATE_PREFIX "--r_debug=0x" -#define R_DEBUG_TEMPLATE_DIGITS "XXXXXXXXXXXXXXXX" -static const char kRDebugTemplate[] = - R_DEBUG_TEMPLATE_PREFIX R_DEBUG_TEMPLATE_DIGITS; -static const size_t kRDebugPrefixLen = sizeof(R_DEBUG_TEMPLATE_PREFIX) - 1; - - -/* - * We're not using <string.h> functions here, to avoid dependencies. - * In the x86 libc, even "simple" functions like memset and strlen can - * depend on complex startup code, because in newer libc - * implementations they are defined using STT_GNU_IFUNC. - */ - -static void my_bzero(void *buf, size_t n) { - char *p = buf; - while (n-- > 0) - *p++ = 0; -} - -static size_t my_strlen(const char *s) { - size_t n = 0; - while (*s++ != '\0') - ++n; - return n; -} - -static int my_strcmp(const char *a, const char *b) { - while (*a == *b) { - if (*a == '\0') - return 0; - ++a; - ++b; - } - return (int) (unsigned char) *a - (int) (unsigned char) *b; -} - - -/* - * Get inline functions for system calls. - */ -static int my_errno; -#define SYS_ERRNO my_errno -#include "third_party/lss/linux_syscall_support.h" - - -/* - * We're avoiding libc, so no printf. The only nontrivial thing we need - * is rendering numbers, which is, in fact, pretty trivial. - */ -static void iov_int_string(int value, struct kernel_iovec *iov, - char *buf, size_t bufsz) { - char *p = &buf[bufsz]; - do { - --p; - *p = "0123456789"[value % 10]; - value /= 10; - } while (value != 0); - iov->iov_base = p; - iov->iov_len = &buf[bufsz] - p; -} - -#define STRING_IOV(string_constant, cond) \ - { (void *) string_constant, cond ? (sizeof(string_constant) - 1) : 0 } - -__attribute__((noreturn)) static void fail(const char *filename, - const char *message, - const char *item1, int value1, - const char *item2, int value2) { - char valbuf1[32]; - char valbuf2[32]; - struct kernel_iovec iov[] = { - STRING_IOV("bootstrap_helper: ", 1), - { (void *) filename, my_strlen(filename) }, - STRING_IOV(": ", 1), - { (void *) message, my_strlen(message) }, - { (void *) item1, item1 == NULL ? 0 : my_strlen(item1) }, - STRING_IOV("=", item1 != NULL), - {}, - STRING_IOV(", ", item1 != NULL && item2 != NULL), - { (void *) item2, item2 == NULL ? 0 : my_strlen(item2) }, - STRING_IOV("=", item2 != NULL), - {}, - { "\n", 1 }, - }; - const int niov = sizeof(iov) / sizeof(iov[0]); - - if (item1 != NULL) - iov_int_string(value1, &iov[6], valbuf1, sizeof(valbuf1)); - if (item2 != NULL) - iov_int_string(value1, &iov[10], valbuf2, sizeof(valbuf2)); - - sys_writev(2, iov, niov); - sys_exit_group(2); - while (1) *(volatile int *) 0 = 0; /* Crash. */ -} - - -static int my_open(const char *file, int oflag) { - int result = sys_open(file, oflag, 0); - if (result < 0) - fail(file, "Cannot open ELF file! ", "errno", my_errno, NULL, 0); - return result; -} - -static void my_pread(const char *file, const char *fail_message, - int fd, void *buf, size_t bufsz, uintptr_t pos) { - ssize_t result = sys_pread64(fd, buf, bufsz, pos); - if (result < 0) - fail(file, fail_message, "errno", my_errno, NULL, 0); - if ((size_t) result != bufsz) - fail(file, fail_message, "read count", result, NULL, 0); -} - -static uintptr_t my_mmap(const char *file, - const char *segment_type, unsigned int segnum, - uintptr_t address, size_t size, - int prot, int flags, int fd, uintptr_t pos) { -#if defined(__NR_mmap2) - void *result = sys_mmap2((void *) address, size, prot, flags, fd, pos >> 12); -#else - void *result = sys_mmap((void *) address, size, prot, flags, fd, pos); -#endif - if (result == MAP_FAILED) - fail(file, "Failed to map segment! ", - segment_type, segnum, "errno", my_errno); - return (uintptr_t) result; -} - -static void my_mprotect(const char *file, unsigned int segnum, - uintptr_t address, size_t size, int prot) { - if (sys_mprotect((void *) address, size, prot) < 0) - fail(file, "Failed to mprotect segment hole! ", - "segment", segnum, "errno", my_errno); -} - - -static int prot_from_phdr(const ElfW(Phdr) *phdr) { - int prot = 0; - if (phdr->p_flags & PF_R) - prot |= PROT_READ; - if (phdr->p_flags & PF_W) - prot |= PROT_WRITE; - if (phdr->p_flags & PF_X) - prot |= PROT_EXEC; - return prot; -} - -static uintptr_t round_up(uintptr_t value, uintptr_t size) { - return (value + size - 1) & -size; -} - -static uintptr_t round_down(uintptr_t value, uintptr_t size) { - return value & -size; -} - -/* - * Handle the "bss" portion of a segment, where the memory size - * exceeds the file size and we zero-fill the difference. For any - * whole pages in this region, we over-map anonymous pages. For the - * sub-page remainder, we zero-fill bytes directly. - */ -static void handle_bss(const char *file, - unsigned int segnum, const ElfW(Phdr) *ph, - ElfW(Addr) load_bias, size_t pagesize) { - if (ph->p_memsz > ph->p_filesz) { - ElfW(Addr) file_end = ph->p_vaddr + load_bias + ph->p_filesz; - ElfW(Addr) file_page_end = round_up(file_end, pagesize); - ElfW(Addr) page_end = round_up(ph->p_vaddr + load_bias + - ph->p_memsz, pagesize); - if (page_end > file_page_end) - my_mmap(file, "bss segment", segnum, - file_page_end, page_end - file_page_end, - prot_from_phdr(ph), MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0); - if (file_page_end > file_end && (ph->p_flags & PF_W)) - my_bzero((void *) file_end, file_page_end - file_end); - } -} - -/* - * Open an ELF file and load it into memory. - */ -static ElfW(Addr) load_elf_file(const char *filename, - size_t pagesize, - ElfW(Addr) *out_phdr, - ElfW(Addr) *out_phnum, - const char **out_interp) { - int fd = my_open(filename, O_RDONLY); - - ElfW(Ehdr) ehdr; - my_pread(filename, "Failed to read ELF header from file! ", - fd, &ehdr, sizeof(ehdr), 0); - - if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || - ehdr.e_ident[EI_MAG1] != ELFMAG1 || - ehdr.e_ident[EI_MAG2] != ELFMAG2 || - ehdr.e_ident[EI_MAG3] != ELFMAG3 || - ehdr.e_version != EV_CURRENT || - ehdr.e_ehsize != sizeof(ehdr) || - ehdr.e_phentsize != sizeof(ElfW(Phdr))) - fail(filename, "File has no valid ELF header!", NULL, 0, NULL, 0); - - switch (ehdr.e_machine) { -#if defined(__i386__) - case EM_386: -#elif defined(__x86_64__) - case EM_X86_64: -#elif defined(__arm__) - case EM_ARM: -#else -# error "Don't know the e_machine value for this architecture!" -#endif - break; - default: - fail(filename, "ELF file has wrong architecture! ", - "e_machine", ehdr.e_machine, NULL, 0); - break; - } - - ElfW(Phdr) phdr[MAX_PHNUM]; - if (ehdr.e_phnum > sizeof(phdr) / sizeof(phdr[0]) || ehdr.e_phnum < 1) - fail(filename, "ELF file has unreasonable ", - "e_phnum", ehdr.e_phnum, NULL, 0); - - if (ehdr.e_type != ET_DYN) - fail(filename, "ELF file not ET_DYN! ", - "e_type", ehdr.e_type, NULL, 0); - - my_pread(filename, "Failed to read program headers from ELF file! ", - fd, phdr, sizeof(phdr[0]) * ehdr.e_phnum, ehdr.e_phoff); - - size_t i = 0; - while (i < ehdr.e_phnum && phdr[i].p_type != PT_LOAD) - ++i; - if (i == ehdr.e_phnum) - fail(filename, "ELF file has no PT_LOAD header!", - NULL, 0, NULL, 0); - - /* - * ELF requires that PT_LOAD segments be in ascending order of p_vaddr. - * Find the last one to calculate the whole address span of the image. - */ - const ElfW(Phdr) *first_load = &phdr[i]; - const ElfW(Phdr) *last_load = &phdr[ehdr.e_phnum - 1]; - while (last_load > first_load && last_load->p_type != PT_LOAD) - --last_load; - - size_t span = last_load->p_vaddr + last_load->p_memsz - first_load->p_vaddr; - - /* - * Map the first segment and reserve the space used for the rest and - * for holes between segments. - */ - const uintptr_t mapping = my_mmap(filename, "segment", first_load - phdr, - round_down(first_load->p_vaddr, pagesize), - span, prot_from_phdr(first_load), - MAP_PRIVATE, fd, - round_down(first_load->p_offset, pagesize)); - - const ElfW(Addr) load_bias = mapping - round_down(first_load->p_vaddr, - pagesize); - - if (first_load->p_offset > ehdr.e_phoff || - first_load->p_filesz < ehdr.e_phoff + (ehdr.e_phnum * sizeof(ElfW(Phdr)))) - fail(filename, "First load segment of ELF file does not contain phdrs!", - NULL, 0, NULL, 0); - - handle_bss(filename, first_load - phdr, first_load, load_bias, pagesize); - - ElfW(Addr) last_end = first_load->p_vaddr + load_bias + first_load->p_memsz; - - /* - * Map the remaining segments, and protect any holes between them. - */ - const ElfW(Phdr) *ph; - for (ph = first_load + 1; ph <= last_load; ++ph) { - if (ph->p_type == PT_LOAD) { - ElfW(Addr) last_page_end = round_up(last_end, pagesize); - - last_end = ph->p_vaddr + load_bias + ph->p_memsz; - ElfW(Addr) start = round_down(ph->p_vaddr + load_bias, pagesize); - ElfW(Addr) end = round_up(last_end, pagesize); - - if (start > last_page_end) - my_mprotect(filename, - ph - phdr, last_page_end, start - last_page_end, PROT_NONE); - - my_mmap(filename, "segment", ph - phdr, - start, end - start, - prot_from_phdr(ph), MAP_PRIVATE | MAP_FIXED, fd, - round_down(ph->p_offset, pagesize)); - - handle_bss(filename, ph - phdr, ph, load_bias, pagesize); - } - } - - if (out_interp != NULL) { - /* - * Find the PT_INTERP header, if there is one. - */ - for (i = 0; i < ehdr.e_phnum; ++i) { - if (phdr[i].p_type == PT_INTERP) { - /* - * The PT_INTERP isn't really required to sit inside the first - * (or any) load segment, though it normally does. So we can - * easily avoid an extra read in that case. - */ - if (phdr[i].p_offset >= first_load->p_offset && - phdr[i].p_filesz <= first_load->p_filesz) { - *out_interp = (const char *) (phdr[i].p_vaddr + load_bias); - } else { - static char interp_buffer[PATH_MAX + 1]; - if (phdr[i].p_filesz >= sizeof(interp_buffer)) { - fail(filename, "ELF file has unreasonable PT_INTERP size! ", - "segment", i, "p_filesz", phdr[i].p_filesz); - } - my_pread(filename, "Cannot read PT_INTERP segment contents!", - fd, interp_buffer, phdr[i].p_filesz, phdr[i].p_offset); - *out_interp = interp_buffer; - } - break; - } - } - } - - sys_close(fd); - - if (out_phdr != NULL) - *out_phdr = (ehdr.e_phoff - first_load->p_offset + - first_load->p_vaddr + load_bias); - if (out_phnum != NULL) - *out_phnum = ehdr.e_phnum; - - return ehdr.e_entry + load_bias; -} - - -/* - * GDB looks for this symbol name when it cannot find PT_DYNAMIC->DT_DEBUG. - * We don't have a PT_DYNAMIC, so it will find this. Now all we have to do - * is arrange for this space to be filled in with the dynamic linker's - * _r_debug contents after they're initialized. That way, attaching GDB to - * this process or examining its core file will find the PIE we loaded, the - * dynamic linker, and all the shared libraries, making debugging pleasant. - */ -struct r_debug _r_debug __attribute__((nocommon, section(".r_debug"))); - -/* - * If the argument matches the kRDebugTemplate string, then replace - * the 16 Xs with the hexadecimal address of our _r_debug variable. - */ -static int check_r_debug_arg(char *arg) { - if (my_strcmp(arg, kRDebugTemplate) == 0) { - uintptr_t addr = (uintptr_t) &_r_debug; - size_t i = 16; - while (i-- > 0) { - arg[kRDebugPrefixLen + i] = "0123456789abcdef"[addr & 0xf]; - addr >>= 4; - } - return 1; - } - return 0; -} - - -/* - * This is the main loading code. It's called with the starting stack pointer. - * This points to a sequence of pointer-size words: - * [0] argc - * [1..argc] argv[0..argc-1] - * [1+argc] NULL - * [2+argc..] envp[0..] - * NULL - * auxv[0].a_type - * auxv[1].a_un.a_val - * ... - * It returns the dynamic linker's runtime entry point address, where - * we should jump to. This is called by the machine-dependent _start - * code (below). On return, it restores the original stack pointer - * and jumps to this entry point. - * - * argv[0] is the uninteresting name of this bootstrap program. argv[1] is - * the real program file name we'll open, and also the argv[0] for that - * program. We need to modify argc, move argv[1..] back to the argv[0..] - * position, and also examine and modify the auxiliary vector on the stack. - */ -ElfW(Addr) do_load(uintptr_t *stack) { - size_t i; - - /* - * First find the end of the auxiliary vector. - */ - int argc = stack[0]; - char **argv = (char **) &stack[1]; - const char *program = argv[1]; - char **envp = &argv[argc + 1]; - char **ep = envp; - while (*ep != NULL) - ++ep; - ElfW(auxv_t) *auxv = (ElfW(auxv_t) *) (ep + 1); - ElfW(auxv_t) *av = auxv; - while (av->a_type != AT_NULL) - ++av; - size_t stack_words = (uintptr_t *) (av + 1) - &stack[1]; - - if (argc < 2) - fail("Usage", "PROGRAM ARGS...", NULL, 0, NULL, 0); - - /* - * Now move everything back to eat our original argv[0]. When we've done - * that, envp and auxv will start one word back from where they were. - */ - --argc; - --envp; - auxv = (ElfW(auxv_t) *) ep; - stack[0] = argc; - for (i = 1; i < stack_words; ++i) - stack[i] = stack[i + 1]; - - /* - * If one of our arguments is the kRDebugTemplate string, then - * we'll modify that argument string in place to specify the - * address of our _r_debug structure. - */ - for (i = 1; i < argc; ++i) { - if (check_r_debug_arg(argv[i])) - break; - } - - /* - * Record the auxv entries that are specific to the file loaded. - * The incoming entries point to our own static executable. - */ - ElfW(auxv_t) *av_entry = NULL; - ElfW(auxv_t) *av_phdr = NULL; - ElfW(auxv_t) *av_phnum = NULL; - size_t pagesize = 0; - - for (av = auxv; - av_entry == NULL || av_phdr == NULL || av_phnum == NULL || pagesize == 0; - ++av) { - switch (av->a_type) { - case AT_NULL: - fail("startup", - "Failed to find AT_ENTRY, AT_PHDR, AT_PHNUM, or AT_PAGESZ!", - NULL, 0, NULL, 0); - /*NOTREACHED*/ - break; - case AT_ENTRY: - av_entry = av; - break; - case AT_PAGESZ: - pagesize = av->a_un.a_val; - break; - case AT_PHDR: - av_phdr = av; - break; - case AT_PHNUM: - av_phnum = av; - break; - } - } - - /* Load the program and point the auxv elements at its phdrs and entry. */ - const char *interp = NULL; - av_entry->a_un.a_val = load_elf_file(program, - pagesize, - &av_phdr->a_un.a_val, - &av_phnum->a_un.a_val, - &interp); - - ElfW(Addr) entry = av_entry->a_un.a_val; - - if (interp != NULL) { - /* - * There was a PT_INTERP, so we have a dynamic linker to load. - */ - entry = load_elf_file(interp, pagesize, NULL, NULL, NULL); - } - - return entry; -} - -/* - * We have to define the actual entry point code (_start) in assembly for - * each machine. The kernel startup protocol is not compatible with the - * normal C function calling convention. Here, we call do_load (above) - * using the normal C convention as per the ABI, with the starting stack - * pointer as its argument; restore the original starting stack; and - * finally, jump to the dynamic linker's entry point address. - */ -#if defined(__i386__) -asm(".pushsection \".text\",\"ax\",@progbits\n" - ".globl _start\n" - ".type _start,@function\n" - "_start:\n" - "xorl %ebp, %ebp\n" - "movl %esp, %ebx\n" /* Save starting SP in %ebx. */ - "andl $-16, %esp\n" /* Align the stack as per ABI. */ - "pushl %ebx\n" /* Argument: stack block. */ - "call do_load\n" - "movl %ebx, %esp\n" /* Restore the saved SP. */ - "jmp *%eax\n" /* Jump to the entry point. */ - ".popsection" - ); -#elif defined(__x86_64__) -asm(".pushsection \".text\",\"ax\",@progbits\n" - ".globl _start\n" - ".type _start,@function\n" - "_start:\n" - "xorq %rbp, %rbp\n" - "movq %rsp, %rbx\n" /* Save starting SP in %rbx. */ - "andq $-16, %rsp\n" /* Align the stack as per ABI. */ - "movq %rbx, %rdi\n" /* Argument: stack block. */ - "call do_load\n" - "movq %rbx, %rsp\n" /* Restore the saved SP. */ - "jmp *%rax\n" /* Jump to the entry point. */ - ".popsection" - ); -#elif defined(__arm__) -asm(".pushsection \".text\",\"ax\",%progbits\n" - ".globl _start\n" - ".type _start,#function\n" - "_start:\n" -#if defined(__thumb2__) - ".thumb\n" - ".syntax unified\n" -#endif - "mov fp, #0\n" - "mov lr, #0\n" - "mov r4, sp\n" /* Save starting SP in r4. */ - "mov r0, sp\n" /* Argument: stack block. */ - "bl do_load\n" - "mov sp, r4\n" /* Restore the saved SP. */ - "blx r0\n" /* Jump to the entry point. */ - ".popsection" - ); -#else -# error "Need stack-preserving _start code for this architecture!" -#endif diff --git a/chrome/nacl/nacl_helper_bootstrap_linux.x b/chrome/nacl/nacl_helper_bootstrap_linux.x deleted file mode 100644 index 89acd90..0000000 --- a/chrome/nacl/nacl_helper_bootstrap_linux.x +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2011 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * This is a custom linker script used to build nacl_helper_bootstrap. - * It has a very special layout. This script will only work with input - * that is kept extremely minimal. If there are unexpected input sections - * not named here, the result will not be correct. - * - * We need to use a standalone loader program rather than just using a - * dynamically-linked program here because its entire address space will be - * taken over for the NaCl untrusted address space. A normal program would - * cause dynamic linker data structures to point to its .dynamic section, - * which is no longer available after startup. - * - * We need this special layout (and the nacl_helper_bootstrap_munge_phdr - * step) because simply having bss space large enough to reserve the - * address space would cause the kernel loader to think we're using that - * much anonymous memory and refuse to execute the program on a machine - * with not much memory available. - */ - -/* - * Set the entry point to the symbol called _start, which we define in assembly. - */ -ENTRY(_start) - -/* - * This is the address where the program text starts. - * We set this as low as we think we can get away with. - * The common settings for sysctl vm.mmap_min_addr range from 4k to 64k. - */ -TEXT_START = 0x10000; - -/* - * The symbol RESERVE_TOP is the top of the range we are trying to reserve. - * This is set via --defsym on the linker command line, because the correct - * value differs for each machine. It's not defined at all if we do not - * actually need any space reserved for this configuration. - */ - -/* - * We specify the program headers we want explicitly, to get the layout - * exactly right and to give the "reserve" segment p_flags of zero, so - * that it gets mapped as PROT_NONE. - */ -PHDRS { - text PT_LOAD FILEHDR PHDRS; - data PT_LOAD; - reserve PT_LOAD FLAGS(0); - r_debug PT_LOAD; - note PT_NOTE; - stack PT_GNU_STACK FLAGS(6); /* RW, no E */ -} - -/* - * Now we lay out the sections across those segments. - */ -SECTIONS { - . = TEXT_START + SIZEOF_HEADERS; - - /* - * The build ID note usually comes first. - * It's both part of the text PT_LOAD segment (like other rodata) and - * it's what the PT_NOTE header points to. - */ - .note.gnu.build-id : { - *(.note.gnu.build-id) - } :text :note - - /* - * Here is the program itself. - */ - .text : { - *(.text*) - } :text - .rodata : { - *(.rodata*) - *(.eh_frame*) - } - - etext = .; - - /* - * Adjust the address for the data segment. We want to adjust up to - * the same address within the page on the next page up. - */ - . = (ALIGN(CONSTANT(MAXPAGESIZE)) - - ((CONSTANT(MAXPAGESIZE) - .) & (CONSTANT(MAXPAGESIZE) - 1))); - . = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE)); - - .data : { - *(.data*) - } :data - .bss : { - *(.bss*) - } - - /* - * Now we move up to the next p_align increment, and place the dummy - * segment there. The linker emits this segment with the p_vaddr and - * p_memsz we want, which reserves the address space. But the linker - * gives it a p_filesz of zero. We have to edit the phdr after link - * time to give it a p_filesz matching its p_memsz. That way, the - * kernel doesn't think we are preallocating a huge amount of memory. - * It just maps it from the file, i.e. way off the end of the file, - * which is perfect for reserving the address space. - */ - . = ALIGN(CONSTANT(COMMONPAGESIZE)); - RESERVE_START = .; - .reserve : { - . += DEFINED(RESERVE_TOP) ? (RESERVE_TOP - RESERVE_START) : 0; - } :reserve - - /* - * This must be placed above the reserved address space, so it won't - * be clobbered by NaCl. We want this to be visible at its fixed address - * in the memory image so the debugger can make sense of things. - */ - .r_debug : { - *(.r_debug) - } :r_debug - - /* - * These are empty input sections the linker generates. - * If we don't discard them, they pollute the flags in the output segment. - */ - /DISCARD/ : { - *(.iplt) - *(.rel*) - *(.igot.plt) - } -} diff --git a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c b/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c deleted file mode 100644 index 87fe73f..0000000 --- a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2011 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * This is a trivial program to edit an ELF file in place, making - * one crucial modification to a program header. It's invoked: - * bootstrap_phdr_hacker FILENAME SEGMENT_NUMBER - * where SEGMENT_NUMBER is the zero-origin index of the program header - * we'll touch. This is a PT_LOAD with p_filesz of zero. We change its - * p_filesz to match its p_memsz value. - */ - -#include <errno.h> -#include <error.h> -#include <fcntl.h> -#include <gelf.h> -#include <libelf.h> -#include <stdlib.h> -#include <unistd.h> - -int main(int argc, char **argv) { - if (argc != 3) - error(1, 0, "Usage: %s FILENAME SEGMENT_NUMBER", argv[0]); - - const char *const file = argv[1]; - const int segment = atoi(argv[2]); - - int fd = open(file, O_RDWR); - if (fd < 0) - error(2, errno, "Cannot open %s for read/write", file); - - if (elf_version(EV_CURRENT) == EV_NONE) - error(2, 0, "elf_version: %s", elf_errmsg(-1)); - - Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL); - if (elf == NULL) - error(2, 0, "elf_begin: %s", elf_errmsg(-1)); - - if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) - error(2, 0, "elf_flagelf: %s", elf_errmsg(-1)); - - GElf_Phdr phdr; - GElf_Phdr *ph = gelf_getphdr(elf, segment, &phdr); - if (ph == NULL) - error(2, 0, "gelf_getphdr: %s", elf_errmsg(-1)); - - if (ph->p_type != PT_LOAD) - error(3, 0, "Program header %d is %u, not PT_LOAD", - segment, (unsigned int) ph->p_type); - if (ph->p_filesz != 0) - error(3, 0, "Program header %d has nonzero p_filesz", segment); - - ph->p_filesz = ph->p_memsz; - if (gelf_update_phdr(elf, segment, ph) == 0) - error(2, 0, "gelf_update_phdr: %s", elf_errmsg(-1)); - - if (elf_flagphdr(elf, ELF_C_SET, ELF_F_DIRTY) == 0) - error(2, 0, "elf_flagphdr: %s", elf_errmsg(-1)); - - if (elf_update(elf, ELF_C_WRITE) < 0) - error(2, 0, "elf_update: %s", elf_errmsg(-1)); - - close(fd); - - return 0; -} diff --git a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.py b/chrome/nacl/nacl_helper_bootstrap_munge_phdr.py deleted file mode 100755 index 2b33050..0000000 --- a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""This takes three command-line arguments: - MUNGE-PHDR-PROGRAM file name of program built from - nacl_helper_bootstrap_munge_phdr.c - INFILE raw linked ELF file name - OUTFILE output file name - -We just run the MUNGE-PHDR-PROGRAM on a copy of INFILE. -That modifies the file in place. Then we move it to OUTFILE. - -We only have this wrapper script because nacl_helper_bootstrap_munge_phdr.c -wants to modify a file in place (and it would be a much longer and more -fragile program if it created a fresh ELF output file instead). -""" - -import shutil -import subprocess -import sys - - -def Main(argv): - if len(argv) != 4: - print 'Usage: %s MUNGE-PHDR-PROGRAM INFILE OUTFILE' % argv[0] - return 1 - [prog, munger, infile, outfile] = argv - tmpfile = outfile + '.tmp' - shutil.copy(infile, tmpfile) - segment_num = '2' - subprocess.check_call([munger, tmpfile, segment_num]) - shutil.move(tmpfile, outfile) - return 0 - - -if __name__ == '__main__': - sys.exit(Main(sys.argv)) diff --git a/tools/ld_bfd/ld b/tools/ld_bfd/ld deleted file mode 100755 index f8ed124..0000000 --- a/tools/ld_bfd/ld +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Wrapper for invoking the BFD loader - -A simple script to invoke the bfd loader instead of gold. -This script is in a filename "ld" so it can be invoked from gcc -via the -B flag. -""" -# TODO(bradchen): Delete this script when Gold supports linker scripts properly. -import os -import subprocess -import sys - -def PathTo(fname): - if fname[0] == os.pathsep: - return fname - for p in os.environ["PATH"].split(os.pathsep): - fpath = os.path.join(p, fname) - if os.path.exists(fpath): - return fpath - return fname - -def FindLDBFD(): - cxx = os.getenv("CXX") - if not cxx: - cxx = "g++" - popen = subprocess.Popen(cxx + " -print-prog-name=ld", - shell=True, - stdout=subprocess.PIPE, - stdin=subprocess.PIPE) - (ld, error) = popen.communicate() - if popen.wait() != 0: - print "Could not find ld:" + error - return "ld" - ld = ld.strip() - ld_bfd = PathTo(ld + ".bfd") - if os.access(ld_bfd, os.X_OK): - return ld_bfd - return ld - -def main(): - args = [FindLDBFD()] + sys.argv[1:] - print("tools/ld_bfd/ld: exec " + ' '.join(args)) - sys.exit(subprocess.call(args)) - -if __name__ == "__main__": - main() |