From ce44166c737b6737c3a0820bef10b074a5e36cf8 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Tue, 17 Jun 2014 15:56:38 -0700 Subject: [PATCH] Fix weak function lookups * Linker now correctly resolves function defined with __attribute__((weak)). Bug: https://code.google.com/p/android/issues/detail?id=70206 Change-Id: I82efb905676c25fefb1b11a13f5fecb0f1384657 --- linker/dlfcn.cpp | 2 +- tests/dlfcn_test.cpp | 12 ++++++++++++ tests/libs/Android.mk | 12 ++++++++++++ tests/libs/dlsym_weak_function.cpp | 20 ++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/libs/dlsym_weak_function.cpp diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 6d63ad646..0b60ef5f4 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -118,7 +118,7 @@ void* dlsym(void* handle, const char* symbol) { if (sym != NULL) { unsigned bind = ELF_ST_BIND(sym->st_info); - if (bind == STB_GLOBAL && sym->st_shndx != 0) { + if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) { return reinterpret_cast(sym->st_value + found->load_bias); } diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index 49cbb7d17..8b8918326 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -254,6 +254,18 @@ TEST(dlfcn, rtld_next_known_symbol) { ASSERT_TRUE(addr != NULL); } +TEST(dlfcn, dlsym_weak_func) { + dlerror(); + void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW); + ASSERT_TRUE(handle != NULL); + + int (*weak_func)(); + weak_func = reinterpret_cast(dlsym(handle, "weak_func")); + ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror(); + EXPECT_EQ(42, weak_func()); + dlclose(handle); +} + TEST(dlfcn, dlopen_symlink) { void* handle1 = dlopen("libdlext_test.so", RTLD_NOW); void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW); diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index e75582dbc..67ea562b3 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -103,3 +103,15 @@ include $(TEST_PATH)/Android.build.mk build_type := host include $(TEST_PATH)/Android.build.mk +# ----------------------------------------------------------------------------- +# Library with weak function +# ----------------------------------------------------------------------------- +libtest_dlsym_weak_func_src_files := \ + dlsym_weak_function.cpp + +module := libtest_dlsym_weak_func +build_target := SHARED_LIBRARY +build_type := target +include $(TEST_PATH)/Android.build.mk +build_type := host +include $(TEST_PATH)/Android.build.mk diff --git a/tests/libs/dlsym_weak_function.cpp b/tests/libs/dlsym_weak_function.cpp new file mode 100644 index 000000000..e38f2b886 --- /dev/null +++ b/tests/libs/dlsym_weak_function.cpp @@ -0,0 +1,20 @@ +/* + * 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. + */ + +extern "C" int __attribute__((weak)) weak_func() { + return 42; +} +