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
is_system(QEMUCPUState * s)27 int is_system(QEMUCPUState *s)
28 {
29 return s->gs.base >> 63;
30 }
31
nhdr_get_name(Elf64_Nhdr * nhdr)32 static char *nhdr_get_name(Elf64_Nhdr *nhdr)
33 {
34 return (char *)nhdr + ROUND_UP(sizeof(*nhdr), 4);
35 }
36
nhdr_get_desc(Elf64_Nhdr * nhdr)37 static void *nhdr_get_desc(Elf64_Nhdr *nhdr)
38 {
39 return nhdr_get_name(nhdr) + ROUND_UP(nhdr->n_namesz, 4);
40 }
41
nhdr_get_next(Elf64_Nhdr * nhdr)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
elf64_getphdr(void * map)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
elf_getphdrnum(void * map)56 Elf64_Half elf_getphdrnum(void *map)
57 {
58 Elf64_Ehdr *ehdr = map;
59
60 return ehdr->e_phnum;
61 }
62
init_states(QEMU_Elf * qe)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 = g_new(QEMUCPUState*, cpu_nr);
98
99 cpu_nr = 0;
100
101 for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) {
102 if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) {
103 qe->state[cpu_nr] = nhdr_get_desc(nhdr);
104 cpu_nr++;
105 }
106 }
107
108 qe->state_nr = cpu_nr;
109
110 return 0;
111 }
112
exit_states(QEMU_Elf * qe)113 static void exit_states(QEMU_Elf *qe)
114 {
115 g_free(qe->state);
116 }
117
check_ehdr(QEMU_Elf * qe)118 static bool check_ehdr(QEMU_Elf *qe)
119 {
120 Elf64_Ehdr *ehdr = qe->map;
121
122 if (sizeof(Elf64_Ehdr) > qe->size) {
123 eprintf("Invalid input dump file size\n");
124 return false;
125 }
126
127 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
128 eprintf("Invalid ELF signature, input file is not ELF\n");
129 return false;
130 }
131
132 if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
133 ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
134 eprintf("Invalid ELF class or byte order, must be 64-bit LE\n");
135 return false;
136 }
137
138 if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
139 eprintf("Invalid ELF version\n");
140 return false;
141 }
142
143 if (ehdr->e_machine != EM_X86_64) {
144 eprintf("Invalid input dump architecture, only x86_64 is supported\n");
145 return false;
146 }
147
148 if (ehdr->e_type != ET_CORE) {
149 eprintf("Invalid ELF type, must be core file\n");
150 return false;
151 }
152
153 /*
154 * ELF dump file must contain one PT_NOTE and at least one PT_LOAD to
155 * restore physical address space.
156 */
157 if (ehdr->e_phnum < 2) {
158 eprintf("Invalid number of ELF program headers\n");
159 return false;
160 }
161
162 return true;
163 }
164
QEMU_Elf_map(QEMU_Elf * qe,const char * filename)165 static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
166 {
167 #ifdef CONFIG_LINUX
168 struct stat st;
169 int fd;
170
171 printf("Using Linux mmap\n");
172
173 fd = open(filename, O_RDONLY, 0);
174 if (fd == -1) {
175 eprintf("Failed to open ELF dump file \'%s\'\n", filename);
176 return 1;
177 }
178
179 if (fstat(fd, &st)) {
180 eprintf("Failed to get size of ELF dump file\n");
181 close(fd);
182 return 1;
183 }
184 qe->size = st.st_size;
185
186 qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE,
187 MAP_PRIVATE | MAP_NORESERVE, fd, 0);
188 if (qe->map == MAP_FAILED) {
189 eprintf("Failed to map ELF file\n");
190 close(fd);
191 return 1;
192 }
193
194 close(fd);
195 #else
196 GError *gerr = NULL;
197
198 printf("Using GLib mmap\n");
199
200 qe->gmf = g_mapped_file_new(filename, TRUE, &gerr);
201 if (gerr) {
202 eprintf("Failed to map ELF dump file \'%s\'\n", filename);
203 g_error_free(gerr);
204 return 1;
205 }
206
207 qe->map = g_mapped_file_get_contents(qe->gmf);
208 qe->size = g_mapped_file_get_length(qe->gmf);
209 #endif
210
211 return 0;
212 }
213
QEMU_Elf_unmap(QEMU_Elf * qe)214 static void QEMU_Elf_unmap(QEMU_Elf *qe)
215 {
216 #ifdef CONFIG_LINUX
217 munmap(qe->map, qe->size);
218 #else
219 g_mapped_file_unref(qe->gmf);
220 #endif
221 }
222
QEMU_Elf_init(QEMU_Elf * qe,const char * filename)223 int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
224 {
225 if (QEMU_Elf_map(qe, filename)) {
226 return 1;
227 }
228
229 if (!check_ehdr(qe)) {
230 eprintf("Input file has the wrong format\n");
231 QEMU_Elf_unmap(qe);
232 return 1;
233 }
234
235 if (init_states(qe)) {
236 eprintf("Failed to extract QEMU CPU states\n");
237 QEMU_Elf_unmap(qe);
238 return 1;
239 }
240
241 return 0;
242 }
243
QEMU_Elf_exit(QEMU_Elf * qe)244 void QEMU_Elf_exit(QEMU_Elf *qe)
245 {
246 exit_states(qe);
247 QEMU_Elf_unmap(qe);
248 }
249