1708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov/* 2708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * Copyright (C) 2016 The Android Open Source Project 3708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * 4708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * Licensed under the Apache License, Version 2.0 (the "License"); 5708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * you may not use this file except in compliance with the License. 6708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * You may obtain a copy of the License at 7708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * 8708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * http://www.apache.org/licenses/LICENSE-2.0 9708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * 10708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * Unless required by applicable law or agreed to in writing, software 11708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * distributed under the License is distributed on an "AS IS" BASIS, 12708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * See the License for the specific language governing permissions and 14708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov * limitations under the License. 15708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov */ 16708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 17708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include "dlfcn_symlink_support.h" 18708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 19708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <gtest/gtest.h> 20708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 21708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <dlfcn.h> 22708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <libgen.h> 23708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <link.h> 24708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <unistd.h> 25708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 26708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <android-base/strings.h> 27708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 28708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <algorithm> 29708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <string> 30708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov#include <vector> 31708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 32708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanovstatic const constexpr char* source_file_name = "libdlext_test.so"; 33708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanovstatic const constexpr char* symlink_name_prefix = "libdlext_test_"; 34708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 35708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanovstatic int dl_callback(struct dl_phdr_info *info, size_t /* size */, void *data) { 36708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov // The case when path is not absolute and is equal to source_file_name 37708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov // is disregarded intentionally since in bionic dlpi_name should always 38708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov // be realpath to a shared object. 39708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov const std::string suffix = std::string("/") + source_file_name; 40708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 41708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov // TODO (dimitry): remove this check once fake libdl.so is gone 42708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov if (info->dlpi_name == nullptr) { 43708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov // This is linker imposing as libdl.so - skip it 44708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov return 0; 45708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov } 46708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 476db9af039259aa6682577f369f2bc8eee1ba6fdeElliott Hughes if (android::base::EndsWith(info->dlpi_name, suffix)) { 48708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::string* path = reinterpret_cast<std::string*>(data); 49708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov *path = info->dlpi_name; 50708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov return 1; // found 51708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov } 52708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 53708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov return 0; 54708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov} 55708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 56708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanovvoid create_dlfcn_test_symlink(const char* suffix, std::string* result) { 57708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov void* handle = dlopen(source_file_name, RTLD_NOW); 58708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::string source_file_path; 59708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 60708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 61708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov ASSERT_TRUE(dl_iterate_phdr(dl_callback, &source_file_path) == 1) 62708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov << "dl_phdr_info for \"" << source_file_name << "\" was not found."; 63708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 64708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov dlclose(handle); 65708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::vector<char> buf; 66708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::copy(source_file_path.begin(), source_file_path.end(), std::back_inserter(buf)); 67708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov buf.push_back('\0'); 68708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 69708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::string path_dir = dirname(&buf[0]); 70708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov std::string link_path = path_dir + "/" + symlink_name_prefix + suffix + ".so"; 71708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 72708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov ASSERT_TRUE(symlink(source_file_path.c_str(), link_path.c_str()) == 0) << strerror(errno); 73708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov *result = link_path; 74708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov} 75708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov 76708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanovvoid remove_dlfcn_test_symlink(const std::string& path) { 77708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov ASSERT_TRUE(unlink(path.c_str()) == 0) << strerror(errno); 78708589f5e8244a17d690848eed5f0fbfcce48a26Dimitry Ivanov} 79