DynamicLoader: Use file backed mmap when possible
This commit is contained in:
		
							parent
							
								
									2f241e1b61
								
							
						
					
					
						commit
						e8bcebfb8e
					
				|  | @ -622,98 +622,57 @@ static void load_program_header(const ElfNativeProgramHeader& program_header, in | ||||||
| 			return result; | 			return result; | ||||||
| 		}(); | 		}(); | ||||||
| 
 | 
 | ||||||
| 	const uintptr_t aligned_vaddr = program_header.p_vaddr & ~(uintptr_t)0xFFF; | 	if ((program_header.p_vaddr & 0xFFF) || (program_header.p_offset & 0xFFF)) | ||||||
|  | 	{ | ||||||
|  | 		const uintptr_t aligned_addr = program_header.p_vaddr & ~(uintptr_t)0xFFF; | ||||||
| 
 | 
 | ||||||
|  | 		// unaligned addresses, cannot use file mmap
 | ||||||
| 		sys_mmap_t mmap_args; | 		sys_mmap_t mmap_args; | ||||||
| 	mmap_args.addr = reinterpret_cast<void*>(aligned_vaddr); | 		mmap_args.addr = reinterpret_cast<void*>(aligned_addr); | ||||||
| 		mmap_args.fildes = -1; | 		mmap_args.fildes = -1; | ||||||
| 		mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; | 		mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; | ||||||
| 	mmap_args.len = (program_header.p_vaddr + program_header.p_memsz) - aligned_vaddr; | 		mmap_args.len = (program_header.p_vaddr + program_header.p_memsz) - aligned_addr; | ||||||
| 		mmap_args.off = 0; | 		mmap_args.off = 0; | ||||||
| 		mmap_args.prot = prot | PROT_WRITE; | 		mmap_args.prot = prot | PROT_WRITE; | ||||||
| 
 | 
 | ||||||
| 	if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(aligned_vaddr)) | 		if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(aligned_addr)) | ||||||
| 		print_error_and_exit("could not load program header", ret); |  | ||||||
| 	if (auto ret = syscall(SYS_PREAD, fd, program_header.p_vaddr, program_header.p_filesz, program_header.p_offset); ret != static_cast<long>(program_header.p_filesz)) |  | ||||||
| 			print_error_and_exit("could not load program header", ret); | 			print_error_and_exit("could not load program header", ret); | ||||||
| 
 | 
 | ||||||
| 	return; | 		const uintptr_t addr = program_header.p_vaddr; | ||||||
|  | 		const uintptr_t size = program_header.p_filesz; | ||||||
|  | 		const size_t offset = program_header.p_offset; | ||||||
|  | 		if (auto ret = syscall(SYS_PREAD, fd, addr, size, offset); ret != static_cast<long>(size)) | ||||||
|  | 			print_error_and_exit("could not load program header", ret); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		// aligned addresses, use file mmap
 | ||||||
|  | 		sys_mmap_t mmap_args; | ||||||
|  | 		mmap_args.addr = reinterpret_cast<void*>(program_header.p_vaddr); | ||||||
|  | 		mmap_args.fildes = fd; | ||||||
|  | 		mmap_args.flags = MAP_PRIVATE | MAP_FIXED; | ||||||
|  | 		mmap_args.len = program_header.p_memsz; | ||||||
|  | 		mmap_args.off = program_header.p_offset; | ||||||
|  | 		mmap_args.prot = prot | PROT_WRITE; | ||||||
| 
 | 
 | ||||||
