Make dt_runpath work for libraries opened from apk
This patch also fixes realpath for libraries opened directly from apks. Bug: http://b/21960914 Bug: http://b/21961857 Change-Id: I35ade661c87f1d448191f385811f6e9fd3cacf11
This commit is contained in:
parent
748421beef
commit
a1feb117e4
@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \
|
|||||||
linker_libc_support.c \
|
linker_libc_support.c \
|
||||||
linker_memory.cpp \
|
linker_memory.cpp \
|
||||||
linker_phdr.cpp \
|
linker_phdr.cpp \
|
||||||
|
linker_utils.cpp \
|
||||||
rt.cpp \
|
rt.cpp \
|
||||||
|
|
||||||
LOCAL_SRC_FILES_arm := arch/arm/begin.S
|
LOCAL_SRC_FILES_arm := arch/arm/begin.S
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "linker_phdr.h"
|
#include "linker_phdr.h"
|
||||||
#include "linker_relocs.h"
|
#include "linker_relocs.h"
|
||||||
#include "linker_reloc_iterators.h"
|
#include "linker_reloc_iterators.h"
|
||||||
|
#include "linker_utils.h"
|
||||||
|
|
||||||
#include "base/strings.h"
|
#include "base/strings.h"
|
||||||
#include "ziparchive/zip_archive.h"
|
#include "ziparchive/zip_archive.h"
|
||||||
@ -360,13 +361,13 @@ static void parse_LD_PRELOAD(const char* path) {
|
|||||||
|
|
||||||
static bool realpath_fd(int fd, std::string* realpath) {
|
static bool realpath_fd(int fd, std::string* realpath) {
|
||||||
std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
|
std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
|
||||||
snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
|
__libc_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
|
||||||
if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
|
if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
|
||||||
PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
|
PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*realpath = std::string(&buf[0]);
|
*realpath = &buf[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,15 +1166,21 @@ ZipArchiveCache::~ZipArchiveCache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
|
static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
|
||||||
const char* const path,
|
const char* const input_path,
|
||||||
off64_t* file_offset) {
|
off64_t* file_offset, std::string* realpath) {
|
||||||
TRACE("Trying zip file open from path '%s'", path);
|
std::string normalized_path;
|
||||||
|
if (!normalize_path(input_path, &normalized_path)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* const path = normalized_path.c_str();
|
||||||
|
TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path);
|
||||||
|
|
||||||
// Treat an '!/' separator inside a path as the separator between the name
|
// Treat an '!/' separator inside a path as the separator between the name
|
||||||
// of the zip file on disk and the subdirectory to search within it.
|
// of the zip file on disk and the subdirectory to search within it.
|
||||||
// For example, if path is "foo.zip!/bar/bas/x.so", then we search for
|
// For example, if path is "foo.zip!/bar/bas/x.so", then we search for
|
||||||
// "bar/bas/x.so" within "foo.zip".
|
// "bar/bas/x.so" within "foo.zip".
|
||||||
const char* separator = strstr(path, kZipFileSeparator);
|
const char* const separator = strstr(path, kZipFileSeparator);
|
||||||
if (separator == nullptr) {
|
if (separator == nullptr) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1215,6 +1222,15 @@ static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*file_offset = entry.offset;
|
*file_offset = entry.offset;
|
||||||
|
|
||||||
|
if (realpath_fd(fd, realpath)) {
|
||||||
|
*realpath += separator;
|
||||||
|
} else {
|
||||||
|
PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
|
||||||
|
normalized_path.c_str());
|
||||||
|
*realpath = normalized_path;
|
||||||
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,7 +1244,7 @@ static bool format_path(char* buf, size_t buf_size, const char* path, const char
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_library_on_default_path(const char* name, off64_t* file_offset) {
|
static int open_library_on_default_path(const char* name, off64_t* file_offset, std::string* realpath) {
|
||||||
for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
|
for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
if (!format_path(buf, sizeof(buf), g_default_ld_paths[i], name)) {
|
if (!format_path(buf, sizeof(buf), g_default_ld_paths[i], name)) {
|
||||||
@ -1238,6 +1254,10 @@ static int open_library_on_default_path(const char* name, off64_t* file_offset)
|
|||||||
int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
|
int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
*file_offset = 0;
|
*file_offset = 0;
|
||||||
|
if (!realpath_fd(fd, realpath)) {
|
||||||
|
PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", buf);
|
||||||
|
*realpath = buf;
|
||||||
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1247,7 +1267,8 @@ static int open_library_on_default_path(const char* name, off64_t* file_offset)
|
|||||||
|
|
||||||
static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
|
static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
|
||||||
const char* name, off64_t* file_offset,
|
const char* name, off64_t* file_offset,
|
||||||
const std::vector<std::string>& paths) {
|
const std::vector<std::string>& paths,
|
||||||
|
std::string* realpath) {
|
||||||
for (const auto& path_str : paths) {
|
for (const auto& path_str : paths) {
|
||||||
char buf[512];
|
char buf[512];
|
||||||
const char* const path = path_str.c_str();
|
const char* const path = path_str.c_str();
|
||||||
@ -1257,13 +1278,17 @@ static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
|
|||||||
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
if (strstr(buf, kZipFileSeparator) != nullptr) {
|
if (strstr(buf, kZipFileSeparator) != nullptr) {
|
||||||
fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset);
|
fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset, realpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
|
fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
*file_offset = 0;
|
*file_offset = 0;
|
||||||
|
if (!realpath_fd(fd, realpath)) {
|
||||||
|
PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.", buf);
|
||||||
|
*realpath = buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,13 +1302,13 @@ static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
|
|||||||
|
|
||||||
static int open_library(ZipArchiveCache* zip_archive_cache,
|
static int open_library(ZipArchiveCache* zip_archive_cache,
|
||||||
const char* name, soinfo *needed_by,
|
const char* name, soinfo *needed_by,
|
||||||
off64_t* file_offset) {
|
off64_t* file_offset, std::string* realpath) {
|
||||||
TRACE("[ opening %s ]", name);
|
TRACE("[ opening %s ]", name);
|
||||||
|
|
||||||
// If the name contains a slash, we should attempt to open it directly and not search the paths.
|
// If the name contains a slash, we should attempt to open it directly and not search the paths.
|
||||||
if (strchr(name, '/') != nullptr) {
|
if (strchr(name, '/') != nullptr) {
|
||||||
if (strstr(name, kZipFileSeparator) != nullptr) {
|
if (strstr(name, kZipFileSeparator) != nullptr) {
|
||||||
int fd = open_library_in_zipfile(zip_archive_cache, name, file_offset);
|
int fd = open_library_in_zipfile(zip_archive_cache, name, file_offset, realpath);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@ -1297,13 +1322,13 @@ static int open_library(ZipArchiveCache* zip_archive_cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
|
// Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
|
||||||
int fd = open_library_on_paths(zip_archive_cache, name, file_offset, g_ld_library_paths);
|
int fd = open_library_on_paths(zip_archive_cache, name, file_offset, g_ld_library_paths, realpath);
|
||||||
if (fd == -1 && needed_by) {
|
if (fd == -1 && needed_by) {
|
||||||
fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath());
|
fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fd = open_library_on_default_path(name, file_offset);
|
fd = open_library_on_default_path(name, file_offset, realpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@ -1336,7 +1361,8 @@ static void for_each_dt_needed(const soinfo* si, F action) {
|
|||||||
static soinfo* load_library(int fd, off64_t file_offset,
|
static soinfo* load_library(int fd, off64_t file_offset,
|
||||||
LoadTaskList& load_tasks,
|
LoadTaskList& load_tasks,
|
||||||
const char* name, int rtld_flags,
|
const char* name, int rtld_flags,
|
||||||
const android_dlextinfo* extinfo) {
|
const android_dlextinfo* extinfo,
|
||||||
|
const std::string& realpath) {
|
||||||
if ((file_offset % PAGE_SIZE) != 0) {
|
if ((file_offset % PAGE_SIZE) != 0) {
|
||||||
DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
|
DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -1378,12 +1404,6 @@ static soinfo* load_library(int fd, off64_t file_offset,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string realpath = name;
|
|
||||||
if (!realpath_fd(fd, &realpath)) {
|
|
||||||
PRINT("warning: unable to get realpath for the library \"%s\". Will use given name.", name);
|
|
||||||
realpath = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the ELF header and load the segments.
|
// Read the ELF header and load the segments.
|
||||||
ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size);
|
ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size);
|
||||||
if (!elf_reader.Load(extinfo)) {
|
if (!elf_reader.Load(extinfo)) {
|
||||||
@ -1416,22 +1436,29 @@ static soinfo* load_library(ZipArchiveCache* zip_archive_cache,
|
|||||||
LoadTaskList& load_tasks, const char* name,
|
LoadTaskList& load_tasks, const char* name,
|
||||||
soinfo* needed_by, int rtld_flags,
|
soinfo* needed_by, int rtld_flags,
|
||||||
const android_dlextinfo* extinfo) {
|
const android_dlextinfo* extinfo) {
|
||||||
|
off64_t file_offset;
|
||||||
|
std::string realpath;
|
||||||
if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
|
if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
|
||||||
off64_t file_offset = 0;
|
file_offset = 0;
|
||||||
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
|
if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
|
||||||
file_offset = extinfo->library_fd_offset;
|
file_offset = extinfo->library_fd_offset;
|
||||||
}
|
}
|
||||||
return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo);
|
|
||||||
|
if (!realpath_fd(extinfo->library_fd, &realpath)) {
|
||||||
|
PRINT("warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
|
||||||
|
"Will use given name.", name);
|
||||||
|
realpath = name;
|
||||||
|
}
|
||||||
|
return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo, realpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the file.
|
// Open the file.
|
||||||
off64_t file_offset;
|
int fd = open_library(zip_archive_cache, name, needed_by, &file_offset, &realpath);
|
||||||
int fd = open_library(zip_archive_cache, name, needed_by, &file_offset);
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
DL_ERR("library \"%s\" not found", name);
|
DL_ERR("library \"%s\" not found", name);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo);
|
soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo, realpath);
|
||||||
close(fd);
|
close(fd);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
63
linker/linker_utils.cpp
Normal file
63
linker/linker_utils.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 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 "linker_utils.h"
|
||||||
|
#include "linker_debug.h"
|
||||||
|
|
||||||
|
bool normalize_path(const char* path, std::string* normalized_path) {
|
||||||
|
// Input should be an absolute path
|
||||||
|
if (path[0] != '/') {
|
||||||
|
PRINT("canonize_path - invalid input: '%s', the input path should be absolute", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = strlen(path) + 1;
|
||||||
|
char buf[len];
|
||||||
|
|
||||||
|
const char* in_ptr = path;
|
||||||
|
char* out_ptr = buf;
|
||||||
|
|
||||||
|
while (*in_ptr != 0) {
|
||||||
|
if (*in_ptr == '/') {
|
||||||
|
char c1 = in_ptr[1];
|
||||||
|
if (c1 == '.') {
|
||||||
|
char c2 = in_ptr[2];
|
||||||
|
if (c2 == '/') {
|
||||||
|
in_ptr += 2;
|
||||||
|
continue;
|
||||||
|
} else if (c2 == '.' && (in_ptr[3] == '/' || in_ptr[3] == 0)) {
|
||||||
|
in_ptr += 3;
|
||||||
|
while (out_ptr > buf && *--out_ptr != '/') {
|
||||||
|
}
|
||||||
|
if (in_ptr[0] == 0) {
|
||||||
|
// retain '/'
|
||||||
|
out_ptr++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (c1 == '/') {
|
||||||
|
++in_ptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out_ptr++ = *in_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_ptr = 0;
|
||||||
|
*normalized_path = buf;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
23
linker/linker_utils.h
Normal file
23
linker/linker_utils.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 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 __LINKER_UTILS_H
|
||||||
|
#define __LINKER_UTILS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
bool normalize_path(const char* path, std::string* normalized_path);
|
||||||
|
|
||||||
|
#endif
|
@ -27,11 +27,14 @@ LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror
|
|||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
|
linker_globals.cpp \
|
||||||
linked_list_test.cpp \
|
linked_list_test.cpp \
|
||||||
linker_block_allocator_test.cpp \
|
linker_block_allocator_test.cpp \
|
||||||
../linker_block_allocator.cpp \
|
../linker_block_allocator.cpp \
|
||||||
linker_memory_allocator_test.cpp \
|
linker_memory_allocator_test.cpp \
|
||||||
../linker_allocator.cpp
|
../linker_allocator.cpp \
|
||||||
|
linker_utils_test.cpp \
|
||||||
|
../linker_utils.cpp
|
||||||
|
|
||||||
# for __libc_fatal
|
# for __libc_fatal
|
||||||
LOCAL_SRC_FILES += ../../libc/bionic/libc_logging.cpp
|
LOCAL_SRC_FILES += ../../libc/bionic/libc_logging.cpp
|
||||||
|
19
linker/tests/linker_globals.cpp
Normal file
19
linker/tests/linker_globals.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// To enable logging
|
||||||
|
int g_ld_debug_verbosity = 0;
|
||||||
|
|
45
linker/tests/linker_utils_test.cpp
Normal file
45
linker/tests/linker_utils_test.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "../linker_utils.h"
|
||||||
|
|
||||||
|
TEST(linker_utils, normalize_path_smoke) {
|
||||||
|
std::string output;
|
||||||
|
ASSERT_TRUE(normalize_path("/../root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
|
||||||
|
ASSERT_EQ("/root/dir/dir2/zipfile!/dir/afile", output);
|
||||||
|
|
||||||
|
ASSERT_TRUE(normalize_path("/../root///dir/.///dir2/somedir/.../zipfile!/.dir/dir9//..///afile", &output));
|
||||||
|
ASSERT_EQ("/root/dir/dir2/somedir/.../zipfile!/.dir/afile", output);
|
||||||
|
|
||||||
|
ASSERT_TRUE(normalize_path("/root/..", &output));
|
||||||
|
ASSERT_EQ("/", output);
|
||||||
|
|
||||||
|
ASSERT_TRUE(normalize_path("/root/notroot/..", &output));
|
||||||
|
ASSERT_EQ("/root/", output);
|
||||||
|
|
||||||
|
ASSERT_TRUE(normalize_path("/a/../../b", &output));
|
||||||
|
ASSERT_EQ("/b", output);
|
||||||
|
|
||||||
|
output = "unchanged";
|
||||||
|
ASSERT_FALSE(normalize_path("root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
|
||||||
|
ASSERT_EQ("unchanged", output);
|
||||||
|
}
|
@ -59,6 +59,7 @@ typedef int (*fn)(void);
|
|||||||
|
|
||||||
#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd/libdlext_test_fd.so"
|
#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd/libdlext_test_fd.so"
|
||||||
#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_zip/libdlext_test_zip_zipaligned.zip"
|
#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_zip/libdlext_test_zip_zipaligned.zip"
|
||||||
|
#define LIBZIPPATH_WITH_RUNPATH LIBPATH_PREFIX "libdlext_test_runpath_zip/libdlext_test_runpath_zip_zipaligned.zip"
|
||||||
|
|
||||||
#define LIBZIP_OFFSET PAGE_SIZE
|
#define LIBZIP_OFFSET PAGE_SIZE
|
||||||
|
|
||||||
@ -228,6 +229,24 @@ TEST(dlfcn, dlopen_from_zip_absolute_path) {
|
|||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(dlfcn, dlopen_from_zip_with_dt_runpath) {
|
||||||
|
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH_WITH_RUNPATH;
|
||||||
|
|
||||||
|
void* handle = dlopen((lib_path + "!/libdir/libtest_dt_runpath_d_zip.so").c_str(), RTLD_NOW);
|
||||||
|
|
||||||
|
ASSERT_TRUE(handle != nullptr) << dlerror();
|
||||||
|
|
||||||
|
typedef void *(* dlopen_b_fn)();
|
||||||
|
dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
|
||||||
|
ASSERT_TRUE(fn != nullptr) << dlerror();
|
||||||
|
|
||||||
|
void *p = fn();
|
||||||
|
ASSERT_TRUE(p != nullptr) << dlerror();
|
||||||
|
|
||||||
|
dlclose(p);
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(dlfcn, dlopen_from_zip_ld_library_path) {
|
TEST(dlfcn, dlopen_from_zip_ld_library_path) {
|
||||||
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH + "!/libdir";
|
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH + "!/libdir";
|
||||||
|
|
||||||
|
@ -34,8 +34,49 @@ my_shared_libs := \
|
|||||||
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libatest_simple_zip.so
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libatest_simple_zip.so
|
||||||
|
|
||||||
$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(ZIPALIGN)
|
$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(ZIPALIGN)
|
||||||
@echo "Zipalign $(PRIVATE_ALIGNMENT): $@"
|
@echo "Zipalign: $@"
|
||||||
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir
|
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir
|
||||||
$(hide) cp $^ $(dir $@)/libdir
|
$(hide) cp $^ $(dir $@)/libdir
|
||||||
$(hide) (cd $(dir $@) && touch empty_file.txt && zip -qrD0 $(notdir $@).unaligned empty_file.txt libdir/*.so)
|
$(hide) (cd $(dir $@) && touch empty_file.txt && zip -qrD0 $(notdir $@).unaligned empty_file.txt libdir/*.so)
|
||||||
$(hide) $(ZIPALIGN) -p 4 $@.unaligned $@
|
$(hide) $(ZIPALIGN) -p 4 $@.unaligned $@
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
|
||||||
|
LOCAL_MODULE := libdlext_test_runpath_zip_zipaligned
|
||||||
|
LOCAL_MODULE_SUFFIX := .zip
|
||||||
|
LOCAL_MODULE_TAGS := tests
|
||||||
|
LOCAL_MODULE_PATH := $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/libdlext_test_runpath_zip
|
||||||
|
LOCAL_2ND_ARCH_VAR_PREFIX := $(bionic_2nd_arch_prefix)
|
||||||
|
|
||||||
|
include $(BUILD_SYSTEM)/base_rules.mk
|
||||||
|
my_shared_libs := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_d_zip.so \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_b.so \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_a.so \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_c.so \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_x.so
|
||||||
|
|
||||||
|
|
||||||
|
$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_D := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_d_zip.so
|
||||||
|
$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_A := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_a.so
|
||||||
|
$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_B := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_b.so
|
||||||
|
$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_C := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_c.so
|
||||||
|
$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_X := \
|
||||||
|
$($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_x.so
|
||||||
|
$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(ZIPALIGN)
|
||||||
|
@echo "Zipalign: $@"
|
||||||
|
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir && \
|
||||||
|
mkdir -p $(dir $@)/libdir/dt_runpath_a && mkdir -p $(dir $@)/libdir/dt_runpath_b_c_x
|
||||||
|
$(hide) cp $(PRIVATE_LIB_D) $(dir $@)/libdir
|
||||||
|
$(hide) cp $(PRIVATE_LIB_A) $(dir $@)/libdir/dt_runpath_a
|
||||||
|
$(hide) cp $(PRIVATE_LIB_B) $(dir $@)/libdir/dt_runpath_b_c_x
|
||||||
|
$(hide) cp $(PRIVATE_LIB_C) $(dir $@)/libdir/dt_runpath_b_c_x
|
||||||
|
$(hide) cp $(PRIVATE_LIB_X) $(dir $@)/libdir/dt_runpath_b_c_x
|
||||||
|
$(hide) (cd $(dir $@) && touch empty_file.txt && zip -qrD0 $(notdir $@).unaligned empty_file.txt libdir)
|
||||||
|
$(hide) $(ZIPALIGN) -p 4 $@.unaligned $@
|
||||||
|
|
||||||
|
@ -18,6 +18,19 @@
|
|||||||
# Libraries used by dt_runpath tests.
|
# Libraries used by dt_runpath tests.
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dependencies
|
||||||
|
#
|
||||||
|
# libtest_dt_runpath_d.so runpath: ${ORIGIN}/dt_runpath_b_c_x
|
||||||
|
# |-> dt_runpath_b_c_x/libtest_dt_runpath_b.so runpath: ${ORIGIN}/../dt_runpath_a
|
||||||
|
# | |-> dt_runpath_a/libtest_dt_runpath_a.so
|
||||||
|
# |-> dt_runpath_b_c_x/libtest_dt_runpath_c.so runpath: ${ORIGIN}/invalid_dt_runpath
|
||||||
|
# | |-> libtest_dt_runpath_a.so (soname)
|
||||||
|
#
|
||||||
|
# This one is used to test dlopen
|
||||||
|
# dt_runpath_b_c_x/libtest_dt_runpath_x.so
|
||||||
|
#
|
||||||
|
|
||||||
# A leaf library in a non-standard directory.
|
# A leaf library in a non-standard directory.
|
||||||
libtest_dt_runpath_a_src_files := \
|
libtest_dt_runpath_a_src_files := \
|
||||||
empty.cpp
|
empty.cpp
|
||||||
@ -57,6 +70,20 @@ libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--e
|
|||||||
module := libtest_dt_runpath_d
|
module := libtest_dt_runpath_d
|
||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
|
include $(LOCAL_PATH)/Android.build.testlib.mk
|
||||||
|
|
||||||
|
# D version for open-from-zip test with runpath
|
||||||
|
libtest_dt_runpath_d_zip_src_files := \
|
||||||
|
dlopen_b.cpp
|
||||||
|
|
||||||
|
libtest_dt_runpath_d_zip_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
|
||||||
|
libtest_dt_runpath_d_zip_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
|
||||||
|
libtest_dt_runpath_d_zip_install_to_out_data := true
|
||||||
|
module := libtest_dt_runpath_d_zip
|
||||||
|
module_tag := optional
|
||||||
|
build_type := target
|
||||||
|
build_target := SHARED_LIBRARY
|
||||||
|
include $(TEST_PATH)/Android.build.mk
|
||||||
|
|
||||||
|
|
||||||
# A leaf library in a directory library D has DT_RUNPATH for.
|
# A leaf library in a directory library D has DT_RUNPATH for.
|
||||||
libtest_dt_runpath_x_src_files := \
|
libtest_dt_runpath_x_src_files := \
|
||||||
empty.cpp
|
empty.cpp
|
||||||
@ -64,3 +91,4 @@ libtest_dt_runpath_x_src_files := \
|
|||||||
libtest_dt_runpath_x_relative_path := dt_runpath_b_c_x
|
libtest_dt_runpath_x_relative_path := dt_runpath_b_c_x
|
||||||
module := libtest_dt_runpath_x
|
module := libtest_dt_runpath_x
|
||||||
include $(LOCAL_PATH)/Android.build.testlib.mk
|
include $(LOCAL_PATH)/Android.build.testlib.mk
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ extern "C" void *dlopen_b() {
|
|||||||
// remove once it is fixed
|
// remove once it is fixed
|
||||||
static int dummy = 0;
|
static int dummy = 0;
|
||||||
|
|
||||||
// This is not supposed to succeed. Even though this library has DT_RUNPATH
|
// This is supposed to succeed because this library has DT_RUNPATH
|
||||||
// for libtest_dt_runpath_x.so, it is not taked into account for dlopen.
|
// for libtest_dt_runpath_x.so which should be taken into account
|
||||||
|
// by dlopen.
|
||||||
void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
|
void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
|
||||||
if (handle != nullptr) {
|
if (handle != nullptr) {
|
||||||
dummy++;
|
dummy++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user