debuggers.hg

view tools/libxc/xc_core.c @ 16408:f669bf5c6720

libxc: Consolidate read()/write() syscall wrappers to read/write an
exact number of bytes. The consolidated versions are more watertight
than the various versions previously distributed around the library
source code.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Sun Nov 11 18:22:33 2007 +0000 (2007-11-11)
parents ecbda3783c85
children 7186e9611d55
line source
1 /*
2 * Elf format, (pfn, gmfn) table, IA64 support.
3 * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
4 * VA Linux Systems Japan K.K.
5 *
6 * xen dump-core file format follows ELF format specification.
7 * Analisys tools shouldn't depends on the order of sections.
8 * They should follow elf header and check section names.
9 *
10 * +--------------------------------------------------------+
11 * |ELF header |
12 * +--------------------------------------------------------+
13 * |section headers |
14 * | null section header |
15 * | .shstrtab |
16 * | .note.Xen |
17 * | .xen_prstatus |
18 * | .xen_ia64_mmapped_regs if ia64 |
19 * | .xen_shared_info if present |
20 * | .xen_pages |
21 * | .xen_p2m or .xen_pfn |
22 * +--------------------------------------------------------+
23 * |.note.Xen:note section |
24 * | "Xen" is used as note name, |
25 * | types are defined in xen/include/public/elfnote.h |
26 * | and descriptors are defined in xc_core.h. |
27 * | dumpcore none |
28 * | dumpcore header |
29 * | dumpcore xen version |
30 * | dumpcore format version |
31 * +--------------------------------------------------------+
32 * |.xen_prstatus |
33 * | vcpu_guest_context_t[nr_vcpus] |
34 * +--------------------------------------------------------+
35 * |.xen_ia64_mmapped_regs if ia64 pv |
36 * | mmapped_regs_t[nr_vcpus] |
37 * +--------------------------------------------------------+
38 * |.xen_shared_info if possible |
39 * +--------------------------------------------------------+
40 * |.xen_pages |
41 * | page * nr_pages |
42 * +--------------------------------------------------------+
43 * |.xen_p2m or .xen_pfn |
44 * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] |
45 * | .xen_pfn: uint64_t[nr_pages] |
46 * +--------------------------------------------------------+
47 * |.shstrtab: section header string table |
48 * +--------------------------------------------------------+
49 *
50 */
52 #include "xg_private.h"
53 #include "xc_core.h"
54 #include "xc_dom.h"
55 #include <stdlib.h>
56 #include <unistd.h>
58 /* number of pages to write at a time */
59 #define DUMP_INCREMENT (4 * 1024)
61 /* Don't yet support cross-address-size core dump */
62 #define guest_width (sizeof (unsigned long))
64 /* string table */
65 struct xc_core_strtab {
66 char *strings;
67 uint16_t current;
68 uint16_t max;
69 };
71 static struct xc_core_strtab*
72 xc_core_strtab_init(void)
73 {
74 struct xc_core_strtab *strtab;
75 char *strings;
76 strtab = malloc(sizeof(*strtab));
77 if ( strtab == NULL )
78 return NULL;
80 strings = malloc(PAGE_SIZE);
81 if ( strings == NULL )
82 {
83 PERROR("Could not allocate string table init");
84 free(strtab);
85 return NULL;
86 }
87 strtab->strings = strings;
88 strtab->max = PAGE_SIZE;
90 /* index 0 represents none */
91 strtab->strings[0] = '\0';
92 strtab->current = 1;
94 return strtab;
95 }
97 static void
98 xc_core_strtab_free(struct xc_core_strtab *strtab)
99 {
100 free(strtab->strings);
101 free(strtab);
102 }
104 static uint16_t
105 xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name)
106 {
107 uint16_t ret = 0;
108 uint16_t len = strlen(name) + 1;
110 if ( strtab->current + len > strtab->max )
111 {
112 char *tmp;
113 if ( strtab->max * 2 < strtab->max )
114 {
115 PERROR("too long string table");
116 errno = ENOMEM;
117 return ret;
118 }
121 tmp = realloc(strtab->strings, strtab->max * 2);
122 if ( tmp == NULL )
123 {
124 PERROR("Could not allocate string table");
125 return ret;
126 }
128 strtab->strings = tmp;
129 strtab->max *= 2;
130 }
132 ret = strtab->current;
133 strcpy(strtab->strings + strtab->current, name);
134 strtab->current += len;
135 return ret;
136 }
139 /* section headers */
140 struct xc_core_section_headers {
141 uint16_t num;
142 uint16_t num_max;
144 Elf64_Shdr *shdrs;
145 };
146 #define SHDR_INIT 16
147 #define SHDR_INC 4U
149 static struct xc_core_section_headers*
150 xc_core_shdr_init(void)
151 {
152 struct xc_core_section_headers *sheaders;
153 sheaders = malloc(sizeof(*sheaders));
154 if ( sheaders == NULL )
155 return NULL;
157 sheaders->num = 0;
158 sheaders->num_max = SHDR_INIT;
159 sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
160 if ( sheaders->shdrs == NULL )
161 {
162 free(sheaders);
163 return NULL;
164 }
165 return sheaders;
166 }
168 static void
169 xc_core_shdr_free(struct xc_core_section_headers *sheaders)
170 {
171 free(sheaders->shdrs);
172 free(sheaders);
173 }
175 Elf64_Shdr*
176 xc_core_shdr_get(struct xc_core_section_headers *sheaders)
177 {
178 Elf64_Shdr *shdr;
180 if ( sheaders->num == sheaders->num_max )
181 {
182 Elf64_Shdr *shdrs;
183 if ( sheaders->num_max + SHDR_INC < sheaders->num_max )
184 {
185 errno = E2BIG;
186 return NULL;
187 }
188 sheaders->num_max += SHDR_INC;
189 shdrs = realloc(sheaders->shdrs,
190 sizeof(sheaders->shdrs[0]) * sheaders->num_max);
191 if ( shdrs == NULL )
192 return NULL;
193 sheaders->shdrs = shdrs;
194 }
196 shdr = &sheaders->shdrs[sheaders->num];
197 sheaders->num++;
198 memset(shdr, 0, sizeof(*shdr));
199 return shdr;
200 }
202 int
203 xc_core_shdr_set(Elf64_Shdr *shdr,
204 struct xc_core_strtab *strtab,
205 const char *name, uint32_t type,
206 uint64_t offset, uint64_t size,
207 uint64_t addralign, uint64_t entsize)
208 {
209 uint64_t name_idx = xc_core_strtab_get(strtab, name);
210 if ( name_idx == 0 )
211 return -1;
213 shdr->sh_name = name_idx;
214 shdr->sh_type = type;
215 shdr->sh_offset = offset;
216 shdr->sh_size = size;
217 shdr->sh_addralign = addralign;
218 shdr->sh_entsize = entsize;
219 return 0;
220 }
222 static void
223 xc_core_ehdr_init(Elf64_Ehdr *ehdr)
224 {
225 memset(ehdr, 0, sizeof(*ehdr));
226 ehdr->e_ident[EI_MAG0] = ELFMAG0;
227 ehdr->e_ident[EI_MAG1] = ELFMAG1;
228 ehdr->e_ident[EI_MAG2] = ELFMAG2;
229 ehdr->e_ident[EI_MAG3] = ELFMAG3;
230 ehdr->e_ident[EI_CLASS] = ELFCLASS64;
231 ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
232 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
233 ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
234 ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
236 ehdr->e_type = ET_CORE;
237 ehdr->e_machine = ELF_ARCH_MACHINE;
238 ehdr->e_version = EV_CURRENT;
239 ehdr->e_entry = 0;
240 ehdr->e_phoff = 0;
241 ehdr->e_shoff = sizeof(*ehdr);
242 ehdr->e_flags = ELF_CORE_EFLAGS;
243 ehdr->e_ehsize = sizeof(*ehdr);
244 ehdr->e_phentsize = sizeof(Elf64_Phdr);
245 ehdr->e_phnum = 0;
246 ehdr->e_shentsize = sizeof(Elf64_Shdr);
247 /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
248 * fill it later */
249 }
251 static int
252 elfnote_fill_xen_version(int xc_handle,
253 struct xen_dumpcore_elfnote_xen_version_desc
254 *xen_version)
255 {
256 int rc;
257 memset(xen_version, 0, sizeof(*xen_version));
259 rc = xc_version(xc_handle, XENVER_version, NULL);
260 if ( rc < 0 )
261 return rc;
262 xen_version->major_version = rc >> 16;
263 xen_version->minor_version = rc & ((1 << 16) - 1);
265 rc = xc_version(xc_handle, XENVER_extraversion,
266 &xen_version->extra_version);
267 if ( rc < 0 )
268 return rc;
270 rc = xc_version(xc_handle, XENVER_compile_info,
271 &xen_version->compile_info);
272 if ( rc < 0 )
273 return rc;
275 rc = xc_version(xc_handle,
276 XENVER_capabilities, &xen_version->capabilities);
277 if ( rc < 0 )
278 return rc;
280 rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
281 if ( rc < 0 )
282 return rc;
284 rc = xc_version(xc_handle, XENVER_platform_parameters,
285 &xen_version->platform_parameters);
286 if ( rc < 0 )
287 return rc;
289 rc = xc_version(xc_handle, XENVER_pagesize, NULL);
290 if ( rc < 0 )
291 return rc;
292 xen_version->pagesize = rc;
294 return 0;
295 }
297 static void
298 elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
299 *format_version)
300 {
301 format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
302 }
304 static void
305 elfnote_init(struct elfnote *elfnote)
306 {
307 /* elf note section */
308 memset(elfnote, 0, sizeof(*elfnote));
309 elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
310 strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
311 }
313 static int
314 elfnote_dump_none(void *args, dumpcore_rtn_t dump_rtn)
315 {
316 int sts;
317 struct elfnote elfnote;
318 struct xen_dumpcore_elfnote_none_desc none;
320 elfnote_init(&elfnote);
321 memset(&none, 0, sizeof(none));
323 elfnote.descsz = sizeof(none);
324 elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
325 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
326 if ( sts != 0 )
327 return sts;
328 return dump_rtn(args, (char*)&none, sizeof(none));
329 }
331 static int
332 elfnote_dump_core_header(
333 void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
334 int nr_vcpus, unsigned long nr_pages)
335 {
336 int sts;
337 struct elfnote elfnote;
338 struct xen_dumpcore_elfnote_header_desc header;
340 elfnote_init(&elfnote);
341 memset(&header, 0, sizeof(header));
343 elfnote.descsz = sizeof(header);
344 elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
345 header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
346 header.xch_nr_vcpus = nr_vcpus;
347 header.xch_nr_pages = nr_pages;
348 header.xch_page_size = PAGE_SIZE;
349 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
350 if ( sts != 0 )
351 return sts;
352 return dump_rtn(args, (char*)&header, sizeof(header));
353 }
355 static int
356 elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle)
357 {
358 int sts;
359 struct elfnote elfnote;
360 struct xen_dumpcore_elfnote_xen_version_desc xen_version;
362 elfnote_init(&elfnote);
363 memset(&xen_version, 0, sizeof(xen_version));
365 elfnote.descsz = sizeof(xen_version);
366 elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
367 elfnote_fill_xen_version(xc_handle, &xen_version);
368 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
369 if ( sts != 0 )
370 return sts;
371 return dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
372 }
374 static int
375 elfnote_dump_format_version(void *args, dumpcore_rtn_t dump_rtn)
376 {
377 int sts;
378 struct elfnote elfnote;
379 struct xen_dumpcore_elfnote_format_version_desc format_version;
381 elfnote_init(&elfnote);
382 memset(&format_version, 0, sizeof(format_version));
384 elfnote.descsz = sizeof(format_version);
385 elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
386 elfnote_fill_format_version(&format_version);
387 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
388 if ( sts != 0 )
389 return sts;
390 return dump_rtn(args, (char*)&format_version, sizeof(format_version));
391 }
393 int
394 xc_domain_dumpcore_via_callback(int xc_handle,
395 uint32_t domid,
396 void *args,
397 dumpcore_rtn_t dump_rtn)
398 {
399 xc_dominfo_t info;
400 shared_info_t *live_shinfo = NULL;
402 int nr_vcpus = 0;
403 char *dump_mem, *dump_mem_start = NULL;
404 vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
405 struct xc_core_arch_context arch_ctxt;
406 char dummy[PAGE_SIZE];
407 int dummy_len;
408 int sts = -1;
410 unsigned long i;
411 unsigned long j;
412 unsigned long nr_pages;
414 xc_core_memory_map_t *memory_map = NULL;
415 unsigned int nr_memory_map;
416 unsigned int map_idx;
418 int auto_translated_physmap;
419 xen_pfn_t *p2m = NULL;
420 unsigned long p2m_size = 0;
421 struct xen_dumpcore_p2m *p2m_array = NULL;
423 uint64_t *pfn_array = NULL;
425 Elf64_Ehdr ehdr;
426 uint64_t filesz;
427 uint64_t offset;
428 uint64_t fixup;
430 struct xc_core_strtab *strtab = NULL;
431 uint16_t strtab_idx;
432 struct xc_core_section_headers *sheaders = NULL;
433 Elf64_Shdr *shdr;
435 xc_core_arch_context_init(&arch_ctxt);
436 if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
437 {
438 PERROR("Could not allocate dump_mem");
439 goto out;
440 }
442 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
443 {
444 PERROR("Could not get info for domain");
445 goto out;
446 }
447 /* Map the shared info frame */
448 live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
449 PROT_READ, info.shared_info_frame);
450 if ( !live_shinfo && !info.hvm )
451 {
452 PERROR("Couldn't map live_shinfo");
453 goto out;
454 }
455 auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
457 if ( domid != info.domid )
458 {
459 PERROR("Domain %d does not exist", domid);
460 goto out;
461 }
463 for ( i = 0; i <= info.max_vcpu_id; i++ )
464 {
465 if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
466 {
467 if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
468 xc_handle, domid) )
469 continue;
470 nr_vcpus++;
471 }
472 }
473 if ( nr_vcpus == 0 )
474 {
475 PERROR("No VCPU context could be grabbed");
476 goto out;
477 }
479 /* obtain memory map */
480 sts = xc_core_arch_memory_map_get(xc_handle, &arch_ctxt, &info,
481 live_shinfo, &memory_map,
482 &nr_memory_map);
483 if ( sts != 0 )
484 goto out;
486 nr_pages = info.nr_pages;
487 if ( !auto_translated_physmap )
488 {
489 /* obtain p2m table */
490 p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
491 if ( p2m_array == NULL )
492 {
493 PERROR("Could not allocate p2m array");
494 goto out;
495 }
497 sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo,
498 &p2m, &p2m_size);
499 if ( sts != 0 )
500 goto out;
501 }
502 else
503 {
504 pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
505 if ( pfn_array == NULL )
506 {
507 PERROR("Could not allocate pfn array");
508 goto out;
509 }
510 }
512 /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
513 xc_core_ehdr_init(&ehdr);
515 /* create section header */
516 strtab = xc_core_strtab_init();
517 if ( strtab == NULL )
518 {
519 PERROR("Could not allocate string table");
520 goto out;
521 }
522 sheaders = xc_core_shdr_init();
523 if ( sheaders == NULL )
524 {
525 PERROR("Could not allocate section headers");
526 goto out;
527 }
528 /* null section */
529 shdr = xc_core_shdr_get(sheaders);
530 if ( shdr == NULL )
531 {
532 PERROR("Could not get section header for null section");
533 goto out;
534 }
536 /* .shstrtab */
537 shdr = xc_core_shdr_get(sheaders);
538 if ( shdr == NULL )
539 {
540 PERROR("Could not get section header for shstrtab");
541 goto out;
542 }
543 strtab_idx = shdr - sheaders->shdrs;
544 /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
545 * fill it later
546 */
547 sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
548 if ( sts != 0 )
549 goto out;
551 /* elf note section */
552 /* here the number of section header is unknown. fix up offset later. */
553 offset = sizeof(ehdr);
554 filesz =
555 sizeof(struct xen_dumpcore_elfnote_none) + /* none */
556 sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
557 sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
558 sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
559 shdr = xc_core_shdr_get(sheaders);
560 if ( shdr == NULL )
561 {
562 PERROR("Could not get section header for note section");
563 goto out;
564 }
565 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
566 offset, filesz, 0, 0);
567 if ( sts != 0 )
568 goto out;
569 offset += filesz;
571 /* prstatus */
572 shdr = xc_core_shdr_get(sheaders);
573 if ( shdr == NULL )
574 {
575 PERROR("Could not get section header for .xen_prstatus");
576 goto out;
577 }
578 filesz = sizeof(ctxt[0]) * nr_vcpus;
579 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
580 SHT_PROGBITS, offset, filesz,
581 __alignof__(ctxt[0]), sizeof(ctxt[0]));
582 if ( sts != 0 )
583 goto out;
584 offset += filesz;
586 /* arch context */
587 sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
588 &filesz, offset);
589 if ( sts != 0 )
590 goto out;
591 offset += filesz;
593 /* shared_info */
594 if ( live_shinfo != NULL )
595 {
596 shdr = xc_core_shdr_get(sheaders);
597 if ( shdr == NULL )
598 {
599 PERROR("Could not get section header for .xen_shared_info");
600 goto out;
601 }
602 filesz = PAGE_SIZE;
603 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
604 SHT_PROGBITS, offset, filesz,
605 __alignof__(*live_shinfo), PAGE_SIZE);
606 if ( sts != 0 )
607 goto out;
608 offset += filesz;
609 }
611 /*
612 * pages and p2m/pfn are the last section to allocate section headers
613 * so that we know the number of section headers here.
614 * 2 = pages section and p2m/pfn table section
615 */
616 fixup = (sheaders->num + 2) * sizeof(*shdr);
617 /* zeroth section should have zero offset */
618 for ( i = 1; i < sheaders->num; i++ )
619 sheaders->shdrs[i].sh_offset += fixup;
620 offset += fixup;
621 dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
622 offset += dummy_len;
624 /* pages */
625 shdr = xc_core_shdr_get(sheaders);
626 if ( shdr == NULL )
627 {
628 PERROR("could not get section headers for .xen_pages");
629 goto out;
630 }
631 filesz = (uint64_t)nr_pages * PAGE_SIZE;
632 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
633 offset, filesz, PAGE_SIZE, PAGE_SIZE);
634 if ( sts != 0 )
635 goto out;
636 offset += filesz;
638 /* p2m/pfn table */
639 shdr = xc_core_shdr_get(sheaders);
640 if ( shdr == NULL )
641 {
642 PERROR("Could not get section header for .xen_{p2m, pfn} table");
643 goto out;
644 }
645 if ( !auto_translated_physmap )
646 {
647 filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
648 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
649 SHT_PROGBITS,
650 offset, filesz, __alignof__(p2m_array[0]),
651 sizeof(p2m_array[0]));
652 }
653 else
654 {
655 filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
656 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
657 SHT_PROGBITS,
658 offset, filesz, __alignof__(pfn_array[0]),
659 sizeof(pfn_array[0]));
660 }
661 if ( sts != 0 )
662 goto out;
663 offset += filesz;
665 /* fixing up section header string table section header */
666 filesz = strtab->current;
667 sheaders->shdrs[strtab_idx].sh_offset = offset;
668 sheaders->shdrs[strtab_idx].sh_size = filesz;
670 /* write out elf header */
671 ehdr.e_shnum = sheaders->num;
672 ehdr.e_shstrndx = strtab_idx;
673 sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
674 if ( sts != 0 )
675 goto out;
677 /* section headers */
678 sts = dump_rtn(args, (char*)sheaders->shdrs,
679 sheaders->num * sizeof(sheaders->shdrs[0]));
680 if ( sts != 0 )
681 goto out;
683 /* elf note section: xen core header */
684 sts = elfnote_dump_none(args, dump_rtn);
685 if ( sts != 0 )
686 goto out;
688 /* elf note section: xen core header */
689 sts = elfnote_dump_core_header(args, dump_rtn, &info, nr_vcpus, nr_pages);
690 if ( sts != 0 )
691 goto out;
693 /* elf note section: xen version */
694 sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle);
695 if ( sts != 0 )
696 goto out;
698 /* elf note section: format version */
699 sts = elfnote_dump_format_version(args, dump_rtn);
700 if ( sts != 0 )
701 goto out;
703 /* prstatus: .xen_prstatus */
704 sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus);
705 if ( sts != 0 )
706 goto out;
708 if ( live_shinfo != NULL )
709 {
710 /* shared_info: .xen_shared_info */
711 sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
712 if ( sts != 0 )
713 goto out;
714 }
716 /* arch specific context */
717 sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
718 if ( sts != 0 )
719 goto out;
721 /* Pad the output data to page alignment. */
722 memset(dummy, 0, PAGE_SIZE);
723 sts = dump_rtn(args, dummy, dummy_len);
724 if ( sts != 0 )
725 goto out;
727 /* dump pages: .xen_pages */
728 j = 0;
729 dump_mem = dump_mem_start;
730 for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
731 {
732 uint64_t pfn_start;
733 uint64_t pfn_end;
735 pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
736 pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
737 for ( i = pfn_start; i < pfn_end; i++ )
738 {
739 uint64_t gmfn;
740 void *vaddr;
742 if ( j >= nr_pages )
743 {
744 /*
745 * When live dump-mode (-L option) is specified,
746 * guest domain may increase memory.
747 */
748 IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages);
749 goto copy_done;
750 }
752 if ( !auto_translated_physmap )
753 {
754 gmfn = p2m[i];
755 if ( gmfn == INVALID_P2M_ENTRY )
756 continue;
758 p2m_array[j].pfn = i;
759 p2m_array[j].gmfn = gmfn;
760 }
761 else
762 {
763 if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
764 continue;
766 gmfn = i;
767 pfn_array[j] = i;
768 }
770 vaddr = xc_map_foreign_range(
771 xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn);
772 if ( vaddr == NULL )
773 continue;
774 memcpy(dump_mem, vaddr, PAGE_SIZE);
775 munmap(vaddr, PAGE_SIZE);
776 dump_mem += PAGE_SIZE;
777 if ( (j + 1) % DUMP_INCREMENT == 0 )
778 {
779 sts = dump_rtn(
780 args, dump_mem_start, dump_mem - dump_mem_start);
781 if ( sts != 0 )
782 goto out;
783 dump_mem = dump_mem_start;
784 }
786 j++;
787 }
788 }
790 copy_done:
791 sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
792 if ( sts != 0 )
793 goto out;
794 if ( j < nr_pages )
795 {
796 /* When live dump-mode (-L option) is specified,
797 * guest domain may reduce memory. pad with zero pages.
798 */
799 IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages);
800 memset(dump_mem_start, 0, PAGE_SIZE);
801 for (; j < nr_pages; j++) {
802 sts = dump_rtn(args, dump_mem_start, PAGE_SIZE);
803 if ( sts != 0 )
804 goto out;
805 if ( !auto_translated_physmap )
806 {
807 p2m_array[j].pfn = XC_CORE_INVALID_PFN;
808 p2m_array[j].gmfn = XC_CORE_INVALID_GMFN;
809 }
810 else
811 pfn_array[j] = XC_CORE_INVALID_PFN;
812 }
813 }
815 /* p2m/pfn table: .xen_p2m/.xen_pfn */
816 if ( !auto_translated_physmap )
817 sts = dump_rtn(
818 args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
819 else
820 sts = dump_rtn(
821 args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
822 if ( sts != 0 )
823 goto out;
825 /* elf section header string table: .shstrtab */
826 sts = dump_rtn(args, strtab->strings, strtab->current);
827 if ( sts != 0 )
828 goto out;
830 sts = 0;
832 out:
833 if ( memory_map != NULL )
834 free(memory_map);
835 if ( p2m != NULL )
836 munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
837 if ( p2m_array != NULL )
838 free(p2m_array);
839 if ( pfn_array != NULL )
840 free(pfn_array);
841 if ( sheaders != NULL )
842 xc_core_shdr_free(sheaders);
843 if ( strtab != NULL )
844 xc_core_strtab_free(strtab);
845 if ( dump_mem_start != NULL )
846 free(dump_mem_start);
847 if ( live_shinfo != NULL )
848 munmap(live_shinfo, PAGE_SIZE);
849 xc_core_arch_context_free(&arch_ctxt);
851 return sts;
852 }
854 /* Callback args for writing to a local dump file. */
855 struct dump_args {
856 int fd;
857 };
859 /* Callback routine for writing to a local dump file. */
860 static int local_file_dump(void *args, char *buffer, unsigned int length)
861 {
862 struct dump_args *da = args;
864 if ( write_exact(da->fd, buffer, length) == -1 )
865 {
866 PERROR("Failed to write buffer");
867 return -errno;
868 }
870 if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
871 {
872 // Now dumping pages -- make sure we discard clean pages from
873 // the cache after each write
874 discard_file_cache(da->fd, 0 /* no flush */);
875 }
877 return 0;
878 }
880 int
881 xc_domain_dumpcore(int xc_handle,
882 uint32_t domid,
883 const char *corename)
884 {
885 struct dump_args da;
886 int sts;
888 if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 )
889 {
890 PERROR("Could not open corefile %s", corename);
891 return -errno;
892 }
894 sts = xc_domain_dumpcore_via_callback(
895 xc_handle, domid, &da, &local_file_dump);
897 /* flush and discard any remaining portion of the file from cache */
898 discard_file_cache(da.fd, 1/* flush first*/);
900 close(da.fd);
902 return sts;
903 }
905 /*
906 * Local variables:
907 * mode: C
908 * c-set-style: "BSD"
909 * c-basic-offset: 4
910 * tab-width: 4
911 * indent-tabs-mode: nil
912 * End:
913 */