forked from Bananymous/banan-os
				
			DynamicLoader: Add support for LD_LIBRARY_PATH
Also fix a bug with dlopen with TLS
This commit is contained in:
		
							parent
							
								
									c1978f9133
								
							
						
					
					
						commit
						7831c74e8c
					
				|  | @ -195,6 +195,8 @@ struct LoadedElf | ||||||
| static LoadedElf s_loaded_files[128]; | static LoadedElf s_loaded_files[128]; | ||||||
| static size_t s_loaded_file_count = 0; | static size_t s_loaded_file_count = 0; | ||||||
| 
 | 
 | ||||||
|  | static const char* s_ld_library_path = nullptr; | ||||||
|  | 
 | ||||||
| constexpr uintptr_t SYM_NOT_FOUND = -1; | constexpr uintptr_t SYM_NOT_FOUND = -1; | ||||||
| 
 | 
 | ||||||
| static uint32_t elf_hash(const char* name) | static uint32_t elf_hash(const char* name) | ||||||
|  | @ -717,16 +719,15 @@ uintptr_t resolve_symbol(const LoadedElf& elf, uintptr_t plt_entry) | ||||||
| 
 | 
 | ||||||
| static LoadedElf& load_elf(const char* path, int fd); | static LoadedElf& load_elf(const char* path, int fd); | ||||||
| 
 | 
 | ||||||
| static bool find_library(const char* library_name, char out[PATH_MAX]) | static bool check_library(const char* library_dir, const char* library_name, char out[PATH_MAX]) | ||||||
| { | { | ||||||
| 	const char* library_dir = "/usr/lib/"; |  | ||||||
| 
 |  | ||||||
| 	char path_buffer[PATH_MAX]; | 	char path_buffer[PATH_MAX]; | ||||||
| 	char* path_ptr = path_buffer; | 	char* path_ptr = path_buffer; | ||||||
| 
 | 
 | ||||||
| 	if (library_name[0] != '/') | 	if (library_name[0] != '/') | ||||||
| 		for (size_t i = 0; library_dir[i]; i++) | 		for (size_t i = 0; library_dir[i]; i++) | ||||||
| 			*path_ptr++ = library_dir[i]; | 			*path_ptr++ = library_dir[i]; | ||||||
|  | 	*path_ptr++ = '/'; | ||||||
| 	for (size_t i = 0; library_name[i]; i++) | 	for (size_t i = 0; library_name[i]; i++) | ||||||
| 		*path_ptr++ = library_name[i]; | 		*path_ptr++ = library_name[i]; | ||||||
| 	*path_ptr = '\0'; | 	*path_ptr = '\0'; | ||||||
|  | @ -734,6 +735,15 @@ static bool find_library(const char* library_name, char out[PATH_MAX]) | ||||||
| 	return syscall(SYS_REALPATH, path_buffer, out) >= 0; | 	return syscall(SYS_REALPATH, path_buffer, out) >= 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool find_library(const char* library_name, char out[PATH_MAX]) | ||||||
|  | { | ||||||
|  | 	if (s_ld_library_path && check_library(s_ld_library_path, library_name, out)) | ||||||
|  | 		return true; | ||||||
|  | 	if (check_library("/usr/lib", library_name, out)) | ||||||
|  | 		return true; | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void handle_dynamic(LoadedElf& elf) | static void handle_dynamic(LoadedElf& elf) | ||||||
| { | { | ||||||
| 	uintptr_t pltgot = 0; | 	uintptr_t pltgot = 0; | ||||||
|  | @ -798,7 +808,10 @@ static void handle_dynamic(LoadedElf& elf) | ||||||
| 
 | 
 | ||||||
| 		char path_buffer[PATH_MAX]; | 		char path_buffer[PATH_MAX]; | ||||||
| 		if (!find_library(library_name, path_buffer)) | 		if (!find_library(library_name, path_buffer)) | ||||||
| 			print_error_and_exit("could not open shared object", 0); | 		{ | ||||||
|  | 			print(STDERR_FILENO, "could not open shared object: "); | ||||||
|  | 			print_error_and_exit(library_name, 0); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		const auto& loaded_elf = load_elf(path_buffer, -1); | 		const auto& loaded_elf = load_elf(path_buffer, -1); | ||||||
| 		dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf); | 		dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf); | ||||||
|  | @ -1346,16 +1359,21 @@ void* __dlopen(const char* file, int mode) | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	const size_t old_loaded_count = s_loaded_file_count; | ||||||
|  | 
 | ||||||
| 	init_random(); | 	init_random(); | ||||||
| 	auto& elf = load_elf(path_buffer, -1); | 	auto& elf = load_elf(path_buffer, -1); | ||||||
| 	fini_random(); | 	fini_random(); | ||||||
| 
 | 
 | ||||||
| 	if (!elf.is_relocating && !elf.is_calling_init) | 	if (!elf.is_relocating && !elf.is_calling_init) | ||||||
| 	{ | 	{ | ||||||
| 		if (elf.tls_header.p_type == PT_TLS) | 		for (size_t i = old_loaded_count + 1; i < s_loaded_file_count; i++) | ||||||
| 		{ | 		{ | ||||||
| 			s_dlerror_string = "TODO: __dlopen with TLS"; | 			if (s_loaded_files[i].tls_header.p_type == PT_TLS) | ||||||
| 			return nullptr; | 			{ | ||||||
|  | 				s_dlerror_string = "TODO: __dlopen with TLS"; | ||||||
|  | 				return nullptr; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		relocate_elf(elf, lazy); | 		relocate_elf(elf, lazy); | ||||||
|  | @ -1399,10 +1417,23 @@ static LibELF::AuxiliaryVector* find_auxv(char** envp) | ||||||
| 	return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1); | 	return reinterpret_cast<LibELF::AuxiliaryVector*>(null_env + 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool starts_with(const char* string, const char* comp) | ||||||
|  | { | ||||||
|  | 	size_t i = 0; | ||||||
|  | 	for (; string[i] && comp[i]; i++) | ||||||
|  | 		if (string[i] != comp[i]) | ||||||
|  | 			return false; | ||||||
|  | 	return comp[i] == '\0'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| extern "C" | extern "C" | ||||||
| __attribute__((used)) | __attribute__((used)) | ||||||
| uintptr_t _entry(int argc, char* argv[], char* envp[]) | uintptr_t _entry(int argc, char* argv[], char* envp[]) | ||||||
| { | { | ||||||
|  | 	for (size_t i = 0; envp[i]; i++) | ||||||
|  | 		if (starts_with(envp[i], "LD_LIBRARY_PATH=")) | ||||||
|  | 			s_ld_library_path = envp[i] + 16; | ||||||
|  | 
 | ||||||
| 	int execfd = -1; | 	int execfd = -1; | ||||||
| 	if (auto* auxv = find_auxv(envp)) | 	if (auto* auxv = find_auxv(envp)) | ||||||
| 		for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++) | 		for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue