Statistics
| Branch: | Revision:

root / dump.c @ 6a1751b7

History | View | Annotate | Download (23.4 kB)

1 783e9b48 Wen Congyang
/*
2 783e9b48 Wen Congyang
 * QEMU dump
3 783e9b48 Wen Congyang
 *
4 783e9b48 Wen Congyang
 * Copyright Fujitsu, Corp. 2011, 2012
5 783e9b48 Wen Congyang
 *
6 783e9b48 Wen Congyang
 * Authors:
7 783e9b48 Wen Congyang
 *     Wen Congyang <wency@cn.fujitsu.com>
8 783e9b48 Wen Congyang
 *
9 352666e2 Stefan Weil
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 352666e2 Stefan Weil
 * See the COPYING file in the top-level directory.
11 783e9b48 Wen Congyang
 *
12 783e9b48 Wen Congyang
 */
13 783e9b48 Wen Congyang
14 783e9b48 Wen Congyang
#include "qemu-common.h"
15 783e9b48 Wen Congyang
#include "elf.h"
16 783e9b48 Wen Congyang
#include "cpu.h"
17 022c62cb Paolo Bonzini
#include "exec/cpu-all.h"
18 022c62cb Paolo Bonzini
#include "exec/hwaddr.h"
19 83c9089e Paolo Bonzini
#include "monitor/monitor.h"
20 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
21 9c17d615 Paolo Bonzini
#include "sysemu/dump.h"
22 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
23 9c17d615 Paolo Bonzini
#include "sysemu/memory_mapping.h"
24 1b3509ca Andreas Färber
#include "sysemu/cpus.h"
25 7b1b5d19 Paolo Bonzini
#include "qapi/error.h"
26 783e9b48 Wen Congyang
#include "qmp-commands.h"
27 783e9b48 Wen Congyang
28 783e9b48 Wen Congyang
static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
29 783e9b48 Wen Congyang
{
30 783e9b48 Wen Congyang
    if (endian == ELFDATA2LSB) {
31 783e9b48 Wen Congyang
        val = cpu_to_le16(val);
32 783e9b48 Wen Congyang
    } else {
33 783e9b48 Wen Congyang
        val = cpu_to_be16(val);
34 783e9b48 Wen Congyang
    }
35 783e9b48 Wen Congyang
36 783e9b48 Wen Congyang
    return val;
37 783e9b48 Wen Congyang
}
38 783e9b48 Wen Congyang
39 783e9b48 Wen Congyang
static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
40 783e9b48 Wen Congyang
{
41 783e9b48 Wen Congyang
    if (endian == ELFDATA2LSB) {
42 783e9b48 Wen Congyang
        val = cpu_to_le32(val);
43 783e9b48 Wen Congyang
    } else {
44 783e9b48 Wen Congyang
        val = cpu_to_be32(val);
45 783e9b48 Wen Congyang
    }
46 783e9b48 Wen Congyang
47 783e9b48 Wen Congyang
    return val;
48 783e9b48 Wen Congyang
}
49 783e9b48 Wen Congyang
50 783e9b48 Wen Congyang
static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
51 783e9b48 Wen Congyang
{
52 783e9b48 Wen Congyang
    if (endian == ELFDATA2LSB) {
53 783e9b48 Wen Congyang
        val = cpu_to_le64(val);
54 783e9b48 Wen Congyang
    } else {
55 783e9b48 Wen Congyang
        val = cpu_to_be64(val);
56 783e9b48 Wen Congyang
    }
57 783e9b48 Wen Congyang
58 783e9b48 Wen Congyang
    return val;
59 783e9b48 Wen Congyang
}
60 783e9b48 Wen Congyang
61 783e9b48 Wen Congyang
typedef struct DumpState {
62 5ee163e8 Laszlo Ersek
    GuestPhysBlockList guest_phys_blocks;
63 783e9b48 Wen Congyang
    ArchDumpInfo dump_info;
64 783e9b48 Wen Congyang
    MemoryMappingList list;
65 783e9b48 Wen Congyang
    uint16_t phdr_num;
66 783e9b48 Wen Congyang
    uint32_t sh_info;
67 783e9b48 Wen Congyang
    bool have_section;
68 783e9b48 Wen Congyang
    bool resume;
69 783e9b48 Wen Congyang
    size_t note_size;
70 a8170e5e Avi Kivity
    hwaddr memory_offset;
71 783e9b48 Wen Congyang
    int fd;
72 783e9b48 Wen Congyang
73 56c4bfb3 Laszlo Ersek
    GuestPhysBlock *next_block;
74 783e9b48 Wen Congyang
    ram_addr_t start;
75 783e9b48 Wen Congyang
    bool has_filter;
76 783e9b48 Wen Congyang
    int64_t begin;
77 783e9b48 Wen Congyang
    int64_t length;
78 783e9b48 Wen Congyang
    Error **errp;
79 783e9b48 Wen Congyang
} DumpState;
80 783e9b48 Wen Congyang
81 783e9b48 Wen Congyang
static int dump_cleanup(DumpState *s)
82 783e9b48 Wen Congyang
{
83 783e9b48 Wen Congyang
    int ret = 0;
84 783e9b48 Wen Congyang
85 5ee163e8 Laszlo Ersek
    guest_phys_blocks_free(&s->guest_phys_blocks);
86 783e9b48 Wen Congyang
    memory_mapping_list_free(&s->list);
87 783e9b48 Wen Congyang
    if (s->fd != -1) {
88 783e9b48 Wen Congyang
        close(s->fd);
89 783e9b48 Wen Congyang
    }
90 783e9b48 Wen Congyang
    if (s->resume) {
91 783e9b48 Wen Congyang
        vm_start();
92 783e9b48 Wen Congyang
    }
93 783e9b48 Wen Congyang
94 783e9b48 Wen Congyang
    return ret;
95 783e9b48 Wen Congyang
}
96 783e9b48 Wen Congyang
97 783e9b48 Wen Congyang
static void dump_error(DumpState *s, const char *reason)
98 783e9b48 Wen Congyang
{
99 783e9b48 Wen Congyang
    dump_cleanup(s);
100 783e9b48 Wen Congyang
}
101 783e9b48 Wen Congyang
102 783e9b48 Wen Congyang
static int fd_write_vmcore(void *buf, size_t size, void *opaque)
103 783e9b48 Wen Congyang
{
104 783e9b48 Wen Congyang
    DumpState *s = opaque;
105 2f61652d Luiz Capitulino
    size_t written_size;
106 2f61652d Luiz Capitulino
107 2f61652d Luiz Capitulino
    written_size = qemu_write_full(s->fd, buf, size);
108 2f61652d Luiz Capitulino
    if (written_size != size) {
109 2f61652d Luiz Capitulino
        return -1;
110 783e9b48 Wen Congyang
    }
111 783e9b48 Wen Congyang
112 783e9b48 Wen Congyang
    return 0;
113 783e9b48 Wen Congyang
}
114 783e9b48 Wen Congyang
115 783e9b48 Wen Congyang
static int write_elf64_header(DumpState *s)
116 783e9b48 Wen Congyang
{
117 783e9b48 Wen Congyang
    Elf64_Ehdr elf_header;
118 783e9b48 Wen Congyang
    int ret;
119 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
120 783e9b48 Wen Congyang
121 783e9b48 Wen Congyang
    memset(&elf_header, 0, sizeof(Elf64_Ehdr));
122 783e9b48 Wen Congyang
    memcpy(&elf_header, ELFMAG, SELFMAG);
123 783e9b48 Wen Congyang
    elf_header.e_ident[EI_CLASS] = ELFCLASS64;
124 783e9b48 Wen Congyang
    elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
125 783e9b48 Wen Congyang
    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
126 783e9b48 Wen Congyang
    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
127 783e9b48 Wen Congyang
    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
128 783e9b48 Wen Congyang
                                                   endian);
129 783e9b48 Wen Congyang
    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
130 783e9b48 Wen Congyang
    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
131 783e9b48 Wen Congyang
    elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
132 783e9b48 Wen Congyang
    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
133 783e9b48 Wen Congyang
                                                     endian);
134 783e9b48 Wen Congyang
    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
135 783e9b48 Wen Congyang
    if (s->have_section) {
136 783e9b48 Wen Congyang
        uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
137 783e9b48 Wen Congyang
138 783e9b48 Wen Congyang
        elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
139 783e9b48 Wen Congyang
        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
140 783e9b48 Wen Congyang
                                                         endian);
141 783e9b48 Wen Congyang
        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
142 783e9b48 Wen Congyang
    }
143 783e9b48 Wen Congyang
144 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
145 783e9b48 Wen Congyang
    if (ret < 0) {
146 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write elf header.\n");
147 783e9b48 Wen Congyang
        return -1;
148 783e9b48 Wen Congyang
    }
149 783e9b48 Wen Congyang
150 783e9b48 Wen Congyang
    return 0;
151 783e9b48 Wen Congyang
}
152 783e9b48 Wen Congyang
153 783e9b48 Wen Congyang
static int write_elf32_header(DumpState *s)
154 783e9b48 Wen Congyang
{
155 783e9b48 Wen Congyang
    Elf32_Ehdr elf_header;
156 783e9b48 Wen Congyang
    int ret;
157 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
158 783e9b48 Wen Congyang
159 783e9b48 Wen Congyang
    memset(&elf_header, 0, sizeof(Elf32_Ehdr));
160 783e9b48 Wen Congyang
    memcpy(&elf_header, ELFMAG, SELFMAG);
161 783e9b48 Wen Congyang
    elf_header.e_ident[EI_CLASS] = ELFCLASS32;
162 783e9b48 Wen Congyang
    elf_header.e_ident[EI_DATA] = endian;
163 783e9b48 Wen Congyang
    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
164 783e9b48 Wen Congyang
    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
165 783e9b48 Wen Congyang
    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
166 783e9b48 Wen Congyang
                                                   endian);
167 783e9b48 Wen Congyang
    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
168 783e9b48 Wen Congyang
    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
169 783e9b48 Wen Congyang
    elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
170 783e9b48 Wen Congyang
    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
171 783e9b48 Wen Congyang
                                                     endian);
172 783e9b48 Wen Congyang
    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
173 783e9b48 Wen Congyang
    if (s->have_section) {
174 783e9b48 Wen Congyang
        uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
175 783e9b48 Wen Congyang
176 783e9b48 Wen Congyang
        elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
177 783e9b48 Wen Congyang
        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
178 783e9b48 Wen Congyang
                                                         endian);
179 783e9b48 Wen Congyang
        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
180 783e9b48 Wen Congyang
    }
181 783e9b48 Wen Congyang
182 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
183 783e9b48 Wen Congyang
    if (ret < 0) {
184 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write elf header.\n");
185 783e9b48 Wen Congyang
        return -1;
186 783e9b48 Wen Congyang
    }
187 783e9b48 Wen Congyang
188 783e9b48 Wen Congyang
    return 0;
189 783e9b48 Wen Congyang
}
190 783e9b48 Wen Congyang
191 783e9b48 Wen Congyang
static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
192 2cac2607 Laszlo Ersek
                            int phdr_index, hwaddr offset,
193 2cac2607 Laszlo Ersek
                            hwaddr filesz)
194 783e9b48 Wen Congyang
{
195 783e9b48 Wen Congyang
    Elf64_Phdr phdr;
196 783e9b48 Wen Congyang
    int ret;
197 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
198 783e9b48 Wen Congyang
199 783e9b48 Wen Congyang
    memset(&phdr, 0, sizeof(Elf64_Phdr));
200 783e9b48 Wen Congyang
    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
201 783e9b48 Wen Congyang
    phdr.p_offset = cpu_convert_to_target64(offset, endian);
202 783e9b48 Wen Congyang
    phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
203 2cac2607 Laszlo Ersek
    phdr.p_filesz = cpu_convert_to_target64(filesz, endian);
204 783e9b48 Wen Congyang
    phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
205 783e9b48 Wen Congyang
    phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
206 783e9b48 Wen Congyang
207 2cac2607 Laszlo Ersek
    assert(memory_mapping->length >= filesz);
208 2cac2607 Laszlo Ersek
209 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
210 783e9b48 Wen Congyang
    if (ret < 0) {
211 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write program header table.\n");
212 783e9b48 Wen Congyang
        return -1;
213 783e9b48 Wen Congyang
    }
214 783e9b48 Wen Congyang
215 783e9b48 Wen Congyang
    return 0;
216 783e9b48 Wen Congyang
}
217 783e9b48 Wen Congyang
218 783e9b48 Wen Congyang
static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
219 2cac2607 Laszlo Ersek
                            int phdr_index, hwaddr offset,
220 2cac2607 Laszlo Ersek
                            hwaddr filesz)
221 783e9b48 Wen Congyang
{
222 783e9b48 Wen Congyang
    Elf32_Phdr phdr;
223 783e9b48 Wen Congyang
    int ret;
224 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
225 783e9b48 Wen Congyang
226 783e9b48 Wen Congyang
    memset(&phdr, 0, sizeof(Elf32_Phdr));
227 783e9b48 Wen Congyang
    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
228 783e9b48 Wen Congyang
    phdr.p_offset = cpu_convert_to_target32(offset, endian);
229 783e9b48 Wen Congyang
    phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
230 2cac2607 Laszlo Ersek
    phdr.p_filesz = cpu_convert_to_target32(filesz, endian);
231 783e9b48 Wen Congyang
    phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
232 783e9b48 Wen Congyang
    phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
233 783e9b48 Wen Congyang
234 2cac2607 Laszlo Ersek
    assert(memory_mapping->length >= filesz);
235 2cac2607 Laszlo Ersek
236 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
237 783e9b48 Wen Congyang
    if (ret < 0) {
238 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write program header table.\n");
239 783e9b48 Wen Congyang
        return -1;
240 783e9b48 Wen Congyang
    }
241 783e9b48 Wen Congyang
242 783e9b48 Wen Congyang
    return 0;
243 783e9b48 Wen Congyang
}
244 783e9b48 Wen Congyang
245 783e9b48 Wen Congyang
static int write_elf64_note(DumpState *s)
246 783e9b48 Wen Congyang
{
247 783e9b48 Wen Congyang
    Elf64_Phdr phdr;
248 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
249 a8170e5e Avi Kivity
    hwaddr begin = s->memory_offset - s->note_size;
250 783e9b48 Wen Congyang
    int ret;
251 783e9b48 Wen Congyang
252 783e9b48 Wen Congyang
    memset(&phdr, 0, sizeof(Elf64_Phdr));
253 783e9b48 Wen Congyang
    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
254 783e9b48 Wen Congyang
    phdr.p_offset = cpu_convert_to_target64(begin, endian);
255 783e9b48 Wen Congyang
    phdr.p_paddr = 0;
256 783e9b48 Wen Congyang
    phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
257 783e9b48 Wen Congyang
    phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
258 783e9b48 Wen Congyang
    phdr.p_vaddr = 0;
259 783e9b48 Wen Congyang
260 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
261 783e9b48 Wen Congyang
    if (ret < 0) {
262 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write program header table.\n");
263 783e9b48 Wen Congyang
        return -1;
264 783e9b48 Wen Congyang
    }
265 783e9b48 Wen Congyang
266 783e9b48 Wen Congyang
    return 0;
267 783e9b48 Wen Congyang
}
268 783e9b48 Wen Congyang
269 0bc3cd62 Paolo Bonzini
static inline int cpu_index(CPUState *cpu)
270 0bc3cd62 Paolo Bonzini
{
271 0bc3cd62 Paolo Bonzini
    return cpu->cpu_index + 1;
272 0bc3cd62 Paolo Bonzini
}
273 0bc3cd62 Paolo Bonzini
274 783e9b48 Wen Congyang
static int write_elf64_notes(DumpState *s)
275 783e9b48 Wen Congyang
{
276 0d34282f Andreas Färber
    CPUState *cpu;
277 783e9b48 Wen Congyang
    int ret;
278 783e9b48 Wen Congyang
    int id;
279 783e9b48 Wen Congyang
280 182735ef Andreas Färber
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
281 0d34282f Andreas Färber
        id = cpu_index(cpu);
282 c72bf468 Jens Freimann
        ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
283 783e9b48 Wen Congyang
        if (ret < 0) {
284 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write elf notes.\n");
285 783e9b48 Wen Congyang
            return -1;
286 783e9b48 Wen Congyang
        }
287 783e9b48 Wen Congyang
    }
288 783e9b48 Wen Congyang
289 182735ef Andreas Färber
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
290 c72bf468 Jens Freimann
        ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
291 783e9b48 Wen Congyang
        if (ret < 0) {
292 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write CPU status.\n");
293 783e9b48 Wen Congyang
            return -1;
294 783e9b48 Wen Congyang
        }
295 783e9b48 Wen Congyang
    }
296 783e9b48 Wen Congyang
297 783e9b48 Wen Congyang
    return 0;
298 783e9b48 Wen Congyang
}
299 783e9b48 Wen Congyang
300 783e9b48 Wen Congyang
static int write_elf32_note(DumpState *s)
301 783e9b48 Wen Congyang
{
302 a8170e5e Avi Kivity
    hwaddr begin = s->memory_offset - s->note_size;
303 783e9b48 Wen Congyang
    Elf32_Phdr phdr;
304 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
305 783e9b48 Wen Congyang
    int ret;
306 783e9b48 Wen Congyang
307 783e9b48 Wen Congyang
    memset(&phdr, 0, sizeof(Elf32_Phdr));
308 783e9b48 Wen Congyang
    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
309 783e9b48 Wen Congyang
    phdr.p_offset = cpu_convert_to_target32(begin, endian);
310 783e9b48 Wen Congyang
    phdr.p_paddr = 0;
311 783e9b48 Wen Congyang
    phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
312 783e9b48 Wen Congyang
    phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
313 783e9b48 Wen Congyang
    phdr.p_vaddr = 0;
314 783e9b48 Wen Congyang
315 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
316 783e9b48 Wen Congyang
    if (ret < 0) {
317 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write program header table.\n");
318 783e9b48 Wen Congyang
        return -1;
319 783e9b48 Wen Congyang
    }
320 783e9b48 Wen Congyang
321 783e9b48 Wen Congyang
    return 0;
322 783e9b48 Wen Congyang
}
323 783e9b48 Wen Congyang
324 783e9b48 Wen Congyang
static int write_elf32_notes(DumpState *s)
325 783e9b48 Wen Congyang
{
326 0d34282f Andreas Färber
    CPUState *cpu;
327 783e9b48 Wen Congyang
    int ret;
328 783e9b48 Wen Congyang
    int id;
329 783e9b48 Wen Congyang
330 182735ef Andreas Färber
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
331 0d34282f Andreas Färber
        id = cpu_index(cpu);
332 c72bf468 Jens Freimann
        ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
333 783e9b48 Wen Congyang
        if (ret < 0) {
334 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write elf notes.\n");
335 783e9b48 Wen Congyang
            return -1;
336 783e9b48 Wen Congyang
        }
337 783e9b48 Wen Congyang
    }
338 783e9b48 Wen Congyang
339 182735ef Andreas Färber
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
340 c72bf468 Jens Freimann
        ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
341 783e9b48 Wen Congyang
        if (ret < 0) {
342 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write CPU status.\n");
343 783e9b48 Wen Congyang
            return -1;
344 783e9b48 Wen Congyang
        }
345 783e9b48 Wen Congyang
    }
346 783e9b48 Wen Congyang
347 783e9b48 Wen Congyang
    return 0;
