Add ANDROID_DLEXT_FORCE_LOAD flag
This flag allows to force loading of the library in the case when for some reason multiple ELF files share the same filename (because the already-loaded library has been removed and overwritten, for example). Change-Id: I798d44409ee13d63eaa75d685e99c4d028d2b0c1
This commit is contained in:
parent
ab7c79e22e
commit
9b82136b98
@ -59,16 +59,28 @@ enum {
|
|||||||
/* If opening a library using library_fd read it starting at library_fd_offset.
|
/* If opening a library using library_fd read it starting at library_fd_offset.
|
||||||
* This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set.
|
* This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20,
|
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20,
|
||||||
|
|
||||||
|
/* When set, do not check if the library has already been loaded by file stat(2)s.
|
||||||
|
*
|
||||||
|
* This flag allows forced loading of the library in the case when for some
|
||||||
|
* reason multiple ELF files share the same filename (because the already-loaded
|
||||||
|
* library has been removed and overwritten, for example).
|
||||||
|
*
|
||||||
|
* Note that if the library has the same dt_soname as an old one and some other
|
||||||
|
* library has the soname in DT_NEEDED list, the first one will be used to resolve any
|
||||||
|
* dependencies.
|
||||||
|
*/
|
||||||
|
ANDROID_DLEXT_FORCE_LOAD = 0x40,
|
||||||
|
|
||||||
/* 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 |
|
ANDROID_DLEXT_USE_LIBRARY_FD |
|
||||||
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET,
|
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
|
||||||
|
ANDROID_DLEXT_FORCE_LOAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -1014,16 +1014,18 @@ static soinfo* load_library(LoadTaskList& load_tasks,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for symlink and other situations where
|
// Check for symlink and other situations where
|
||||||
// file can have different names.
|
// file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
|
||||||
for (soinfo* si = solist; si != nullptr; si = si->next) {
|
if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
|
||||||
if (si->get_st_dev() != 0 &&
|
for (soinfo* si = solist; si != nullptr; si = si->next) {
|
||||||
si->get_st_ino() != 0 &&
|
if (si->get_st_dev() != 0 &&
|
||||||
si->get_st_dev() == file_stat.st_dev &&
|
si->get_st_ino() != 0 &&
|
||||||
si->get_st_ino() == file_stat.st_ino &&
|
si->get_st_dev() == file_stat.st_dev &&
|
||||||
si->get_file_offset() == file_offset) {
|
si->get_st_ino() == file_stat.st_ino &&
|
||||||
TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
|
si->get_file_offset() == file_offset) {
|
||||||
"will return existing soinfo", name, si->name);
|
TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
|
||||||
return si;
|
"will return existing soinfo", name, si->name);
|
||||||
|
return si;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +173,40 @@ TEST_F(DlExtTest, ExtInfoUseOffsetWihtoutFd) {
|
|||||||
ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
|
ASSERT_STREQ("dlopen failed: invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x20", dlerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(dlext, android_dlopen_ext_force_load_smoke) {
|
||||||
|
// 1. Open actual file
|
||||||
|
void* handle = dlopen("libdlext_test.so", RTLD_NOW);
|
||||||
|
ASSERT_DL_NOTNULL(handle);
|
||||||
|
// 2. Open link with force_load flag set
|
||||||
|
android_dlextinfo extinfo;
|
||||||
|
extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
|
||||||
|
void* handle2 = android_dlopen_ext("libdlext_test_v2.so", RTLD_NOW, &extinfo);
|
||||||
|
ASSERT_DL_NOTNULL(handle2);
|
||||||
|
ASSERT_TRUE(handle != handle2);
|
||||||
|
|
||||||
|
dlclose(handle2);
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
|
||||||
|
// Check if soname lookup still returns already loaded library
|
||||||
|
// when ANDROID_DLEXT_FORCE_LOAD flag is specified.
|
||||||
|
void* handle = dlopen("libdlext_test_v2.so", RTLD_NOW);
|
||||||
|
ASSERT_DL_NOTNULL(handle);
|
||||||
|
|
||||||
|
android_dlextinfo extinfo;
|
||||||
|
extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
|
||||||
|
|
||||||
|
// Note that 'libdlext_test.so' is dt_soname for libdlext_test_v2.so
|
||||||
|
void* handle2 = android_dlopen_ext("libdlext_test.so", RTLD_NOW, &extinfo);
|
||||||
|
|
||||||
|
ASSERT_DL_NOTNULL(handle2);
|
||||||
|
ASSERT_TRUE(handle == handle2);
|
||||||
|
|
||||||
|
dlclose(handle2);
|
||||||
|
dlclose(handle);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(dlfcn, dlopen_from_zip_absolute_path) {
|
TEST(dlfcn, dlopen_from_zip_absolute_path) {
|
||||||
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH;
|
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user