diff options
Diffstat (limited to 'libc/bionic')
-rw-r--r-- | libc/bionic/abort.cpp | 1 | ||||
-rw-r--r-- | libc/bionic/ctype.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/dl_iterate_phdr_static.cpp | 11 | ||||
-rw-r--r-- | libc/bionic/libc_init_common.cpp | 5 | ||||
-rw-r--r-- | libc/bionic/libc_init_dynamic.cpp | 2 | ||||
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 3 | ||||
-rw-r--r-- | libc/bionic/ptrace.cpp | 40 | ||||
-rw-r--r-- | libc/bionic/rand.cpp | 29 | ||||
-rw-r--r-- | libc/bionic/vdso.cpp | 129 |
9 files changed, 191 insertions, 33 deletions
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp index 69ac0e503..75413c608 100644 --- a/libc/bionic/abort.cpp +++ b/libc/bionic/abort.cpp @@ -30,7 +30,6 @@ #include <signal.h> #include <stdlib.h> #include <unistd.h> -#include "atexit.h" #ifdef __arm__ extern "C" __LIBC_HIDDEN__ void __libc_android_abort() diff --git a/libc/bionic/ctype.cpp b/libc/bionic/ctype.cpp index 3960d9d4c..2b31d5268 100644 --- a/libc/bionic/ctype.cpp +++ b/libc/bionic/ctype.cpp @@ -36,10 +36,6 @@ int isalpha_l(int c, locale_t) { return isalpha(c); } -int isascii_l(int c, locale_t) { - return isascii(c); -} - int isblank_l(int c, locale_t) { return isblank(c); } diff --git a/libc/bionic/dl_iterate_phdr_static.cpp b/libc/bionic/dl_iterate_phdr_static.cpp index 7e9eeddb2..155a7a00a 100644 --- a/libc/bionic/dl_iterate_phdr_static.cpp +++ b/libc/bionic/dl_iterate_phdr_static.cpp @@ -27,6 +27,7 @@ */ #include <elf.h> +#include <string.h> #include <sys/auxv.h> #include <sys/types.h> #include <link.h> @@ -37,11 +38,9 @@ extern "C" void* __executable_start; int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) { ElfW(Ehdr)* ehdr = reinterpret_cast<ElfW(Ehdr)*>(&__executable_start); - // TODO: again, copied from linker.c. Find a better home for this later. - if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1; - if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1; - if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1; - if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1; + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { + return -1; + } // Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but // static binaries get this. We don't have a list of shared objects to @@ -54,7 +53,7 @@ int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data exe_info.dlpi_phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(ehdr) + ehdr->e_phoff); exe_info.dlpi_phnum = ehdr->e_phnum; -#ifdef AT_SYSINFO_EHDR +#if defined(AT_SYSINFO_EHDR) // Try the executable first. int rc = cb(&exe_info, sizeof(exe_info), data); if (rc != 0) { diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp index fa61c3c10..9e4eecde4 100644 --- a/libc/bionic/libc_init_common.cpp +++ b/libc/bionic/libc_init_common.cpp @@ -39,7 +39,6 @@ #include <sys/resource.h> #include <unistd.h> -#include "atexit.h" #include "private/bionic_auxv.h" #include "private/bionic_ssp.h" #include "private/bionic_tls.h" @@ -52,6 +51,8 @@ extern "C" int __system_properties_init(void); extern "C" int __set_tls(void* ptr); extern "C" int __set_tid_address(int* tid_address); +void __libc_init_vdso(); + // Not public, but well-known in the BSDs. const char* __progname; @@ -130,6 +131,8 @@ void __libc_init_common(KernelArgumentBlock& args) { _pthread_internal_add(main_thread); __system_properties_init(); // Requires 'environ'. + + __libc_init_vdso(); } /* This function will be called during normal program termination diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 7c463643b..78125f968 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -48,7 +48,6 @@ #include <stdlib.h> #include <stdint.h> #include <elf.h> -#include "atexit.h" #include "libc_init_common.h" #include "private/bionic_tls.h" @@ -58,6 +57,7 @@ extern "C" { extern void malloc_debug_init(void); extern void malloc_debug_fini(void); extern void netdClientInit(void); + extern int __cxa_atexit(void (*)(void *), void *, void *); }; // We flag the __libc_preinit function as a constructor to ensure diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index ab0b3a69f..bc11f3d93 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -46,7 +46,6 @@ #include <sys/auxv.h> #include <sys/mman.h> -#include "atexit.h" #include "libc_init_common.h" #include "pthread_internal.h" @@ -60,6 +59,8 @@ // itself at the start of a page. #define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) +extern "C" int __cxa_atexit(void (*)(void *), void *, void *); + static void call_array(void(**list)()) { // First element is -1, list is null-terminated while (*++list) { diff --git a/libc/bionic/ptrace.cpp b/libc/bionic/ptrace.cpp index 5715b0934..5156ec24c 100644 --- a/libc/bionic/ptrace.cpp +++ b/libc/bionic/ptrace.cpp @@ -26,28 +26,30 @@ * SUCH DAMAGE. */ -#include <sys/types.h> +#include <stdarg.h> #include <sys/ptrace.h> -extern "C" long __ptrace(int request, pid_t pid, void* addr, void* data); +extern "C" long __ptrace(int req, pid_t pid, void* addr, void* data); -long ptrace(int request, pid_t pid, void* addr, void* data) { - switch (request) { - case PTRACE_PEEKUSR: - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - { - long word; - long ret = __ptrace(request, pid, addr, &word); - if (ret == 0) { - return word; - } else { - // __ptrace already set errno for us. - return -1; - } - } +long ptrace(int req, ...) { + bool is_peek = (req == PTRACE_PEEKUSR || req == PTRACE_PEEKTEXT || req == PTRACE_PEEKDATA); + long peek_result; - default: - return __ptrace(request, pid, addr, data); + va_list args; + va_start(args, req); + pid_t pid = va_arg(args, pid_t); + void* addr = va_arg(args, void*); + void* data; + if (is_peek) { + data = &peek_result; + } else { + data = va_arg(args, void*); } + va_end(args); + + long result = __ptrace(req, pid, addr, data); + if (is_peek && result == 0) { + return peek_result; + } + return result; } diff --git a/libc/bionic/rand.cpp b/libc/bionic/rand.cpp new file mode 100644 index 000000000..0074f2d24 --- /dev/null +++ b/libc/bionic/rand.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +// The BSD rand/srand is very weak. glibc just uses random/srandom instead. +// Since we're likely to run code intended for glibc, and POSIX doesn't seem +// to disallow this, we go that route too. + +int rand() { + return random(); +} + +void srand(unsigned int seed) { + return srandom(seed); +} diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp new file mode 100644 index 000000000..0875ee633 --- /dev/null +++ b/libc/bionic/vdso.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <link.h> +#include <sys/auxv.h> +#include <unistd.h> + +// x86 has a vdso, but there's nothing useful to us in it. +#if defined(__aarch64__) || defined(__x86_64__) + +#if defined(__aarch64__) +#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime" +#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday" +#elif defined(__x86_64__) +#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime" +#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday" +#endif + +#include <time.h> + +extern "C" int __clock_gettime(int, timespec*); +extern "C" int __gettimeofday(timeval*, struct timezone*); + +struct vdso_entry { + const char* name; + void* fn; +}; + +enum { + VDSO_CLOCK_GETTIME = 0, + VDSO_GETTIMEOFDAY, + VDSO_END +}; + +static vdso_entry vdso_entries[] = { + [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) }, + [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) }, +}; + +int clock_gettime(int clock_id, timespec* tp) { + static int (*vdso_clock_gettime)(int, timespec*) = + (int (*)(int, timespec*)) vdso_entries[VDSO_CLOCK_GETTIME].fn; + return vdso_clock_gettime(clock_id, tp); +} + +int gettimeofday(timeval* tv, struct timezone* tz) { + static int (*vdso_gettimeofday)(timeval*, struct timezone*) = + (int (*)(timeval*, struct timezone*)) vdso_entries[VDSO_GETTIMEOFDAY].fn; + return vdso_gettimeofday(tv, tz); +} + +void __libc_init_vdso() { + // Do we have a vdso? + uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR); + ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr); + if (vdso_ehdr == NULL) { + return; + } + + // How many symbols does it have? + size_t symbol_count = 0; + ElfW(Shdr)* vdso_shdr = reinterpret_cast<ElfW(Shdr)*>(vdso_ehdr_addr + vdso_ehdr->e_shoff); + for (size_t i = 0; i < vdso_ehdr->e_shnum; ++i) { + if (vdso_shdr[i].sh_type == SHT_DYNSYM) { + symbol_count = vdso_shdr[i].sh_size / sizeof(ElfW(Sym)); + } + } + if (symbol_count == 0) { + return; + } + + // Where's the dynamic table? + ElfW(Addr) vdso_addr = 0; + ElfW(Dyn)* vdso_dyn = NULL; + ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff); + for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) { + if (vdso_phdr[i].p_type == PT_DYNAMIC) { + vdso_dyn = reinterpret_cast<ElfW(Dyn)*>(vdso_ehdr_addr + vdso_phdr[i].p_offset); + } else if (vdso_phdr[i].p_type == PT_LOAD) { + vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr; + } + } + if (vdso_addr == 0 || vdso_dyn == NULL) { + return; + } + + // Where are the string and symbol tables? + const char* strtab = NULL; + ElfW(Sym)* symtab = NULL; + for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) { + if (d->d_tag == DT_STRTAB) { + strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr); + } else if (d->d_tag == DT_SYMTAB) { + symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr); + } + } + if (strtab == NULL || symtab == NULL) { + return; + } + + // Are there any symbols we want? + for (size_t i = 0; i < symbol_count; ++i) { + for (size_t j = 0; j < VDSO_END; ++j) { + if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) { + vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value); + } + } + } +} + +#else + +void __libc_init_vdso() { +} + +#endif |