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