1 /* 2 * tools/testing/selftests/kvm/lib/elf.c 3 * 4 * Copyright (C) 2018, Google LLC. 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2. 7 */ 8 9 #include "test_util.h" 10 11 #include <bits/endian.h> 12 #include <linux/elf.h> 13 14 #include "kvm_util.h" 15 #include "kvm_util_internal.h" 16 17 static void elfhdr_get(const char *filename, Elf64_Ehdr *hdrp) 18 { 19 off_t offset_rv; 20 21 /* Open the ELF file. */ 22 int fd; 23 fd = open(filename, O_RDONLY); 24 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n" 25 " filename: %s\n" 26 " rv: %i errno: %i", filename, fd, errno); 27 28 /* Read in and validate ELF Identification Record. 29 * The ELF Identification record is the first 16 (EI_NIDENT) bytes 30 * of the ELF header, which is at the beginning of the ELF file. 31 * For now it is only safe to read the first EI_NIDENT bytes. Once 32 * read and validated, the value of e_ehsize can be used to determine 33 * the real size of the ELF header. 34 */ 35 unsigned char ident[EI_NIDENT]; 36 test_read(fd, ident, sizeof(ident)); 37 TEST_ASSERT((ident[EI_MAG0] == ELFMAG0) && (ident[EI_MAG1] == ELFMAG1) 38 && (ident[EI_MAG2] == ELFMAG2) && (ident[EI_MAG3] == ELFMAG3), 39 "ELF MAGIC Mismatch,\n" 40 " filename: %s\n" 41 " ident[EI_MAG0 - EI_MAG3]: %02x %02x %02x %02x\n" 42 " Expected: %02x %02x %02x %02x", 43 filename, 44 ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3], 45 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3); 46 TEST_ASSERT(ident[EI_CLASS] == ELFCLASS64, 47 "Current implementation only able to handle ELFCLASS64,\n" 48 " filename: %s\n" 49 " ident[EI_CLASS]: %02x\n" 50 " expected: %02x", 51 filename, 52 ident[EI_CLASS], ELFCLASS64); 53 TEST_ASSERT(((BYTE_ORDER == LITTLE_ENDIAN) 54 && (ident[EI_DATA] == ELFDATA2LSB)) 55 || ((BYTE_ORDER == BIG_ENDIAN) 56 && (ident[EI_DATA] == ELFDATA2MSB)), "Current " 57 "implementation only able to handle\n" 58 "cases where the host and ELF file endianness\n" 59 "is the same:\n" 60 " host BYTE_ORDER: %u\n" 61 " host LITTLE_ENDIAN: %u\n" 62 " host BIG_ENDIAN: %u\n" 63 " ident[EI_DATA]: %u\n" 64 " ELFDATA2LSB: %u\n" 65 " ELFDATA2MSB: %u", 66 BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN, 67 ident[EI_DATA], ELFDATA2LSB, ELFDATA2MSB); 68 TEST_ASSERT(ident[EI_VERSION] == EV_CURRENT, 69 "Current implementation only able to handle current " 70 "ELF version,\n" 71 " filename: %s\n" 72 " ident[EI_VERSION]: %02x\n" 73 " expected: %02x", 74 filename, ident[EI_VERSION], EV_CURRENT); 75 76 /* Read in the ELF header. 77 * With the ELF Identification portion of the ELF header 78 * validated, especially that the value at EI_VERSION is 79 * as expected, it is now safe to read the entire ELF header. 80 */ 81 offset_rv = lseek(fd, 0, SEEK_SET); 82 TEST_ASSERT(offset_rv == 0, "Seek to ELF header failed,\n" 83 " rv: %zi expected: %i", offset_rv, 0); 84 test_read(fd, hdrp, sizeof(*hdrp)); 85 TEST_ASSERT(hdrp->e_phentsize == sizeof(Elf64_Phdr), 86 "Unexpected physical header size,\n" 87 " hdrp->e_phentsize: %x\n" 88 " expected: %zx", 89 hdrp->e_phentsize, sizeof(Elf64_Phdr)); 90 TEST_ASSERT(hdrp->e_shentsize == sizeof(Elf64_Shdr), 91 "Unexpected section header size,\n" 92 " hdrp->e_shentsize: %x\n" 93 " expected: %zx", 94 hdrp->e_shentsize, sizeof(Elf64_Shdr)); 95 } 96 97 /* VM ELF Load 98 * 99 * Input Args: 100 * filename - Path to ELF file 101 * 102 * Output Args: None 103 * 104 * Input/Output Args: 105 * vm - Pointer to opaque type that describes the VM. 106 * 107 * Return: None, TEST_ASSERT failures for all error conditions 108 * 109 * Loads the program image of the ELF file specified by filename, 110 * into the virtual address space of the VM pointed to by vm. On entry 111 * the VM needs to not be using any of the virtual address space used 112 * by the image and it needs to have sufficient available physical pages, to 113 * back the virtual pages used to load the image. 114 */ 115 void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename, 116 uint32_t data_memslot, uint32_t pgd_memslot) 117 { 118 off_t offset, offset_rv; 119 Elf64_Ehdr hdr; 120 121 /* Open the ELF file. */ 122 int fd; 123 fd = open(filename, O_RDONLY); 124 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n" 125 " filename: %s\n" 126 " rv: %i errno: %i", filename, fd, errno); 127 128 /* Read in the ELF header. */ 129 elfhdr_get(filename, &hdr); 130 131 /* For each program header. 132 * The following ELF header members specify the location 133 * and size of the program headers: 134 * 135 * e_phoff - File offset to start of program headers 136 * e_phentsize - Size of each program header 137 * e_phnum - Number of program header entries 138 */ 139 for (unsigned int n1 = 0; n1 < hdr.e_phnum; n1++) { 140 /* Seek to the beginning of the program header. */ 141 offset = hdr.e_phoff + (n1 * hdr.e_phentsize); 142 offset_rv = lseek(fd, offset, SEEK_SET); 143 TEST_ASSERT(offset_rv == offset, 144 "Failed to seek to begining of program header %u,\n" 145 " filename: %s\n" 146 " rv: %jd errno: %i", 147 n1, filename, (intmax_t) offset_rv, errno); 148 149 /* Read in the program header. */ 150 Elf64_Phdr phdr; 151 test_read(fd, &phdr, sizeof(phdr)); 152 153 /* Skip if this header doesn't describe a loadable segment. */ 154 if (phdr.p_type != PT_LOAD) 155 continue; 156 157 /* Allocate memory for this segment within the VM. */ 158 TEST_ASSERT(phdr.p_memsz > 0, "Unexpected loadable segment " 159 "memsize of 0,\n" 160 " phdr index: %u p_memsz: 0x%" PRIx64, 161 n1, (uint64_t) phdr.p_memsz); 162 vm_vaddr_t seg_vstart = phdr.p_vaddr; 163 seg_vstart &= ~(vm_vaddr_t)(vm->page_size - 1); 164 vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1; 165 seg_vend |= vm->page_size - 1; 166 size_t seg_size = seg_vend - seg_vstart + 1; 167 168 vm_vaddr_t vaddr = vm_vaddr_alloc(vm, seg_size, seg_vstart, 169 data_memslot, pgd_memslot); 170 TEST_ASSERT(vaddr == seg_vstart, "Unable to allocate " 171 "virtual memory for segment at requested min addr,\n" 172 " segment idx: %u\n" 173 " seg_vstart: 0x%lx\n" 174 " vaddr: 0x%lx", 175 n1, seg_vstart, vaddr); 176 memset(addr_gva2hva(vm, vaddr), 0, seg_size); 177 /* TODO(lhuemill): Set permissions of each memory segment 178 * based on the least-significant 3 bits of phdr.p_flags. 179 */ 180 181 /* Load portion of initial state that is contained within 182 * the ELF file. 183 */ 184 if (phdr.p_filesz) { 185 offset_rv = lseek(fd, phdr.p_offset, SEEK_SET); 186 TEST_ASSERT(offset_rv == phdr.p_offset, 187 "Seek to program segment offset failed,\n" 188 " program header idx: %u errno: %i\n" 189 " offset_rv: 0x%jx\n" 190 " expected: 0x%jx\n", 191 n1, errno, (intmax_t) offset_rv, 192 (intmax_t) phdr.p_offset); 193 test_read(fd, addr_gva2hva(vm, phdr.p_vaddr), 194 phdr.p_filesz); 195 } 196 } 197 } 198