am 950a435f: Merge "Load library using file handle."
* commit '950a435fc0dffc22a816194af175420176b86908': Load library using file handle.
This commit is contained in:
commit
8551bfb043
@ -49,11 +49,17 @@ enum {
|
|||||||
*/
|
*/
|
||||||
ANDROID_DLEXT_USE_RELRO = 0x8,
|
ANDROID_DLEXT_USE_RELRO = 0x8,
|
||||||
|
|
||||||
|
/* Instruct dlopen to use library_fd instead of opening file by name.
|
||||||
|
* The filename parameter is still used to identify the library.
|
||||||
|
*/
|
||||||
|
ANDROID_DLEXT_USE_LIBRARY_FD = 0x10,
|
||||||
|
|
||||||
/* Mask of valid bits */
|
/* Mask of valid bits */
|
||||||
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
|
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
|
||||||
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
|
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
|
||||||
ANDROID_DLEXT_WRITE_RELRO |
|
ANDROID_DLEXT_WRITE_RELRO |
|
||||||
ANDROID_DLEXT_USE_RELRO,
|
ANDROID_DLEXT_USE_RELRO |
|
||||||
|
ANDROID_DLEXT_USE_LIBRARY_FD,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -61,6 +67,7 @@ typedef struct {
|
|||||||
void* reserved_addr;
|
void* reserved_addr;
|
||||||
size_t reserved_size;
|
size_t reserved_size;
|
||||||
int relro_fd;
|
int relro_fd;
|
||||||
|
int library_fd;
|
||||||
} android_dlextinfo;
|
} android_dlextinfo;
|
||||||
|
|
||||||
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
|
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
|
||||||
|
59
libc/private/ScopedFd.h
Normal file
59
libc/private/ScopedFd.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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 SCOPED_FD_H
|
||||||
|
#define SCOPED_FD_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "bionic_macros.h"
|
||||||
|
|
||||||
|
// A smart pointer that closes the given fd on going out of scope.
|
||||||
|
// Use this when the fd is incidental to the purpose of your function,
|
||||||
|
// but needs to be cleaned up on exit.
|
||||||
|
class ScopedFd {
|
||||||
|
public:
|
||||||
|
explicit ScopedFd(int fd) : fd(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedFd() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get() const {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int release() __attribute__((warn_unused_result)) {
|
||||||
|
int localFd = fd;
|
||||||
|
fd = -1;
|
||||||
|
return localFd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(int new_fd = -1) {
|
||||||
|
if (fd != -1) {
|
||||||
|
TEMP_FAILURE_RETRY(close(fd));
|
||||||
|
}
|
||||||
|
fd = new_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// Disallow copy and assignment.
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ScopedFd);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCOPED_FD_H
|
@ -42,6 +42,7 @@
|
|||||||
#include "private/bionic_tls.h"
|
#include "private/bionic_tls.h"
|
||||||
#include "private/KernelArgumentBlock.h"
|
#include "private/KernelArgumentBlock.h"
|
||||||
#include "private/ScopedPthreadMutexLocker.h"
|
#include "private/ScopedPthreadMutexLocker.h"
|
||||||
|
#include "private/ScopedFd.h"
|
||||||
|
|
||||||
#include "linker.h"
|
#include "linker.h"
|
||||||
#include "linker_debug.h"
|
#include "linker_debug.h"
|
||||||
@ -696,13 +697,22 @@ static int open_library(const char* name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static soinfo* load_library(const char* name, int dlflags, const android_dlextinfo* extinfo) {
|
static soinfo* load_library(const char* name, int dlflags, const android_dlextinfo* extinfo) {
|
||||||
|
int fd = -1;
|
||||||
|
ScopedFd file_guard(-1);
|
||||||
|
|
||||||
|
if (extinfo != NULL && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
|
||||||
|
fd = extinfo->library_fd;
|
||||||
|
} else {
|
||||||
// Open the file.
|
// Open the file.
|
||||||
int fd = open_library(name);
|
fd = open_library(name);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
DL_ERR("library \"%s\" not found", name);
|
DL_ERR("library \"%s\" not found", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_guard.reset(fd);
|
||||||
|
}
|
||||||
|
|
||||||
ElfReader elf_reader(name, fd);
|
ElfReader elf_reader(name, fd);
|
||||||
|
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
@ -744,7 +754,7 @@ static soinfo* load_library(const char* name, int dlflags, const android_dlextin
|
|||||||
|
|
||||||
// At this point we know that whatever is loaded @ base is a valid ELF
|
// At this point we know that whatever is loaded @ base is a valid ELF
|
||||||
// shared library whose segments are properly mapped in.
|
// shared library whose segments are properly mapped in.
|
||||||
TRACE("[ find_library_internal base=%p size=%zu name='%s' ]",
|
TRACE("[ load_library base=%p size=%zu name='%s' ]",
|
||||||
reinterpret_cast<void*>(si->base), si->size, si->name);
|
reinterpret_cast<void*>(si->base), si->size, si->name);
|
||||||
|
|
||||||
if (!soinfo_link_image(si, extinfo)) {
|
if (!soinfo_link_image(si, extinfo)) {
|
||||||
@ -847,7 +857,7 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extinfo != NULL && ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0)) {
|
if (extinfo != NULL && ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0)) {
|
||||||
DL_ERR("invalid extended flags to android_dlopen_ext: %x", extinfo->flags);
|
DL_ERR("invalid extended flags to android_dlopen_ext: %llx", extinfo->flags);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
protect_data(PROT_READ | PROT_WRITE);
|
protect_data(PROT_READ | PROT_WRITE);
|
||||||
|
@ -127,9 +127,6 @@ ElfReader::ElfReader(const char* name, int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ElfReader::~ElfReader() {
|
ElfReader::~ElfReader() {
|
||||||
if (fd_ != -1) {
|
|
||||||
close(fd_);
|
|
||||||
}
|
|
||||||
if (phdr_mmap_ != NULL) {
|
if (phdr_mmap_ != NULL) {
|
||||||
munmap(phdr_mmap_, phdr_size_);
|
munmap(phdr_mmap_, phdr_size_);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,11 @@ endif
|
|||||||
ifneq ($(findstring LIBRARY, $(build_target)),LIBRARY)
|
ifneq ($(findstring LIBRARY, $(build_target)),LIBRARY)
|
||||||
LOCAL_MODULE_STEM_32 := $(module)32
|
LOCAL_MODULE_STEM_32 := $(module)32
|
||||||
LOCAL_MODULE_STEM_64 := $(module)64
|
LOCAL_MODULE_STEM_64 := $(module)64
|
||||||
|
else
|
||||||
|
ifeq ($($(module)_install_to_out_data),true)
|
||||||
|
LOCAL_MODULE_PATH_32 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
|
||||||
|
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)64/$(module)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LOCAL_CLANG := $($(module)_clang_$(build_type))
|
LOCAL_CLANG := $($(module)_clang_$(build_type))
|
||||||
|
@ -45,6 +45,11 @@ typedef int (*fn)(void);
|
|||||||
#define LIBNAME_NORELRO "libdlext_test_norelro.so"
|
#define LIBNAME_NORELRO "libdlext_test_norelro.so"
|
||||||
#define LIBSIZE 1024*1024 // how much address space to reserve for it
|
#define LIBSIZE 1024*1024 // how much address space to reserve for it
|
||||||
|
|
||||||
|
#if defined(__LP64__)
|
||||||
|
#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so"
|
||||||
|
#else
|
||||||
|
#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so"
|
||||||
|
#endif
|
||||||
|
|
||||||
class DlExtTest : public ::testing::Test {
|
class DlExtTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
@ -83,6 +88,23 @@ TEST_F(DlExtTest, ExtInfoNoFlags) {
|
|||||||
EXPECT_EQ(4, f());
|
EXPECT_EQ(4, f());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DlExtTest, ExtInfoUseFd) {
|
||||||
|
const char* android_data = getenv("ANDROID_DATA");
|
||||||
|
ASSERT_TRUE(android_data != NULL);
|
||||||
|
char lib_path[PATH_MAX];
|
||||||
|
snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
|
||||||
|
|
||||||
|
android_dlextinfo extinfo;
|
||||||
|
extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
|
||||||
|
extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC));
|
||||||
|
ASSERT_TRUE(extinfo.library_fd != -1);
|
||||||
|
handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo);
|
||||||
|
ASSERT_DL_NOTNULL(handle_);
|
||||||
|
fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
|
||||||
|
ASSERT_DL_NOTNULL(f);
|
||||||
|
EXPECT_EQ(4, f());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DlExtTest, Reserved) {
|
TEST_F(DlExtTest, Reserved) {
|
||||||
void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
|
void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
|
||||||
-1, 0);
|
-1, 0);
|
||||||
|
@ -77,6 +77,19 @@ build_type := target
|
|||||||
build_target := SHARED_LIBRARY
|
build_target := SHARED_LIBRARY
|
||||||
include $(TEST_PATH)/Android.build.mk
|
include $(TEST_PATH)/Android.build.mk
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Library used by dlext tests - different name non-default location
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
libdlext_test_fd_src_files := \
|
||||||
|
dlext_test_library.cpp \
|
||||||
|
|
||||||
|
libdlext_test_fd_install_to_out_data := true
|
||||||
|
module := libdlext_test_fd
|
||||||
|
module_tag := optional
|
||||||
|
build_type := target
|
||||||
|
build_target := SHARED_LIBRARY
|
||||||
|
include $(TEST_PATH)/Android.build.mk
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Library used by dlfcn tests
|
# Library used by dlfcn tests
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user