Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									4e4a6fb542
								
							
						
					
					
						commit
						d4cb87efd6
					
				
							
								
								
									
										187
									
								
								kernel/elf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								kernel/elf.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,187 @@ | ||||||
|  | /*
 | ||||||
|  | Copyright (C) 2015-2019 The University of Notre Dame | ||||||
|  | This software is distributed under the GNU General Public License. | ||||||
|  | See the file LICENSE for details. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "elf.h" | ||||||
|  | #include "fs.h" | ||||||
|  | #include "string.h" | ||||||
|  | #include "console.h" | ||||||
|  | #include "process.h" | ||||||
|  | #include "kernel/syscall.h" | ||||||
|  | #include "memorylayout.h" | ||||||
|  | 
 | ||||||
|  | struct elf_header { | ||||||
|  | 	char ident[16]; | ||||||
|  | 	uint16_t type; | ||||||
|  | 	uint16_t machine; | ||||||
|  | 	uint32_t version; | ||||||
|  | 	uint32_t entry; | ||||||
|  | 	uint32_t program_offset; | ||||||
|  | 	uint32_t section_offset; | ||||||
|  | 	uint32_t flags; | ||||||
|  | 	uint16_t header_size; | ||||||
|  | 	uint16_t phentsize; | ||||||
|  | 	uint16_t phnum; | ||||||
|  | 	uint16_t shentsize; | ||||||
|  | 	uint16_t shnum; | ||||||
|  | 	uint16_t shstrndx; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define ELF_HEADER_TYPE_NONE         0 | ||||||
|  | #define ELF_HEADER_TYPE_OBJECT       1 | ||||||
|  | #define ELF_HEADER_TYPE_EXECUTABLE   2 | ||||||
|  | #define ELF_HEADER_TYPE_DYNAMIC      3 | ||||||
|  | #define ELF_HEADER_TYPE_CORE         4 | ||||||
|  | 
 | ||||||
|  | #define ELF_HEADER_MACHINE_I386   3 | ||||||
|  | #define ELF_HEADER_MACHINE_ARM    40 | ||||||
|  | #define ELF_HEADER_MACHINE_X86_64 62 | ||||||
|  | 
 | ||||||
|  | #define ELF_HEADER_VERSION     1 | ||||||
|  | 
 | ||||||
|  | struct elf_program { | ||||||
|  | 	uint32_t type; | ||||||
|  | 	uint32_t offset; | ||||||
|  | 	uint32_t vaddr; | ||||||
|  | 	uint32_t paddr; | ||||||
|  | 	uint32_t file_size; | ||||||
|  | 	uint32_t memory_size; | ||||||
|  | 	uint32_t flags; | ||||||
|  | 	uint32_t align; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define ELF_PROGRAM_TYPE_LOADABLE 1 | ||||||
|  | 
 | ||||||
|  | struct elf_section { | ||||||
|  | 	uint32_t name; | ||||||
|  | 	uint32_t type; | ||||||
|  | 	uint32_t flags; | ||||||
|  | 	uint32_t address; | ||||||
|  | 	uint32_t offset; | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint32_t link; | ||||||
|  | 	uint32_t info; | ||||||
|  | 	uint32_t alignment; | ||||||
|  | 	uint32_t entry_size; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define ELF_SECTION_TYPE_NULL         0 | ||||||
|  | #define ELF_SECTION_TYPE_PROGRAM      1 | ||||||
|  | #define ELF_SECTION_TYPE_SYMBOL_TABLE 2 | ||||||
|  | #define ELF_SECTION_TYPE_STRING_TABLE 3 | ||||||
|  | #define ELF_SECTION_TYPE_RELA         4 | ||||||
|  | #define ELF_SECTION_TYPE_HASH         5 | ||||||
|  | #define ELF_SECTION_TYPE_DYNAMIC      6 | ||||||
|  | #define ELF_SECTION_TYPE_NOTE         7 | ||||||
|  | #define ELF_SECTION_TYPE_BSS          8 | ||||||
|  | 
 | ||||||
|  | #define ELF_SECTION_FLAGS_WRITE    1 | ||||||
|  | #define ELF_SECTION_FLAGS_MEMORY   2 | ||||||
|  | #define ELF_SECTION_FLAGS_EXEC     8 | ||||||
|  | #define ELF_SECTION_FLAGS_MERGE    16 | ||||||
|  | #define ELF_SECTION_FLAGS_STRINGS  32 | ||||||
|  | #define ELF_SECTION_FLAGS_INFO_LINK 64 | ||||||
|  | #define ELF_SECTION_FLAGS_LINK_ORDER 128 | ||||||
|  | #define ELF_SECTION_FLAGS_NONSTANDARD 256 | ||||||
|  | #define ELF_SECTION_FLAGS_GROUP 512 | ||||||
|  | #define ELF_SECTION_FLAGS_TLS 1024 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Ensure that the current process has address space up to this value. */ | ||||||
|  | 
 | ||||||
