Statistics
| Branch: | Revision:

root / dump.c @ 29b358f9

History | View | Annotate | Download (22.3 kB)

1
/*
2
 * QEMU dump
3
 *
4
 * Copyright Fujitsu, Corp. 2011, 2012
5
 *
6
 * Authors:
7
 *     Wen Congyang <wency@cn.fujitsu.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
 * See the COPYING file in the top-level directory.
11
 *
12
 */
13

    
14
#include "qemu-common.h"
15
#include "elf.h"
16
#include "cpu.h"
17
#include "exec/cpu-all.h"
18
#include "exec/hwaddr.h"
19
#include "monitor/monitor.h"
20
#include "sysemu/kvm.h"
21
#include "sysemu/dump.h"
22
#include "sysemu/sysemu.h"
23
#include "sysemu/memory_mapping.h"
24
#include "sysemu/cpus.h"
25
#include "qapi/error.h"
26
#include "qmp-commands.h"
27

    
28
static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
29
{
30
    if (endian == ELFDATA2LSB) {
31
        val = cpu_to_le16(val);
32
    } else {
33
        val = cpu_to_be16(val);
34
    }
35

    
36
    return val;
37
}
38

    
39
static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
40
{
41
    if (endian == ELFDATA2LSB) {
42
        val = cpu_to_le32(val);
43
    } else {
44
        val = cpu_to_be32(val);
45
    }
46

    
47
    return val;
48
}
49

    
50
static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
51
{
52
    if (endian == ELFDATA2LSB) {
53
        val = cpu_to_le64(val);
54
    } else {
55
        val = cpu_to_be64(val);
56
    }
57

    
58
    return val;
59
}
60

    
61
typedef struct DumpState {
62
    ArchDumpInfo dump_info;
63
    MemoryMappingList list;
64
    uint16_t phdr_num;
65
    uint32_t sh_info;
66
    bool have_section;
67
    bool resume;
68
    size_t note_size;
69
    hwaddr memory_offset;
70
    int fd;
71

    
72
    RAMBlock *block;
73
    ram_addr_t start;
74
    bool has_filter;
75
    int64_t begin;
76
    int64_t length;
77
    Error **errp;
78
} DumpState;
79

    
80
static int dump_cleanup(DumpState *s)
81
{
82
    int ret = 0;
83

    
84
    memory_mapping_list_free(&s->list);
85
    if (s->fd != -1) {
86
        close(s->fd);
87
    }
88
    if (s->resume) {
89
        vm_start();
90
    }
91

    
92
    return ret;
93
}
94

    
95
static void dump_error(DumpState *s, const char *reason)
96
{
97
    dump_cleanup(s);
98
}
99

    
100
static int fd_write_vmcore(void *buf, size_t size, void *opaque)
101
{
102
    DumpState *s = opaque;
103
    size_t written_size;
104

    
105
    written_size = qemu_write_full(s->fd, buf, size);
106
    if (written_size != size) {
107
        return -1;
108
    }
109

    
110
    return 0;
111
}
112

    
113
static int write_elf64_header(DumpState *s)
114
{
115
    Elf64_Ehdr elf_header;
116
    int ret;
117
    int endian = s->dump_info.d_endian;
118

    
119
    memset(&elf_header, 0, sizeof(Elf64_Ehdr));
120
    memcpy(&elf_header, ELFMAG, SELFMAG);
121
    elf_header.e_ident[EI_CLASS] = ELFCLASS64;
122
    elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
123
    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
124
    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
125
    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
126
                                                   endian);
127
    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
128
    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
129
    elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
130
    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
131
                                                     endian);
132
    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
133
    if (s->have_section) {
134
        uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
135

    
136
        elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
137
        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
138
                                                         endian);
139
        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
140
    }
141

    
142
    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
143
    if (ret < 0) {
144
        dump_error(s, "dump: failed to write elf header.\n");
145
        return -1;
146
    }
147

    
148
    return 0;
