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 size_t s_loaded_file_count = 0; | ||||
| 
 | ||||
| static const char* s_ld_library_path = nullptr; | ||||
| 
 | ||||
| constexpr uintptr_t SYM_NOT_FOUND = -1; | ||||
| 
 | ||||
| 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 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_ptr = path_buffer; | ||||
| 
 | ||||
| 	if (library_name[0] != '/') | ||||
| 		for (size_t i = 0; library_dir[i]; i++) | ||||
| 			*path_ptr++ = library_dir[i]; | ||||
| 	*path_ptr++ = '/'; | ||||
| 	for (size_t i = 0; library_name[i]; i++) | ||||
| 		*path_ptr++ = library_name[i]; | ||||
| 	*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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	uintptr_t pltgot = 0; | ||||
|  | @ -798,7 +808,10 @@ static void handle_dynamic(LoadedElf& elf) | |||
| 
 | ||||
| 		char path_buffer[PATH_MAX]; | ||||
| 		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); | ||||
| 		dynamic.d_un.d_ptr = reinterpret_cast<uintptr_t>(&loaded_elf); | ||||
|  | @ -1346,17 +1359,22 @@ void* __dlopen(const char* file, int mode) | |||
| 		return nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	const size_t old_loaded_count = s_loaded_file_count; | ||||
| 
 | ||||
| 	init_random(); | ||||
| 	auto& elf = load_elf(path_buffer, -1); | ||||
| 	fini_random(); | ||||
| 
 | ||||
| 	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++) | ||||
| 		{ | ||||
| 			if (s_loaded_files[i].tls_header.p_type == PT_TLS) | ||||
| 			{ | ||||
| 				s_dlerror_string = "TODO: __dlopen with TLS"; | ||||
| 				return nullptr; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		relocate_elf(elf, lazy); | ||||
| 		call_init_funcs(elf, false); | ||||
|  | @ -1399,10 +1417,23 @@ static LibELF::AuxiliaryVector* find_auxv(char** envp) | |||
| 	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" | ||||
| __attribute__((used)) | ||||
| 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; | ||||
| 	if (auto* auxv = find_auxv(envp)) | ||||
| 		for (auto* aux = auxv; aux->a_type != LibELF::AT_NULL; aux++) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue