diff options
-rw-r--r-- | libc/bionic/legacy_32_bit_support.cpp | 19 | ||||
-rw-r--r-- | libc/dns/net/getaddrinfo.c | 8 | ||||
-rw-r--r-- | libc/include/libgen.h | 17 | ||||
-rw-r--r-- | libc/include/string.h | 4 | ||||
-rw-r--r-- | libc/include/sys/resource.h | 3 | ||||
-rw-r--r-- | linker/linker.cpp | 10 | ||||
-rw-r--r-- | tests/Android.mk | 1 | ||||
-rw-r--r-- | tests/libgen_basename_test.cpp | 89 | ||||
-rw-r--r-- | tests/libgen_test.cpp | 24 | ||||
-rwxr-xr-x[-rw-r--r--] | tests/pthread_test.cpp | 7 | ||||
-rw-r--r-- | tests/sys_resource_test.cpp | 25 |
11 files changed, 157 insertions, 50 deletions
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp index a107664..1336b43 100644 --- a/libc/bionic/legacy_32_bit_support.cpp +++ b/libc/bionic/legacy_32_bit_support.cpp @@ -91,3 +91,22 @@ int getrlimit64(int resource, rlimit64* limits64) { int setrlimit64(int resource, const rlimit64* limits64) { return prlimit64(0, resource, limits64, NULL); } + +// There is no prlimit system call, so we need to use prlimit64. +int prlimit(pid_t pid, int resource, const rlimit* n32, rlimit* o32) { + rlimit64 n64; + if (n32 != nullptr) { + n64.rlim_cur = (n32->rlim_cur == RLIM_INFINITY) ? RLIM64_INFINITY : n32->rlim_cur; + n64.rlim_max = (n32->rlim_max == RLIM_INFINITY) ? RLIM64_INFINITY : n32->rlim_max; + } + + rlimit64 o64; + int result = prlimit64(pid, resource, + (n32 != nullptr) ? &n64 : nullptr, + (o32 != nullptr) ? &o64 : nullptr); + if (result != -1 && o32 != nullptr) { + o32->rlim_cur = (o64.rlim_cur == RLIM64_INFINITY) ? RLIM_INFINITY : o64.rlim_cur; + o32->rlim_max = (o64.rlim_max == RLIM64_INFINITY) ? RLIM_INFINITY : o64.rlim_max; + } + return result; +} diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c index 829b679..cc8b8b4 100644 --- a/libc/dns/net/getaddrinfo.c +++ b/libc/dns/net/getaddrinfo.c @@ -1791,10 +1791,14 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned return -1; } } - if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) + if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) { + close(sock); return 0; - if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0) + } + if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0) { + close(sock); return 0; + } do { ret = __connect(sock, addr, len); } while (ret == -1 && errno == EINTR); diff --git a/libc/include/libgen.h b/libc/include/libgen.h index e89328e..4d22d15 100644 --- a/libc/include/libgen.h +++ b/libc/include/libgen.h @@ -32,18 +32,19 @@ #include <sys/cdefs.h> #include <sys/types.h> + __BEGIN_DECLS -#if !defined(__bionic_using_gnu_basename) /* - * <string.h> gets you the GNU basename. - * <libgen.h> the POSIX one. - * Note that our "POSIX" one has the wrong argument cv-qualifiers, but doesn't - * modify its input and uses thread-local storage for the result if necessary. + * Including <string.h> will get you the GNU basename, unless <libgen.h> is + * included, either before or after including <string.h>. + * + * Note that this has the wrong argument cv-qualifiers, but doesn't modify its + * input and uses thread-local storage for the result if necessary. */ -extern char* basename(const char*); -#define __bionic_using_posix_basename -#endif +extern char* __posix_basename(const char*) __RENAME(basename); + +#define basename __posix_basename /* This has the wrong argument cv-qualifiers, but doesn't modify its input and uses thread-local storage for the result if necessary. */ extern char* dirname(const char*); diff --git a/libc/include/string.h b/libc/include/string.h index d32c164..8ceccd5 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -107,18 +107,18 @@ extern size_t strxfrm(char* __restrict, const char* __restrict, size_t); extern int strcoll_l(const char *, const char *, locale_t) __purefunc; extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t); -#if defined(__USE_GNU) && !defined(__bionic_using_posix_basename) +#if defined(__USE_GNU) && !defined(basename) /* * glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>. * It doesn't modify its argument, and in C++ it's const-correct. */ + #if defined(__cplusplus) extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1)); extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)); #else extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1)); #endif -#define __bionic_using_gnu_basename #endif extern void* __memchr_chk(const void*, int, size_t, size_t); diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h index 3f8dd45..8209dfb 100644 --- a/libc/include/sys/resource.h +++ b/libc/include/sys/resource.h @@ -53,10 +53,7 @@ extern int setpriority(int, int, int); extern int getrusage(int, struct rusage*); -#if __LP64__ -/* Implementing prlimit for 32-bit isn't worth the effort. */ extern int prlimit(pid_t, int, const struct rlimit*, struct rlimit*); -#endif extern int prlimit64(pid_t, int, const struct rlimit64*, struct rlimit64*); __END_DECLS diff --git a/linker/linker.cpp b/linker/linker.cpp index c81f5d3..bc40cf1 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -980,16 +980,16 @@ static bool walk_dependencies_tree(soinfo* root_soinfos[], size_t root_soinfos_s visited.push_back(si); - si->get_children().for_each([&](soinfo* child) { - visit_list.push_back(child); - }); - if (do_shims) { shim_libs_for_each(si->get_realpath(), [&](soinfo* child) { si->add_child(child); visit_list.push_back(child); }); } + + si->get_children().for_each([&](soinfo* child) { + visit_list.push_back(child); + }); } return true; @@ -3013,12 +3013,14 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& if (has_text_relocations) { // Fail if app is targeting sdk version > 22 // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed +#if !defined(__i386__) // ffmpeg says that they require text relocations on x86 if (get_application_target_sdk_version() != __ANDROID_API__ && get_application_target_sdk_version() > 22) { PRINT("%s: has text relocations", get_realpath()); DL_ERR("%s: has text relocations", get_realpath()); return false; } +#endif // Make segments writable to allow text relocations to work properly. We will later call // phdr_table_protect_segments() after all of them are applied and all constructors are run. DL_WARN("%s has text relocations. This is wasting memory and prevents " diff --git a/tests/Android.mk b/tests/Android.mk index dc2e410..b994cc3 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -64,6 +64,7 @@ libBionicStandardTests_src_files := \ getcwd_test.cpp \ inttypes_test.cpp \ libc_logging_test.cpp \ + libgen_basename_test.cpp \ libgen_test.cpp \ locale_test.cpp \ malloc_test.cpp \ diff --git a/tests/libgen_basename_test.cpp b/tests/libgen_basename_test.cpp new file mode 100644 index 0000000..55939d1 --- /dev/null +++ b/tests/libgen_basename_test.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 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. + */ + +#ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 +#endif + +#include <string.h> + +#if defined(basename) + #error basename should not be defined at this point +#endif + +static const char* gnu_basename(const char* in) { + return basename(in); +} + +#include <libgen.h> + +#if !defined(basename) + #error basename should be defined at this point +#endif + +static char* posix_basename(char* in) { + return basename(in); +} + +#include <errno.h> +#include <gtest/gtest.h> + +static void __TestGnuBasename(const char* in, const char* expected_out, int line) { + const char* out = gnu_basename(in); + ASSERT_STREQ(expected_out, out) << "(" << line << "): " << in << std::endl; + ASSERT_EQ(0, errno) << "(" << line << "): " << in << std::endl; +} + +static void __TestPosixBasename(const char* in, const char* expected_out, int line) { + char* writable_in = (in != NULL) ? strdup(in) : NULL; + errno = 0; + const char* out = posix_basename(&writable_in[0]); + ASSERT_STREQ(expected_out, out) << "(" << line << "): " << in << std::endl; + ASSERT_EQ(0, errno) << "(" << line << "): " << in << std::endl; + free(writable_in); +} + +#define TestGnuBasename(in, expected) __TestGnuBasename(in, expected, __LINE__) +#define TestPosixBasename(in, expected) __TestPosixBasename(in, expected, __LINE__) + +TEST(libgen_basename, gnu_basename) { + // GNU's basename doesn't accept NULL + // TestGnuBasename(NULL, "."); + TestGnuBasename("", ""); + TestGnuBasename("/usr/lib", "lib"); + TestGnuBasename("/system/bin/sh/", ""); + TestGnuBasename("/usr/", ""); + TestGnuBasename("usr", "usr"); + TestGnuBasename("/", ""); + TestGnuBasename(".", "."); + TestGnuBasename("..", ".."); + TestGnuBasename("///", ""); + TestGnuBasename("//usr//lib//", ""); +} + +TEST(libgen_basename, posix_basename) { + TestPosixBasename(NULL, "."); + TestPosixBasename("", "."); + TestPosixBasename("/usr/lib", "lib"); + TestPosixBasename("/system/bin/sh/", "sh"); + TestPosixBasename("/usr/", "usr"); + TestPosixBasename("usr", "usr"); + TestPosixBasename("/", "/"); + TestPosixBasename(".", "."); + TestPosixBasename("..", ".."); + TestPosixBasename("///", "/"); + TestPosixBasename("//usr//lib//", "lib"); +} diff --git a/tests/libgen_test.cpp b/tests/libgen_test.cpp index e9a5d5c..8a37a3f 100644 --- a/tests/libgen_test.cpp +++ b/tests/libgen_test.cpp @@ -19,15 +19,6 @@ #include <errno.h> #include <gtest/gtest.h> -static void TestBasename(const char* in, const char* expected_out) { - char* writable_in = (in != NULL) ? strdup(in) : NULL; - errno = 0; - const char* out = basename(&writable_in[0]); - ASSERT_STREQ(expected_out, out) << in; - ASSERT_EQ(0, errno) << in; - free(writable_in); -} - static void TestDirname(const char* in, const char* expected_out) { char* writable_in = (in != NULL) ? strdup(in) : NULL; errno = 0; @@ -37,21 +28,6 @@ static void TestDirname(const char* in, const char* expected_out) { free(writable_in); } -// Do not use basename as the test name, it's defined to another value in glibc -// so leads to a differently named test on host versus target architectures. -TEST(libgen, posix_basename) { - TestBasename(NULL, "."); - TestBasename("", "."); - TestBasename("/usr/lib", "lib"); - TestBasename("/usr/", "usr"); - TestBasename("usr", "usr"); - TestBasename("/", "/"); - TestBasename(".", "."); - TestBasename("..", ".."); - TestBasename("///", "/"); - TestBasename("//usr//lib//", "lib"); -} - TEST(libgen, dirname) { TestDirname(NULL, "."); TestDirname("", "."); diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index ad8fac6..e210255 100644..100755 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -1245,8 +1245,11 @@ TEST(pthread, pthread_attr_getstack_18908062) { } #if defined(__BIONIC__) +static pthread_mutex_t gettid_mutex; static void* pthread_gettid_np_helper(void* arg) { + pthread_mutex_lock(&gettid_mutex); *reinterpret_cast<pid_t*>(arg) = gettid(); + pthread_mutex_unlock(&gettid_mutex); return NULL; } #endif @@ -1257,11 +1260,15 @@ TEST(pthread, pthread_gettid_np) { pid_t t_gettid_result; pthread_t t; + pthread_mutex_init(&gettid_mutex, NULL); + pthread_mutex_lock(&gettid_mutex); pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result); pid_t t_pthread_gettid_np_result = pthread_gettid_np(t); + pthread_mutex_unlock(&gettid_mutex); pthread_join(t, NULL); + pthread_mutex_destroy(&gettid_mutex); ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result); #else diff --git a/tests/sys_resource_test.cpp b/tests/sys_resource_test.cpp index 8cefc65..0b6b6ef 100644 --- a/tests/sys_resource_test.cpp +++ b/tests/sys_resource_test.cpp @@ -33,7 +33,8 @@ class SysResourceTest : public ::testing::Test { virtual void SetUp() { ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_)); ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_)); - ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_)); + ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, nullptr, &pr_l32_)); + ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, nullptr, &pr_l64_)); } void CheckResourceLimits(); @@ -41,21 +42,28 @@ class SysResourceTest : public ::testing::Test { protected: rlimit l32_; rlimit64 l64_; + rlimit pr_l32_; rlimit64 pr_l64_; }; void SysResourceTest::CheckResourceLimits() { ASSERT_EQ(0, getrlimit(RLIMIT_CORE, &l32_)); ASSERT_EQ(0, getrlimit64(RLIMIT_CORE, &l64_)); - ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, NULL, &pr_l64_)); + ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, nullptr, &pr_l32_)); + ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, nullptr, &pr_l64_)); + + ASSERT_EQ(l32_.rlim_cur, pr_l32_.rlim_cur); ASSERT_EQ(l64_.rlim_cur, pr_l64_.rlim_cur); + if (l64_.rlim_cur == RLIM64_INFINITY) { ASSERT_EQ(RLIM_INFINITY, l32_.rlim_cur); } else { ASSERT_EQ(l64_.rlim_cur, l32_.rlim_cur); } + ASSERT_EQ(l32_.rlim_max, pr_l32_.rlim_max); ASSERT_EQ(l64_.rlim_max, pr_l64_.rlim_max); + if (l64_.rlim_max == RLIM64_INFINITY) { ASSERT_EQ(RLIM_INFINITY, l32_.rlim_max); } else { @@ -88,13 +96,16 @@ TEST_F(SysResourceTest, setrlimit64) { ASSERT_EQ(456U, l64_.rlim_cur); } +TEST_F(SysResourceTest, prlimit) { + pr_l32_.rlim_cur = pr_l32_.rlim_max; + ASSERT_EQ(0, prlimit(0, RLIMIT_CORE, &pr_l32_, nullptr)); + CheckResourceLimits(); + ASSERT_EQ(pr_l32_.rlim_max, pr_l32_.rlim_cur); +} + TEST_F(SysResourceTest, prlimit64) { pr_l64_.rlim_cur = pr_l64_.rlim_max; - ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &pr_l64_, NULL)); + ASSERT_EQ(0, prlimit64(0, RLIMIT_CORE, &pr_l64_, nullptr)); CheckResourceLimits(); ASSERT_EQ(pr_l64_.rlim_max, pr_l64_.rlim_cur); } - -TEST_F(SysResourceTest, prlimit) { - // prlimit is prlimit64 on LP64 and unimplemented on 32-bit. So we only test prlimit64. -} |