elf.c 6.3 KB

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