am 06b6e3c5: Merge "Look into local group on dlsym with RTLD_DEFAULT"
				
					
				
			* commit '06b6e3c51d38d70c5ca99f3a3f795697031ac27f': Look into local group on dlsym with RTLD_DEFAULT
This commit is contained in:
		@@ -101,16 +101,11 @@ void* dlsym(void* handle, const char* symbol) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  soinfo* found = nullptr;
 | 
					  soinfo* found = nullptr;
 | 
				
			||||||
  ElfW(Sym)* sym = nullptr;
 | 
					  ElfW(Sym)* sym = nullptr;
 | 
				
			||||||
  if (handle == RTLD_DEFAULT) {
 | 
					 | 
				
			||||||
    sym = dlsym_linear_lookup(symbol, &found, nullptr);
 | 
					 | 
				
			||||||
  } else if (handle == RTLD_NEXT) {
 | 
					 | 
				
			||||||
  void* caller_addr = __builtin_return_address(0);
 | 
					  void* caller_addr = __builtin_return_address(0);
 | 
				
			||||||
    soinfo* si = find_containing_library(caller_addr);
 | 
					  soinfo* caller = find_containing_library(caller_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sym = nullptr;
 | 
					  if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
 | 
				
			||||||
    if (si && si->next) {
 | 
					    sym = dlsym_linear_lookup(symbol, &found, caller, handle);
 | 
				
			||||||
      sym = dlsym_linear_lookup(symbol, &found, si->next);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
 | 
					    sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -738,15 +738,21 @@ ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) {
 | 
				
			|||||||
   beginning of the global solist. Otherwise the search starts at the
 | 
					   beginning of the global solist. Otherwise the search starts at the
 | 
				
			||||||
   specified soinfo (for RTLD_NEXT).
 | 
					   specified soinfo (for RTLD_NEXT).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) {
 | 
					ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle) {
 | 
				
			||||||
  SymbolName symbol_name(name);
 | 
					  SymbolName symbol_name(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (start == nullptr) {
 | 
					  soinfo* start = solist;
 | 
				
			||||||
    start = solist;
 | 
					
 | 
				
			||||||
 | 
					  if (handle == RTLD_NEXT) {
 | 
				
			||||||
 | 
					    if (caller == nullptr || caller->next == nullptr) {
 | 
				
			||||||
 | 
					      return nullptr;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      start = caller->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ElfW(Sym)* s = nullptr;
 | 
					  ElfW(Sym)* s = nullptr;
 | 
				
			||||||
  for (soinfo* si = start; (s == nullptr) && (si != nullptr); si = si->next) {
 | 
					  for (soinfo* si = start; si != nullptr; si = si->next) {
 | 
				
			||||||
    if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0) {
 | 
					    if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0) {
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -758,6 +764,30 @@ ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If not found - look into local_group unless
 | 
				
			||||||
 | 
					  // caller is part of the global group in which
 | 
				
			||||||
 | 
					  // case we already did it.
 | 
				
			||||||
 | 
					  if (s == nullptr && caller != nullptr &&
 | 
				
			||||||
 | 
					      (caller->get_rtld_flags() & RTLD_GLOBAL) == 0) {
 | 
				
			||||||
 | 
					    soinfo* local_group_root = caller->get_local_group_root();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (handle == RTLD_DEFAULT) {
 | 
				
			||||||
 | 
					      start = local_group_root;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (soinfo* si = start; si != nullptr; si = si->next) {
 | 
				
			||||||
 | 
					      if (si->get_local_group_root() != local_group_root) {
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      s = si->find_symbol_by_name(symbol_name);
 | 
				
			||||||
 | 
					      if (s != nullptr) {
 | 
				
			||||||
 | 
					        *found = si;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (s != nullptr) {
 | 
					  if (s != nullptr) {
 | 
				
			||||||
    TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
 | 
					    TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
 | 
				
			||||||
               name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
 | 
					               name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -351,7 +351,7 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 | 
				
			|||||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 | 
					soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 | 
				
			||||||
void do_dlclose(soinfo* si);
 | 
					void do_dlclose(soinfo* si);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
 | 
					ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
 | 
				
			||||||
soinfo* find_containing_library(const void* addr);
 | 
					soinfo* find_containing_library(const void* addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
 | 
					ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,7 +46,7 @@ TEST(dlfcn, ctor_function_call) {
 | 
				
			|||||||
  ASSERT_EQ(17, g_ctor_function_called);
 | 
					  ASSERT_EQ(17, g_ctor_function_called);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlsym_in_self) {
 | 
					TEST(dlfcn, dlsym_in_executable) {
 | 
				
			||||||
  dlerror(); // Clear any pending errors.
 | 
					  dlerror(); // Clear any pending errors.
 | 
				
			||||||
  void* self = dlopen(NULL, RTLD_NOW);
 | 
					  void* self = dlopen(NULL, RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(self != NULL);
 | 
					  ASSERT_TRUE(self != NULL);
 | 
				
			||||||
@@ -64,6 +64,27 @@ TEST(dlfcn, dlsym_in_self) {
 | 
				
			|||||||
  ASSERT_EQ(0, dlclose(self));
 | 
					  ASSERT_EQ(0, dlclose(self));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(dlfcn, dlsym_from_sofile) {
 | 
				
			||||||
 | 
					  void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL);
 | 
				
			||||||
 | 
					  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check that we cant find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
 | 
				
			||||||
 | 
					  void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
 | 
				
			||||||
 | 
					  ASSERT_TRUE(symbol == nullptr);
 | 
				
			||||||
 | 
					  ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  typedef int* (*fn_t)();
 | 
				
			||||||
 | 
					  fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int* ptr = fn();
 | 
				
			||||||
 | 
					  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
				
			||||||
 | 
					  ASSERT_EQ(42, *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dlclose(handle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(dlfcn, dlsym_with_dependencies) {
 | 
					TEST(dlfcn, dlsym_with_dependencies) {
 | 
				
			||||||
  void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
 | 
					  void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
 | 
				
			||||||
  ASSERT_TRUE(handle != NULL);
 | 
					  ASSERT_TRUE(handle != NULL);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -370,6 +370,15 @@ libtest_dlsym_weak_func_src_files := \
 | 
				
			|||||||
module := libtest_dlsym_weak_func
 | 
					module := libtest_dlsym_weak_func
 | 
				
			||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					# Library to check RTLD_LOCAL with dlsym in 'this'
 | 
				
			||||||
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					libtest_dlsym_from_this_src_files := dlsym_from_this.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module := libtest_dlsym_from_this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
# Library with weak undefined function
 | 
					# Library with weak undefined function
 | 
				
			||||||
# -----------------------------------------------------------------------------
 | 
					# -----------------------------------------------------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								tests/libs/dlsym_from_this.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/libs/dlsym_from_this.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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 <dlfcn.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int test_dlsym_symbol = 42;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int* lookup_dlsym_symbol_using_RTLD_DEFAULT() {
 | 
				
			||||||
 | 
					  dlerror();
 | 
				
			||||||
 | 
					  int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol"));
 | 
				
			||||||
 | 
					  // TODO: remove this once b/20049306 is fixed
 | 
				
			||||||
 | 
					  if (result == nullptr) {
 | 
				
			||||||
 | 
					    printf("Cannot find the answer\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user