149
}
150

    
151
static int write_elf32_header(DumpState *s)
152
{
153
    Elf32_Ehdr elf_header;
154
    int ret;
155
    int endian = s->dump_info.d_endian;
156

    
157
    memset(&elf_header, 0, sizeof(Elf32_Ehdr));
158
    memcpy(&elf_header, ELFMAG, SELFMAG);
159
    elf_header.e_ident[EI_CLASS] = ELFCLASS32;
160
    elf_header.e_ident[EI_DATA] = endian;
161
    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
162
    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
163
    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
164
                                                   endian);
165
    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
166
    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
167
    elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
168
    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
169
                                                     endian);
170
    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
171
    if (s->have_section) {
172
        uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
173

    
174
        elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
175
        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
176
                                                         endian);
177
        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
178
    }
179

    
180
    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
181
    if (ret < 0) {
182
        dump_error(s, "dump: failed to write elf header.\n");
183
        return -1;
184
    }
185

    
186
    return 0;
187
}
188

    
189
static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
190
                            int phdr_index, hwaddr offset)
191
{
192
    Elf64_Phdr phdr;
193
    int ret;
194
    int endian = s->dump_info.d_endian;
195

    
196
    memset(&phdr, 0, sizeof(Elf64_Phdr));
197
    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
198
    phdr.p_offset = cpu_convert_to_target64(offset, endian);
199
    phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
200
    if (offset == -1) {
201
        /* When the memory is not stored into vmcore, offset will be -1 */
202
        phdr.p_filesz = 0;
203
    } else {
204
        phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian);
205
    }
206
    phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
207
    phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
208

    
209
    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
210
    if (ret < 0) {
211
        dump_error(s, "dump: failed to write program header table.\n");
212
        return -1;
213
    }
214

    
215
    return 0;
216
}
217

    
218
static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
219
                            int phdr_index, hwaddr offset)
220
{
221
    Elf32_Phdr phdr;
222
    int ret;
223
    int endian = s->dump_info.d_endian;
224

    
225
    memset(&phdr, 0, sizeof(Elf32_Phdr));
226
    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
227
    phdr.p_offset = cpu_convert_to_target32(offset, endian);
228
    phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
229
    if (offset == -1) {
230
        /* When the memory is not stored into vmcore, offset will be -1 */
231
        phdr.p_filesz = 0;
232
    } else {
233
        phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian);
234
    }
235
    phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
236
    phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
237

    
238
    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
239
    if (ret < 0) {
240
        dump_error(s, "dump: failed to write program header table.\n");
241
        return -1;
242
    }
243

    
244
    return 0;
245
}
246

    
247
static int write_elf64_note(DumpState *s)
248
{
249
    Elf64_Phdr phdr;
250
    int endian = s->dump_info.d_endian;
251
    hwaddr begin = s->memory_offset - s->note_size;
252
    int ret;
253

    
254
    memset(&phdr, 0, sizeof(Elf64_Phdr));
255
    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
256
    phdr.p_offset = cpu_convert_to_target64(begin, endian);
257
    phdr.p_paddr = 0;
258
    phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
259
    phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
260
    phdr.p_vaddr = 0;
261

    
262
    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
263
    if (ret < 0) {
264
        dump_error(s, "dump: failed to write program header table.\n");
265
        return -1;
266
    }
267

    
268
    return 0;
269
}
270

    
271
static inline int cpu_index(CPUState *cpu)
272
{
273
    return cpu->cpu_index + 1;
274
}
275

    
276
static int write_elf64_notes(DumpState *s)
277
{
278
    CPUArchState *env;
279
    CPUState *cpu;
280
    int ret;
281
    int id;
282

    
283
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
284
        cpu = ENV_GET_CPU(env);
285
        id = cpu_index(cpu);
286
        ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s);
287
        if (ret < 0) {
288
            dump_error(s, "dump: failed to write elf notes.\n");
289
            return -1;
290
        }
291
    }
292

    
293
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
294
        ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s);
295
        if (ret < 0) {
296
            dump_error(s, "dump: failed to write CPU status.\n");
297
            return -1;
298
        }
299
    }
300

    
301
    return 0;
302
}
303

    
304
static int write_elf32_note(DumpState *s)
305
{
306
    hwaddr begin = s->memory_offset - s->note_size;
307
    Elf32_Phdr phdr;
308
    int endian = s->dump_info.d_endian;
309
    int ret;
310

    
311
    memset(&phdr, 0, sizeof(Elf32_Phdr));
312
    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
313
    phdr.p_offset = cpu_convert_to_target32(begin, endian);
314
    phdr.p_paddr = 0;
315
    phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
316
    phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
317
    phdr.p_vaddr = 0;
318

    
319
    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
320
    if (ret < 0) {
321
        dump_error(s, "dump: failed to write program header table.\n");
322
        return -1;
323
    }
324

    
325
    return 0;
326
}
327

    
328
static int write_elf32_notes(DumpState *s)
329
{
330
    CPUArchState *env;
331
    CPUState *cpu;
332
    int ret;
333
    int id;
334

    
335
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
336
        cpu = ENV_GET_CPU(env);
337
        id = cpu_index(cpu);
338
        ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s);
339
        if (ret < 0) {
340
            dump_error(s, "dump: failed to write elf notes.\n");
341
            return -1;
342
        }
343
    }
344

    
345
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
346
        ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s);
347
        if (ret < 0) {
348
            dump_error(s, "dump: failed to write CPU status.\n");
349
            return -1;
350
        }
351
    }
352

    
353
    return 0;
354
}
355

    
356
static int write_elf_section(DumpState *s, int type)
357
{
358
    Elf32_Shdr shdr32;
359
    Elf64_Shdr shdr64;
360
    int endian = s->dump_info.d_endian;
361
    int shdr_size;
362
    void *shdr;
363
    int ret;
364

    
365
    if (type == 0) {
366
        shdr_size = sizeof(Elf32_Shdr);
367
        memset(&shdr32, 0, shdr_size);
368
        shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
369
        shdr = &shdr32;
370
    } else {
371
        shdr_size = sizeof(Elf64_Shdr);
372
        memset(&shdr64, 0, shdr_size);
373
        shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
374
        shdr = &shdr64;
375
    }
376

    
377
    ret = fd_write_vmcore(&shdr, shdr_size, s);
378
    if (ret < 0) {
379
        dump_error(s, "dump: failed to write section header table.\n");
380
        return -1;
381
    }
382

    
383
    return 0;
384
}
385

    
386
static int write_data(DumpState *s, void *buf, int length)
387
{
388
    int ret;
389

    
390
    ret = fd_write_vmcore(buf, length, s);
391
    if (ret < 0) {
392
        dump_error(s, "dump: failed to save memory.\n");
393
        return -1;
394
    }
395

    
396
    return 0;
397
}
398

    
399
/* write the memroy to vmcore. 1 page per I/O. */
400
static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
401
                        int64_t size)
402
{
403
    int64_t i;
404
    int ret;
405

    
406
    for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
407
        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
408
                         TARGET_PAGE_SIZE);
409
        if (ret < 0) {
410
            return ret;
411
        }
412
    }
413

    
414
    if ((size % TARGET_PAGE_SIZE) != 0) {
415
        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
416
                         size % TARGET_PAGE_SIZE);
417
        if (ret < 0) {
418
            return ret;
419
        }
420
    }
421

    
422
    return 0;
423
}
424

    
425
/* get the memory's offset in the vmcore */
426
static hwaddr get_offset(hwaddr phys_addr,
427
                                     DumpState *s)
428
{
429
    RAMBlock *block;
430
    hwaddr offset = s->memory_offset;
431
    int64_t size_in_block, start;
432

    
433
    if (s->has_filter) {
434
        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
435
            return -1;
436
        }
437
    }
438

    
439
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
440
        if (s->has_filter) {
441
            if (block->offset >= s->begin + s->length ||
442
                block->offset + block->length <= s->begin) {
443
                /* This block is out of the range */
444
                continue;
445
            }
446

    
447
            if (s->begin <= block->offset) {
448
                start = block->offset;
449
            } else {
450
                start = s->begin;
451
            }
452

    
453
            size_in_block = block->length - (start - block->offset);
454
            if (s->begin + s->length < block->offset + block->length) {
455
                size_in_block -= block->offset + block->length -
456
                                 (s->begin + s->length);
457
            }
458
        } else {
459
            start = block->offset;
460
            size_in_block = block->length;
461
        }
462

    
463
        if (phys_addr >= start && phys_addr < start + size_in_block) {
464
            return phys_addr - start + offset;
465
        }
466

    
467
        offset += size_in_block;
468
    }
469

    
470
    return -1;
471
}
472

    
473
static int write_elf_loads(DumpState *s)
474
{
475
    hwaddr offset;
476
    MemoryMapping *memory_mapping;
477
    uint32_t phdr_index = 1;
478
    int ret;
479
    uint32_t max_index;
480

    
481
    if (s->have_section) {
482
        max_index = s->sh_info;
483
    } else {
484
        max_index = s->phdr_num;
485
    }
486

    
487
    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
488
        offset = get_offset(memory_mapping->phys_addr, s);
489
        if (s->dump_info.d_class == ELFCLASS64) {
490
            ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
491
        } else {
492
            ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
493
        }
494

    
495
        if (ret < 0) {
496
            return -1;
497
        }
498

    
499
        if (phdr_index >= max_index) {
500
            break;
501
        }
502
    }
503

    
504
    return 0;
505
}
506

    
507
/* write elf header, PT_NOTE and elf note to vmcore. */
508
static int dump_begin(DumpState *s)
509
{
510
    int ret;
511

    
512
    /*
513
     * the vmcore's format is:
514
     *   --------------
515
     *   |  elf header |
516
     *   --------------
517
     *   |  PT_NOTE    |
518
     *   --------------
519
     *   |  PT_LOAD    |
520
     *   --------------
521
     *   |  ......     |
522
     *   --------------
523
     *   |  PT_LOAD    |
524
     *   --------------
525
     *   |  sec_hdr    |
526
     *   --------------
527
     *   |  elf note   |
528
     *   --------------
529
     *   |  memory     |
530
     *   --------------
531
     *
532
     * we only know where the memory is saved after we write elf note into
533
     * vmcore.
534
     */
535

    
536
    /* write elf header to vmcore */
537
    if (s->dump_info.d_class == ELFCLASS64) {
538
        ret = write_elf64_header(s);
539
    } else {
540
        ret = write_elf32_header(s);
541
    }
542
    if (ret < 0) {
543
        return -1;
544
    }
545

    
546
    if (s->dump_info.d_class == ELFCLASS64) {
547
        /* write PT_NOTE to vmcore */
548
        if (write_elf64_note(s) < 0) {
549
            return -1;
550
        }
551

    
552
        /* write all PT_LOAD to vmcore */
553
        if (write_elf_loads(s) < 0) {
554
            return -1;
555
        }
556

    
557
        /* write section to vmcore */
558
        if (s->have_section) {
559
            if (write_elf_section(s, 1) < 0) {
560
                return -1;
561
            }
562
        }
563

    
564
        /* write notes to vmcore */
565
        if (write_elf64_notes(s) < 0) {
566
            return -1;
567
        }
568

    
569
    } else {
570
        /* write PT_NOTE to vmcore */
571
        if (write_elf32_note(s) < 0) {
572
            return -1;
573
        }
574

    
575
        /* write all PT_LOAD to vmcore */
576
        if (write_elf_loads(s) < 0) {
577
            return -1;
578
        }
579

    
580
        /* write section to vmcore */
581
        if (s->have_section) {
582
            if (write_elf_section(s, 0) < 0) {
583
                return -1;
584
            }
585
        }
586

    
587
        /* write notes to vmcore */
588
        if (write_elf32_notes(s) < 0) {
589
            return -1;
590
        }
591
    }
592

    
593
    return 0;
594
}
595

    
596
/* write PT_LOAD to vmcore */
597
static int dump_completed(DumpState *s)
598
{
599
    dump_cleanup(s);
600
    return 0;
601
}
602

    
603
static int get_next_block(DumpState *s, RAMBlock *block)
604
{
605
    while (1) {
606
        block = QTAILQ_NEXT(block, next);
607
        if (!block) {
608
            /* no more block */
609
            return 1;
610
        }
611

    
612
        s->start = 0;
613
        s->block = block;
614
        if (s->has_filter) {
615
            if (block->offset >= s->begin + s->length ||
616
                block->offset + block->length <= s->begin) {
617
                /* This block is out of the range */
618
                continue;
619
            }
620

    
621
            if (s->begin > block->offset) {
622
                s->start = s->begin - block->offset;
623
            }
624
        }
625

    
626
        return 0;
627
    }
628
}
629

    
630
/* write all memory to vmcore */
631
static int dump_iterate(DumpState *s)
632
{
633
    RAMBlock *block;
634
    int64_t size;
635
    int ret;
636

    
637
    while (1) {
638
        block = s->block;
639

    
640
        size = block->length;
641
        if (s->has_filter) {
642
            size -= s->start;
643
            if (s->begin + s->length < block->offset + block->length) {
644
                size -= block->offset + block->length - (s->begin + s->length);
645
            }
646
        }
647
        ret = write_memory(s, block, s->start, size);
648
        if (ret == -1) {
649
            return ret;
650
        }
651

    
652
        ret = get_next_block(s, block);
653
        if (ret == 1) {
654
            dump_completed(s);
655
            return 0;
656
        }
657
    }
658
}
659

    
660
static int create_vmcore(DumpState *s)
661
{
662
    int ret;
663

    
664
    ret = dump_begin(s);
665
    if (ret < 0) {
666
        return -1;
667
    }
668

    
669
    ret = dump_iterate(s);
670
    if (ret < 0) {
671
        return -1;
672
    }
673

    
674
    return 0;
675
}
676

    
677
static ram_addr_t get_start_block(DumpState *s)
678
{
679
    RAMBlock *block;
680

    
681
    if (!s->has_filter) {
682
        s->block = QTAILQ_FIRST(&ram_list.blocks);
683
        return 0;
684
    }
685

    
686
    QTAILQ_FOREACH(block, &ram_list.blocks, next) {
687
        if (block->offset >= s->begin + s->length ||
688
            block->offset + block->length <= s->begin) {
689
            /* This block is out of the range */
690
            continue;
691
        }
692

    
693
        s->block = block;
694
        if (s->begin > block->offset) {
695
            s->start = s->begin - block->offset;
696
        } else {
697
            s->start = 0;
698
        }
699
        return s->start;
700
    }
701

    
702
    return -1;
703
}
704

    
705
static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
706
                     int64_t begin, int64_t length, Error **errp)