| 	uintptr_t filesz = program_header.p_filesz; | 		if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(program_header.p_vaddr)) | ||||||
|  | 			print_error_and_exit("could not load program header", ret); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (program_header.p_filesz != program_header.p_memsz) | 	if (program_header.p_filesz != program_header.p_memsz) | ||||||
| 	{ | 	{ | ||||||
| 		const uintptr_t data_end_vaddr = program_header.p_vaddr + program_header.p_filesz; | 		memset( | ||||||
| 		const uintptr_t zero_end_vaddr = program_header.p_vaddr + program_header.p_memsz; | 			reinterpret_cast<void*>(program_header.p_vaddr + program_header.p_filesz), | ||||||
| 
 | 			0x00, | ||||||
| 		uintptr_t start_vaddr = data_end_vaddr & ~(uintptr_t)0xFFF; | 			program_header.p_memsz - program_header.p_filesz | ||||||
| 		if (program_header.p_vaddr & 0xFFF) | 		); | ||||||
| 			start_vaddr = program_header.p_vaddr & ~(uintptr_t)0xFFF; | 	} | ||||||
| 
 |  | ||||||
| 		if (start_vaddr != data_end_vaddr) |  | ||||||
| 		{ |  | ||||||
| 			const uintptr_t end_vaddr = (data_end_vaddr + 4095) & ~(uintptr_t)0xFFF; |  | ||||||
| 			const ptrdiff_t length = min(end_vaddr - start_vaddr, zero_end_vaddr - start_vaddr); |  | ||||||
| 
 |  | ||||||
| 			sys_mmap_t mmap_args; |  | ||||||
| 			mmap_args.addr = reinterpret_cast<void*>(start_vaddr); |  | ||||||
| 			mmap_args.fildes = -1; |  | ||||||
| 			mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; |  | ||||||
| 			mmap_args.len = length; |  | ||||||
| 			mmap_args.off = 0; |  | ||||||
| 			mmap_args.prot = prot | PROT_WRITE; |  | ||||||
| 
 |  | ||||||
| 			if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(start_vaddr)) |  | ||||||
| 				print_error_and_exit("could not load program header", ret); |  | ||||||
| 
 |  | ||||||
| 			uintptr_t dummy_bytes = program_header.p_vaddr - start_vaddr; |  | ||||||
| 			if (program_header.p_vaddr & 0xFFF) |  | ||||||
| 				dummy_bytes = 0; |  | ||||||
| 
 |  | ||||||
| 			const uintptr_t data_vaddr = program_header.p_vaddr + dummy_bytes; |  | ||||||
| 			const ptrdiff_t data_bytes = data_end_vaddr - data_vaddr; |  | ||||||
| 			const uintptr_t data_offset = program_header.p_offset + dummy_bytes; |  | ||||||
| 			if (auto ret = syscall(SYS_PREAD, fd, data_vaddr, data_bytes, data_offset); ret != data_bytes) |  | ||||||
| 				print_error_and_exit("could not load program header", ret); |  | ||||||
| 
 | 
 | ||||||
| 	if (!(prot & PROT_WRITE) && !needs_writable) | 	if (!(prot & PROT_WRITE) && !needs_writable) | ||||||
| 	{ | 	{ | ||||||
| 		// FIXME: Implement mprotect so PROT_WRITE can be removed
 | 		// FIXME: Implement mprotect so PROT_WRITE can be removed
 | ||||||
| 		//syscall(SYS_MPROTECT, start_vaddr, length, prot);
 | 		//syscall(SYS_MPROTECT, start_vaddr, length, prot);
 | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 			filesz -= data_bytes; |  | ||||||
| 			start_vaddr += 4096; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (start_vaddr < zero_end_vaddr) |  | ||||||
| 		{ |  | ||||||
| 			sys_mmap_t mmap_args; |  | ||||||
| 			mmap_args.addr = reinterpret_cast<void*>(start_vaddr); |  | ||||||
| 			mmap_args.fildes = -1; |  | ||||||
| 			mmap_args.flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED; |  | ||||||
| 			mmap_args.len = zero_end_vaddr - start_vaddr; |  | ||||||
| 			mmap_args.off = 0; |  | ||||||
| 			mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0); |  | ||||||
| 
 |  | ||||||
| 			if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(start_vaddr)) |  | ||||||
| 				print_error_and_exit("could not load program header", ret); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (filesz) |  | ||||||
| 	{ |  | ||||||
| 		sys_mmap_t mmap_args; |  | ||||||
| 		mmap_args.addr = reinterpret_cast<void*>(program_header.p_vaddr); |  | ||||||
| 		mmap_args.fildes = fd; |  | ||||||
| 		mmap_args.flags = MAP_PRIVATE | MAP_FIXED; |  | ||||||
| 		mmap_args.len = filesz; |  | ||||||
| 		mmap_args.off = program_header.p_offset; |  | ||||||
| 		mmap_args.prot = prot | (needs_writable ? PROT_WRITE : 0); |  | ||||||
| 
 |  | ||||||
| 		if (auto ret = syscall(SYS_MMAP, &mmap_args); ret != static_cast<long>(program_header.p_vaddr)) |  | ||||||
| 			print_error_and_exit("could not load program header", ret); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static LoadedElf s_loaded_files[128]; | static LoadedElf s_loaded_files[128]; | ||||||
|  |  | ||||||
|  | @ -56,6 +56,14 @@ void* memcpy(void* __restrict dstp, const void* __restrict srcp, size_t n) | ||||||
| 	return dstp; | 	return dstp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void* memset(void* s, int c, size_t n) | ||||||
|  | { | ||||||
|  | 	unsigned char* p = static_cast<unsigned char*>(s); | ||||||
|  | 	for (size_t i = 0; i < n; i++) | ||||||
|  | 		p[i] = c; | ||||||
|  | 	return s; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int s_random_fd; | static int s_random_fd; | ||||||
| 
 | 
 | ||||||
| void init_random() | void init_random() | ||||||
|  |  | ||||||
|  | @ -42,7 +42,9 @@ inline void print_uint(int fd, T val, uint8_t base = 10) | ||||||
| 
 | 
 | ||||||
| int strcmp(const char* s1, const char* s2); | int strcmp(const char* s1, const char* s2); | ||||||
| char* strcpy(char* __restrict s1, const char* __restrict s2); | char* strcpy(char* __restrict s1, const char* __restrict s2); | ||||||
|  | 
 | ||||||
| void* memcpy(void* __restrict s1, const void* __restrict s2, size_t n); | void* memcpy(void* __restrict s1, const void* __restrict s2, size_t n); | ||||||
|  | void* memset(void* s, int c, size_t n); | ||||||
| 
 | 
 | ||||||
| void init_random(); | void init_random(); | ||||||
| void fini_random(); | void fini_random(); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue