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 bool 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;
77 states
= g_ptr_array_new();
79 for (nhdr
= start
; nhdr
< end
; nhdr
= nhdr_get_next(nhdr
)) {
80 if (!strcmp(nhdr_get_name(nhdr
), QEMU_NOTE_NAME
)) {
81 QEMUCPUState
*state
= nhdr_get_desc(nhdr
);
83 if (state
->size
< sizeof(*state
)) {
84 eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n",
85 states
->len
, state
->size
);
87 * We assume either every QEMU CPU state has KERNEL_GS_BASE or
90 qe
->has_kernel_gs_base
= 0;
92 g_ptr_array_add(states
, state
);
96 printf("%u CPU states has been found\n", states
->len
);
98 qe
->state_nr
= states
->len
;
99 qe
->state
= (void *)g_ptr_array_free(states
, FALSE
);
104 static void exit_states(QEMU_Elf
*qe
)
109 static bool check_ehdr(QEMU_Elf
*qe
)
111 Elf64_Ehdr
*ehdr
= qe
->map
;
113 if (sizeof(Elf64_Ehdr
) > qe
->size
) {
114 eprintf("Invalid input dump file size\n");
118 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
)) {
119 eprintf("Invalid ELF signature, input file is not ELF\n");
123 if (ehdr
->e_ident
[EI_CLASS
] != ELFCLASS64
||
124 ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
125 eprintf("Invalid ELF class or byte order, must be 64-bit LE\n");
129 if (ehdr
->e_ident
[EI_VERSION
] != EV_CURRENT
) {
130 eprintf("Invalid ELF version\n");
134 if (ehdr
->e_machine
!= EM_X86_64
) {
135 eprintf("Invalid input dump architecture, only x86_64 is supported\n");
139 if (ehdr
->e_type
!= ET_CORE
) {
140 eprintf("Invalid ELF type, must be core file\n");
145 * ELF dump file must contain one PT_NOTE and at least one PT_LOAD to
146 * restore physical address space.
148 if (ehdr
->e_phnum
< 2) {
149 eprintf("Invalid number of ELF program headers\n");
156 static bool QEMU_Elf_map(QEMU_Elf
*qe
, const char *filename
)
162 printf("Using Linux mmap\n");
164 fd
= open(filename
, O_RDONLY
, 0);
166 eprintf("Failed to open ELF dump file \'%s\'\n", filename
);
170 if (fstat(fd
, &st
)) {
171 eprintf("Failed to get size of ELF dump file\n");
175 qe
->size
= st
.st_size
;
177 qe
->map
= mmap(NULL
, qe
->size
, PROT_READ
| PROT_WRITE
,
178 MAP_PRIVATE
| MAP_NORESERVE
, fd
, 0);
179 if (qe
->map
== MAP_FAILED
) {
180 eprintf("Failed to map ELF file\n");
189 printf("Using GLib mmap\n");
191 qe
->gmf
= g_mapped_file_new(filename
, TRUE
, &gerr
);
193 eprintf("Failed to map ELF dump file \'%s\'\n", filename
);
198 qe
->map
= g_mapped_file_get_contents(qe
->gmf
);
199 qe
->size
= g_mapped_file_get_length(qe
->gmf
);
205 static void QEMU_Elf_unmap(QEMU_Elf
*qe
)
208 munmap(qe
->map
, qe
->size
);
210 g_mapped_file_unref(qe
->gmf
);
214 bool QEMU_Elf_init(QEMU_Elf
*qe
, const char *filename
)
216 if (!QEMU_Elf_map(qe
, filename
)) {
220 if (!check_ehdr(qe
)) {
221 eprintf("Input file has the wrong format\n");
226 if (!init_states(qe
)) {
227 eprintf("Failed to extract QEMU CPU states\n");
235 void QEMU_Elf_exit(QEMU_Elf
*qe
)