Statistics
| Branch: | Revision:

root / dump.c @ 0834c9ea

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