|  | static int elf_ensure_address_space( struct process *p, uint32_t addr ) | ||||||
|  | { | ||||||
|  | 	/* Size of user data area, ignoring start addr */ | ||||||
|  | 	uint32_t limit = addr - PROCESS_ENTRY_POINT; | ||||||
|  | 
 | ||||||
|  | 	/* Round up to next page size. */ | ||||||
|  | 	uint32_t overflow = limit % PAGE_SIZE; | ||||||
|  | 	limit += (PAGE_SIZE-overflow); | ||||||
|  | 
 | ||||||
|  | 	/* Extend virtual memory if needed. */ | ||||||
|  | 	if(limit > p->vm_data_size) { | ||||||
|  | 		return process_data_size_set(p,limit); | ||||||
|  | 	} else { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Return zero on success. */ | ||||||
|  | } | ||||||
|  |   | ||||||
|  | int elf_load(struct process *p, struct fs_dirent *d, addr_t * entry) | ||||||
|  | { | ||||||
|  | 	struct elf_header header; | ||||||
|  | 	struct elf_program program; | ||||||
|  | 	struct elf_section section; | ||||||
|  | 	int i; | ||||||
|  | 	uint32_t actual; | ||||||
|  | 
 | ||||||
|  | 	actual = fs_dirent_read(d, (char *) &header, sizeof(header), 0); | ||||||
|  | 	if(actual != sizeof(header)) | ||||||
|  | 		goto noload; | ||||||
|  | 
 | ||||||
|  | 	if(strncmp(header.ident, "\177ELF", 4) || header.machine != ELF_HEADER_MACHINE_I386 || header.version != ELF_HEADER_VERSION) | ||||||
|  | 		goto noexec; | ||||||
|  | 
 | ||||||
|  | 	actual = fs_dirent_read(d, (char *) &program, sizeof(program), header.program_offset); | ||||||
|  | 	if(actual != sizeof(program)) | ||||||
|  | 		goto noload; | ||||||
|  | 
 | ||||||
|  |   // @blab+ fix first empty section with vaddr=0 (after newly needed objcopy removing unnessary symbols and sections)
 | ||||||
|  |   if (program.vaddr==0) program.vaddr=header.entry; | ||||||
|  | 
 | ||||||
|  | 	//printf("elf: text %x bytes from offset %x at address %x length %x\n",program.file_size,program.offset,program.vaddr,program.memory_size);
 | ||||||
|  | 
 | ||||||
|  | 	if(program.type != ELF_PROGRAM_TYPE_LOADABLE || program.vaddr < PROCESS_ENTRY_POINT || program.memory_size > 0x8000000 || program.memory_size != program.file_size) | ||||||
|  | 		goto noexec; | ||||||
|  | 
 | ||||||
|  | 	process_data_size_set(p, program.memory_size); | ||||||
|  | 
 | ||||||
|  | 	actual = fs_dirent_read(d, (char *) program.vaddr, program.memory_size, program.offset); | ||||||
|  | 	if(actual != program.memory_size) | ||||||
|  | 		goto mustdie; | ||||||
|  | 
 | ||||||
|  | 	for(i = 0; i < header.shnum; i++) { | ||||||
|  | 		actual = fs_dirent_read(d, (char *) §ion, sizeof(section), header.section_offset + i * header.shentsize); | ||||||
|  | 		if(actual != sizeof(section)) | ||||||
|  | 			goto mustdie; | ||||||
|  | 
 | ||||||
|  | 		if(section.type == ELF_SECTION_TYPE_BSS) { | ||||||
|  | 			/* For BSS, just clear that address space to zero. */ | ||||||
|  | 			actual = elf_ensure_address_space(p,section.address+section.size); | ||||||
|  | 			if(actual!=0) goto nomem; | ||||||
|  | 			memset((void *) section.address, section.size, 0); | ||||||
|  | 		} else if(section.type == ELF_SECTION_TYPE_PROGRAM && section.address!=0) { | ||||||
|  | 			/* For other loadable section types (usually data), load from file. */ | ||||||
|  | 			actual = elf_ensure_address_space(p,section.address+section.size); | ||||||
|  | 			if(actual!=0) goto nomem; | ||||||
|  | 			actual = fs_dirent_read(d,(char*)section.address,section.size,section.offset); | ||||||
|  | 			if(actual != section.size) goto mustdie; | ||||||
|  | 		} else { | ||||||
|  | 			/* skip all other section types */ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*entry = header.entry; | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  |       noload: | ||||||
|  | 	printf("elf: failed to load correctly!\n"); | ||||||
|  | 	return KERROR_NOT_FOUND; | ||||||
|  | 
 | ||||||
|  |       noexec: | ||||||
|  | 	printf("elf: not a valid i386 ELF executable [%c%c%c%c:%x(%x):%x(%x):%d(%d)]\n", | ||||||
|  | 	      header.ident[0],header.ident[1],header.ident[2],header.ident[3], | ||||||
|  | 	      program.type,ELF_PROGRAM_TYPE_LOADABLE,program.vaddr,PROCESS_ENTRY_POINT,program.memory_size,program.file_size); // @blab+
 | ||||||
|  | 	return KERROR_NOT_EXECUTABLE; | ||||||
|  | 
 | ||||||
|  |       nomem: | ||||||
|  | 	printf("elf: failed to allocate memory\n"); | ||||||
|  | 	return KERROR_OUT_OF_MEMORY; | ||||||
|  | 
 | ||||||
|  |       mustdie: | ||||||
|  | 	printf("elf: did not load correctly\n"); | ||||||
|  | 	return KERROR_EXECUTION_FAILED; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user