348 783e9b48 Wen Congyang
}
349 783e9b48 Wen Congyang
350 783e9b48 Wen Congyang
static int write_elf_section(DumpState *s, int type)
351 783e9b48 Wen Congyang
{
352 783e9b48 Wen Congyang
    Elf32_Shdr shdr32;
353 783e9b48 Wen Congyang
    Elf64_Shdr shdr64;
354 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
355 783e9b48 Wen Congyang
    int shdr_size;
356 783e9b48 Wen Congyang
    void *shdr;
357 783e9b48 Wen Congyang
    int ret;
358 783e9b48 Wen Congyang
359 783e9b48 Wen Congyang
    if (type == 0) {
360 783e9b48 Wen Congyang
        shdr_size = sizeof(Elf32_Shdr);
361 783e9b48 Wen Congyang
        memset(&shdr32, 0, shdr_size);
362 783e9b48 Wen Congyang
        shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
363 783e9b48 Wen Congyang
        shdr = &shdr32;
364 783e9b48 Wen Congyang
    } else {
365 783e9b48 Wen Congyang
        shdr_size = sizeof(Elf64_Shdr);
366 783e9b48 Wen Congyang
        memset(&shdr64, 0, shdr_size);
367 783e9b48 Wen Congyang
        shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
368 783e9b48 Wen Congyang
        shdr = &shdr64;
369 783e9b48 Wen Congyang
    }
370 783e9b48 Wen Congyang
371 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&shdr, shdr_size, s);
372 783e9b48 Wen Congyang
    if (ret < 0) {
373 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write section header table.\n");
374 783e9b48 Wen Congyang
        return -1;
375 783e9b48 Wen Congyang
    }
376 783e9b48 Wen Congyang
377 783e9b48 Wen Congyang
    return 0;
378 783e9b48 Wen Congyang
}
379 783e9b48 Wen Congyang
380 783e9b48 Wen Congyang
static int write_data(DumpState *s, void *buf, int length)
381 783e9b48 Wen Congyang
{
382 783e9b48 Wen Congyang
    int ret;
383 783e9b48 Wen Congyang
384 783e9b48 Wen Congyang
    ret = fd_write_vmcore(buf, length, s);
385 783e9b48 Wen Congyang
    if (ret < 0) {
386 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to save memory.\n");
387 783e9b48 Wen Congyang
        return -1;
388 783e9b48 Wen Congyang
    }
389 783e9b48 Wen Congyang
390 783e9b48 Wen Congyang
    return 0;
391 783e9b48 Wen Congyang
}
392 783e9b48 Wen Congyang
393 783e9b48 Wen Congyang
/* write the memroy to vmcore. 1 page per I/O. */
394 56c4bfb3 Laszlo Ersek
static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start,
395 783e9b48 Wen Congyang
                        int64_t size)
396 783e9b48 Wen Congyang
{
397 783e9b48 Wen Congyang
    int64_t i;
398 783e9b48 Wen Congyang
    int ret;
399 783e9b48 Wen Congyang
400 783e9b48 Wen Congyang
    for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
401 56c4bfb3 Laszlo Ersek
        ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
402 783e9b48 Wen Congyang
                         TARGET_PAGE_SIZE);
403 783e9b48 Wen Congyang
        if (ret < 0) {
404 783e9b48 Wen Congyang
            return ret;
405 783e9b48 Wen Congyang
        }
406 783e9b48 Wen Congyang
    }
407 783e9b48 Wen Congyang
408 783e9b48 Wen Congyang
    if ((size % TARGET_PAGE_SIZE) != 0) {
409 56c4bfb3 Laszlo Ersek
        ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
410 783e9b48 Wen Congyang
                         size % TARGET_PAGE_SIZE);
411 783e9b48 Wen Congyang
        if (ret < 0) {
412 783e9b48 Wen Congyang
            return ret;
413 783e9b48 Wen Congyang
        }
414 783e9b48 Wen Congyang
    }
415 783e9b48 Wen Congyang
416 783e9b48 Wen Congyang
    return 0;
417 783e9b48 Wen Congyang
}
418 783e9b48 Wen Congyang
419 2cac2607 Laszlo Ersek
/* get the memory's offset and size in the vmcore */
420 2cac2607 Laszlo Ersek
static void get_offset_range(hwaddr phys_addr,
421 2cac2607 Laszlo Ersek
                             ram_addr_t mapping_length,
422 2cac2607 Laszlo Ersek
                             DumpState *s,
423 2cac2607 Laszlo Ersek
                             hwaddr *p_offset,
424 2cac2607 Laszlo Ersek
                             hwaddr *p_filesz)
425 783e9b48 Wen Congyang
{
426 56c4bfb3 Laszlo Ersek
    GuestPhysBlock *block;
427 a8170e5e Avi Kivity
    hwaddr offset = s->memory_offset;
428 783e9b48 Wen Congyang
    int64_t size_in_block, start;
429 783e9b48 Wen Congyang
430 2cac2607 Laszlo Ersek
    /* When the memory is not stored into vmcore, offset will be -1 */
431 2cac2607 Laszlo Ersek
    *p_offset = -1;
432 2cac2607 Laszlo Ersek
    *p_filesz = 0;
433 2cac2607 Laszlo Ersek
434 783e9b48 Wen Congyang
    if (s->has_filter) {
435 783e9b48 Wen Congyang
        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
436 2cac2607 Laszlo Ersek
            return;
437 783e9b48 Wen Congyang
        }
438 783e9b48 Wen Congyang
    }
439 783e9b48 Wen Congyang
440 56c4bfb3 Laszlo Ersek
    QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
441 783e9b48 Wen Congyang
        if (s->has_filter) {
442 56c4bfb3 Laszlo Ersek
            if (block->target_start >= s->begin + s->length ||
443 56c4bfb3 Laszlo Ersek
                block->target_end <= s->begin) {
444 783e9b48 Wen Congyang
                /* This block is out of the range */
445 783e9b48 Wen Congyang
                continue;
446 783e9b48 Wen Congyang
            }
447 783e9b48 Wen Congyang
448 56c4bfb3 Laszlo Ersek
            if (s->begin <= block->target_start) {
449 56c4bfb3 Laszlo Ersek
                start = block->target_start;
450 783e9b48 Wen Congyang
            } else {
451 783e9b48 Wen Congyang
                start = s->begin;
452 783e9b48 Wen Congyang
            }
453 783e9b48 Wen Congyang
454 56c4bfb3 Laszlo Ersek
            size_in_block = block->target_end - start;
455 56c4bfb3 Laszlo Ersek
            if (s->begin + s->length < block->target_end) {
456 56c4bfb3 Laszlo Ersek
                size_in_block -= block->target_end - (s->begin + s->length);
457 783e9b48 Wen Congyang
            }
458 783e9b48 Wen Congyang
        } else {
459 56c4bfb3 Laszlo Ersek
            start = block->target_start;
460 56c4bfb3 Laszlo Ersek
            size_in_block = block->target_end - block->target_start;
461 783e9b48 Wen Congyang
        }
462 783e9b48 Wen Congyang
463 783e9b48 Wen Congyang
        if (phys_addr >= start && phys_addr < start + size_in_block) {
464 2cac2607 Laszlo Ersek
            *p_offset = phys_addr - start + offset;
465 2cac2607 Laszlo Ersek
466 2cac2607 Laszlo Ersek
            /* The offset range mapped from the vmcore file must not spill over
467 56c4bfb3 Laszlo Ersek
             * the GuestPhysBlock, clamp it. The rest of the mapping will be
468 2cac2607 Laszlo Ersek
             * zero-filled in memory at load time; see
469 2cac2607 Laszlo Ersek
             * <http://refspecs.linuxbase.org/elf/gabi4+/ch5.pheader.html>.
470 2cac2607 Laszlo Ersek
             */
471 2cac2607 Laszlo Ersek
            *p_filesz = phys_addr + mapping_length <= start + size_in_block ?
472 2cac2607 Laszlo Ersek
                        mapping_length :
473 2cac2607 Laszlo Ersek
                        size_in_block - (phys_addr - start);
474 2cac2607 Laszlo Ersek
            return;
475 783e9b48 Wen Congyang
        }
476 783e9b48 Wen Congyang
477 783e9b48 Wen Congyang
        offset += size_in_block;
478 783e9b48 Wen Congyang
    }
479 783e9b48 Wen Congyang
}
480 783e9b48 Wen Congyang
481 783e9b48 Wen Congyang
static int write_elf_loads(DumpState *s)
482 783e9b48 Wen Congyang
{
483 2cac2607 Laszlo Ersek
    hwaddr offset, filesz;
484 783e9b48 Wen Congyang
    MemoryMapping *memory_mapping;
485 783e9b48 Wen Congyang
    uint32_t phdr_index = 1;
486 783e9b48 Wen Congyang
    int ret;
487 783e9b48 Wen Congyang
    uint32_t max_index;
488 783e9b48 Wen Congyang
489 783e9b48 Wen Congyang
    if (s->have_section) {
490 783e9b48 Wen Congyang
        max_index = s->sh_info;
491 783e9b48 Wen Congyang
    } else {
492 783e9b48 Wen Congyang
        max_index = s->phdr_num;
493 783e9b48 Wen Congyang
    }
494 783e9b48 Wen Congyang
495 783e9b48 Wen Congyang
    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
496 2cac2607 Laszlo Ersek
        get_offset_range(memory_mapping->phys_addr,
497 2cac2607 Laszlo Ersek
                         memory_mapping->length,
498 2cac2607 Laszlo Ersek
                         s, &offset, &filesz);
499 783e9b48 Wen Congyang
        if (s->dump_info.d_class == ELFCLASS64) {
500 2cac2607 Laszlo Ersek
            ret = write_elf64_load(s, memory_mapping, phdr_index++, offset,
501 2cac2607 Laszlo Ersek
                                   filesz);
502 783e9b48 Wen Congyang
        } else {
503 2cac2607 Laszlo Ersek
            ret = write_elf32_load(s, memory_mapping, phdr_index++, offset,
504 2cac2607 Laszlo Ersek
                                   filesz);
505 783e9b48 Wen Congyang
        }
506 783e9b48 Wen Congyang
507 783e9b48 Wen Congyang
        if (ret < 0) {
508 783e9b48 Wen Congyang
            return -1;
509 783e9b48 Wen Congyang
        }
510 783e9b48 Wen Congyang
511 783e9b48 Wen Congyang
        if (phdr_index >= max_index) {
512 783e9b48 Wen Congyang
            break;
513 783e9b48 Wen Congyang
        }
514 783e9b48 Wen Congyang
    }
515 783e9b48 Wen Congyang
516 783e9b48 Wen Congyang
    return 0;
517 783e9b48 Wen Congyang
}
518 783e9b48 Wen Congyang
519 783e9b48 Wen Congyang
/* write elf header, PT_NOTE and elf note to vmcore. */
520 783e9b48 Wen Congyang
static int dump_begin(DumpState *s)
521 783e9b48 Wen Congyang
{
522 783e9b48 Wen Congyang
    int ret;
523 783e9b48 Wen Congyang
524 783e9b48 Wen Congyang
    /*
525 783e9b48 Wen Congyang
     * the vmcore's format is:
526 783e9b48 Wen Congyang
     *   --------------
527 783e9b48 Wen Congyang
     *   |  elf header |
528 783e9b48 Wen Congyang
     *   --------------
529 783e9b48 Wen Congyang
     *   |  PT_NOTE    |
530 783e9b48 Wen Congyang
     *   --------------
531 783e9b48 Wen Congyang
     *   |  PT_LOAD    |
532 783e9b48 Wen Congyang
     *   --------------
533 783e9b48 Wen Congyang
     *   |  ......     |
534 783e9b48 Wen Congyang
     *   --------------
535 783e9b48 Wen Congyang
     *   |  PT_LOAD    |
536 783e9b48 Wen Congyang
     *   --------------
537 783e9b48 Wen Congyang
     *   |  sec_hdr    |
538 783e9b48 Wen Congyang
     *   --------------
539 783e9b48 Wen Congyang
     *   |  elf note   |
540 783e9b48 Wen Congyang
     *   --------------
541 783e9b48 Wen Congyang
     *   |  memory     |
542 783e9b48 Wen Congyang
     *   --------------
543 783e9b48 Wen Congyang
     *
544 783e9b48 Wen Congyang
     * we only know where the memory is saved after we write elf note into
545 783e9b48 Wen Congyang
     * vmcore.
546 783e9b48 Wen Congyang
     */
547 783e9b48 Wen Congyang
548 783e9b48 Wen Congyang
    /* write elf header to vmcore */
549 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
550 783e9b48 Wen Congyang
        ret = write_elf64_header(s);
551 783e9b48 Wen Congyang
    } else {
552 783e9b48 Wen Congyang
        ret = write_elf32_header(s);
553 783e9b48 Wen Congyang
    }
554 783e9b48 Wen Congyang
    if (ret < 0) {
555 783e9b48 Wen Congyang
        return -1;
556 783e9b48 Wen Congyang
    }
557 783e9b48 Wen Congyang
558 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
559 783e9b48 Wen Congyang
        /* write PT_NOTE to vmcore */
560 783e9b48 Wen Congyang
        if (write_elf64_note(s) < 0) {
561 783e9b48 Wen Congyang
            return -1;
562 783e9b48 Wen Congyang
        }
563 783e9b48 Wen Congyang
564 783e9b48 Wen Congyang
        /* write all PT_LOAD to vmcore */
565 783e9b48 Wen Congyang
        if (write_elf_loads(s) < 0) {
566 783e9b48 Wen Congyang
            return -1;
567 783e9b48 Wen Congyang
        }
