Merge "Revert "Added a bionic systrace class and tracing to pthread_mutex.cpp."" into lmp-dev
diff --git a/libc/Android.mk b/libc/Android.mk
index 1fb5e84..d641d89 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -45,7 +45,6 @@
bionic/fts.c \
bionic/gethostname.c \
bionic/getpriority.c \
- bionic/getpt.c \
bionic/if_indextoname.c \
bionic/if_nametoindex.c \
bionic/initgroups.c \
@@ -53,8 +52,6 @@
bionic/isatty.c \
bionic/memmem.c \
bionic/pathconf.c \
- bionic/ptsname.c \
- bionic/ptsname_r.c \
bionic/pututline.c \
bionic/sched_cpualloc.c \
bionic/sched_cpucount.c \
@@ -63,7 +60,6 @@
bionic/siginterrupt.c \
bionic/sigsetmask.c \
bionic/system_properties_compat.c \
- bionic/unlockpt.c \
stdio/snprintf.c\
stdio/sprintf.c \
@@ -174,6 +170,7 @@
bionic/pthread_setschedparam.cpp \
bionic/pthread_sigmask.cpp \
bionic/ptrace.cpp \
+ bionic/pty.cpp \
bionic/raise.cpp \
bionic/rand.cpp \
bionic/readlink.cpp \
diff --git a/libc/bionic/getpt.c b/libc/bionic/getpt.c
deleted file mode 100644
index 8bb5c11..0000000
--- a/libc/bionic/getpt.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 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 <unistd.h>
-#include <fcntl.h>
-
-int getpt(void)
-{
- return open("/dev/ptmx", O_RDWR|O_NOCTTY);
-}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index e656a12..d0172ed 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -620,7 +620,11 @@
out_vformat(os, format, args);
// log to stderr for the benefit of "adb shell" users.
- write(2, msg, strlen(msg));
+ struct iovec iov[2] = {
+ {msg, strlen(msg)},
+ {const_cast<void*>(static_cast<const void*>("\n")), 1},
+ };
+ writev(2, iov, 2);
// Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
__libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 5a1da43..363140e 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -79,7 +79,9 @@
static bool __is_supported_locale(const char* locale) {
return (strcmp(locale, "") == 0 ||
- strcmp(locale, "C") == 0 || strcmp(locale, "C.UTF-8") == 0 ||
+ strcmp(locale, "C") == 0 ||
+ strcmp(locale, "C.UTF-8") == 0 ||
+ strcmp(locale, "en_US.UTF-8") == 0 ||
strcmp(locale, "POSIX") == 0);
}
diff --git a/libc/bionic/ptsname.c b/libc/bionic/ptsname.c
deleted file mode 100644
index 24d5d30..0000000
--- a/libc/bionic/ptsname.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 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 <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-/* not thread-safe */
-char* ptsname( int fd )
-{
- unsigned int pty_num;
- static char buff[64];
-
- if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 )
- return NULL;
-
- snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
- return buff;
-}
diff --git a/libc/bionic/ptsname_r.c b/libc/bionic/ptsname_r.c
deleted file mode 100644
index 2fa4c3d..0000000
--- a/libc/bionic/ptsname_r.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 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 <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <string.h>
-
-int ptsname_r( int fd, char* buf, size_t buflen)
-{
- unsigned int pty_num;
- char buff[64];
- int len;
-
- if (buf == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if ( ioctl( fd, TIOCGPTN, &pty_num ) != 0 ) {
- errno = ENOTTY;
- return -1;
- }
-
- len = snprintf( buff, sizeof(buff), "/dev/pts/%u", pty_num );
- if (len+1 > (int)buflen) {
- errno = ERANGE;
- return -1;
- }
- memcpy( buf, buff, len+1 );
- return 0;
-}
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
new file mode 100644
index 0000000..995e006
--- /dev/null
+++ b/libc/bionic/pty.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+
+int getpt(void) {
+ return posix_openpt(O_RDWR|O_NOCTTY);
+}
+
+int grantpt(int) {
+ return 0;
+}
+
+int posix_openpt(int flags) {
+ return open("/dev/ptmx", flags);
+}
+
+char* ptsname(int fd) {
+ static char buf[64];
+ return ptsname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ptsname_r(int fd, char* buf, size_t len) {
+ if (buf == NULL) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ unsigned int pty_num;
+ if (ioctl(fd, TIOCGPTN, &pty_num) != 0) {
+ errno = ENOTTY;
+ return errno;
+ }
+
+ if (snprintf(buf, len, "/dev/pts/%u", pty_num) >= static_cast<int>(len)) {
+ errno = ERANGE;
+ return errno;
+ }
+
+ return 0;
+}
+
+char* ttyname(int fd) {
+ static char buf[64];
+ return ttyname_r(fd, buf, sizeof(buf)) == 0 ? buf : NULL;
+}
+
+int ttyname_r(int fd, char* buf, size_t len) {
+ if (buf == NULL) {
+ errno = EINVAL;
+ return errno;
+ }
+
+ if (!isatty(fd)) {
+ return errno;
+ }
+
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+ ssize_t count = readlink(path, buf, len);
+ if (count == -1) {
+ return errno;
+ }
+ if (static_cast<size_t>(count) == len) {
+ errno = ERANGE;
+ return errno;
+ }
+ buf[count] = '\0';
+ return 0;
+}
+
+int unlockpt(int fd) {
+ int unlock = 0;
+ return ioctl(fd, TIOCSPTLCK, &unlock);
+}
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index 0937e9c..b1e38be 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -444,16 +444,6 @@
UNIMPLEMENTED;
}
-char* ttyname(int /*fd*/) { // NOLINT: implementing bad function.
- UNIMPLEMENTED;
- return NULL;
-}
-
-int ttyname_r(int /*fd*/, char* /*buf*/, size_t /*buflen*/) {
- UNIMPLEMENTED;
- return -ERANGE;
-}
-
char* getusershell() {
UNIMPLEMENTED;
return NULL;
diff --git a/libc/bionic/unlockpt.c b/libc/bionic/unlockpt.c
deleted file mode 100644
index 998b7a3..0000000
--- a/libc/bionic/unlockpt.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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 <unistd.h>
-#include <sys/ioctl.h>
-
-int unlockpt( int fd )
-{
- int unlock = 0;
-
- return ioctl( fd, TIOCSPTLCK, &unlock );
-}
diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index ecb8b33..438ce03 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -116,11 +116,10 @@
if (static_cast<uint8_t>((*src)[i]) < 0x80) {
// Fast path for plain ASCII characters.
dst[o] = (*src)[i];
- if ((*src)[i] == '\0') {
- *src = NULL;
- return reset_and_return_illegal(EILSEQ, state);
- }
r = 1;
+ if ((*src)[i] == '\0') {
+ break;
+ }
} else {
r = mbrtowc(dst + o, *src + i, nmc - i, state);
if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index f34843c..a6f8505 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -203,7 +203,7 @@
#if defined(__WINT_UNSIGNED__)
# define WINT_MAX UINT32_MAX
-# define WINT_MIN UINT32_MIN
+# define WINT_MIN 0
#else
# define WINT_MAX INT32_MAX
# define WINT_MIN INT32_MIN
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 195765a..857d631 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -120,18 +120,12 @@
char* setstate(char*);
void srandom(unsigned int);
-/* Basic PTY functions. These only work if devpts is mounted! */
-
-extern int unlockpt(int);
-extern char* ptsname(int);
-extern int ptsname_r(int, char*, size_t);
-extern int getpt(void);
-
-static __inline__ int grantpt(int __fd __attribute((unused)))
-{
- (void)__fd;
- return 0; /* devpts does this all for us! */
-}
+int getpt(void);
+int grantpt(int);
+int posix_openpt(int);
+char* ptsname(int) __warnattr("ptsname is not thread-safe; use ptsname_r instead");
+int ptsname_r(int, char*, size_t);
+int unlockpt(int);
typedef struct {
int quot;
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 12e6257..82c53e8 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -170,7 +170,7 @@
extern int optind, opterr, optopt;
extern int isatty(int);
-extern char* ttyname(int);
+extern char* ttyname(int) __warnattr("ttyname is not thread-safe; use ttyname_r instead");
extern int ttyname_r(int, char*, size_t);
extern int acct(const char* filepath);
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index efb829e..8ebf357 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -111,8 +111,7 @@
sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
}
} else {
- found = reinterpret_cast<soinfo*>(handle);
- sym = dlsym_handle_lookup(found, symbol, caller_si);
+ sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol, caller_si);
}
if (sym != NULL && sym->st_shndx != 0) {
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 52af0f1..7f8c901 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -31,13 +31,45 @@
template<typename T, typename Allocator>
class LinkedList {
public:
- LinkedList() : head_(nullptr) {}
+ LinkedList() : head_(nullptr), tail_(nullptr) {}
void push_front(T* const element) {
LinkedListEntry<T>* new_entry = Allocator::alloc();
new_entry->next = head_;
new_entry->element = element;
head_ = new_entry;
+ if (tail_ == nullptr) {
+ tail_ = new_entry;
+ }
+ }
+
+ void push_back(T* const element) {
+ LinkedListEntry<T>* new_entry = Allocator::alloc();
+ new_entry->next = nullptr;
+ new_entry->element = element;
+ if (tail_ == nullptr) {
+ tail_ = head_ = new_entry;
+ } else {
+ tail_->next = new_entry;
+ tail_ = new_entry;
+ }
+ }
+
+ T* pop_front() {
+ if (head_ == nullptr) {
+ return nullptr;
+ }
+
+ LinkedListEntry<T>* entry = head_;
+ T* element = entry->element;
+ head_ = entry->next;
+ Allocator::free(entry);
+
+ if (head_ == nullptr) {
+ tail_ = nullptr;
+ }
+
+ return element;
}
void clear() {
@@ -46,6 +78,8 @@
head_ = head_->next;
Allocator::free(p);
}
+
+ tail_ = nullptr;
}
template<typename F>
@@ -68,6 +102,7 @@
private:
LinkedListEntry<T>* head_;
+ LinkedListEntry<T>* tail_;
DISALLOW_COPY_AND_ASSIGN(LinkedList);
};
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 59b9938..f8b35d7 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -469,6 +469,10 @@
}
}
+ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
+ name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket);
+
+
return NULL;
}
@@ -585,18 +589,43 @@
return NULL;
}
-/* This is used by dlsym(3). It performs symbol lookup only within the
- specified soinfo object and not in any of its dependencies.
+// Another soinfo list allocator to use in dlsym. We don't reuse
+// SoinfoListAllocator because it is write-protected most of the time.
+static LinkerAllocator<LinkedListEntry<soinfo>> g_soinfo_list_allocator_rw;
+class SoinfoListAllocatorRW {
+ public:
+ static LinkedListEntry<soinfo>* alloc() {
+ return g_soinfo_list_allocator_rw.alloc();
+ }
- TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says
- that it should do a breadth first search through the dependency
- tree. This agrees with the ELF spec (aka System V Application
- Binary Interface) where in Chapter 5 it discuss resolving "Shared
- Object Dependencies" in breadth first search order.
- */
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) {
- return soinfo_elf_lookup(si, elfhash(name), name,
- caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+ static void free(LinkedListEntry<soinfo>* ptr) {
+ g_soinfo_list_allocator_rw.free(ptr);
+ }
+};
+
+// This is used by dlsym(3). It performs symbol lookup only within the
+// specified soinfo object and its dependencies in breadth first order.
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
+ LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
+ visit_list.push_back(si);
+ soinfo* current_soinfo;
+ while ((current_soinfo = visit_list.pop_front()) != nullptr) {
+ ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
+ caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
+
+ if (result != nullptr) {
+ *found = current_soinfo;
+ visit_list.clear();
+ return result;
+ }
+
+ current_soinfo->get_children().for_each([&](soinfo* child) {
+ visit_list.push_back(child);
+ });
+ }
+
+ visit_list.clear();
+ return nullptr;
}
/* This is used by dlsym(3) to performs a global symbol lookup. If the
diff --git a/linker/linker.h b/linker/linker.h
index e1112e6..03672b2 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -238,7 +238,7 @@
soinfo* find_containing_library(const void* addr);
ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr);
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller_si);
void debuggerd_init();
extern "C" abort_msg_t* g_abort_message;
diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp
index 31ec7d5..b9816fa 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/tests/linked_list_test.cpp
@@ -95,3 +95,23 @@
ASSERT_TRUE(free_called);
ASSERT_EQ("", test_list_to_string(list));
}
+
+TEST(linked_list, push_pop) {
+ test_list_t list;
+ list.push_front("b");
+ list.push_front("a");
+ ASSERT_EQ("ab", test_list_to_string(list));
+ list.push_back("c");
+ ASSERT_EQ("abc", test_list_to_string(list));
+ ASSERT_EQ("a", list.pop_front());
+ ASSERT_EQ("bc", test_list_to_string(list));
+ ASSERT_EQ("b", list.pop_front());
+ ASSERT_EQ("c", test_list_to_string(list));
+ ASSERT_EQ("c", list.pop_front());
+ ASSERT_EQ("", test_list_to_string(list));
+ ASSERT_TRUE(list.pop_front() == nullptr);
+ list.push_back("r");
+ ASSERT_EQ("r", test_list_to_string(list));
+ ASSERT_EQ("r", list.pop_front());
+ ASSERT_TRUE(list.pop_front() == nullptr);
+}
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index f056fb6..9bc2557 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -62,10 +62,9 @@
ASSERT_EQ(0, dlclose(self));
}
-#if !defined(__LP64__)
-// Current compiler/static linker used for aarch64
-// platform optimizes LOCAL PROTECTED symbol
-// in libtest_local_symbol.so out of existence
+#if defined(__arm__)
+// This seems to be working only for arm.
+// Others platforms optimize LOCAL PROTECTED symbols.
TEST(dlfcn, dlsym_local_symbol) {
void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
ASSERT_TRUE(handle != NULL);
@@ -78,9 +77,23 @@
f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
ASSERT_TRUE(f != NULL);
ASSERT_EQ(1729U, f());
+ dlclose(handle);
}
#endif
+TEST(dlfcn, dlsym_with_dependencies) {
+ void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
+ ASSERT_TRUE(handle != NULL);
+ dlerror();
+ // This symbol is in DT_NEEDED library.
+ void* sym = dlsym(handle, "getRandomNumber");
+ ASSERT_TRUE(sym != NULL);
+ int (*fn)(void);
+ fn = reinterpret_cast<int (*)(void)>(sym);
+ EXPECT_EQ(4, fn());
+ dlclose(handle);
+}
+
TEST(dlfcn, dlopen_noload) {
void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
ASSERT_TRUE(handle == NULL);
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a374e48..7ed3e7b 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -102,6 +102,19 @@
include $(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
+# Library with dependency used by dlfcn tests
+# -----------------------------------------------------------------------------
+libtest_with_dependency_src_files := \
+ dlopen_testlib_simple.cpp
+
+libtest_with_dependency_shared_libraries := libdlext_test
+
+module := libtest_with_dependency
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
# Library used to test local symbol lookup
# -----------------------------------------------------------------------------
libtest_local_symbol_src_files := \
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 6d29421..553f018 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -262,3 +262,102 @@
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(99, WEXITSTATUS(status));
}
+
+TEST(stdlib, pty_smoke) {
+ // getpt returns a pty with O_RDWR|O_NOCTTY.
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+
+ // grantpt is a no-op.
+ ASSERT_EQ(0, grantpt(fd));
+
+ // ptsname_r should start "/dev/pts/".
+ char name_r[128];
+ ASSERT_EQ(0, ptsname_r(fd, name_r, sizeof(name_r)));
+ name_r[9] = 0;
+ ASSERT_STREQ("/dev/pts/", name_r);
+
+ close(fd);
+}
+
+TEST(stdlib, posix_openpt) {
+ int fd = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC);
+ ASSERT_NE(-1, fd);
+ close(fd);
+}
+
+TEST(stdlib, ptsname_r_ENOTTY) {
+ errno = 0;
+ char buf[128];
+ ASSERT_EQ(ENOTTY, ptsname_r(STDOUT_FILENO, buf, sizeof(buf)));
+ ASSERT_EQ(ENOTTY, errno);
+}
+
+TEST(stdlib, ptsname_r_EINVAL) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char* buf = NULL;
+ ASSERT_EQ(EINVAL, ptsname_r(fd, buf, 128));
+ ASSERT_EQ(EINVAL, errno);
+ close(fd);
+}
+
+TEST(stdlib, ptsname_r_ERANGE) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char buf[1];
+ ASSERT_EQ(ERANGE, ptsname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ERANGE, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+
+ // ttyname_r returns "/dev/ptmx" for a pty.
+ char name_r[128];
+ ASSERT_EQ(0, ttyname_r(fd, name_r, sizeof(name_r)));
+ ASSERT_STREQ("/dev/ptmx", name_r);
+
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_ENOTTY) {
+ int fd = open("/dev/null", O_WRONLY);
+ errno = 0;
+ char buf[128];
+ ASSERT_EQ(ENOTTY, ttyname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ENOTTY, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_EINVAL) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char* buf = NULL;
+ ASSERT_EQ(EINVAL, ttyname_r(fd, buf, 128));
+ ASSERT_EQ(EINVAL, errno);
+ close(fd);
+}
+
+TEST(stdlib, ttyname_r_ERANGE) {
+ int fd = getpt();
+ ASSERT_NE(-1, fd);
+ errno = 0;
+ char buf[1];
+ ASSERT_EQ(ERANGE, ttyname_r(fd, buf, sizeof(buf)));
+ ASSERT_EQ(ERANGE, errno);
+ close(fd);
+}
+
+TEST(stdlib, unlockpt_ENOTTY) {
+ int fd = open("/dev/null", O_WRONLY);
+ errno = 0;
+ ASSERT_EQ(-1, unlockpt(fd));
+ ASSERT_EQ(ENOTTY, errno);
+ close(fd);
+}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index a5f5f63..f052ce6 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -340,8 +340,19 @@
ASSERT_EQ(static_cast<wchar_t>(0x00a2), out[1]);
ASSERT_EQ(static_cast<wchar_t>(0x20ac), out[2]);
ASSERT_EQ(static_cast<wchar_t>(0x24b62), out[3]);
+ // Check that valid has advanced to the next unread character.
ASSERT_EQ('e', *valid);
+ wmemset(out, L'x', sizeof(out) / sizeof(wchar_t));
+ ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps));
+ ASSERT_EQ(L'e', out[0]);
+ ASSERT_EQ(L'f', out[1]);
+ ASSERT_EQ(L'\0', out[2]);
+ // Check that we didn't clobber the rest of out.
+ ASSERT_EQ(L'x', out[3]);
+ // Check that valid has advanced to the end of the string.
+ ASSERT_EQ(L'\0', *valid);
+
const char* invalid = "A" "\xc2\x20" "ef";
ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps));
EXPECT_EQ(EILSEQ, errno);