1 /* 2 * Copyright (c) 2018 Virtuozzo International GmbH 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * 6 */ 7 8 #include "qemu/osdep.h" 9 #include "qemu/host-utils.h" 10 #include "err.h" 11 #include "qemu_elf.h" 12 13 #define QEMU_NOTE_NAME "QEMU" 14 15 #ifndef ROUND_UP 16 #define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) 17 #endif 18 19 int is_system(QEMUCPUState *s) 20 { 21 return s->gs.base >> 63; 22 } 23 24 Elf64_Phdr *elf64_getphdr(void *map) 25 { 26 Elf64_Ehdr *ehdr = map; 27 Elf64_Phdr *phdr = (void *)((uint8_t *)map + ehdr->e_phoff); 28 29 return phdr; 30 } 31 32 Elf64_Half elf_getphdrnum(void *map) 33 { 34 Elf64_Ehdr *ehdr = map; 35 36 return ehdr->e_phnum; 37 } 38 39 static bool advance_note_offset(uint64_t *offsetp, uint64_t size, uint64_t end) 40 { 41 uint64_t offset = *offsetp; 42 43 if (uadd64_overflow(offset, size, &offset) || offset > UINT64_MAX - 3) { 44 return false; 45 } 46 47 offset = ROUND_UP(offset, 4); 48 49 if (offset > end) { 50 return false; 51 } 52 53 *offsetp = offset; 54 55 return true; 56 } 57 58 static bool init_states(QEMU_Elf *qe) 59 { 60 Elf64_Phdr *phdr = elf64_getphdr(qe->map); 61 Elf64_Nhdr *nhdr; 62 GPtrArray *states; 63 QEMUCPUState *state; 64 uint32_t state_size; 65 uint64_t offset; 66 uint64_t end_offset; 67 char *name; 68 69 if (phdr[0].p_type != PT_NOTE) { 70 eprintf("Failed to find PT_NOTE\n"); 71 return false; 72 } 73 74 qe->has_kernel_gs_base = 1; 75 offset = phdr[0].p_offset; 76 states = g_ptr_array_new(); 77 78 if (uadd64_overflow(offset, phdr[0].p_memsz, &end_offset) || 79 end_offset > qe->size) { 80 end_offset = qe->size; 81 } 82 83 while (offset < end_offset) { 84 nhdr = (void *)((uint8_t *)qe->map + offset); 85 86 if (!advance_note_offset(&offset, sizeof(*nhdr), end_offset)) { 87 break; 88 } 89 90 name = (char *)qe->map + offset; 91 92 if (!advance_note_offset(&offset, nhdr->n_namesz, end_offset)) { 93 break; 94 } 95 96 state = (void *)((uint8_t *)qe->map + offset); 97 98 if (!advance_note_offset(&offset, nhdr->n_descsz, end_offset)) { 99 break; 100 } 101 102 if (!strcmp(name, QEMU_NOTE_NAME) && 103 nhdr->n_descsz >= offsetof(QEMUCPUState, kernel_gs_base)) { 104 state_size = MIN(state->size, nhdr->n_descsz); 105 106 if (state_size < sizeof(*state)) { 107 eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n", 108 states->len, state_size); 109 /* 110 * We assume either every QEMU CPU state has KERNEL_GS_BASE or 111 * no one has. 112 */ 113 qe->has_kernel_gs_base = 0; 114 } 115 g_ptr_array_add(states, state); 116 } 117 } 118 119 printf("%u CPU states has been found\n", states->len); 120 121 qe->state_nr = states->len; 122 qe->state = (void *)g_ptr_array_free(states, FALSE); 123 124 return true; 125 } 126 127 static void exit_states(QEMU_Elf *qe) 128 { 129 g_free(qe->state); 130 } 131 132 static bool check_ehdr(QEMU_Elf *qe) 133 { 134 Elf64_Ehdr *ehdr = qe->map; 135 uint64_t phendoff; 136 137 if (sizeof(Elf64_Ehdr) > qe->size) { 138 eprintf("Invalid input dump file size\n"); 139 return false; 140 } 141 142 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { 143 eprintf("Invalid ELF signature, input file is not ELF\n"); 144 return false; 145 } 146 147 if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 || 148 ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { 149 eprintf("Invalid ELF class or byte order, must be 64-bit LE\n"); 150 return false; 151 } 152 153 if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) { 154 eprintf("Invalid ELF version\n"); 155 return false; 156 } 157 158 if (ehdr->e_machine != EM_X86_64) { 159 eprintf("Invalid input dump architecture, only x86_64 is supported\n"); 160 return false; 161 } 162 163 if (ehdr->e_type != ET_CORE) { 164 eprintf("Invalid ELF type, must be core file\n"); 165 return false; 166 } 167 168 /* 169 * ELF dump file must contain one PT_NOTE and at least one PT_LOAD to 170 * restore physical address space. 171 */ 172 if (ehdr->e_phnum < 2) { 173 eprintf("Invalid number of ELF program headers\n"); 174 return false; 175 } 176 177 if (umul64_overflow(ehdr->e_phnum, sizeof(Elf64_Phdr), &phendoff) || 178 uadd64_overflow(phendoff, ehdr->e_phoff, &phendoff) || 179 phendoff > qe->size) { 180 eprintf("phdrs do not fit in file\n"); 181 return false; 182 } 183 184 return true; 185 } 186 187 static bool QEMU_Elf_map(QEMU_Elf *qe, const char *filename) 188 { 189 #ifdef CONFIG_LINUX 190 struct stat st; 191 int fd; 192 193 printf("Using Linux mmap\n"); 194 195 fd = open(filename, O_RDONLY, 0); 196 if (fd == -1) { 197 eprintf("Failed to open ELF dump file \'%s\'\n", filename); 198 return false; 199 } 200 201 if (fstat(fd, &st)) { 202 eprintf("Failed to get size of ELF dump file\n"); 203 close(fd); 204 return false; 205 } 206 qe->size = st.st_size; 207 208 qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE, 209 MAP_PRIVATE | MAP_NORESERVE, fd, 0); 210 if (qe->map == MAP_FAILED) { 211 eprintf("Failed to map ELF file\n"); 212 close(fd); 213 return false; 214 } 215 216 close(fd); 217 #else 218 GError *gerr = NULL; 219 220 printf("Using GLib mmap\n"); 221 222 qe->gmf = g_mapped_file_new(filename, TRUE, &gerr); 223 if (gerr) { 224 eprintf("Failed to map ELF dump file \'%s\'\n", filename); 225 g_error_free(gerr); 226 return false; 227 } 228 229 qe->map = g_mapped_file_get_contents(qe->gmf); 230 qe->size = g_mapped_file_get_length(qe->gmf); 231 #endif 232 233 return true; 234 } 235 236 static void QEMU_Elf_unmap(QEMU_Elf *qe) 237 { 238 #ifdef CONFIG_LINUX 239 munmap(qe->map, qe->size); 240 #else 241 g_mapped_file_unref(qe->gmf); 242 #endif 243 } 244 245 bool QEMU_Elf_init(QEMU_Elf *qe, const char *filename) 246 { 247 if (!QEMU_Elf_map(qe, filename)) { 248 return false; 249 } 250 251 if (!check_ehdr(qe)) { 252 eprintf("Input file has the wrong format\n"); 253 QEMU_Elf_unmap(qe); 254 return false; 255 } 256 257 if (!init_states(qe)) { 258 eprintf("Failed to extract QEMU CPU states\n"); 259 QEMU_Elf_unmap(qe); 260 return false; 261 } 262 263 return true; 264 } 265 266 void QEMU_Elf_exit(QEMU_Elf *qe) 267 { 268 exit_states(qe); 269 QEMU_Elf_unmap(qe); 270 } 271