568 783e9b48 Wen Congyang
569 783e9b48 Wen Congyang
        /* write section to vmcore */
570 783e9b48 Wen Congyang
        if (s->have_section) {
571 783e9b48 Wen Congyang
            if (write_elf_section(s, 1) < 0) {
572 783e9b48 Wen Congyang
                return -1;
573 783e9b48 Wen Congyang
            }
574 783e9b48 Wen Congyang
        }
575 783e9b48 Wen Congyang
576 783e9b48 Wen Congyang
        /* write notes to vmcore */
577 783e9b48 Wen Congyang
        if (write_elf64_notes(s) < 0) {
578 783e9b48 Wen Congyang
            return -1;
579 783e9b48 Wen Congyang
        }
580 783e9b48 Wen Congyang
581 783e9b48 Wen Congyang
    } else {
582 783e9b48 Wen Congyang
        /* write PT_NOTE to vmcore */
583 783e9b48 Wen Congyang
        if (write_elf32_note(s) < 0) {
584 783e9b48 Wen Congyang
            return -1;
585 783e9b48 Wen Congyang
        }
586 783e9b48 Wen Congyang
587 783e9b48 Wen Congyang
        /* write all PT_LOAD to vmcore */
588 783e9b48 Wen Congyang
        if (write_elf_loads(s) < 0) {
589 783e9b48 Wen Congyang
            return -1;
590 783e9b48 Wen Congyang
        }
591 783e9b48 Wen Congyang
592 783e9b48 Wen Congyang
        /* write section to vmcore */
593 783e9b48 Wen Congyang
        if (s->have_section) {
594 783e9b48 Wen Congyang
            if (write_elf_section(s, 0) < 0) {
595 783e9b48 Wen Congyang
                return -1;
596 783e9b48 Wen Congyang
            }
597 783e9b48 Wen Congyang
        }
598 783e9b48 Wen Congyang
599 783e9b48 Wen Congyang
        /* write notes to vmcore */
600 783e9b48 Wen Congyang
        if (write_elf32_notes(s) < 0) {
601 783e9b48 Wen Congyang
            return -1;
602 783e9b48 Wen Congyang
        }
603 783e9b48 Wen Congyang
    }
604 783e9b48 Wen Congyang
605 783e9b48 Wen Congyang
    return 0;
606 783e9b48 Wen Congyang
}
607 783e9b48 Wen Congyang
608 783e9b48 Wen Congyang
/* write PT_LOAD to vmcore */
609 783e9b48 Wen Congyang
static int dump_completed(DumpState *s)
610 783e9b48 Wen Congyang
{
611 783e9b48 Wen Congyang
    dump_cleanup(s);
612 783e9b48 Wen Congyang
    return 0;
613 783e9b48 Wen Congyang
}
614 783e9b48 Wen Congyang
615 56c4bfb3 Laszlo Ersek
static int get_next_block(DumpState *s, GuestPhysBlock *block)
616 783e9b48 Wen Congyang
{
617 783e9b48 Wen Congyang
    while (1) {
618 a3161038 Paolo Bonzini
        block = QTAILQ_NEXT(block, next);
619 783e9b48 Wen Congyang
        if (!block) {
620 783e9b48 Wen Congyang
            /* no more block */
621 783e9b48 Wen Congyang
            return 1;
622 783e9b48 Wen Congyang
        }
623 783e9b48 Wen Congyang
624 783e9b48 Wen Congyang
        s->start = 0;
625 56c4bfb3 Laszlo Ersek
        s->next_block = block;
626 783e9b48 Wen Congyang
        if (s->has_filter) {
627 56c4bfb3 Laszlo Ersek
            if (block->target_start >= s->begin + s->length ||
628 56c4bfb3 Laszlo Ersek
                block->target_end <= s->begin) {
629 783e9b48 Wen Congyang
                /* This block is out of the range */
630 783e9b48 Wen Congyang
                continue;
631 783e9b48 Wen Congyang
            }
632 783e9b48 Wen Congyang
633 56c4bfb3 Laszlo Ersek
            if (s->begin > block->target_start) {
634 56c4bfb3 Laszlo Ersek
                s->start = s->begin - block->target_start;
635 783e9b48 Wen Congyang
            }
636 783e9b48 Wen Congyang
        }
637 783e9b48 Wen Congyang
638 783e9b48 Wen Congyang
        return 0;
639 783e9b48 Wen Congyang
    }
640 783e9b48 Wen Congyang
}
641 783e9b48 Wen Congyang
642 783e9b48 Wen Congyang
/* write all memory to vmcore */
643 783e9b48 Wen Congyang
static int dump_iterate(DumpState *s)
644 783e9b48 Wen Congyang
{
645 56c4bfb3 Laszlo Ersek
    GuestPhysBlock *block;
646 783e9b48 Wen Congyang
    int64_t size;
647 783e9b48 Wen Congyang
    int ret;
648 783e9b48 Wen Congyang
649 783e9b48 Wen Congyang
    while (1) {
650 56c4bfb3 Laszlo Ersek
        block = s->next_block;
651 783e9b48 Wen Congyang
652 56c4bfb3 Laszlo Ersek
        size = block->target_end - block->target_start;
653 783e9b48 Wen Congyang
        if (s->has_filter) {
654 783e9b48 Wen Congyang
            size -= s->start;
655 56c4bfb3 Laszlo Ersek
            if (s->begin + s->length < block->target_end) {
656 56c4bfb3 Laszlo Ersek
                size -= block->target_end - (s->begin + s->length);
657 783e9b48 Wen Congyang
            }
658 783e9b48 Wen Congyang
        }
659 783e9b48 Wen Congyang
        ret = write_memory(s, block, s->start, size);
660 783e9b48 Wen Congyang
        if (ret == -1) {
661 783e9b48 Wen Congyang
            return ret;
662 783e9b48 Wen Congyang
        }
663 783e9b48 Wen Congyang
664 783e9b48 Wen Congyang
        ret = get_next_block(s, block);
665 783e9b48 Wen Congyang
        if (ret == 1) {
666 783e9b48 Wen Congyang
            dump_completed(s);
667 783e9b48 Wen Congyang
            return 0;
668 783e9b48 Wen Congyang
        }
669 783e9b48 Wen Congyang
    }
670 783e9b48 Wen Congyang
}
671 783e9b48 Wen Congyang
672 783e9b48 Wen Congyang
static int create_vmcore(DumpState *s)
673 783e9b48 Wen Congyang
{
674 783e9b48 Wen Congyang
    int ret;
675 783e9b48 Wen Congyang
676 783e9b48 Wen Congyang
    ret = dump_begin(s);
677 783e9b48 Wen Congyang
    if (ret < 0) {
678 783e9b48 Wen Congyang
        return -1;
679 783e9b48 Wen Congyang
    }
680 783e9b48 Wen Congyang
681 783e9b48 Wen Congyang
    ret = dump_iterate(s);
682 783e9b48 Wen Congyang
    if (ret < 0) {
683 783e9b48 Wen Congyang
        return -1;
684 783e9b48 Wen Congyang
    }
685 783e9b48 Wen Congyang
686 783e9b48 Wen Congyang
    return 0;
687 783e9b48 Wen Congyang
}
688 783e9b48 Wen Congyang
689 783e9b48 Wen Congyang
static ram_addr_t get_start_block(DumpState *s)
690 783e9b48 Wen Congyang
{
691 56c4bfb3 Laszlo Ersek
    GuestPhysBlock *block;
692 783e9b48 Wen Congyang
693 783e9b48 Wen Congyang
    if (!s->has_filter) {
694 56c4bfb3 Laszlo Ersek
        s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
695 783e9b48 Wen Congyang
        return 0;
696 783e9b48 Wen Congyang
    }
697 783e9b48 Wen Congyang
698 56c4bfb3 Laszlo Ersek
    QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
699 56c4bfb3 Laszlo Ersek
        if (block->target_start >= s->begin + s->length ||
700 56c4bfb3 Laszlo Ersek
            block->target_end <= s->begin) {
701 783e9b48 Wen Congyang
            /* This block is out of the range */
702 783e9b48 Wen Congyang
            continue;
703 783e9b48 Wen Congyang
        }
704 783e9b48 Wen Congyang
705 56c4bfb3 Laszlo Ersek
        s->next_block = block;
706 56c4bfb3 Laszlo Ersek
        if (s->begin > block->target_start) {
707 56c4bfb3 Laszlo Ersek
            s->start = s->begin - block->target_start;
708 783e9b48 Wen Congyang
        } else {
709 783e9b48 Wen Congyang
            s->start = 0;
710 783e9b48 Wen Congyang
        }
711 783e9b48 Wen Congyang
        return s->start;
712 783e9b48 Wen Congyang
    }
