2 * Copyright (c) 2018 Virtuozzo International GmbH
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 #include "qemu/osdep.h"
9 #include "qemu/host-utils.h"
13 #define QEMU_NOTE_NAME "QEMU"
16 #define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d)))
19 int is_system(QEMUCPUState
*s
)
21 return s
->gs
.base
>> 63;
24 Elf64_Phdr
*elf64_getphdr(void *map
)
26 Elf64_Ehdr
*ehdr
= map
;
27 Elf64_Phdr
*phdr
= (void *)((uint8_t *)map
+ ehdr
->e_phoff
);
32 Elf64_Half
elf_getphdrnum(void *map
)
34 Elf64_Ehdr
*ehdr
= map
;
39 static bool advance_note_offset(uint64_t *offsetp
, uint64_t size
, uint64_t end
)
41 uint64_t offset
= *offsetp
;
43 if (uadd64_overflow(offset
, size
, &offset
) || offset
> UINT64_MAX
- 3) {
47 offset
= ROUND_UP(offset
, 4);
58 static bool init_states(QEMU_Elf
*qe
)
60 Elf64_Phdr
*phdr
= elf64_getphdr(qe
->map
);
69 if (phdr
[0].p_type
!= PT_NOTE
) {
70 eprintf("Failed to find PT_NOTE\n");
74 qe
->has_kernel_gs_base
= 1;
75 offset
= phdr
[0].p_offset
;
76 states
= g_ptr_array_new();
78 if (uadd64_overflow(offset
, phdr
[0].p_memsz
, &end_offset
) ||
79 end_offset
> qe
->size
) {
80 end_offset
= qe
->size
;
83 while (offset
< end_offset
) {
84 nhdr
= (void *)((uint8_t *)qe
->map
+ offset
);
86 if (!advance_note_offset(&offset
, sizeof(*nhdr
), end_offset
)) {
90 name
= (char *)qe
->map
+ offset
;
92 if (!advance_note_offset(&offset
, nhdr
->n_namesz
, end_offset
)) {
96 state
= (void *)((uint8_t *)qe
->map
+ offset
);
98 if (!advance_note_offset(&offset
, nhdr
->n_descsz
, end_offset
)) {
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
);
106 if (state_size
< sizeof(*state
)) {
107 eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n",
108 states
->len
, state_size
);
110 * We assume either every QEMU CPU state has KERNEL_GS_BASE or
113 qe
->has_kernel_gs_base
= 0;
115 g_ptr_array_add(states
, state
);
119 printf("%u CPU states has been found\n", states
->len
);
121 qe
->state_nr
= states
->len
;
122 qe
->state
= (void *)g_ptr_array_free(states
, FALSE
);
127 static void exit_states(QEMU_Elf
*qe
)
132 static bool check_ehdr(QEMU_Elf
*qe
)
134 Elf64_Ehdr
*ehdr
= qe
->map
;
137 if (sizeof(Elf64_Ehdr
) > qe
->size
) {
138 eprintf("Invalid input dump file size\n");
142 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
)) {
143 eprintf("Invalid ELF signature, input file is not ELF\n");
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");
153 if (ehdr
->e_ident
[EI_VERSION
] != EV_CURRENT
) {
154 eprintf("Invalid ELF version\n");
158 if (ehdr
->e_machine
!= EM_X86_64
) {
159 eprintf("Invalid input dump architecture, only x86_64 is supported\n");
163 if (ehdr
->e_type
!= ET_CORE
) {
164 eprintf("Invalid ELF type, must be core file\n");
169 * ELF dump file must contain one PT_NOTE and at least one PT_LOAD to
170 * restore physical address space.
172 if (ehdr
->e_phnum
< 2) {
173 eprintf("Invalid number of ELF program headers\n");
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");
187 static bool QEMU_Elf_map(QEMU_Elf
*qe
, const char *filename
)
193 printf("Using Linux mmap\n");
195 fd
= open(filename
, O_RDONLY
, 0);
197 eprintf("Failed to open ELF dump file \'%s\'\n", filename
);
201 if (fstat(fd
, &st
)) {
202 eprintf("Failed to get size of ELF dump file\n");
206 qe
->size
= st
.st_size
;
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");
220 printf("Using GLib mmap\n");
222 qe
->gmf
= g_mapped_file_new(filename
, TRUE
, &gerr
);
224 eprintf("Failed to map ELF dump file \'%s\'\n", filename
);
229 qe
->map
= g_mapped_file_get_contents(qe
->gmf
);
230 qe
->size
= g_mapped_file_get_length(qe
->gmf
);
236 static void QEMU_Elf_unmap(QEMU_Elf
*qe
)
239 munmap(qe
->map
, qe
->size
);
241 g_mapped_file_unref(qe
->gmf
);
245 bool QEMU_Elf_init(QEMU_Elf
*qe
, const char *filename
)
247 if (!QEMU_Elf_map(qe
, filename
)) {
251 if (!check_ehdr(qe
)) {
252 eprintf("Input file has the wrong format\n");
257 if (!init_states(qe
)) {
258 eprintf("Failed to extract QEMU CPU states\n");
266 void QEMU_Elf_exit(QEMU_Elf
*qe
)