707
{
708
    CPUArchState *env;
709
    int nr_cpus;
710
    Error *err = NULL;
711
    int ret;
712

    
713
    if (runstate_is_running()) {
714
        vm_stop(RUN_STATE_SAVE_VM);
715
        s->resume = true;
716
    } else {
717
        s->resume = false;
718
    }
719

    
720
    s->errp = errp;
721
    s->fd = fd;
722
    s->has_filter = has_filter;
723
    s->begin = begin;
724
    s->length = length;
725
    s->start = get_start_block(s);
726
    if (s->start == -1) {
727
        error_set(errp, QERR_INVALID_PARAMETER, "begin");
728
        goto cleanup;
729
    }
730

    
731
    /*
732
     * get dump info: endian, class and architecture.
733
     * If the target architecture is not supported, cpu_get_dump_info() will
734
     * return -1.
735
     *
736
     * If we use KVM, we should synchronize the registers before we get dump
737
     * info.
738
     */
739
    cpu_synchronize_all_states();
740
    nr_cpus = 0;
741
    for (env = first_cpu; env != NULL; env = env->next_cpu) {
742
        nr_cpus++;
743
    }
744

    
745
    ret = cpu_get_dump_info(&s->dump_info);
746
    if (ret < 0) {
747
        error_set(errp, QERR_UNSUPPORTED);
748
        goto cleanup;
749
    }
750

    
751
    s->note_size = cpu_get_note_size(s->dump_info.d_class,
752
                                     s->dump_info.d_machine, nr_cpus);
753
    if (ret < 0) {
754
        error_set(errp, QERR_UNSUPPORTED);
755
        goto cleanup;
756
    }
757

    
758
    /* get memory mapping */
759
    memory_mapping_list_init(&s->list);
760
    if (paging) {
761
        qemu_get_guest_memory_mapping(&s->list, &err);
762
        if (err != NULL) {
763
            error_propagate(errp, err);
764
            goto cleanup;
765
        }
766
    } else {
767
        qemu_get_guest_simple_memory_mapping(&s->list);
768
    }
769

    
770
    if (s->has_filter) {
771
        memory_mapping_filter(&s->list, s->begin, s->length);
772
    }
773

    
774
    /*
775
     * calculate phdr_num
776
     *
777
     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
778
     */
779
    s->phdr_num = 1; /* PT_NOTE */
780
    if (s->list.num < UINT16_MAX - 2) {
781
        s->phdr_num += s->list.num;
782
        s->have_section = false;
783
    } else {
784
        s->have_section = true;
785
        s->phdr_num = PN_XNUM;
786
        s->sh_info = 1; /* PT_NOTE */
787

    
788
        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
789
        if (s->list.num <= UINT32_MAX - 1) {
790
            s->sh_info += s->list.num;
791
        } else {
792
            s->sh_info = UINT32_MAX;
793
        }
794
    }
795

    
796
    if (s->dump_info.d_class == ELFCLASS64) {
797
        if (s->have_section) {
798
            s->memory_offset = sizeof(Elf64_Ehdr) +
799
                               sizeof(Elf64_Phdr) * s->sh_info +
800
                               sizeof(Elf64_Shdr) + s->note_size;
801
        } else {
802
            s->memory_offset = sizeof(Elf64_Ehdr) +
803
                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
804
        }
805
    } else {
806
        if (s->have_section) {
807
            s->memory_offset = sizeof(Elf32_Ehdr) +
808
                               sizeof(Elf32_Phdr) * s->sh_info +
809
                               sizeof(Elf32_Shdr) + s->note_size;
810
        } else {
811
            s->memory_offset = sizeof(Elf32_Ehdr) +
812
                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
813
        }
814
    }
815

    
816
    return 0;
817

    
818
cleanup:
819
    if (s->resume) {
820
        vm_start();
821
    }
822

    
823
    return -1;
824
}
825

    
826
void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
827
                           int64_t begin, bool has_length, int64_t length,
828
                           Error **errp)
829
{
830
    const char *p;
831
    int fd = -1;
832
    DumpState *s;
833
    int ret;
834

    
835
    if (has_begin && !has_length) {
836
        error_set(errp, QERR_MISSING_PARAMETER, "length");
837
        return;
838
    }
839
    if (!has_begin && has_length) {
840
        error_set(errp, QERR_MISSING_PARAMETER, "begin");
841
        return;
842
    }
843

    
844
#if !defined(WIN32)
845
    if (strstart(file, "fd:", &p)) {
846
        fd = monitor_get_fd(cur_mon, p, errp);
847
        if (fd == -1) {
848
            return;
849
        }
850
    }
851
#endif
852

    
853
    if  (strstart(file, "file:", &p)) {
854
        fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
855
        if (fd < 0) {
856
            error_setg_file_open(errp, errno, p);
857
            return;
858
        }
859
    }
860

    
861
    if (fd == -1) {
862
        error_set(errp, QERR_INVALID_PARAMETER, "protocol");
863
        return;
864
    }
865

    
866
    s = g_malloc(sizeof(DumpState));
867

    
868
    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
869
    if (ret < 0) {
870
        g_free(s);
871
        return;
872
    }
873

    
874
    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
875
        error_set(errp, QERR_IO_ERROR);
876
    }
877

    
878
    g_free(s);
879
}