Statistics
| Branch: | Revision:

root / dump.c @ a8aec295

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