713 783e9b48 Wen Congyang
714 783e9b48 Wen Congyang
    return -1;
715 783e9b48 Wen Congyang
}
716 783e9b48 Wen Congyang
717 783e9b48 Wen Congyang
static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
718 783e9b48 Wen Congyang
                     int64_t begin, int64_t length, Error **errp)
719 783e9b48 Wen Congyang
{
720 182735ef Andreas Färber
    CPUState *cpu;
721 783e9b48 Wen Congyang
    int nr_cpus;
722 11ed09cf Andreas Färber
    Error *err = NULL;
723 783e9b48 Wen Congyang
    int ret;
724 783e9b48 Wen Congyang
725 783e9b48 Wen Congyang
    if (runstate_is_running()) {
726 783e9b48 Wen Congyang
        vm_stop(RUN_STATE_SAVE_VM);
727 783e9b48 Wen Congyang
        s->resume = true;
728 783e9b48 Wen Congyang
    } else {
729 783e9b48 Wen Congyang
        s->resume = false;
730 783e9b48 Wen Congyang
    }
731 783e9b48 Wen Congyang
732 5ee163e8 Laszlo Ersek
    /* If we use KVM, we should synchronize the registers before we get dump
733 5ee163e8 Laszlo Ersek
     * info or physmap info.
734 5ee163e8 Laszlo Ersek
     */
735 5ee163e8 Laszlo Ersek
    cpu_synchronize_all_states();
736 5ee163e8 Laszlo Ersek
    nr_cpus = 0;
737 5ee163e8 Laszlo Ersek
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
738 5ee163e8 Laszlo Ersek
        nr_cpus++;
739 5ee163e8 Laszlo Ersek
    }
740 5ee163e8 Laszlo Ersek
741 783e9b48 Wen Congyang
    s->errp = errp;
742 783e9b48 Wen Congyang
    s->fd = fd;
743 783e9b48 Wen Congyang
    s->has_filter = has_filter;
744 783e9b48 Wen Congyang
    s->begin = begin;
745 783e9b48 Wen Congyang
    s->length = length;
746 5ee163e8 Laszlo Ersek
747 5ee163e8 Laszlo Ersek
    guest_phys_blocks_init(&s->guest_phys_blocks);
748 c5d7f60f Laszlo Ersek
    guest_phys_blocks_append(&s->guest_phys_blocks);
749 5ee163e8 Laszlo Ersek
750 783e9b48 Wen Congyang
    s->start = get_start_block(s);
751 783e9b48 Wen Congyang
    if (s->start == -1) {
752 783e9b48 Wen Congyang
        error_set(errp, QERR_INVALID_PARAMETER, "begin");
753 783e9b48 Wen Congyang
        goto cleanup;
754 783e9b48 Wen Congyang
    }
755 783e9b48 Wen Congyang
756 5ee163e8 Laszlo Ersek
    /* get dump info: endian, class and architecture.
757 783e9b48 Wen Congyang
     * If the target architecture is not supported, cpu_get_dump_info() will
758 783e9b48 Wen Congyang
     * return -1.
759 783e9b48 Wen Congyang
     */
760 56c4bfb3 Laszlo Ersek
    ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);
761 783e9b48 Wen Congyang
    if (ret < 0) {
762 783e9b48 Wen Congyang
        error_set(errp, QERR_UNSUPPORTED);
763 783e9b48 Wen Congyang
        goto cleanup;
764 783e9b48 Wen Congyang
    }
765 783e9b48 Wen Congyang
766 4720bd05 Paolo Bonzini
    s->note_size = cpu_get_note_size(s->dump_info.d_class,
767 4720bd05 Paolo Bonzini
                                     s->dump_info.d_machine, nr_cpus);
768 4720bd05 Paolo Bonzini
    if (ret < 0) {
769 4720bd05 Paolo Bonzini
        error_set(errp, QERR_UNSUPPORTED);
770 4720bd05 Paolo Bonzini
        goto cleanup;
771 4720bd05 Paolo Bonzini
    }
772 4720bd05 Paolo Bonzini
773 783e9b48 Wen Congyang
    /* get memory mapping */
774 783e9b48 Wen Congyang
    memory_mapping_list_init(&s->list);
775 783e9b48 Wen Congyang
    if (paging) {
776 56c4bfb3 Laszlo Ersek
        qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
777 11ed09cf Andreas Färber
        if (err != NULL) {
778 11ed09cf Andreas Färber
            error_propagate(errp, err);
779 11ed09cf Andreas Färber
            goto cleanup;
780 11ed09cf Andreas Färber
        }
781 783e9b48 Wen Congyang
    } else {
782 56c4bfb3 Laszlo Ersek
        qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);
783 783e9b48 Wen Congyang
    }
