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"
12 #define QEMU_NOTE_NAME "QEMU"
15 #define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d)))
19 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
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)
27 int is_system(QEMUCPUState
*s
)
29 return s
->gs
.base
>> 63;
32 static char *nhdr_get_name(Elf64_Nhdr
*nhdr
)
34 return (char *)nhdr
+ ROUND_UP(sizeof(*nhdr
), 4);
37 static void *nhdr_get_desc(Elf64_Nhdr
*nhdr
)
39 return nhdr_get_name(nhdr
) + ROUND_UP(nhdr
->n_namesz
, 4);
42 static Elf64_Nhdr
*nhdr_get_next(Elf64_Nhdr
*nhdr
)
44 return (void *)((uint8_t *)nhdr
+ ELF_NOTE_SIZE(sizeof(*nhdr
),
45 nhdr
->n_namesz
, nhdr
->n_descsz
));
48 Elf64_Phdr
*elf64_getphdr(void *map
)
50 Elf64_Ehdr
*ehdr
= map
;
51 Elf64_Phdr
*phdr
= (void *)((uint8_t *)map
+ ehdr
->e_phoff
);
56 Elf64_Half
elf_getphdrnum(void *map
)
58 Elf64_Ehdr
*ehdr
= map
;
63 static int init_states(QEMU_Elf
*qe
)
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
);
71 if (phdr
[0].p_type
!= PT_NOTE
) {
72 eprintf("Failed to find PT_NOTE\n");
76 qe
->has_kernel_gs_base
= 1;
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
);
82 if (state
->size
< sizeof(*state
)) {
83 eprintf("CPU #%zu: QEMU CPU state size %u doesn't match\n",
86 * We assume either every QEMU CPU state has KERNEL_GS_BASE or
89 qe
->has_kernel_gs_base
= 0;
95 printf("%zu CPU states has been found\n", cpu_nr
);
97 qe
->state
= g_new(QEMUCPUState
*, cpu_nr
);
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
);
108 qe
->state_nr
= cpu_nr
;
113 static void exit_states(QEMU_Elf
*qe
)
118 static bool check_ehdr(QEMU_Elf
*qe
)
120 Elf64_Ehdr
*ehdr
= qe
->map
;
122 if (sizeof(Elf64_Ehdr
) > qe
->size
) {
123 eprintf("Invalid input dump file size\n");
127 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
)) {
128 eprintf("Invalid ELF signature, input file is not ELF\n");
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");
138 if (ehdr
->e_ident
[EI_VERSION
] != EV_CURRENT
) {
139 eprintf("Invalid ELF version\n");
143 if (ehdr
->e_machine
!= EM_X86_64
) {
144 eprintf("Invalid input dump architecture, only x86_64 is supported\n");
148 if (ehdr
->e_type
!= ET_CORE
) {
149 eprintf("Invalid ELF type, must be core file\n");
154 * ELF dump file must contain one PT_NOTE and at least one PT_LOAD to
155 * restore physical address space.
157 if (ehdr
->e_phnum
< 2) {
158 eprintf("Invalid number of ELF program headers\n");
165 static int QEMU_Elf_map(QEMU_Elf
*qe
, const char *filename
)
171 printf("Using Linux mmap\n");
173 fd
= open(filename
, O_RDONLY
, 0);
175 eprintf("Failed to open ELF dump file \'%s\'\n", filename
);
179 if (fstat(fd
, &st
)) {
180 eprintf("Failed to get size of ELF dump file\n");
184 qe
->size
= st
.st_size
;
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");
198 printf("Using GLib mmap\n");
200 qe
->gmf
= g_mapped_file_new(filename
, TRUE
, &gerr
);
202 eprintf("Failed to map ELF dump file \'%s\'\n", filename
);
207 qe
->map
= g_mapped_file_get_contents(qe
->gmf
);
208 qe
->size
= g_mapped_file_get_length(qe
->gmf
);
214 static void QEMU_Elf_unmap(QEMU_Elf
*qe
)
217 munmap(qe
->map
, qe
->size
);
219 g_mapped_file_unref(qe
->gmf
);
223 int QEMU_Elf_init(QEMU_Elf
*qe
, const char *filename
)
225 if (QEMU_Elf_map(qe
, filename
)) {
229 if (!check_ehdr(qe
)) {
230 eprintf("Input file has the wrong format\n");
235 if (init_states(qe
)) {
236 eprintf("Failed to extract QEMU CPU states\n");
244 void QEMU_Elf_exit(QEMU_Elf
*qe
)