0001
0002
0003
0004
0005
0006
0007
0008 #include "test_util.h"
0009
0010 #include <bits/endian.h>
0011 #include <linux/elf.h>
0012
0013 #include "kvm_util.h"
0014
0015 static void elfhdr_get(const char *filename, Elf64_Ehdr *hdrp)
0016 {
0017 off_t offset_rv;
0018
0019
0020 int fd;
0021 fd = open(filename, O_RDONLY);
0022 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
0023 " filename: %s\n"
0024 " rv: %i errno: %i", filename, fd, errno);
0025
0026
0027
0028
0029
0030
0031
0032
0033 unsigned char ident[EI_NIDENT];
0034 test_read(fd, ident, sizeof(ident));
0035 TEST_ASSERT((ident[EI_MAG0] == ELFMAG0) && (ident[EI_MAG1] == ELFMAG1)
0036 && (ident[EI_MAG2] == ELFMAG2) && (ident[EI_MAG3] == ELFMAG3),
0037 "ELF MAGIC Mismatch,\n"
0038 " filename: %s\n"
0039 " ident[EI_MAG0 - EI_MAG3]: %02x %02x %02x %02x\n"
0040 " Expected: %02x %02x %02x %02x",
0041 filename,
0042 ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3],
0043 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3);
0044 TEST_ASSERT(ident[EI_CLASS] == ELFCLASS64,
0045 "Current implementation only able to handle ELFCLASS64,\n"
0046 " filename: %s\n"
0047 " ident[EI_CLASS]: %02x\n"
0048 " expected: %02x",
0049 filename,
0050 ident[EI_CLASS], ELFCLASS64);
0051 TEST_ASSERT(((BYTE_ORDER == LITTLE_ENDIAN)
0052 && (ident[EI_DATA] == ELFDATA2LSB))
0053 || ((BYTE_ORDER == BIG_ENDIAN)
0054 && (ident[EI_DATA] == ELFDATA2MSB)), "Current "
0055 "implementation only able to handle\n"
0056 "cases where the host and ELF file endianness\n"
0057 "is the same:\n"
0058 " host BYTE_ORDER: %u\n"
0059 " host LITTLE_ENDIAN: %u\n"
0060 " host BIG_ENDIAN: %u\n"
0061 " ident[EI_DATA]: %u\n"
0062 " ELFDATA2LSB: %u\n"
0063 " ELFDATA2MSB: %u",
0064 BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN,
0065 ident[EI_DATA], ELFDATA2LSB, ELFDATA2MSB);
0066 TEST_ASSERT(ident[EI_VERSION] == EV_CURRENT,
0067 "Current implementation only able to handle current "
0068 "ELF version,\n"
0069 " filename: %s\n"
0070 " ident[EI_VERSION]: %02x\n"
0071 " expected: %02x",
0072 filename, ident[EI_VERSION], EV_CURRENT);
0073
0074
0075
0076
0077
0078
0079 offset_rv = lseek(fd, 0, SEEK_SET);
0080 TEST_ASSERT(offset_rv == 0, "Seek to ELF header failed,\n"
0081 " rv: %zi expected: %i", offset_rv, 0);
0082 test_read(fd, hdrp, sizeof(*hdrp));
0083 TEST_ASSERT(hdrp->e_phentsize == sizeof(Elf64_Phdr),
0084 "Unexpected physical header size,\n"
0085 " hdrp->e_phentsize: %x\n"
0086 " expected: %zx",
0087 hdrp->e_phentsize, sizeof(Elf64_Phdr));
0088 TEST_ASSERT(hdrp->e_shentsize == sizeof(Elf64_Shdr),
0089 "Unexpected section header size,\n"
0090 " hdrp->e_shentsize: %x\n"
0091 " expected: %zx",
0092 hdrp->e_shentsize, sizeof(Elf64_Shdr));
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename)
0114 {
0115 off_t offset, offset_rv;
0116 Elf64_Ehdr hdr;
0117
0118
0119 int fd;
0120 fd = open(filename, O_RDONLY);
0121 TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"
0122 " filename: %s\n"
0123 " rv: %i errno: %i", filename, fd, errno);
0124
0125
0126 elfhdr_get(filename, &hdr);
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 for (unsigned int n1 = 0; n1 < hdr.e_phnum; n1++) {
0137
0138 offset = hdr.e_phoff + (n1 * hdr.e_phentsize);
0139 offset_rv = lseek(fd, offset, SEEK_SET);
0140 TEST_ASSERT(offset_rv == offset,
0141 "Failed to seek to begining of program header %u,\n"
0142 " filename: %s\n"
0143 " rv: %jd errno: %i",
0144 n1, filename, (intmax_t) offset_rv, errno);
0145
0146
0147 Elf64_Phdr phdr;
0148 test_read(fd, &phdr, sizeof(phdr));
0149
0150
0151 if (phdr.p_type != PT_LOAD)
0152 continue;
0153
0154
0155 TEST_ASSERT(phdr.p_memsz > 0, "Unexpected loadable segment "
0156 "memsize of 0,\n"
0157 " phdr index: %u p_memsz: 0x%" PRIx64,
0158 n1, (uint64_t) phdr.p_memsz);
0159 vm_vaddr_t seg_vstart = align_down(phdr.p_vaddr, vm->page_size);
0160 vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1;
0161 seg_vend |= vm->page_size - 1;
0162 size_t seg_size = seg_vend - seg_vstart + 1;
0163
0164 vm_vaddr_t vaddr = vm_vaddr_alloc(vm, seg_size, seg_vstart);
0165 TEST_ASSERT(vaddr == seg_vstart, "Unable to allocate "
0166 "virtual memory for segment at requested min addr,\n"
0167 " segment idx: %u\n"
0168 " seg_vstart: 0x%lx\n"
0169 " vaddr: 0x%lx",
0170 n1, seg_vstart, vaddr);
0171 memset(addr_gva2hva(vm, vaddr), 0, seg_size);
0172
0173
0174
0175
0176
0177
0178
0179 if (phdr.p_filesz) {
0180 offset_rv = lseek(fd, phdr.p_offset, SEEK_SET);
0181 TEST_ASSERT(offset_rv == phdr.p_offset,
0182 "Seek to program segment offset failed,\n"
0183 " program header idx: %u errno: %i\n"
0184 " offset_rv: 0x%jx\n"
0185 " expected: 0x%jx\n",
0186 n1, errno, (intmax_t) offset_rv,
0187 (intmax_t) phdr.p_offset);
0188 test_read(fd, addr_gva2hva(vm, phdr.p_vaddr),
0189 phdr.p_filesz);
0190 }
0191 }
0192 }