784 783e9b48 Wen Congyang
785 783e9b48 Wen Congyang
    if (s->has_filter) {
786 783e9b48 Wen Congyang
        memory_mapping_filter(&s->list, s->begin, s->length);
787 783e9b48 Wen Congyang
    }
788 783e9b48 Wen Congyang
789 783e9b48 Wen Congyang
    /*
790 783e9b48 Wen Congyang
     * calculate phdr_num
791 783e9b48 Wen Congyang
     *
792 783e9b48 Wen Congyang
     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
793 783e9b48 Wen Congyang
     */
794 783e9b48 Wen Congyang
    s->phdr_num = 1; /* PT_NOTE */
795 783e9b48 Wen Congyang
    if (s->list.num < UINT16_MAX - 2) {
796 783e9b48 Wen Congyang
        s->phdr_num += s->list.num;
797 783e9b48 Wen Congyang
        s->have_section = false;
798 783e9b48 Wen Congyang
    } else {
799 783e9b48 Wen Congyang
        s->have_section = true;
800 783e9b48 Wen Congyang
        s->phdr_num = PN_XNUM;
801 783e9b48 Wen Congyang
        s->sh_info = 1; /* PT_NOTE */
802 783e9b48 Wen Congyang
803 783e9b48 Wen Congyang
        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
804 783e9b48 Wen Congyang
        if (s->list.num <= UINT32_MAX - 1) {
805 783e9b48 Wen Congyang
            s->sh_info += s->list.num;
806 783e9b48 Wen Congyang
        } else {
807 783e9b48 Wen Congyang
            s->sh_info = UINT32_MAX;
808 783e9b48 Wen Congyang
        }
809 783e9b48 Wen Congyang
    }
810 783e9b48 Wen Congyang
811 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
812 783e9b48 Wen Congyang
        if (s->have_section) {
813 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf64_Ehdr) +
814 783e9b48 Wen Congyang
                               sizeof(Elf64_Phdr) * s->sh_info +
815 783e9b48 Wen Congyang
                               sizeof(Elf64_Shdr) + s->note_size;
816 783e9b48 Wen Congyang
        } else {
817 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf64_Ehdr) +
818 783e9b48 Wen Congyang
                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
819 783e9b48 Wen Congyang
        }
820 783e9b48 Wen Congyang
    } else {
821 783e9b48 Wen Congyang
        if (s->have_section) {
822 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf32_Ehdr) +
823 783e9b48 Wen Congyang
                               sizeof(Elf32_Phdr) * s->sh_info +
824 783e9b48 Wen Congyang
                               sizeof(Elf32_Shdr) + s->note_size;
825 783e9b48 Wen Congyang
        } else {
826 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf32_Ehdr) +
827 783e9b48 Wen Congyang
                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
828 783e9b48 Wen Congyang
        }
829 783e9b48 Wen Congyang
    }
830 783e9b48 Wen Congyang
831 783e9b48 Wen Congyang
    return 0;
832 783e9b48 Wen Congyang
833 783e9b48 Wen Congyang
cleanup:
834 5ee163e8 Laszlo Ersek
    guest_phys_blocks_free(&s->guest_phys_blocks);
835 5ee163e8 Laszlo Ersek
836 783e9b48 Wen Congyang
    if (s->resume) {
837 783e9b48 Wen Congyang
        vm_start();
838 783e9b48 Wen Congyang
    }
839 783e9b48 Wen Congyang
840 783e9b48 Wen Congyang
    return -1;
841 783e9b48 Wen Congyang
}
842 783e9b48 Wen Congyang
843 783e9b48 Wen Congyang
void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
844 783e9b48 Wen Congyang
                           int64_t begin, bool has_length, int64_t length,
845 783e9b48 Wen Congyang
                           Error **errp)
846 783e9b48 Wen Congyang
{
847 783e9b48 Wen Congyang
    const char *p;
848 783e9b48 Wen Congyang
    int fd = -1;
849 783e9b48 Wen Congyang
    DumpState *s;
850 783e9b48 Wen Congyang
    int ret;
851 783e9b48 Wen Congyang
852 783e9b48 Wen Congyang
    if (has_begin && !has_length) {
853 783e9b48 Wen Congyang
        error_set(errp, QERR_MISSING_PARAMETER, "length");
854 783e9b48 Wen Congyang
        return;
855 783e9b48 Wen Congyang
    }
856 783e9b48 Wen Congyang
    if (!has_begin && has_length) {
857 783e9b48 Wen Congyang
        error_set(errp, QERR_MISSING_PARAMETER, "begin");
858 783e9b48 Wen Congyang
        return;
859 783e9b48 Wen Congyang
    }
860 783e9b48 Wen Congyang
861 783e9b48 Wen Congyang
#if !defined(WIN32)
862 783e9b48 Wen Congyang
    if (strstart(file, "fd:", &p)) {
863 a9940fc4 Paolo Bonzini
        fd = monitor_get_fd(cur_mon, p, errp);
864 783e9b48 Wen Congyang
        if (fd == -1) {
865 783e9b48 Wen Congyang
            return;
866 783e9b48 Wen Congyang
        }
867 783e9b48 Wen Congyang
    }
868 783e9b48 Wen Congyang
#endif
869 783e9b48 Wen Congyang
870 783e9b48 Wen Congyang
    if  (strstart(file, "file:", &p)) {
871 783e9b48 Wen Congyang
        fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
872 783e9b48 Wen Congyang
        if (fd < 0) {
873 7581766b Luiz Capitulino
            error_setg_file_open(errp, errno, p);
874 783e9b48 Wen Congyang
            return;
875 783e9b48 Wen Congyang
        }
876 783e9b48 Wen Congyang
    }
877 783e9b48 Wen Congyang
878 783e9b48 Wen Congyang
    if (fd == -1) {
879 783e9b48 Wen Congyang
        error_set(errp, QERR_INVALID_PARAMETER, "protocol");
880 783e9b48 Wen Congyang
        return;
881 783e9b48 Wen Congyang
    }
882 783e9b48 Wen Congyang
883 5ee163e8 Laszlo Ersek
    s = g_malloc0(sizeof(DumpState));
884 783e9b48 Wen Congyang
885 783e9b48 Wen Congyang
    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
886 783e9b48 Wen Congyang
    if (ret < 0) {
887 783e9b48 Wen Congyang
        g_free(s);
888 783e9b48 Wen Congyang
        return;
889 783e9b48 Wen Congyang
    }
890 783e9b48 Wen Congyang
891 783e9b48 Wen Congyang
    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
892 783e9b48 Wen Congyang
        error_set(errp, QERR_IO_ERROR);
893 783e9b48 Wen Congyang
    }
894 783e9b48 Wen Congyang
895 783e9b48 Wen Congyang
    g_free(s);
896 783e9b48 Wen Congyang
}