Replace fixed arrays with vectors
This effectively removes limit on length and count of LD_LIBRARY_PATH and LD_PRELOAD entries. Change-Id: Ie7ea34a50d99c4018f9dd1a33aaebc4049a7f424
This commit is contained in:
parent
ee4997ecc3
commit
d165f56fb6
1 changed files with 70 additions and 52 deletions
|
@ -40,6 +40,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// Private C library headers.
|
// Private C library headers.
|
||||||
#include "private/bionic_tls.h"
|
#include "private/bionic_tls.h"
|
||||||
|
@ -98,19 +100,10 @@ static const char* const kDefaultLdPaths[] = {
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LDPATH_BUFSIZE (LDPATH_MAX*64)
|
static std::vector<std::string> g_ld_library_paths;
|
||||||
#define LDPATH_MAX 8
|
static std::vector<std::string> g_ld_preload_names;
|
||||||
|
|
||||||
#define LDPRELOAD_BUFSIZE (LDPRELOAD_MAX*64)
|
static std::vector<soinfo*> g_ld_preloads;
|
||||||
#define LDPRELOAD_MAX 8
|
|
||||||
|
|
||||||
static char g_ld_library_paths_buffer[LDPATH_BUFSIZE];
|
|
||||||
static const char* g_ld_library_paths[LDPATH_MAX + 1];
|
|
||||||
|
|
||||||
static char g_ld_preloads_buffer[LDPRELOAD_BUFSIZE];
|
|
||||||
static const char* g_ld_preload_names[LDPRELOAD_MAX + 1];
|
|
||||||
|
|
||||||
static soinfo* g_ld_preloads[LDPRELOAD_MAX + 1];
|
|
||||||
|
|
||||||
__LIBC_HIDDEN__ int g_ld_debug_verbosity;
|
__LIBC_HIDDEN__ int g_ld_debug_verbosity;
|
||||||
|
|
||||||
|
@ -295,39 +288,36 @@ static void soinfo_free(soinfo* si) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_path(const char* path, const char* delimiters,
|
static void parse_path(const char* path, const char* delimiters,
|
||||||
const char** array, char* buf, size_t buf_size, size_t max_count) {
|
std::vector<std::string>* paths) {
|
||||||
if (path == nullptr) {
|
if (path == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = strlcpy(buf, path, buf_size);
|
paths->clear();
|
||||||
|
|
||||||
size_t i = 0;
|
for (const char *p = path; ; ++p) {
|
||||||
char* buf_p = buf;
|
size_t len = strcspn(p, delimiters);
|
||||||
while (i < max_count && (array[i] = strsep(&buf_p, delimiters))) {
|
// skip empty tokens
|
||||||
if (*array[i] != '\0') {
|
if (len == 0) {
|
||||||
++i;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Forget the last path if we had to truncate; this occurs if the 2nd to
|
paths->push_back(std::string(p, len));
|
||||||
// last char isn't '\0' (i.e. wasn't originally a delimiter).
|
p += len;
|
||||||
if (i > 0 && len >= buf_size && buf[buf_size - 2] != '\0') {
|
|
||||||
array[i - 1] = nullptr;
|
if (*p == '\0') {
|
||||||
} else {
|
break;
|
||||||
array[i] = nullptr;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_LD_LIBRARY_PATH(const char* path) {
|
static void parse_LD_LIBRARY_PATH(const char* path) {
|
||||||
parse_path(path, ":", g_ld_library_paths,
|
parse_path(path, ":", &g_ld_library_paths);
|
||||||
g_ld_library_paths_buffer, sizeof(g_ld_library_paths_buffer), LDPATH_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_LD_PRELOAD(const char* path) {
|
static void parse_LD_PRELOAD(const char* path) {
|
||||||
// We have historically supported ':' as well as ' ' in LD_PRELOAD.
|
// We have historically supported ':' as well as ' ' in LD_PRELOAD.
|
||||||
parse_path(path, " :", g_ld_preload_names,
|
parse_path(path, " :", &g_ld_preload_names);
|
||||||
g_ld_preloads_buffer, sizeof(g_ld_preloads_buffer), LDPRELOAD_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
|
@ -883,23 +873,43 @@ static int open_library_in_zipfile(const char* const path,
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_library_on_path(const char* name,
|
static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
|
||||||
const char* const paths[],
|
int n = __libc_format_buffer(buf, buf_size, "%s/%s", path, name);
|
||||||
off64_t* file_offset) {
|
if (n < 0 || n >= static_cast<int>(buf_size)) {
|
||||||
char buf[512];
|
PRINT("Warning: ignoring very long library path: %s/%s", path, name);
|
||||||
int fd = -1;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; paths[i] != nullptr && fd == -1; ++i) {
|
return true;
|
||||||
const char* const path = paths[i];
|
}
|
||||||
int n = __libc_format_buffer(buf, sizeof(buf), "%s/%s", path, name);
|
|
||||||
if (n < 0 || n >= static_cast<int>(sizeof(buf))) {
|
static int open_library_on_default_path(const char* name, off64_t* file_offset) {
|
||||||
PRINT("Warning: ignoring very long library path: %s/%s", path, name);
|
for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) {
|
||||||
return -1;
|
char buf[512];
|
||||||
|
if(!format_path(buf, sizeof(buf), kDefaultLdPaths[i], name)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* separator = strchr(path, '!');
|
int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC));
|
||||||
|
if (fd != -1) {
|
||||||
|
*file_offset = 0;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (separator != nullptr) {
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_library_on_ld_library_path(const char* name, off64_t* file_offset) {
|
||||||
|
for (const auto& path_str : g_ld_library_paths) {
|
||||||
|
char buf[512];
|
||||||
|
const char* const path = path_str.c_str();
|
||||||
|
if (!format_path(buf, sizeof(buf), path, name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
if (strchr(buf, '!') != nullptr) {
|
||||||
fd = open_library_in_zipfile(buf, file_offset);
|
fd = open_library_in_zipfile(buf, file_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,9 +919,13 @@ static int open_library_on_path(const char* name,
|
||||||
*file_offset = 0;
|
*file_offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fd != -1) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_library(const char* name, off64_t* file_offset) {
|
static int open_library(const char* name, off64_t* file_offset) {
|
||||||
|
@ -934,9 +948,9 @@ static int open_library(const char* name, off64_t* file_offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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_path(name, g_ld_library_paths, file_offset);
|
int fd = open_library_on_ld_library_path(name, file_offset);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fd = open_library_on_path(name, kDefaultLdPaths, file_offset);
|
fd = open_library_on_default_path(name, file_offset);
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -1086,8 +1100,9 @@ static soinfo::soinfo_list_t make_global_group() {
|
||||||
return global_group;
|
return global_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_libraries(soinfo* start_with, const char* const library_names[], size_t library_names_count, soinfo* soinfos[],
|
static bool find_libraries(soinfo* start_with, const char* const library_names[],
|
||||||
soinfo* ld_preloads[], size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
|
size_t library_names_count, soinfo* soinfos[], std::vector<soinfo*>* ld_preloads,
|
||||||
|
size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
|
||||||
// Step 0: prepare.
|
// Step 0: prepare.
|
||||||
LoadTaskList load_tasks;
|
LoadTaskList load_tasks;
|
||||||
for (size_t i = 0; i < library_names_count; ++i) {
|
for (size_t i = 0; i < library_names_count; ++i) {
|
||||||
|
@ -1150,7 +1165,7 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
|
||||||
// for this run because they are going to appear in the local
|
// for this run because they are going to appear in the local
|
||||||
// group in the correct order.
|
// group in the correct order.
|
||||||
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
|
si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
|
||||||
ld_preloads[soinfos_count] = si;
|
ld_preloads->push_back(si);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soinfos_count < library_names_count) {
|
if (soinfos_count < library_names_count) {
|
||||||
|
@ -2674,8 +2689,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
|
||||||
StringLinkedList needed_library_name_list;
|
StringLinkedList needed_library_name_list;
|
||||||
size_t needed_libraries_count = 0;
|
size_t needed_libraries_count = 0;
|
||||||
size_t ld_preloads_count = 0;
|
size_t ld_preloads_count = 0;
|
||||||
while (g_ld_preload_names[ld_preloads_count] != nullptr) {
|
|
||||||
needed_library_name_list.push_back(g_ld_preload_names[ld_preloads_count++]);
|
for (const auto& ld_preload_name : g_ld_preload_names) {
|
||||||
|
needed_library_name_list.push_back(ld_preload_name.c_str());
|
||||||
++needed_libraries_count;
|
++needed_libraries_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2689,7 +2705,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
|
||||||
memset(needed_library_names, 0, sizeof(needed_library_names));
|
memset(needed_library_names, 0, sizeof(needed_library_names));
|
||||||
needed_library_name_list.copy_to_array(needed_library_names, needed_libraries_count);
|
needed_library_name_list.copy_to_array(needed_library_names, needed_libraries_count);
|
||||||
|
|
||||||
if (needed_libraries_count > 0 && !find_libraries(si, needed_library_names, needed_libraries_count, nullptr, g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) {
|
if (needed_libraries_count > 0 &&
|
||||||
|
!find_libraries(si, needed_library_names, needed_libraries_count, nullptr,
|
||||||
|
&g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) {
|
||||||
__libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
|
__libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
} else if (needed_libraries_count == 0) {
|
} else if (needed_libraries_count == 0) {
|
||||||
|
|
Loading…
Reference in a new issue