Merge "Add getaddrinfo(3) tests for NULL arguments."
diff --git a/libc/Android.mk b/libc/Android.mk
index 345a1f3..3e37ca7 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -213,6 +213,7 @@
bionic/stubs.cpp \
bionic/symlink.cpp \
bionic/sysconf.cpp \
+ bionic/sysinfo.cpp \
bionic/syslog.cpp \
bionic/sys_siglist.c \
bionic/sys_signame.c \
@@ -547,13 +548,6 @@
libc_common_cflags += -DMALLOC_ALIGNMENT=$(BOARD_MALLOC_ALIGNMENT)
endif
-# Define ANDROID_SMP appropriately.
-ifeq ($(TARGET_CPU_SMP),true)
- libc_common_cflags += -DANDROID_SMP=1
-else
- libc_common_cflags += -DANDROID_SMP=0
-endif
-
# Define some common conlyflags
libc_common_conlyflags := \
-std=gnu99
diff --git a/libc/bionic/mntent.cpp b/libc/bionic/mntent.cpp
index 93b6915..f5a8eaa 100644
--- a/libc/bionic/mntent.cpp
+++ b/libc/bionic/mntent.cpp
@@ -28,11 +28,42 @@
#include <mntent.h>
-mntent* getmntent(FILE*) {
- return NULL;
+#include "private/ThreadLocalBuffer.h"
+
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(getmntent_mntent);
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(getmntent_strings);
+
+mntent* getmntent(FILE* fp) {
+ LOCAL_INIT_THREAD_LOCAL_BUFFER(mntent*, getmntent_mntent, sizeof(mntent));
+ LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, getmntent_strings, BUFSIZ);
+ return getmntent_r(fp, getmntent_mntent_tls_buffer,
+ getmntent_strings_tls_buffer, getmntent_strings_tls_buffer_size);
}
-mntent* getmntent_r(FILE*, struct mntent*, char*, int) {
+mntent* getmntent_r(FILE* fp, struct mntent* e, char* buf, int buf_len) {
+ memset(e, 0, sizeof(*e));
+ while (fgets(buf, buf_len, fp) != NULL) {
+ // Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0".
+ // That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0.
+ int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1;
+ if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+ &fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1,
+ &e->mnt_freq, &e->mnt_passno) == 2) {
+ e->mnt_fsname = &buf[fsname0];
+ buf[fsname1] = '\0';
+
+ e->mnt_dir = &buf[dir0];
+ buf[dir1] = '\0';
+
+ e->mnt_type = &buf[type0];
+ buf[type1] = '\0';
+
+ e->mnt_opts = &buf[opts0];
+ buf[opts1] = '\0';
+
+ return e;
+ }
+ }
return NULL;
}
diff --git a/libc/bionic/pathconf.cpp b/libc/bionic/pathconf.cpp
index de9e022..e6f5742 100644
--- a/libc/bionic/pathconf.cpp
+++ b/libc/bionic/pathconf.cpp
@@ -100,12 +100,16 @@
case _PC_2_SYMLINKS:
return __2_symlinks(s);
+ case _PC_ALLOC_SIZE_MIN: /* fall through */
+ case _PC_REC_XFER_ALIGN:
+ return s.f_frsize;
+
+ case _PC_REC_MIN_XFER_SIZE:
+ return s.f_bsize;
+
#if 0
- case _PC_ALLOC_SIZE_MIN:
case _PC_REC_INCR_XFER_SIZE:
case _PC_REC_MAX_XFER_SIZE:
- case _PC_REC_MIN_XFER_SIZE:
- case _PC_REC_XFER_ALIGN:
#endif
case _PC_SYMLINK_MAX:
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 951860d..2df6acc 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -26,20 +26,17 @@
* SUCH DAMAGE.
*/
-#include <ctype.h>
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h> // For FOPEN_MAX.
-#include <string.h>
#include <sys/sysconf.h>
+#include <sys/sysinfo.h>
#include <time.h>
#include <unistd.h>
#include "private/bionic_tls.h"
-#include "private/ScopedReaddir.h"
/* seems to be the default on Linux, per the GLibc sources and my own digging */
@@ -68,88 +65,13 @@
#define SYSTEM_2_UPE -1 /* No UPE for you ! (User Portability Utilities) */
#define SYSTEM_2_VERSION -1 /* No posix command-line tools */
-static bool __matches_cpuN(const char* s) {
- // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
- unsigned cpu;
- char dummy;
- return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
-}
-
-static int __sysconf_nprocessors_conf() {
- // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
- // from there. This method works on both.
- ScopedReaddir reader("/sys/devices/system/cpu");
- if (reader.IsBad()) {
- return 1;
- }
-
- int result = 0;
- dirent* entry;
- while ((entry = reader.ReadEntry()) != NULL) {
- if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
- ++result;
- }
- }
- return result;
-}
-
-static int __sysconf_nprocessors_onln() {
- FILE* fp = fopen("/proc/stat", "re");
- if (fp == NULL) {
- return 1;
- }
-
- int result = 0;
- char buf[256];
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- // Extract just the first word from the line.
- // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
- char* p = strchr(buf, ' ');
- if (p != NULL) {
- *p = 0;
- }
- if (__matches_cpuN(buf)) {
- ++result;
- }
- }
- fclose(fp);
- return result;
-}
-
-static int __get_meminfo(const char* pattern) {
- FILE* fp = fopen("/proc/meminfo", "re");
- if (fp == NULL) {
- return -1;
- }
-
- int result = -1;
- char buf[256];
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- long total;
- if (sscanf(buf, pattern, &total) == 1) {
- result = (int) (total / (PAGE_SIZE/1024));
- break;
- }
- }
- fclose(fp);
- return result;
-}
-
-static int __sysconf_phys_pages() {
- return __get_meminfo("MemTotal: %ld kB");
-}
-
-static int __sysconf_avphys_pages() {
- return __get_meminfo("MemFree: %ld kB");
-}
-
static int __sysconf_monotonic_clock() {
timespec t;
int rc = clock_getres(CLOCK_MONOTONIC, &t);
return (rc == -1) ? -1 : _POSIX_VERSION;
}
-int sysconf(int name) {
+long sysconf(int name) {
switch (name) {
case _SC_ARG_MAX: return _POSIX_ARG_MAX;
case _SC_CHILD_MAX: return CHILD_MAX;
@@ -244,10 +166,10 @@
//case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS
case _SC_MONOTONIC_CLOCK: return __sysconf_monotonic_clock();
- case _SC_NPROCESSORS_CONF: return __sysconf_nprocessors_conf();
- case _SC_NPROCESSORS_ONLN: return __sysconf_nprocessors_onln();
- case _SC_PHYS_PAGES: return __sysconf_phys_pages();
- case _SC_AVPHYS_PAGES: return __sysconf_avphys_pages();
+ case _SC_NPROCESSORS_CONF: return get_nprocs_conf();
+ case _SC_NPROCESSORS_ONLN: return get_nprocs();
+ case _SC_PHYS_PAGES: return get_phys_pages();
+ case _SC_AVPHYS_PAGES: return get_avphys_pages();
default:
// Posix says EINVAL is the only error that shall be returned,
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
new file mode 100644
index 0000000..6f0afb8
--- /dev/null
+++ b/libc/bionic/sysinfo.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/sysinfo.h>
+
+#include <dirent.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "private/ScopedReaddir.h"
+
+static bool __matches_cpuN(const char* s) {
+ // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
+ unsigned cpu;
+ char dummy;
+ return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
+}
+
+int get_nprocs_conf() {
+ // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
+ // from there. This method works on both.
+ ScopedReaddir reader("/sys/devices/system/cpu");
+ if (reader.IsBad()) {
+ return 1;
+ }
+
+ int result = 0;
+ dirent* entry;
+ while ((entry = reader.ReadEntry()) != NULL) {
+ if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
+ ++result;
+ }
+ }
+ return result;
+}
+
+int get_nprocs() {
+ FILE* fp = fopen("/proc/stat", "re");
+ if (fp == NULL) {
+ return 1;
+ }
+
+ int result = 0;
+ char buf[256];
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ // Extract just the first word from the line.
+ // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
+ char* p = strchr(buf, ' ');
+ if (p != NULL) {
+ *p = 0;
+ }
+ if (__matches_cpuN(buf)) {
+ ++result;
+ }
+ }
+ fclose(fp);
+ return result;
+}
+
+static int __get_meminfo(const char* pattern) {
+ FILE* fp = fopen("/proc/meminfo", "re");
+ if (fp == NULL) {
+ return -1;
+ }
+
+ int result = -1;
+ char buf[256];
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ long total;
+ if (sscanf(buf, pattern, &total) == 1) {
+ result = (int) (total / (PAGE_SIZE/1024));
+ break;
+ }
+ }
+ fclose(fp);
+ return result;
+}
+
+long get_phys_pages() {
+ return __get_meminfo("MemTotal: %ld kB");
+}
+
+long get_avphys_pages() {
+ return __get_meminfo("MemFree: %ld kB");
+}
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index a7ec615..c0dac1a 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -146,7 +146,16 @@
fpos_t _offset; /* current lseek offset */
} FILE;
+/* Legacy BSD implementation of stdin/stdout/stderr. */
extern FILE __sF[];
+/* More obvious implementation. */
+extern FILE* stdin;
+extern FILE* stdout;
+extern FILE* stderr;
+/* C99 and earlier plus current C++ standards say these must be macros. */
+#define stdin stdin
+#define stdout stdout
+#define stderr stderr
#define __SLBF 0x0001 /* line buffered */
#define __SNBF 0x0002 /* unbuffered */
@@ -209,10 +218,6 @@
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
-#define stdin (&__sF[0])
-#define stdout (&__sF[1])
-#define stderr (&__sF[2])
-
/*
* Functions defined in ANSI C standard.
*/
diff --git a/libc/include/sys/sysconf.h b/libc/include/sys/sysconf.h
index 0a46e7a..3d058d7 100644
--- a/libc/include/sys/sysconf.h
+++ b/libc/include/sys/sysconf.h
@@ -129,7 +129,7 @@
#define _SC_AVPHYS_PAGES 0x0063
#define _SC_MONOTONIC_CLOCK 0x0064
-extern int sysconf(int name);
+long sysconf(int);
__END_DECLS
diff --git a/libc/include/sys/sysinfo.h b/libc/include/sys/sysinfo.h
index c7e46e6..b66bc8e 100644
--- a/libc/include/sys/sysinfo.h
+++ b/libc/include/sys/sysinfo.h
@@ -33,7 +33,15 @@
__BEGIN_DECLS
-extern int sysinfo (struct sysinfo *info);
+int sysinfo(struct sysinfo* info);
+
+int get_nprocs_conf(void);
+
+int get_nprocs(void);
+
+long get_phys_pages(void);
+
+long get_avphys_pages(void);
__END_DECLS
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index dca9b3d..e94ee66 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -202,7 +202,7 @@
int getpagesize(void);
-extern int sysconf(int name);
+long sysconf(int);
extern int daemon(int, int);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 9e279d3..cfd2299 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -111,6 +111,8 @@
extern int vswscanf(const wchar_t*, const wchar_t*, va_list);
extern int vwprintf(const wchar_t*, va_list);
extern int vwscanf(const wchar_t*, va_list);
+extern wchar_t* wcpcpy (wchar_t*, const wchar_t *);
+extern wchar_t* wcpncpy (wchar_t*, const wchar_t *, size_t);
extern size_t wcrtomb(char *, wchar_t, mbstate_t *);
extern int wcscasecmp(const wchar_t *, const wchar_t *);
extern int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t);
diff --git a/libc/private/bionic_atomic_arm.h b/libc/private/bionic_atomic_arm.h
index 2156e6a..0cb832f 100644
--- a/libc/private/bionic_atomic_arm.h
+++ b/libc/private/bionic_atomic_arm.h
@@ -17,12 +17,7 @@
#define BIONIC_ATOMIC_ARM_H
__ATOMIC_INLINE__ void __bionic_memory_barrier() {
-#if defined(ANDROID_SMP) && ANDROID_SMP == 1
__asm__ __volatile__ ( "dmb ish" : : : "memory" );
-#else
- /* A simple compiler barrier. */
- __asm__ __volatile__ ( "" : : : "memory" );
-#endif
}
/* Compare-and-swap, without any explicit barriers. Note that this function
diff --git a/libc/private/bionic_atomic_inline.h b/libc/private/bionic_atomic_inline.h
index b834a27..f8032c3 100644
--- a/libc/private/bionic_atomic_inline.h
+++ b/libc/private/bionic_atomic_inline.h
@@ -30,10 +30,6 @@
* on SMP systems emits an appropriate instruction.
*/
-#if !defined(ANDROID_SMP)
-# error "Must define ANDROID_SMP before including atomic-inline.h"
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/libc/private/bionic_atomic_mips.h b/libc/private/bionic_atomic_mips.h
index 5e08116..83f75fe 100644
--- a/libc/private/bionic_atomic_mips.h
+++ b/libc/private/bionic_atomic_mips.h
@@ -21,12 +21,7 @@
*/
__ATOMIC_INLINE__ void __bionic_memory_barrier() {
-#if defined(ANDROID_SMP) && ANDROID_SMP == 1
__asm__ __volatile__ ( "sync" : : : "memory" );
-#else
- /* A simple compiler barrier. */
- __asm__ __volatile__ ( "" : : : "memory" );
-#endif
}
/* Compare-and-swap, without any explicit barriers. Note that this function
diff --git a/libc/private/bionic_atomic_x86.h b/libc/private/bionic_atomic_x86.h
index 89639c8..e63df93 100644
--- a/libc/private/bionic_atomic_x86.h
+++ b/libc/private/bionic_atomic_x86.h
@@ -20,12 +20,7 @@
* platform for a multi-core device.
*/
__ATOMIC_INLINE__ void __bionic_memory_barrier() {
-#if defined(ANDROID_SMP) && ANDROID_SMP == 1
__asm__ __volatile__ ( "mfence" : : : "memory" );
-#else
- /* A simple compiler barrier. */
- __asm__ __volatile__ ( "" : : : "memory" );
-#endif
}
/* Compare-and-swap, without any explicit barriers. Note that this function
diff --git a/libc/stdio/fileext.h b/libc/stdio/fileext.h
index 7efff8f..dc89fff 100644
--- a/libc/stdio/fileext.h
+++ b/libc/stdio/fileext.h
@@ -43,10 +43,6 @@
pthread_mutex_t _lock; /* file lock */
};
-__LIBC_HIDDEN__ extern struct __sfileext __sFext[3];
-
-#define _FILEEXT_INITIALIZER {{NULL,0},{0},PTHREAD_RECURSIVE_MUTEX_INITIALIZER}
-
#define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base))
#define _UB(fp) _EXT(fp)->_ub
#define _FLOCK(fp) _EXT(fp)->_lock
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index ef8e9e6..5e51198 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -59,12 +59,15 @@
static struct glue *lastglue = &uglue;
_THREAD_PRIVATE_MUTEX(__sfp_mutex);
-struct __sfileext __sFext[3];
+static struct __sfileext __sFext[3];
FILE __sF[3] = {
std(__SRD, STDIN_FILENO), /* stdin */
std(__SWR, STDOUT_FILENO), /* stdout */
std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
};
+FILE* stdin = &__sF[0];
+FILE* stdout = &__sF[1];
+FILE* stderr = &__sF[2];
struct glue __sglue = { &uglue, 3, __sF };
static struct glue *
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 799284e..2486e02 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -238,14 +238,14 @@
soinfo* get_libdl_info() {
if ((__libdl_info.flags & FLAG_LINKED) == 0) {
__libdl_info.flags |= FLAG_LINKED;
- __libdl_info.strtab = ANDROID_LIBDL_STRTAB;
- __libdl_info.symtab = g_libdl_symtab;
- __libdl_info.nbucket = sizeof(g_libdl_buckets)/sizeof(unsigned);
- __libdl_info.nchain = sizeof(g_libdl_chains)/sizeof(unsigned);
- __libdl_info.bucket = g_libdl_buckets;
- __libdl_info.chain = g_libdl_chains;
+ __libdl_info.strtab_ = ANDROID_LIBDL_STRTAB;
+ __libdl_info.symtab_ = g_libdl_symtab;
+ __libdl_info.nbucket_ = sizeof(g_libdl_buckets)/sizeof(unsigned);
+ __libdl_info.nchain_ = sizeof(g_libdl_chains)/sizeof(unsigned);
+ __libdl_info.bucket_ = g_libdl_buckets;
+ __libdl_info.chain_ = g_libdl_chains;
__libdl_info.ref_count = 1;
- __libdl_info.strtab_size = sizeof(ANDROID_LIBDL_STRTAB);
+ __libdl_info.strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB);
}
return &__libdl_info;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index fdcd83a..11d7b94 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -434,11 +434,11 @@
ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name) {
uint32_t hash = symbol_name.gnu_hash();
- uint32_t h2 = hash >> gnu_shift2;
+ uint32_t h2 = hash >> gnu_shift2_;
uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8;
- uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords;
- ElfW(Addr) bloom_word = gnu_bloom_filter[word_num];
+ uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;
+ ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num];
// test against bloom filter
if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
@@ -446,20 +446,20 @@
}
// bloom test says "probably yes"...
- uint32_t n = bucket[hash % nbucket];
+ uint32_t n = bucket_[hash % nbucket_];
if (n == 0) {
return nullptr;
}
do {
- ElfW(Sym)* s = symtab + n;
- if (((chain[n] ^ hash) >> 1) == 0 &&
+ ElfW(Sym)* s = symtab_ + n;
+ if (((chain_[n] ^ hash) >> 1) == 0 &&
strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
is_symbol_global_and_defined(this, s)) {
return s;
}
- } while ((chain[n++] & 1) == 0);
+ } while ((chain_[n++] & 1) == 0);
return nullptr;
}
@@ -468,10 +468,10 @@
uint32_t hash = symbol_name.elf_hash();
TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
- symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket);
+ symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket_);
- for (uint32_t n = bucket[hash % nbucket]; n != 0; n = chain[n]) {
- ElfW(Sym)* s = symtab + n;
+ for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
+ ElfW(Sym)* s = symtab_ + n;
if (strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && is_symbol_global_and_defined(this, s)) {
TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
symbol_name.get_name(), name, reinterpret_cast<void*>(s->st_value),
@@ -481,7 +481,7 @@
}
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
- symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket);
+ symbol_name.get_name(), name, reinterpret_cast<void*>(base), hash, hash % nbucket_);
return nullptr;
}
@@ -491,15 +491,15 @@
strlcpy(this->name, name, sizeof(this->name));
flags = FLAG_NEW_SOINFO;
- version = SOINFO_VERSION;
+ version_ = SOINFO_VERSION;
if (file_stat != nullptr) {
- this->st_dev = file_stat->st_dev;
- this->st_ino = file_stat->st_ino;
- this->file_offset = file_offset;
+ this->st_dev_ = file_stat->st_dev;
+ this->st_ino_ = file_stat->st_ino;
+ this->file_offset_ = file_offset;
}
- this->rtld_flags = rtld_flags;
+ this->rtld_flags_ = rtld_flags;
}
@@ -793,19 +793,19 @@
ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) {
ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - base;
- for (size_t i = 0; i < nbucket; ++i) {
- uint32_t n = bucket[i];
+ for (size_t i = 0; i < nbucket_; ++i) {
+ uint32_t n = bucket_[i];
if (n == 0) {
continue;
}
do {
- ElfW(Sym)* sym = symtab + n;
+ ElfW(Sym)* sym = symtab_ + n;
if (symbol_matches_soaddr(sym, soaddr)) {
return sym;
}
- } while ((chain[n++] & 1) == 0);
+ } while ((chain_[n++] & 1) == 0);
}
return nullptr;
@@ -816,8 +816,8 @@
// Search the library's symbol table for any defined symbol which
// contains this address.
- for (size_t i = 0; i < nchain; ++i) {
- ElfW(Sym)* sym = symtab + i;
+ for (size_t i = 0; i < nchain_; ++i) {
+ ElfW(Sym)* sym = symtab_ + i;
if (symbol_matches_soaddr(sym, soaddr)) {
return sym;
}
@@ -948,7 +948,7 @@
si->phnum = elf_reader.phdr_count();
si->phdr = elf_reader.loaded_phdr();
- if (!si->PrelinkImage()) {
+ if (!si->prelink_image()) {
soinfo_free(si);
return nullptr;
}
@@ -1104,7 +1104,7 @@
bool linked = local_group.visit([&](soinfo* si) {
if ((si->flags & FLAG_LINKED) == 0) {
- if (!si->LinkImage(global_group, local_group, extinfo)) {
+ if (!si->link_image(global_group, local_group, extinfo)) {
return false;
}
si->flags |= FLAG_LINKED;
@@ -1143,7 +1143,7 @@
if (si->ref_count == 1) {
TRACE("unloading '%s'", si->name);
- si->CallDestructors();
+ si->call_destructors();
if (si->has_min_version(0)) {
soinfo* child = nullptr;
@@ -1217,7 +1217,7 @@
protect_data(PROT_READ | PROT_WRITE);
soinfo* si = find_library(name, flags, extinfo);
if (si != nullptr) {
- si->CallConstructors();
+ si->call_constructors();
}
protect_data(PROT_READ);
return si;
@@ -1239,7 +1239,7 @@
}
#if defined(USE_RELA)
-int soinfo::Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
+int soinfo::relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
for (size_t idx = 0; idx < count; ++idx, ++rela) {
unsigned type = ELFW(R_TYPE)(rela->r_info);
unsigned sym = ELFW(R_SYM)(rela->r_info);
@@ -1256,11 +1256,11 @@
soinfo* lsi = nullptr;
if (sym != 0) {
- sym_name = get_string(symtab[sym].st_name);
+ sym_name = get_string(symtab_[sym].st_name);
s = soinfo_do_lookup(this, sym_name, &lsi, global_group,local_group);
if (s == nullptr) {
// We only allow an undefined symbol if this is a weak reference...
- s = &symtab[sym];
+ s = &symtab_[sym];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
return -1;
@@ -1516,7 +1516,7 @@
}
#else // REL, not RELA.
-int soinfo::Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
+int soinfo::relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
for (size_t idx = 0; idx < count; ++idx, ++rel) {
unsigned type = ELFW(R_TYPE)(rel->r_info);
// TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead.
@@ -1534,11 +1534,11 @@
soinfo* lsi = nullptr;
if (sym != 0) {
- sym_name = get_string(symtab[sym].st_name);
+ sym_name = get_string(symtab_[sym].st_name);
s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
if (s == nullptr) {
// We only allow an undefined symbol if this is a weak reference...
- s = &symtab[sym];
+ s = &symtab_[sym];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
return -1;
@@ -1722,13 +1722,10 @@
#if defined(__mips__)
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
- ElfW(Addr)** got = plt_got;
+ ElfW(Addr)** got = plt_got_;
if (got == nullptr) {
return true;
}
- unsigned local_gotno = mips_local_gotno;
- unsigned gotsym = mips_gotsym;
- unsigned symtabno = mips_symtabno;
// got[0] is the address of the lazy resolver function.
// got[1] may be used for a GNU extension.
@@ -1741,22 +1738,22 @@
got[g++] = reinterpret_cast<ElfW(Addr)*>(0xdeadfeed);
}
// Relocate the local GOT entries.
- for (; g < local_gotno; g++) {
+ for (; g < mips_local_gotno_; g++) {
got[g] = reinterpret_cast<ElfW(Addr)*>(reinterpret_cast<uintptr_t>(got[g]) + load_bias);
}
}
// Now for the global GOT entries...
- ElfW(Sym)* sym = symtab + gotsym;
- got = plt_got + local_gotno;
- for (size_t g = gotsym; g < symtabno; g++, sym++, got++) {
+ ElfW(Sym)* sym = symtab_ + mips_gotsym_;
+ got = plt_got_ + mips_local_gotno_;
+ for (size_t g = mips_gotsym_; g < mips_symtabno_; g++, sym++, got++) {
// This is an undefined reference... try to locate it.
const char* sym_name = get_string(sym->st_name);
soinfo* lsi = nullptr;
ElfW(Sym)* s = soinfo_do_lookup(this, sym_name, &lsi, global_group, local_group);
if (s == nullptr) {
// We only allow an undefined symbol if this is a weak reference.
- s = &symtab[g];
+ s = &symtab_[g];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
DL_ERR("cannot locate \"%s\"...", sym_name);
return false;
@@ -1773,7 +1770,7 @@
}
#endif
-void soinfo::CallArray(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
+void soinfo::call_array(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
if (functions == nullptr) {
return;
}
@@ -1786,13 +1783,13 @@
for (int i = begin; i != end; i += step) {
TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
- CallFunction("function", functions[i]);
+ call_function("function", functions[i]);
}
TRACE("[ Done calling %s for '%s' ]", array_name, name);
}
-void soinfo::CallFunction(const char* function_name __unused, linker_function_t function) {
+void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
return;
}
@@ -1806,13 +1803,13 @@
protect_data(PROT_READ | PROT_WRITE);
}
-void soinfo::CallPreInitConstructors() {
+void soinfo::call_pre_init_constructors() {
// DT_PREINIT_ARRAY functions are called before any other constructors for executables,
// but ignored in a shared library.
- CallArray("DT_PREINIT_ARRAY", preinit_array, preinit_array_count, false);
+ call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false);
}
-void soinfo::CallConstructors() {
+void soinfo::call_constructors() {
if (constructors_called) {
return;
}
@@ -1829,34 +1826,34 @@
// out above, the libc constructor will be called again (recursively!).
constructors_called = true;
- if ((flags & FLAG_EXE) == 0 && preinit_array != nullptr) {
+ if ((flags & FLAG_EXE) == 0 && preinit_array_ != nullptr) {
// The GNU dynamic linker silently ignores these, but we warn the developer.
PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
- name, preinit_array_count);
+ name, preinit_array_count_);
}
get_children().for_each([] (soinfo* si) {
- si->CallConstructors();
+ si->call_constructors();
});
TRACE("\"%s\": calling constructors", name);
// DT_INIT should be called before DT_INIT_ARRAY if both are present.
- CallFunction("DT_INIT", init_func);
- CallArray("DT_INIT_ARRAY", init_array, init_array_count, false);
+ call_function("DT_INIT", init_func_);
+ call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false);
}
-void soinfo::CallDestructors() {
+void soinfo::call_destructors() {
if (!constructors_called) {
return;
}
TRACE("\"%s\": calling destructors", name);
// DT_FINI_ARRAY must be parsed in reverse order.
- CallArray("DT_FINI_ARRAY", fini_array, fini_array_count, true);
+ call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true);
// DT_FINI should be called after DT_FINI_ARRAY if both are present.
- CallFunction("DT_FINI", fini_func);
+ call_function("DT_FINI", fini_func_);
// This is needed on second call to dlopen
// after library has been unloaded with RTLD_NODELETE
@@ -1865,8 +1862,8 @@
void soinfo::add_child(soinfo* child) {
if (has_min_version(0)) {
- child->parents.push_back(this);
- this->children.push_back(child);
+ child->parents_.push_back(this);
+ this->children_.push_back(child);
}
}
@@ -1876,26 +1873,26 @@
}
// 1. Untie connected soinfos from 'this'.
- children.for_each([&] (soinfo* child) {
- child->parents.remove_if([&] (const soinfo* parent) {
+ children_.for_each([&] (soinfo* child) {
+ child->parents_.remove_if([&] (const soinfo* parent) {
return parent == this;
});
});
- parents.for_each([&] (soinfo* parent) {
- parent->children.remove_if([&] (const soinfo* child) {
+ parents_.for_each([&] (soinfo* parent) {
+ parent->children_.remove_if([&] (const soinfo* child) {
return child == this;
});
});
// 2. Once everything untied - clear local lists.
- parents.clear();
- children.clear();
+ parents_.clear();
+ children_.clear();
}
dev_t soinfo::get_st_dev() const {
if (has_min_version(0)) {
- return st_dev;
+ return st_dev_;
}
return 0;
@@ -1903,7 +1900,7 @@
ino_t soinfo::get_st_ino() const {
if (has_min_version(0)) {
- return st_ino;
+ return st_ino_;
}
return 0;
@@ -1911,7 +1908,7 @@
off64_t soinfo::get_file_offset() const {
if (has_min_version(1)) {
- return file_offset;
+ return file_offset_;
}
return 0;
@@ -1919,7 +1916,7 @@
uint32_t soinfo::get_rtld_flags() const {
if (has_min_version(1)) {
- return rtld_flags;
+ return rtld_flags_;
}
return 0;
@@ -1927,7 +1924,7 @@
uint32_t soinfo::get_dt_flags_1() const {
if (has_min_version(1)) {
- return dt_flags_1;
+ return dt_flags_1_;
}
return 0;
@@ -1935,14 +1932,14 @@
void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
if (has_min_version(1)) {
if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
- rtld_flags |= RTLD_GLOBAL;
+ rtld_flags_ |= RTLD_GLOBAL;
}
if ((dt_flags_1 & DF_1_NODELETE) != 0) {
- rtld_flags |= RTLD_NODELETE;
+ rtld_flags_ |= RTLD_NODELETE;
}
- this->dt_flags_1 = dt_flags_1;
+ dt_flags_1_ = dt_flags_1;
}
}
@@ -1952,18 +1949,18 @@
soinfo::soinfo_list_t& soinfo::get_children() {
if (has_min_version(0)) {
- return this->children;
+ return children_;
}
return g_empty_list;
}
soinfo::soinfo_list_t& soinfo::get_parents() {
- if ((this->flags & FLAG_NEW_SOINFO) == 0) {
- return g_empty_list;
+ if (has_min_version(0)) {
+ return parents_;
}
- return this->parents;
+ return g_empty_list;
}
ElfW(Addr) soinfo::resolve_symbol_address(ElfW(Sym)* s) {
@@ -1975,11 +1972,11 @@
}
const char* soinfo::get_string(ElfW(Word) index) const {
- if (has_min_version(1) && (index >= strtab_size)) {
- __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d", name, strtab_size, index);
+ if (has_min_version(1) && (index >= strtab_size_)) {
+ __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d", name, strtab_size_, index);
}
- return strtab + index;
+ return strtab_ + index;
}
bool soinfo::is_gnu_hash() const {
@@ -2051,7 +2048,7 @@
return return_value;
}
-bool soinfo::PrelinkImage() {
+bool soinfo::prelink_image() {
/* Extract dynamic section */
ElfW(Word) dynamic_flags = 0;
phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
@@ -2091,52 +2088,52 @@
break;
case DT_HASH:
- if (nbucket != 0) {
+ if (nbucket_ != 0) {
// in case of --hash-style=both, we prefer gnu
break;
}
- nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
- nchain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
- bucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
- chain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket * 4);
+ nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
+ nchain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
+ bucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
+ chain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);
break;
case DT_GNU_HASH:
- if (nbucket != 0) {
+ if (nbucket_ != 0) {
// in case of --hash-style=both, we prefer gnu
- nchain = 0;
+ nchain_ = 0;
}
- nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
+ nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
// skip symndx
- gnu_maskwords = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
- gnu_shift2 = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
+ gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
+ gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
- gnu_bloom_filter = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
- bucket = reinterpret_cast<uint32_t*>(gnu_bloom_filter + gnu_maskwords);
+ gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
+ bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
// amend chain for symndx = header[1]
- chain = bucket + nbucket - reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
+ chain_ = bucket_ + nbucket_ - reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
- if (!powerof2(gnu_maskwords)) {
- DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", gnu_maskwords, name);
+ if (!powerof2(gnu_maskwords_)) {
+ DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", gnu_maskwords_, name);
return false;
}
- --gnu_maskwords;
+ --gnu_maskwords_;
flags |= FLAG_GNU_HASH;
break;
case DT_STRTAB:
- strtab = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
+ strtab_ = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
break;
case DT_STRSZ:
- strtab_size = d->d_un.d_val;
+ strtab_size_ = d->d_un.d_val;
break;
case DT_SYMTAB:
- symtab = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
+ symtab_ = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
break;
case DT_SYMENT:
@@ -2162,24 +2159,24 @@
case DT_JMPREL:
#if defined(USE_RELA)
- plt_rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
+ plt_rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
#else
- plt_rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
+ plt_rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
#endif
break;
case DT_PLTRELSZ:
#if defined(USE_RELA)
- plt_rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
+ plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
#else
- plt_rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
+ plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
#endif
break;
case DT_PLTGOT:
#if defined(__mips__)
// Used by mips and mips64.
- plt_got = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
+ plt_got_ = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
#endif
// Ignore for other platforms... (because RTLD_LAZY is not supported)
break;
@@ -2199,11 +2196,11 @@
#endif
#if defined(USE_RELA)
case DT_RELA:
- rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
+ rela_ = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
break;
case DT_RELASZ:
- rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
+ rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
break;
case DT_RELAENT:
@@ -2226,11 +2223,11 @@
return false;
#else
case DT_REL:
- rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
+ rel_ = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
break;
case DT_RELSZ:
- rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
+ rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
break;
case DT_RELENT:
@@ -2252,40 +2249,40 @@
return false;
#endif
case DT_INIT:
- init_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_INIT) found at %p", name, init_func);
+ init_func_ = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_INIT) found at %p", name, init_func_);
break;
case DT_FINI:
- fini_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
- DEBUG("%s destructors (DT_FINI) found at %p", name, fini_func);
+ fini_func_ = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s destructors (DT_FINI) found at %p", name, fini_func_);
break;
case DT_INIT_ARRAY:
- init_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", name, init_array);
+ init_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", name, init_array_);
break;
case DT_INIT_ARRAYSZ:
- init_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+ init_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
break;
case DT_FINI_ARRAY:
- fini_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", name, fini_array);
+ fini_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", name, fini_array_);
break;
case DT_FINI_ARRAYSZ:
- fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+ fini_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
break;
case DT_PREINIT_ARRAY:
- preinit_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", name, preinit_array);
+ preinit_array_ = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
+ DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", name, preinit_array_);
break;
case DT_PREINIT_ARRAYSZ:
- preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
+ preinit_array_count_ = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
break;
case DT_TEXTREL:
@@ -2342,15 +2339,15 @@
break;
case DT_MIPS_SYMTABNO:
- mips_symtabno = d->d_un.d_val;
+ mips_symtabno_ = d->d_un.d_val;
break;
case DT_MIPS_LOCAL_GOTNO:
- mips_local_gotno = d->d_un.d_val;
+ mips_local_gotno_ = d->d_un.d_val;
break;
case DT_MIPS_GOTSYM:
- mips_gotsym = d->d_un.d_val;
+ mips_gotsym_ = d->d_un.d_val;
break;
#endif
// Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
@@ -2373,29 +2370,29 @@
}
DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
- reinterpret_cast<void*>(base), strtab, symtab);
+ reinterpret_cast<void*>(base), strtab_, symtab_);
// Sanity checks.
if (relocating_linker && needed_count != 0) {
DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
return false;
}
- if (nbucket == 0) {
+ if (nbucket_ == 0) {
DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" (new hash type from the future?)", name);
return false;
}
- if (strtab == 0) {
+ if (strtab_ == 0) {
DL_ERR("empty/missing DT_STRTAB in \"%s\"", name);
return false;
}
- if (symtab == 0) {
+ if (symtab_ == 0) {
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", name);
return false;
}
return true;
}
-bool soinfo::LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
+bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo) {
#if !defined(__LP64__)
if (has_text_relocations) {
@@ -2412,28 +2409,28 @@
#endif
#if defined(USE_RELA)
- if (rela != nullptr) {
+ if (rela_ != nullptr) {
DEBUG("[ relocating %s ]", name);
- if (Relocate(rela, rela_count, global_group, local_group)) {
+ if (relocate(rela_, rela_count_, global_group, local_group)) {
return false;
}
}
- if (plt_rela != nullptr) {
+ if (plt_rela_ != nullptr) {
DEBUG("[ relocating %s plt ]", name);
- if (Relocate(plt_rela, plt_rela_count, global_group, local_group)) {
+ if (relocate(plt_rela_, plt_rela_count_, global_group, local_group)) {
return false;
}
}
#else
- if (rel != nullptr) {
+ if (rel_ != nullptr) {
DEBUG("[ relocating %s ]", name);
- if (Relocate(rel, rel_count, global_group, local_group)) {
+ if (relocate(rel_, rel_count_, global_group, local_group)) {
return false;
}
}
- if (plt_rel != nullptr) {
+ if (plt_rel_ != nullptr) {
DEBUG("[ relocating %s plt ]", name);
- if (Relocate(plt_rel, plt_rel_count, global_group, local_group)) {
+ if (relocate(plt_rel_, plt_rel_count_, global_group, local_group)) {
return false;
}
}
@@ -2506,8 +2503,8 @@
si->size = phdr_table_get_load_size(si->phdr, si->phnum);
si->load_bias = get_elf_exec_load_bias(ehdr_vdso);
- si->PrelinkImage();
- si->LinkImage(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr);
+ si->prelink_image();
+ si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr);
#endif
}
@@ -2636,7 +2633,7 @@
somain = si;
- si->PrelinkImage();
+ si->prelink_image();
// add somain to global group
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
@@ -2667,15 +2664,15 @@
add_vdso(args);
- si->CallPreInitConstructors();
+ si->call_pre_init_constructors();
- /* After the PrelinkImage, the si->load_bias is initialized.
+ /* After the prelink_image, the si->load_bias is initialized.
* For so lib, the map->l_addr will be updated in notify_gdb_of_load.
* We need to update this value for so exe here. So Unwind_Backtrace
* for some arch like x86 could work correctly within so exe.
*/
map->l_addr = si->load_bias;
- si->CallConstructors();
+ si->call_constructors();
#if TIMING
gettimeofday(&t1, nullptr);
@@ -2790,7 +2787,7 @@
// itself without having to look into local_group and (2) allocators
// are not yet initialized, and therefore we cannot use linked_list.push_*
// functions at this point.
- if (!(linker_so.PrelinkImage() && linker_so.LinkImage(g_empty_list, g_empty_list, nullptr))) {
+ if (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) {
// It would be nice to print an error message, but if the linker
// can't link itself, there's no guarantee that we'll be able to
// call write() (because it involves a GOT reference). We may as
@@ -2805,7 +2802,7 @@
__libc_init_tls(args);
// Initialize the linker's own global variables
- linker_so.CallConstructors();
+ linker_so.call_constructors();
// Initialize static variables. Note that in order to
// get correct libdl_info we need to call constructors
diff --git a/linker/linker.h b/linker/linker.h
index 21ecb22..d28f70e 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -164,60 +164,60 @@
uint32_t flags;
private:
- const char* strtab;
- ElfW(Sym)* symtab;
+ const char* strtab_;
+ ElfW(Sym)* symtab_;
- size_t nbucket;
- size_t nchain;
- uint32_t* bucket;
- uint32_t* chain;
+ size_t nbucket_;
+ size_t nchain_;
+ uint32_t* bucket_;
+ uint32_t* chain_;
- public:
#if defined(__mips__) || !defined(__LP64__)
// This is only used by mips and mips64, but needs to be here for
// all 32-bit architectures to preserve binary compatibility.
- ElfW(Addr)** plt_got;
+ ElfW(Addr)** plt_got_;
#endif
#if defined(USE_RELA)
- ElfW(Rela)* plt_rela;
- size_t plt_rela_count;
+ ElfW(Rela)* plt_rela_;
+ size_t plt_rela_count_;
- ElfW(Rela)* rela;
- size_t rela_count;
+ ElfW(Rela)* rela_;
+ size_t rela_count_;
#else
- ElfW(Rel)* plt_rel;
- size_t plt_rel_count;
+ ElfW(Rel)* plt_rel_;
+ size_t plt_rel_count_;
- ElfW(Rel)* rel;
- size_t rel_count;
+ ElfW(Rel)* rel_;
+ size_t rel_count_;
#endif
- linker_function_t* preinit_array;
- size_t preinit_array_count;
+ linker_function_t* preinit_array_;
+ size_t preinit_array_count_;
- linker_function_t* init_array;
- size_t init_array_count;
- linker_function_t* fini_array;
- size_t fini_array_count;
+ linker_function_t* init_array_;
+ size_t init_array_count_;
+ linker_function_t* fini_array_;
+ size_t fini_array_count_;
- linker_function_t init_func;
- linker_function_t fini_func;
+ linker_function_t init_func_;
+ linker_function_t fini_func_;
+ public:
#if defined(__arm__)
// ARM EABI section used for stack unwinding.
uint32_t* ARM_exidx;
size_t ARM_exidx_count;
#elif defined(__mips__)
private:
- uint32_t mips_symtabno;
- uint32_t mips_local_gotno;
- uint32_t mips_gotsym;
+ uint32_t mips_symtabno_;
+ uint32_t mips_local_gotno_;
+ uint32_t mips_gotsym_;
bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
- public:
#endif
+ public:
size_t ref_count;
link_map link_map_head;
@@ -232,13 +232,14 @@
#endif
bool has_DT_SYMBOLIC;
+ public:
soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
- void CallConstructors();
- void CallDestructors();
- void CallPreInitConstructors();
- bool PrelinkImage();
- bool LinkImage(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
+ void call_constructors();
+ void call_destructors();
+ void call_pre_init_constructors();
+ bool prelink_image();
+ bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, const android_dlextinfo* extinfo);
void add_child(soinfo* child);
void remove_all_links();
@@ -263,7 +264,7 @@
bool is_gnu_hash() const;
bool inline has_min_version(uint32_t min_version) const {
- return (flags & FLAG_NEW_SOINFO) != 0 && version >= min_version;
+ return (flags & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
}
private:
@@ -272,38 +273,38 @@
ElfW(Sym)* gnu_lookup(SymbolName& symbol_name);
ElfW(Sym)* gnu_addr_lookup(const void* addr);
- void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
- void CallFunction(const char* function_name, linker_function_t function);
+ void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
+ void call_function(const char* function_name, linker_function_t function);
#if defined(USE_RELA)
- int Relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
+ int relocate(ElfW(Rela)* rela, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
#else
- int Relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
+ int relocate(ElfW(Rel)* rel, unsigned count, const soinfo_list_t& global_group, const soinfo_list_t& local_group);
#endif
private:
// This part of the structure is only available
// when FLAG_NEW_SOINFO is set in this->flags.
- uint32_t version;
+ uint32_t version_;
// version >= 0
- dev_t st_dev;
- ino_t st_ino;
+ dev_t st_dev_;
+ ino_t st_ino_;
// dependency graph
- soinfo_list_t children;
- soinfo_list_t parents;
+ soinfo_list_t children_;
+ soinfo_list_t parents_;
// version >= 1
- off64_t file_offset;
- uint32_t rtld_flags;
- uint32_t dt_flags_1;
- size_t strtab_size;
+ off64_t file_offset_;
+ uint32_t rtld_flags_;
+ uint32_t dt_flags_1_;
+ size_t strtab_size_;
// version >= 2
- uint32_t gnu_maskwords;
- uint32_t gnu_shift2;
+ uint32_t gnu_maskwords_;
+ uint32_t gnu_shift2_;
- ElfW(Addr)* gnu_bloom_filter;
+ ElfW(Addr)* gnu_bloom_filter_;
friend soinfo* get_libdl_info();
};
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 9c5df0e..0754a7b 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -35,7 +35,10 @@
endif
LOCAL_CLANG := $($(module)_clang_$(build_type))
+
+ifneq ($($(module)_allow_asan),true)
LOCAL_ADDRESS_SANITIZER := false
+endif
LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
diff --git a/tests/Android.mk b/tests/Android.mk
index 5e0c593..92d7976 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -98,6 +98,7 @@
sys_stat_test.cpp \
sys_statvfs_test.cpp \
sys_syscall_test.cpp \
+ sys_sysinfo_test.cpp \
sys_time_test.cpp \
sys_types_test.cpp \
sys_vfs_test.cpp \
@@ -301,9 +302,7 @@
libdl_preempt_test_1 \
libdl_preempt_test_2
-ifneq ($(filter $(TARGET_ARCH),arm arm64),$(TARGET_ARCH))
bionic-unit-tests-glibc_shared_libraries += libdl_test_df_1_global
-endif
bionic-unit-tests-glibc_whole_static_libraries := \
libBionicStandardTests \
@@ -318,6 +317,8 @@
bionic-unit-tests-glibc_cppflags := $(test_cppflags)
bionic-unit-tests-glibc_ldflags := -Wl,--export-dynamic
+bionic-unit-tests-glibc_allow_asan := true
+
module := bionic-unit-tests-glibc
module_tag := optional
build_type := host
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index cd97d55..88f0b19 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -669,12 +669,32 @@
ASSERT_TRUE(fn == dlinfo.dli_saddr);
ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
- ASSERT_STREQ("libgnu-hash-table-library.so", dlinfo.dli_fname);
+ ASSERT_SUBSTR("libgnu-hash-table-library.so", dlinfo.dli_fname);
#else
GTEST_LOG_(INFO) << "This test does nothing for mips/mips64; mips toolchain does not support '--hash-style=gnu'\n";
#endif
}
+TEST(dlfcn, dlopen_library_with_only_sysv_hash) {
+ void* handle = dlopen("libsysv-hash-table-library.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ auto guard = make_scope_guard([&]() {
+ dlclose(handle);
+ });
+ void* sym = dlsym(handle, "getRandomNumber");
+ ASSERT_TRUE(sym != nullptr) << dlerror();
+ int (*fn)(void);
+ fn = reinterpret_cast<int (*)(void)>(sym);
+ EXPECT_EQ(4, fn());
+
+ Dl_info dlinfo;
+ ASSERT_TRUE(0 != dladdr(reinterpret_cast<void*>(fn), &dlinfo));
+
+ ASSERT_TRUE(fn == dlinfo.dli_saddr);
+ ASSERT_STREQ("getRandomNumber", dlinfo.dli_sname);
+ ASSERT_SUBSTR("libsysv-hash-table-library.so", dlinfo.dli_fname);
+}
+
TEST(dlfcn, dlopen_bad_flags) {
dlerror(); // Clear any pending errors.
void* handle;
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index 0793019..fafb9e0 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -28,7 +28,7 @@
$(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
-# Library used by dlfcn tests.
+# Library to test gnu-styled hash
# -----------------------------------------------------------------------------
ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
libgnu-hash-table-library_src_files := \
@@ -43,6 +43,19 @@
endif
# -----------------------------------------------------------------------------
+# Library to test sysv-styled hash
+# -----------------------------------------------------------------------------
+libsysv-hash-table-library_src_files := \
+ dlext_test_library.cpp \
+
+libsysv-hash-table-library_ldflags := \
+ -Wl,--hash-style=sysv \
+
+module := libsysv-hash-table-library
+module_tag := optional
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
# Library used by dlext tests - with GNU RELRO program header
# -----------------------------------------------------------------------------
libdlext_test_src_files := \
@@ -311,12 +324,17 @@
# -----------------------------------------------------------------------------
# Library with DF_1_GLOBAL
# -----------------------------------------------------------------------------
-# TODO: re-enable arm once b/18137520 or b/18130452 are fixed
-ifeq ($(filter $(TARGET_ARCH),arm arm64),)
libdl_test_df_1_global_src_files := dl_df_1_global.cpp
libdl_test_df_1_global_ldflags := -fuse-ld=bfd -Wl,-z,global
module := libdl_test_df_1_global
+# TODO: re-enable arm once b/18137520 or b/18130452 are fixed
+ifeq ($(filter $(TARGET_ARCH),arm arm64),)
include $(LOCAL_PATH)/Android.build.testlib.mk
+else
+# build it for host only
+build_target := SHARED_LIBRARY
+build_type := host
+include $(TEST_PATH)/Android.build.mk
endif
# -----------------------------------------------------------------------------
diff --git a/tests/mntent_test.cpp b/tests/mntent_test.cpp
index 637cb52..a102849 100644
--- a/tests/mntent_test.cpp
+++ b/tests/mntent_test.cpp
@@ -19,16 +19,22 @@
#include <mntent.h>
TEST(mntent, mntent_smoke) {
- FILE* fp = setmntent("/no/mnt/tab/on/android", "r");
- ASSERT_TRUE(fp == NULL);
+ FILE* fp = setmntent("/proc/mounts", "r");
+ ASSERT_TRUE(fp != NULL);
-#if __BIONIC__ // glibc doesn't let you call getmntent/getmntent_r with a NULL FILE*.
- ASSERT_TRUE(getmntent(fp) == NULL);
+ ASSERT_TRUE(getmntent(fp) != NULL);
- struct mntent mbuf;
- char cbuf[32];
- ASSERT_TRUE(getmntent_r(fp, &mbuf, cbuf, sizeof(cbuf)) == NULL);
-#endif
+ bool saw_proc = false;
+
+ struct mntent entry;
+ char buf[BUFSIZ];
+ while (getmntent_r(fp, &entry, buf, sizeof(buf)) != NULL) {
+ if (strcmp(entry.mnt_fsname, "proc") == 0 && strcmp(entry.mnt_dir, "/proc") == 0) {
+ saw_proc = true;
+ }
+ }
+
+ ASSERT_TRUE(saw_proc);
ASSERT_EQ(1, endmntent(fp));
}
diff --git a/tests/sys_sysinfo_test.cpp b/tests/sys_sysinfo_test.cpp
new file mode 100644
index 0000000..b00e13f
--- /dev/null
+++ b/tests/sys_sysinfo_test.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <sys/sysinfo.h>
+
+TEST(sys_sysinfo, smoke) {
+ int nprocessor = get_nprocs();
+ ASSERT_GT(nprocessor, 0);
+
+ int nprocessor_conf = get_nprocs_conf();
+ ASSERT_GE(nprocessor_conf, nprocessor);
+
+ long avail_phys_pages = get_avphys_pages();
+ ASSERT_GT(avail_phys_pages, 0);
+
+ long phys_pages = get_phys_pages();
+ ASSERT_GE(phys_pages, avail_phys_pages);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index c9d9943..b5fcf26 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
+#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/utsname.h>
@@ -499,3 +500,23 @@
ASSERT_EQ(-1, gethostname(hostname, strlen(hostname)));
ASSERT_EQ(ENAMETOOLONG, errno);
}
+
+TEST(unistd, pathconf_fpathconf) {
+ TemporaryFile tf;
+ long rc = 0L;
+ // As a file system's block size is always power of 2, the configure values
+ // for ALLOC and XFER should be power of 2 as well.
+ rc = pathconf(tf.filename, _PC_ALLOC_SIZE_MIN);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+ rc = pathconf(tf.filename, _PC_REC_MIN_XFER_SIZE);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+ rc = pathconf(tf.filename, _PC_REC_XFER_ALIGN);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+
+ rc = fpathconf(tf.fd, _PC_ALLOC_SIZE_MIN);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+ rc = fpathconf(tf.fd, _PC_REC_MIN_XFER_SIZE);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+ rc = fpathconf(tf.fd, _PC_REC_XFER_ALIGN);
+ ASSERT_TRUE(rc > 0 && powerof2(rc));
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 887266c..63f3760 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -22,6 +22,8 @@
#include <stdint.h>
#include <wchar.h>
+#define NUM_WCHARS(num_bytes) (num_bytes/sizeof(wchar_t))
+
TEST(wchar, sizeof_wchar_t) {
EXPECT_EQ(4U, sizeof(wchar_t));
EXPECT_EQ(4U, sizeof(wint_t));
@@ -343,7 +345,7 @@
// Check that valid has advanced to the next unread character.
ASSERT_EQ('e', *valid);
- wmemset(out, L'x', sizeof(out) / sizeof(wchar_t));
+ wmemset(out, L'x', NUM_WCHARS(sizeof(out)));
ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps));
ASSERT_EQ(L'e', out[0]);
ASSERT_EQ(L'f', out[1]);
@@ -450,17 +452,85 @@
EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
}
-TEST(wchar, wmemmove) {
+TEST(wchar, wmemmove_smoke) {
const wchar_t const_wstr[] = L"This is a test of something or other.....";
- wchar_t* wstr = new wchar_t[sizeof(const_wstr)];
+ wchar_t wstr[NUM_WCHARS(sizeof(const_wstr))];
- wmemmove(wstr, const_wstr, sizeof(const_wstr)/sizeof(wchar_t));
+ EXPECT_EQ(wstr, wmemmove(wstr, const_wstr, NUM_WCHARS(sizeof(const_wstr))));
EXPECT_STREQ(const_wstr, wstr);
- wmemmove(wstr+5, wstr, sizeof(const_wstr)/sizeof(wchar_t) - 6);
+ EXPECT_EQ(wstr+5, wmemmove(wstr+5, wstr, NUM_WCHARS(sizeof(const_wstr)) - 6));
EXPECT_STREQ(L"This This is a test of something or other", wstr);
}
+TEST(wchar, wmemcpy_smoke) {
+ const wchar_t src[] = L"Source string";
+ wchar_t dst[NUM_WCHARS(sizeof(src))];
+
+ EXPECT_EQ(dst, wmemcpy(dst, src, NUM_WCHARS(sizeof(src))));
+ EXPECT_STREQ(dst, src);
+}
+
+TEST(wchar, wcpcpy_smoke) {
+ const wchar_t src[] = L"Source string";
+ wchar_t dst[NUM_WCHARS(sizeof(src))];
+
+ EXPECT_EQ(dst + NUM_WCHARS(sizeof(src)) - 1, wcpcpy(dst, src));
+ EXPECT_STREQ(dst, src);
+}
+
+TEST(wchar, wcpncpy_smoke) {
+ const wchar_t src[] = L"Source string";
+ wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
+
+ size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
+ EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 1));
+ EXPECT_STREQ(dst, src);
+
+ EXPECT_EQ(dst + 6, wcpncpy(dst, src, 6));
+ dst[6] = L'\0';
+ EXPECT_STREQ(dst, L"Source");
+
+ wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
+ EXPECT_EQ(dst + src_len, wcpncpy(dst, src, src_len + 4));
+ EXPECT_STREQ(dst, src);
+ EXPECT_EQ(dst[src_len], L'\0');
+ EXPECT_EQ(dst[src_len+1], L'\0');
+ EXPECT_EQ(dst[src_len+2], L'\0');
+ EXPECT_EQ(dst[src_len+3], L'\0');
+ EXPECT_EQ(dst[src_len+4], L'x');
+}
+
+TEST(wchar, wcscpy_smoke) {
+ const wchar_t src[] = L"Source string";
+ wchar_t dst[NUM_WCHARS(sizeof(src))];
+
+ EXPECT_EQ(dst, wcscpy(dst, src));
+ EXPECT_STREQ(src, dst);
+}
+
+TEST(wchar, wcsncpy_smoke) {
+ const wchar_t src[] = L"Source string";
+ wchar_t dst[NUM_WCHARS(sizeof(src)) + 5];
+
+ size_t src_len = NUM_WCHARS(sizeof(src)) - 1;
+ EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 1));
+ EXPECT_STREQ(dst, src);
+
+ EXPECT_EQ(dst, wcsncpy(dst, src, 6));
+ dst[6] = L'\0';
+ EXPECT_STREQ(dst, L"Source");
+
+ wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
+ EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 4));
+ EXPECT_STREQ(dst, src);
+ EXPECT_EQ(dst[src_len], L'\0');
+ EXPECT_EQ(dst[src_len+1], L'\0');
+ EXPECT_EQ(dst[src_len+2], L'\0');
+ EXPECT_EQ(dst[src_len+3], L'\0');
+ EXPECT_EQ(dst[src_len+4], L'x');
+}
+
TEST(wchar, mbrtowc_15439554) {
// http://b/15439554
ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));