Statistics
| Branch: | Revision:

root / dump.c @ c28fa5a0

History | View | Annotate | Download (22 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 a8170e5e Avi Kivity
#include "hwaddr.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 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 783e9b48 Wen Congyang
static int write_elf64_notes(DumpState *s)
272 783e9b48 Wen Congyang
{
273 783e9b48 Wen Congyang
    CPUArchState *env;
274 783e9b48 Wen Congyang
    int ret;
275 783e9b48 Wen Congyang
    int id;
276 783e9b48 Wen Congyang
277 783e9b48 Wen Congyang
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
278 783e9b48 Wen Congyang
        id = cpu_index(env);
279 783e9b48 Wen Congyang
        ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
280 783e9b48 Wen Congyang
        if (ret < 0) {
281 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write elf notes.\n");
282 783e9b48 Wen Congyang
            return -1;
283 783e9b48 Wen Congyang
        }
284 783e9b48 Wen Congyang
    }
285 783e9b48 Wen Congyang
286 783e9b48 Wen Congyang
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
287 783e9b48 Wen Congyang
        ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
288 783e9b48 Wen Congyang
        if (ret < 0) {
289 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write CPU status.\n");
290 783e9b48 Wen Congyang
            return -1;
291 783e9b48 Wen Congyang
        }
292 783e9b48 Wen Congyang
    }
293 783e9b48 Wen Congyang
294 783e9b48 Wen Congyang
    return 0;
295 783e9b48 Wen Congyang
}
296 783e9b48 Wen Congyang
297 783e9b48 Wen Congyang
static int write_elf32_note(DumpState *s)
298 783e9b48 Wen Congyang
{
299 a8170e5e Avi Kivity
    hwaddr begin = s->memory_offset - s->note_size;
300 783e9b48 Wen Congyang
    Elf32_Phdr phdr;
301 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
302 783e9b48 Wen Congyang
    int ret;
303 783e9b48 Wen Congyang
304 783e9b48 Wen Congyang
    memset(&phdr, 0, sizeof(Elf32_Phdr));
305 783e9b48 Wen Congyang
    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
306 783e9b48 Wen Congyang
    phdr.p_offset = cpu_convert_to_target32(begin, endian);
307 783e9b48 Wen Congyang
    phdr.p_paddr = 0;
308 783e9b48 Wen Congyang
    phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
309 783e9b48 Wen Congyang
    phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
310 783e9b48 Wen Congyang
    phdr.p_vaddr = 0;
311 783e9b48 Wen Congyang
312 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
313 783e9b48 Wen Congyang
    if (ret < 0) {
314 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write program header table.\n");
315 783e9b48 Wen Congyang
        return -1;
316 783e9b48 Wen Congyang
    }
317 783e9b48 Wen Congyang
318 783e9b48 Wen Congyang
    return 0;
319 783e9b48 Wen Congyang
}
320 783e9b48 Wen Congyang
321 783e9b48 Wen Congyang
static int write_elf32_notes(DumpState *s)
322 783e9b48 Wen Congyang
{
323 783e9b48 Wen Congyang
    CPUArchState *env;
324 783e9b48 Wen Congyang
    int ret;
325 783e9b48 Wen Congyang
    int id;
326 783e9b48 Wen Congyang
327 783e9b48 Wen Congyang
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
328 783e9b48 Wen Congyang
        id = cpu_index(env);
329 783e9b48 Wen Congyang
        ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
330 783e9b48 Wen Congyang
        if (ret < 0) {
331 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write elf notes.\n");
332 783e9b48 Wen Congyang
            return -1;
333 783e9b48 Wen Congyang
        }
334 783e9b48 Wen Congyang
    }
335 783e9b48 Wen Congyang
336 783e9b48 Wen Congyang
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
337 783e9b48 Wen Congyang
        ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
338 783e9b48 Wen Congyang
        if (ret < 0) {
339 783e9b48 Wen Congyang
            dump_error(s, "dump: failed to write CPU status.\n");
340 783e9b48 Wen Congyang
            return -1;
341 783e9b48 Wen Congyang
        }
342 783e9b48 Wen Congyang
    }
343 783e9b48 Wen Congyang
344 783e9b48 Wen Congyang
    return 0;
345 783e9b48 Wen Congyang
}
346 783e9b48 Wen Congyang
347 783e9b48 Wen Congyang
static int write_elf_section(DumpState *s, int type)
348 783e9b48 Wen Congyang
{
349 783e9b48 Wen Congyang
    Elf32_Shdr shdr32;
350 783e9b48 Wen Congyang
    Elf64_Shdr shdr64;
351 783e9b48 Wen Congyang
    int endian = s->dump_info.d_endian;
352 783e9b48 Wen Congyang
    int shdr_size;
353 783e9b48 Wen Congyang
    void *shdr;
354 783e9b48 Wen Congyang
    int ret;
355 783e9b48 Wen Congyang
356 783e9b48 Wen Congyang
    if (type == 0) {
357 783e9b48 Wen Congyang
        shdr_size = sizeof(Elf32_Shdr);
358 783e9b48 Wen Congyang
        memset(&shdr32, 0, shdr_size);
359 783e9b48 Wen Congyang
        shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
360 783e9b48 Wen Congyang
        shdr = &shdr32;
361 783e9b48 Wen Congyang
    } else {
362 783e9b48 Wen Congyang
        shdr_size = sizeof(Elf64_Shdr);
363 783e9b48 Wen Congyang
        memset(&shdr64, 0, shdr_size);
364 783e9b48 Wen Congyang
        shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
365 783e9b48 Wen Congyang
        shdr = &shdr64;
366 783e9b48 Wen Congyang
    }
367 783e9b48 Wen Congyang
368 783e9b48 Wen Congyang
    ret = fd_write_vmcore(&shdr, shdr_size, s);
369 783e9b48 Wen Congyang
    if (ret < 0) {
370 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to write section header table.\n");
371 783e9b48 Wen Congyang
        return -1;
372 783e9b48 Wen Congyang
    }
373 783e9b48 Wen Congyang
374 783e9b48 Wen Congyang
    return 0;
375 783e9b48 Wen Congyang
}
376 783e9b48 Wen Congyang
377 783e9b48 Wen Congyang
static int write_data(DumpState *s, void *buf, int length)
378 783e9b48 Wen Congyang
{
379 783e9b48 Wen Congyang
    int ret;
380 783e9b48 Wen Congyang
381 783e9b48 Wen Congyang
    ret = fd_write_vmcore(buf, length, s);
382 783e9b48 Wen Congyang
    if (ret < 0) {
383 783e9b48 Wen Congyang
        dump_error(s, "dump: failed to save memory.\n");
384 783e9b48 Wen Congyang
        return -1;
385 783e9b48 Wen Congyang
    }
386 783e9b48 Wen Congyang
387 783e9b48 Wen Congyang
    return 0;
388 783e9b48 Wen Congyang
}
389 783e9b48 Wen Congyang
390 783e9b48 Wen Congyang
/* write the memroy to vmcore. 1 page per I/O. */
391 783e9b48 Wen Congyang
static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
392 783e9b48 Wen Congyang
                        int64_t size)
393 783e9b48 Wen Congyang
{
394 783e9b48 Wen Congyang
    int64_t i;
395 783e9b48 Wen Congyang
    int ret;
396 783e9b48 Wen Congyang
397 783e9b48 Wen Congyang
    for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
398 783e9b48 Wen Congyang
        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
399 783e9b48 Wen Congyang
                         TARGET_PAGE_SIZE);
400 783e9b48 Wen Congyang
        if (ret < 0) {
401 783e9b48 Wen Congyang
            return ret;
402 783e9b48 Wen Congyang
        }
403 783e9b48 Wen Congyang
    }
404 783e9b48 Wen Congyang
405 783e9b48 Wen Congyang
    if ((size % TARGET_PAGE_SIZE) != 0) {
406 783e9b48 Wen Congyang
        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
407 783e9b48 Wen Congyang
                         size % TARGET_PAGE_SIZE);
408 783e9b48 Wen Congyang
        if (ret < 0) {
409 783e9b48 Wen Congyang
            return ret;
410 783e9b48 Wen Congyang
        }
411 783e9b48 Wen Congyang
    }
412 783e9b48 Wen Congyang
413 783e9b48 Wen Congyang
    return 0;
414 783e9b48 Wen Congyang
}
415 783e9b48 Wen Congyang
416 783e9b48 Wen Congyang
/* get the memory's offset in the vmcore */
417 a8170e5e Avi Kivity
static hwaddr get_offset(hwaddr phys_addr,
418 783e9b48 Wen Congyang
                                     DumpState *s)
419 783e9b48 Wen Congyang
{
420 783e9b48 Wen Congyang
    RAMBlock *block;
421 a8170e5e Avi Kivity
    hwaddr offset = s->memory_offset;
422 783e9b48 Wen Congyang
    int64_t size_in_block, start;
423 783e9b48 Wen Congyang
424 783e9b48 Wen Congyang
    if (s->has_filter) {
425 783e9b48 Wen Congyang
        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
426 783e9b48 Wen Congyang
            return -1;
427 783e9b48 Wen Congyang
        }
428 783e9b48 Wen Congyang
    }
429 783e9b48 Wen Congyang
430 783e9b48 Wen Congyang
    QLIST_FOREACH(block, &ram_list.blocks, next) {
431 783e9b48 Wen Congyang
        if (s->has_filter) {
432 783e9b48 Wen Congyang
            if (block->offset >= s->begin + s->length ||
433 783e9b48 Wen Congyang
                block->offset + block->length <= s->begin) {
434 783e9b48 Wen Congyang
                /* This block is out of the range */
435 783e9b48 Wen Congyang
                continue;
436 783e9b48 Wen Congyang
            }
437 783e9b48 Wen Congyang
438 783e9b48 Wen Congyang
            if (s->begin <= block->offset) {
439 783e9b48 Wen Congyang
                start = block->offset;
440 783e9b48 Wen Congyang
            } else {
441 783e9b48 Wen Congyang
                start = s->begin;
442 783e9b48 Wen Congyang
            }
443 783e9b48 Wen Congyang
444 783e9b48 Wen Congyang
            size_in_block = block->length - (start - block->offset);
445 783e9b48 Wen Congyang
            if (s->begin + s->length < block->offset + block->length) {
446 783e9b48 Wen Congyang
                size_in_block -= block->offset + block->length -
447 783e9b48 Wen Congyang
                                 (s->begin + s->length);
448 783e9b48 Wen Congyang
            }
449 783e9b48 Wen Congyang
        } else {
450 783e9b48 Wen Congyang
            start = block->offset;
451 783e9b48 Wen Congyang
            size_in_block = block->length;
452 783e9b48 Wen Congyang
        }
453 783e9b48 Wen Congyang
454 783e9b48 Wen Congyang
        if (phys_addr >= start && phys_addr < start + size_in_block) {
455 783e9b48 Wen Congyang
            return phys_addr - start + offset;
456 783e9b48 Wen Congyang
        }
457 783e9b48 Wen Congyang
458 783e9b48 Wen Congyang
        offset += size_in_block;
459 783e9b48 Wen Congyang
    }
460 783e9b48 Wen Congyang
461 783e9b48 Wen Congyang
    return -1;
462 783e9b48 Wen Congyang
}
463 783e9b48 Wen Congyang
464 783e9b48 Wen Congyang
static int write_elf_loads(DumpState *s)
465 783e9b48 Wen Congyang
{
466 a8170e5e Avi Kivity
    hwaddr offset;
467 783e9b48 Wen Congyang
    MemoryMapping *memory_mapping;
468 783e9b48 Wen Congyang
    uint32_t phdr_index = 1;
469 783e9b48 Wen Congyang
    int ret;
470 783e9b48 Wen Congyang
    uint32_t max_index;
471 783e9b48 Wen Congyang
472 783e9b48 Wen Congyang
    if (s->have_section) {
473 783e9b48 Wen Congyang
        max_index = s->sh_info;
474 783e9b48 Wen Congyang
    } else {
475 783e9b48 Wen Congyang
        max_index = s->phdr_num;
476 783e9b48 Wen Congyang
    }
477 783e9b48 Wen Congyang
478 783e9b48 Wen Congyang
    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
479 783e9b48 Wen Congyang
        offset = get_offset(memory_mapping->phys_addr, s);
480 783e9b48 Wen Congyang
        if (s->dump_info.d_class == ELFCLASS64) {
481 783e9b48 Wen Congyang
            ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
482 783e9b48 Wen Congyang
        } else {
483 783e9b48 Wen Congyang
            ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
484 783e9b48 Wen Congyang
        }
485 783e9b48 Wen Congyang
486 783e9b48 Wen Congyang
        if (ret < 0) {
487 783e9b48 Wen Congyang
            return -1;
488 783e9b48 Wen Congyang
        }
489 783e9b48 Wen Congyang
490 783e9b48 Wen Congyang
        if (phdr_index >= max_index) {
491 783e9b48 Wen Congyang
            break;
492 783e9b48 Wen Congyang
        }
493 783e9b48 Wen Congyang
    }
494 783e9b48 Wen Congyang
495 783e9b48 Wen Congyang
    return 0;
496 783e9b48 Wen Congyang
}
497 783e9b48 Wen Congyang
498 783e9b48 Wen Congyang
/* write elf header, PT_NOTE and elf note to vmcore. */
499 783e9b48 Wen Congyang
static int dump_begin(DumpState *s)
500 783e9b48 Wen Congyang
{
501 783e9b48 Wen Congyang
    int ret;
502 783e9b48 Wen Congyang
503 783e9b48 Wen Congyang
    /*
504 783e9b48 Wen Congyang
     * the vmcore's format is:
505 783e9b48 Wen Congyang
     *   --------------
506 783e9b48 Wen Congyang
     *   |  elf header |
507 783e9b48 Wen Congyang
     *   --------------
508 783e9b48 Wen Congyang
     *   |  PT_NOTE    |
509 783e9b48 Wen Congyang
     *   --------------
510 783e9b48 Wen Congyang
     *   |  PT_LOAD    |
511 783e9b48 Wen Congyang
     *   --------------
512 783e9b48 Wen Congyang
     *   |  ......     |
513 783e9b48 Wen Congyang
     *   --------------
514 783e9b48 Wen Congyang
     *   |  PT_LOAD    |
515 783e9b48 Wen Congyang
     *   --------------
516 783e9b48 Wen Congyang
     *   |  sec_hdr    |
517 783e9b48 Wen Congyang
     *   --------------
518 783e9b48 Wen Congyang
     *   |  elf note   |
519 783e9b48 Wen Congyang
     *   --------------
520 783e9b48 Wen Congyang
     *   |  memory     |
521 783e9b48 Wen Congyang
     *   --------------
522 783e9b48 Wen Congyang
     *
523 783e9b48 Wen Congyang
     * we only know where the memory is saved after we write elf note into
524 783e9b48 Wen Congyang
     * vmcore.
525 783e9b48 Wen Congyang
     */
526 783e9b48 Wen Congyang
527 783e9b48 Wen Congyang
    /* write elf header to vmcore */
528 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
529 783e9b48 Wen Congyang
        ret = write_elf64_header(s);
530 783e9b48 Wen Congyang
    } else {
531 783e9b48 Wen Congyang
        ret = write_elf32_header(s);
532 783e9b48 Wen Congyang
    }
533 783e9b48 Wen Congyang
    if (ret < 0) {
534 783e9b48 Wen Congyang
        return -1;
535 783e9b48 Wen Congyang
    }
536 783e9b48 Wen Congyang
537 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
538 783e9b48 Wen Congyang
        /* write PT_NOTE to vmcore */
539 783e9b48 Wen Congyang
        if (write_elf64_note(s) < 0) {
540 783e9b48 Wen Congyang
            return -1;
541 783e9b48 Wen Congyang
        }
542 783e9b48 Wen Congyang
543 783e9b48 Wen Congyang
        /* write all PT_LOAD to vmcore */
544 783e9b48 Wen Congyang
        if (write_elf_loads(s) < 0) {
545 783e9b48 Wen Congyang
            return -1;
546 783e9b48 Wen Congyang
        }
547 783e9b48 Wen Congyang
548 783e9b48 Wen Congyang
        /* write section to vmcore */
549 783e9b48 Wen Congyang
        if (s->have_section) {
550 783e9b48 Wen Congyang
            if (write_elf_section(s, 1) < 0) {
551 783e9b48 Wen Congyang
                return -1;
552 783e9b48 Wen Congyang
            }
553 783e9b48 Wen Congyang
        }
554 783e9b48 Wen Congyang
555 783e9b48 Wen Congyang
        /* write notes to vmcore */
556 783e9b48 Wen Congyang
        if (write_elf64_notes(s) < 0) {
557 783e9b48 Wen Congyang
            return -1;
558 783e9b48 Wen Congyang
        }
559 783e9b48 Wen Congyang
560 783e9b48 Wen Congyang
    } else {
561 783e9b48 Wen Congyang
        /* write PT_NOTE to vmcore */
562 783e9b48 Wen Congyang
        if (write_elf32_note(s) < 0) {
563 783e9b48 Wen Congyang
            return -1;
564 783e9b48 Wen Congyang
        }
565 783e9b48 Wen Congyang
566 783e9b48 Wen Congyang
        /* write all PT_LOAD to vmcore */
567 783e9b48 Wen Congyang
        if (write_elf_loads(s) < 0) {
568 783e9b48 Wen Congyang
            return -1;
569 783e9b48 Wen Congyang
        }
570 783e9b48 Wen Congyang
571 783e9b48 Wen Congyang
        /* write section to vmcore */
572 783e9b48 Wen Congyang
        if (s->have_section) {
573 783e9b48 Wen Congyang
            if (write_elf_section(s, 0) < 0) {
574 783e9b48 Wen Congyang
                return -1;
575 783e9b48 Wen Congyang
            }
576 783e9b48 Wen Congyang
        }
577 783e9b48 Wen Congyang
578 783e9b48 Wen Congyang
        /* write notes to vmcore */
579 783e9b48 Wen Congyang
        if (write_elf32_notes(s) < 0) {
580 783e9b48 Wen Congyang
            return -1;
581 783e9b48 Wen Congyang
        }
582 783e9b48 Wen Congyang
    }
583 783e9b48 Wen Congyang
584 783e9b48 Wen Congyang
    return 0;
585 783e9b48 Wen Congyang
}
586 783e9b48 Wen Congyang
587 783e9b48 Wen Congyang
/* write PT_LOAD to vmcore */
588 783e9b48 Wen Congyang
static int dump_completed(DumpState *s)
589 783e9b48 Wen Congyang
{
590 783e9b48 Wen Congyang
    dump_cleanup(s);
591 783e9b48 Wen Congyang
    return 0;
592 783e9b48 Wen Congyang
}
593 783e9b48 Wen Congyang
594 783e9b48 Wen Congyang
static int get_next_block(DumpState *s, RAMBlock *block)
595 783e9b48 Wen Congyang
{
596 783e9b48 Wen Congyang
    while (1) {
597 783e9b48 Wen Congyang
        block = QLIST_NEXT(block, next);
598 783e9b48 Wen Congyang
        if (!block) {
599 783e9b48 Wen Congyang
            /* no more block */
600 783e9b48 Wen Congyang
            return 1;
601 783e9b48 Wen Congyang
        }
602 783e9b48 Wen Congyang
603 783e9b48 Wen Congyang
        s->start = 0;
604 783e9b48 Wen Congyang
        s->block = block;
605 783e9b48 Wen Congyang
        if (s->has_filter) {
606 783e9b48 Wen Congyang
            if (block->offset >= s->begin + s->length ||
607 783e9b48 Wen Congyang
                block->offset + block->length <= s->begin) {
608 783e9b48 Wen Congyang
                /* This block is out of the range */
609 783e9b48 Wen Congyang
                continue;
610 783e9b48 Wen Congyang
            }
611 783e9b48 Wen Congyang
612 783e9b48 Wen Congyang
            if (s->begin > block->offset) {
613 783e9b48 Wen Congyang
                s->start = s->begin - block->offset;
614 783e9b48 Wen Congyang
            }
615 783e9b48 Wen Congyang
        }
616 783e9b48 Wen Congyang
617 783e9b48 Wen Congyang
        return 0;
618 783e9b48 Wen Congyang
    }
619 783e9b48 Wen Congyang
}
620 783e9b48 Wen Congyang
621 783e9b48 Wen Congyang
/* write all memory to vmcore */
622 783e9b48 Wen Congyang
static int dump_iterate(DumpState *s)
623 783e9b48 Wen Congyang
{
624 783e9b48 Wen Congyang
    RAMBlock *block;
625 783e9b48 Wen Congyang
    int64_t size;
626 783e9b48 Wen Congyang
    int ret;
627 783e9b48 Wen Congyang
628 783e9b48 Wen Congyang
    while (1) {
629 783e9b48 Wen Congyang
        block = s->block;
630 783e9b48 Wen Congyang
631 783e9b48 Wen Congyang
        size = block->length;
632 783e9b48 Wen Congyang
        if (s->has_filter) {
633 783e9b48 Wen Congyang
            size -= s->start;
634 783e9b48 Wen Congyang
            if (s->begin + s->length < block->offset + block->length) {
635 783e9b48 Wen Congyang
                size -= block->offset + block->length - (s->begin + s->length);
636 783e9b48 Wen Congyang
            }
637 783e9b48 Wen Congyang
        }
638 783e9b48 Wen Congyang
        ret = write_memory(s, block, s->start, size);
639 783e9b48 Wen Congyang
        if (ret == -1) {
640 783e9b48 Wen Congyang
            return ret;
641 783e9b48 Wen Congyang
        }
642 783e9b48 Wen Congyang
643 783e9b48 Wen Congyang
        ret = get_next_block(s, block);
644 783e9b48 Wen Congyang
        if (ret == 1) {
645 783e9b48 Wen Congyang
            dump_completed(s);
646 783e9b48 Wen Congyang
            return 0;
647 783e9b48 Wen Congyang
        }
648 783e9b48 Wen Congyang
    }
649 783e9b48 Wen Congyang
}
650 783e9b48 Wen Congyang
651 783e9b48 Wen Congyang
static int create_vmcore(DumpState *s)
652 783e9b48 Wen Congyang
{
653 783e9b48 Wen Congyang
    int ret;
654 783e9b48 Wen Congyang
655 783e9b48 Wen Congyang
    ret = dump_begin(s);
656 783e9b48 Wen Congyang
    if (ret < 0) {
657 783e9b48 Wen Congyang
        return -1;
658 783e9b48 Wen Congyang
    }
659 783e9b48 Wen Congyang
660 783e9b48 Wen Congyang
    ret = dump_iterate(s);
661 783e9b48 Wen Congyang
    if (ret < 0) {
662 783e9b48 Wen Congyang
        return -1;
663 783e9b48 Wen Congyang
    }
664 783e9b48 Wen Congyang
665 783e9b48 Wen Congyang
    return 0;
666 783e9b48 Wen Congyang
}
667 783e9b48 Wen Congyang
668 783e9b48 Wen Congyang
static ram_addr_t get_start_block(DumpState *s)
669 783e9b48 Wen Congyang
{
670 783e9b48 Wen Congyang
    RAMBlock *block;
671 783e9b48 Wen Congyang
672 783e9b48 Wen Congyang
    if (!s->has_filter) {
673 783e9b48 Wen Congyang
        s->block = QLIST_FIRST(&ram_list.blocks);
674 783e9b48 Wen Congyang
        return 0;
675 783e9b48 Wen Congyang
    }
676 783e9b48 Wen Congyang
677 783e9b48 Wen Congyang
    QLIST_FOREACH(block, &ram_list.blocks, next) {
678 783e9b48 Wen Congyang
        if (block->offset >= s->begin + s->length ||
679 783e9b48 Wen Congyang
            block->offset + block->length <= s->begin) {
680 783e9b48 Wen Congyang
            /* This block is out of the range */
681 783e9b48 Wen Congyang
            continue;
682 783e9b48 Wen Congyang
        }
683 783e9b48 Wen Congyang
684 783e9b48 Wen Congyang
        s->block = block;
685 783e9b48 Wen Congyang
        if (s->begin > block->offset) {
686 783e9b48 Wen Congyang
            s->start = s->begin - block->offset;
687 783e9b48 Wen Congyang
        } else {
688 783e9b48 Wen Congyang
            s->start = 0;
689 783e9b48 Wen Congyang
        }
690 783e9b48 Wen Congyang
        return s->start;
691 783e9b48 Wen Congyang
    }
692 783e9b48 Wen Congyang
693 783e9b48 Wen Congyang
    return -1;
694 783e9b48 Wen Congyang
}
695 783e9b48 Wen Congyang
696 783e9b48 Wen Congyang
static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
697 783e9b48 Wen Congyang
                     int64_t begin, int64_t length, Error **errp)
698 783e9b48 Wen Congyang
{
699 783e9b48 Wen Congyang
    CPUArchState *env;
700 783e9b48 Wen Congyang
    int nr_cpus;
701 783e9b48 Wen Congyang
    int ret;
702 783e9b48 Wen Congyang
703 783e9b48 Wen Congyang
    if (runstate_is_running()) {
704 783e9b48 Wen Congyang
        vm_stop(RUN_STATE_SAVE_VM);
705 783e9b48 Wen Congyang
        s->resume = true;
706 783e9b48 Wen Congyang
    } else {
707 783e9b48 Wen Congyang
        s->resume = false;
708 783e9b48 Wen Congyang
    }
709 783e9b48 Wen Congyang
710 783e9b48 Wen Congyang
    s->errp = errp;
711 783e9b48 Wen Congyang
    s->fd = fd;
712 783e9b48 Wen Congyang
    s->has_filter = has_filter;
713 783e9b48 Wen Congyang
    s->begin = begin;
714 783e9b48 Wen Congyang
    s->length = length;
715 783e9b48 Wen Congyang
    s->start = get_start_block(s);
716 783e9b48 Wen Congyang
    if (s->start == -1) {
717 783e9b48 Wen Congyang
        error_set(errp, QERR_INVALID_PARAMETER, "begin");
718 783e9b48 Wen Congyang
        goto cleanup;
719 783e9b48 Wen Congyang
    }
720 783e9b48 Wen Congyang
721 783e9b48 Wen Congyang
    /*
722 783e9b48 Wen Congyang
     * get dump info: endian, class and architecture.
723 783e9b48 Wen Congyang
     * If the target architecture is not supported, cpu_get_dump_info() will
724 783e9b48 Wen Congyang
     * return -1.
725 783e9b48 Wen Congyang
     *
726 783e9b48 Wen Congyang
     * if we use kvm, we should synchronize the register before we get dump
727 783e9b48 Wen Congyang
     * info.
728 783e9b48 Wen Congyang
     */
729 783e9b48 Wen Congyang
    nr_cpus = 0;
730 783e9b48 Wen Congyang
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
731 783e9b48 Wen Congyang
        cpu_synchronize_state(env);
732 783e9b48 Wen Congyang
        nr_cpus++;
733 783e9b48 Wen Congyang
    }
734 783e9b48 Wen Congyang
735 783e9b48 Wen Congyang
    ret = cpu_get_dump_info(&s->dump_info);
736 783e9b48 Wen Congyang
    if (ret < 0) {
737 783e9b48 Wen Congyang
        error_set(errp, QERR_UNSUPPORTED);
738 783e9b48 Wen Congyang
        goto cleanup;
739 783e9b48 Wen Congyang
    }
740 783e9b48 Wen Congyang
741 4720bd05 Paolo Bonzini
    s->note_size = cpu_get_note_size(s->dump_info.d_class,
742 4720bd05 Paolo Bonzini
                                     s->dump_info.d_machine, nr_cpus);
743 4720bd05 Paolo Bonzini
    if (ret < 0) {
744 4720bd05 Paolo Bonzini
        error_set(errp, QERR_UNSUPPORTED);
745 4720bd05 Paolo Bonzini
        goto cleanup;
746 4720bd05 Paolo Bonzini
    }
747 4720bd05 Paolo Bonzini
748 783e9b48 Wen Congyang
    /* get memory mapping */
749 783e9b48 Wen Congyang
    memory_mapping_list_init(&s->list);
750 783e9b48 Wen Congyang
    if (paging) {
751 783e9b48 Wen Congyang
        qemu_get_guest_memory_mapping(&s->list);
752 783e9b48 Wen Congyang
    } else {
753 783e9b48 Wen Congyang
        qemu_get_guest_simple_memory_mapping(&s->list);
754 783e9b48 Wen Congyang
    }
755 783e9b48 Wen Congyang
756 783e9b48 Wen Congyang
    if (s->has_filter) {
757 783e9b48 Wen Congyang
        memory_mapping_filter(&s->list, s->begin, s->length);
758 783e9b48 Wen Congyang
    }
759 783e9b48 Wen Congyang
760 783e9b48 Wen Congyang
    /*
761 783e9b48 Wen Congyang
     * calculate phdr_num
762 783e9b48 Wen Congyang
     *
763 783e9b48 Wen Congyang
     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
764 783e9b48 Wen Congyang
     */
765 783e9b48 Wen Congyang
    s->phdr_num = 1; /* PT_NOTE */
766 783e9b48 Wen Congyang
    if (s->list.num < UINT16_MAX - 2) {
767 783e9b48 Wen Congyang
        s->phdr_num += s->list.num;
768 783e9b48 Wen Congyang
        s->have_section = false;
769 783e9b48 Wen Congyang
    } else {
770 783e9b48 Wen Congyang
        s->have_section = true;
771 783e9b48 Wen Congyang
        s->phdr_num = PN_XNUM;
772 783e9b48 Wen Congyang
        s->sh_info = 1; /* PT_NOTE */
773 783e9b48 Wen Congyang
774 783e9b48 Wen Congyang
        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
775 783e9b48 Wen Congyang
        if (s->list.num <= UINT32_MAX - 1) {
776 783e9b48 Wen Congyang
            s->sh_info += s->list.num;
777 783e9b48 Wen Congyang
        } else {
778 783e9b48 Wen Congyang
            s->sh_info = UINT32_MAX;
779 783e9b48 Wen Congyang
        }
780 783e9b48 Wen Congyang
    }
781 783e9b48 Wen Congyang
782 783e9b48 Wen Congyang
    if (s->dump_info.d_class == ELFCLASS64) {
783 783e9b48 Wen Congyang
        if (s->have_section) {
784 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf64_Ehdr) +
785 783e9b48 Wen Congyang
                               sizeof(Elf64_Phdr) * s->sh_info +
786 783e9b48 Wen Congyang
                               sizeof(Elf64_Shdr) + s->note_size;
787 783e9b48 Wen Congyang
        } else {
788 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf64_Ehdr) +
789 783e9b48 Wen Congyang
                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
790 783e9b48 Wen Congyang
        }
791 783e9b48 Wen Congyang
    } else {
792 783e9b48 Wen Congyang
        if (s->have_section) {
793 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf32_Ehdr) +
794 783e9b48 Wen Congyang
                               sizeof(Elf32_Phdr) * s->sh_info +
795 783e9b48 Wen Congyang
                               sizeof(Elf32_Shdr) + s->note_size;
796 783e9b48 Wen Congyang
        } else {
797 783e9b48 Wen Congyang
            s->memory_offset = sizeof(Elf32_Ehdr) +
798 783e9b48 Wen Congyang
                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
799 783e9b48 Wen Congyang
        }
800 783e9b48 Wen Congyang
    }
801 783e9b48 Wen Congyang
802 783e9b48 Wen Congyang
    return 0;
803 783e9b48 Wen Congyang
804 783e9b48 Wen Congyang
cleanup:
805 783e9b48 Wen Congyang
    if (s->resume) {
806 783e9b48 Wen Congyang
        vm_start();
807 783e9b48 Wen Congyang
    }
808 783e9b48 Wen Congyang
809 783e9b48 Wen Congyang
    return -1;
810 783e9b48 Wen Congyang
}
811 783e9b48 Wen Congyang
812 783e9b48 Wen Congyang
void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
813 783e9b48 Wen Congyang
                           int64_t begin, bool has_length, int64_t length,
814 783e9b48 Wen Congyang
                           Error **errp)
815 783e9b48 Wen Congyang
{
816 783e9b48 Wen Congyang
    const char *p;
817 783e9b48 Wen Congyang
    int fd = -1;
818 783e9b48 Wen Congyang
    DumpState *s;
819 783e9b48 Wen Congyang
    int ret;
820 783e9b48 Wen Congyang
821 783e9b48 Wen Congyang
    if (has_begin && !has_length) {
822 783e9b48 Wen Congyang
        error_set(errp, QERR_MISSING_PARAMETER, "length");
823 783e9b48 Wen Congyang
        return;
824 783e9b48 Wen Congyang
    }
825 783e9b48 Wen Congyang
    if (!has_begin && has_length) {
826 783e9b48 Wen Congyang
        error_set(errp, QERR_MISSING_PARAMETER, "begin");
827 783e9b48 Wen Congyang
        return;
828 783e9b48 Wen Congyang
    }
829 783e9b48 Wen Congyang
830 783e9b48 Wen Congyang
#if !defined(WIN32)
831 783e9b48 Wen Congyang
    if (strstart(file, "fd:", &p)) {
832 a9940fc4 Paolo Bonzini
        fd = monitor_get_fd(cur_mon, p, errp);
833 783e9b48 Wen Congyang
        if (fd == -1) {
834 783e9b48 Wen Congyang
            return;
835 783e9b48 Wen Congyang
        }
836 783e9b48 Wen Congyang
    }
837 783e9b48 Wen Congyang
#endif
838 783e9b48 Wen Congyang
839 783e9b48 Wen Congyang
    if  (strstart(file, "file:", &p)) {
840 783e9b48 Wen Congyang
        fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
841 783e9b48 Wen Congyang
        if (fd < 0) {
842 783e9b48 Wen Congyang
            error_set(errp, QERR_OPEN_FILE_FAILED, p);
843 783e9b48 Wen Congyang
            return;
844 783e9b48 Wen Congyang
        }
845 783e9b48 Wen Congyang
    }
846 783e9b48 Wen Congyang
847 783e9b48 Wen Congyang
    if (fd == -1) {
848 783e9b48 Wen Congyang
        error_set(errp, QERR_INVALID_PARAMETER, "protocol");
849 783e9b48 Wen Congyang
        return;
850 783e9b48 Wen Congyang
    }
851 783e9b48 Wen Congyang
852 783e9b48 Wen Congyang
    s = g_malloc(sizeof(DumpState));
853 783e9b48 Wen Congyang
854 783e9b48 Wen Congyang
    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
855 783e9b48 Wen Congyang
    if (ret < 0) {
856 783e9b48 Wen Congyang
        g_free(s);
857 783e9b48 Wen Congyang
        return;
858 783e9b48 Wen Congyang
    }
859 783e9b48 Wen Congyang
860 783e9b48 Wen Congyang
    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
861 783e9b48 Wen Congyang
        error_set(errp, QERR_IO_ERROR);
862 783e9b48 Wen Congyang
    }
863 783e9b48 Wen Congyang
864 783e9b48 Wen Congyang
    g_free(s);
865 783e9b48 Wen Congyang
}