debuggers.hg

view tools/libxc/xc_core.c @ 16715:c5deb251b9dc

Update version to 3.2.0-rc4
author Keir Fraser <keir.fraser@citrix.com>
date Sat Dec 29 17:57:37 2007 +0000 (2007-12-29)
parents 7186e9611d55
children 90c37c32182c
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 > UINT16_MAX - len )
111 {
112 PERROR("too long string table");
113 errno = E2BIG;
114 return ret;
115 }
117 if ( strtab->current + len > strtab->max )
118 {
119 char *tmp;
120 if ( strtab->max > UINT16_MAX / 2 )
121 {
122 PERROR("too long string table");
123 errno = ENOMEM;
124 return ret;
125 }
127 tmp = realloc(strtab->strings, strtab->max * 2);
128 if ( tmp == NULL )
129 {
130 PERROR("Could not allocate string table");
131 return ret;
132 }
134 strtab->strings = tmp;
135 strtab->max *= 2;
136 }
138 ret = strtab->current;
139 strcpy(strtab->strings + strtab->current, name);
140 strtab->current += len;
141 return ret;
142 }
145 /* section headers */
146 struct xc_core_section_headers {
147 uint16_t num;
148 uint16_t num_max;
150 Elf64_Shdr *shdrs;
151 };
152 #define SHDR_INIT ((uint16_t)16)
153 #define SHDR_INC ((uint16_t)4)
155 static struct xc_core_section_headers*
156 xc_core_shdr_init(void)
157 {
158 struct xc_core_section_headers *sheaders;
159 sheaders = malloc(sizeof(*sheaders));
160 if ( sheaders == NULL )
161 return NULL;
163 sheaders->num = 0;
164 sheaders->num_max = SHDR_INIT;
165 sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
166 if ( sheaders->shdrs == NULL )
167 {
168 free(sheaders);
169 return NULL;
170 }
171 return sheaders;
172 }
174 static void
175 xc_core_shdr_free(struct xc_core_section_headers *sheaders)
176 {
177 free(sheaders->shdrs);
178 free(sheaders);
179 }
181 Elf64_Shdr*
182 xc_core_shdr_get(struct xc_core_section_headers *sheaders)
183 {
184 Elf64_Shdr *shdr;
186 if ( sheaders->num == sheaders->num_max )
187 {
188 Elf64_Shdr *shdrs;
189 if ( sheaders->num_max > UINT16_MAX - SHDR_INC )
190 {
191 errno = E2BIG;
192 return NULL;
193 }
194 sheaders->num_max += SHDR_INC;
195 shdrs = realloc(sheaders->shdrs,
196 sizeof(sheaders->shdrs[0]) * sheaders->num_max);
197 if ( shdrs == NULL )
198 return NULL;
199 sheaders->shdrs = shdrs;
200 }
202 shdr = &sheaders->shdrs[sheaders->num];
203 sheaders->num++;
204 memset(shdr, 0, sizeof(*shdr));
205 return shdr;
206 }
208 int
209 xc_core_shdr_set(Elf64_Shdr *shdr,
210 struct xc_core_strtab *strtab,
211 const char *name, uint32_t type,
212 uint64_t offset, uint64_t size,
213 uint64_t addralign, uint64_t entsize)
214 {
215 uint64_t name_idx = xc_core_strtab_get(strtab, name);
216 if ( name_idx == 0 )
217 return -1;
219 shdr->sh_name = name_idx;
220 shdr->sh_type = type;
221 shdr->sh_offset = offset;
222 shdr->sh_size = size;
223 shdr->sh_addralign = addralign;
224 shdr->sh_entsize = entsize;
225 return 0;
226 }
228 static void
229 xc_core_ehdr_init(Elf64_Ehdr *ehdr)
230 {
231 memset(ehdr, 0, sizeof(*ehdr));
232 ehdr->e_ident[EI_MAG0] = ELFMAG0;
233 ehdr->e_ident[EI_MAG1] = ELFMAG1;
234 ehdr->e_ident[EI_MAG2] = ELFMAG2;
235 ehdr->e_ident[EI_MAG3] = ELFMAG3;
236 ehdr->e_ident[EI_CLASS] = ELFCLASS64;
237 ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
238 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
239 ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
240 ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
242 ehdr->e_type = ET_CORE;
243 ehdr->e_machine = ELF_ARCH_MACHINE;
244 ehdr->e_version = EV_CURRENT;
245 ehdr->e_entry = 0;
246 ehdr->e_phoff = 0;
247 ehdr->e_shoff = sizeof(*ehdr);
248 ehdr->e_flags = ELF_CORE_EFLAGS;
249 ehdr->e_ehsize = sizeof(*ehdr);
250 ehdr->e_phentsize = sizeof(Elf64_Phdr);
251 ehdr->e_phnum = 0;
252 ehdr->e_shentsize = sizeof(Elf64_Shdr);
253 /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
254 * fill it later */
255 }
257 static int
258 elfnote_fill_xen_version(int xc_handle,
259 struct xen_dumpcore_elfnote_xen_version_desc
260 *xen_version)
261 {
262 int rc;
263 memset(xen_version, 0, sizeof(*xen_version));
265 rc = xc_version(xc_handle, XENVER_version, NULL);
266 if ( rc < 0 )
267 return rc;
268 xen_version->major_version = rc >> 16;
269 xen_version->minor_version = rc & ((1 << 16) - 1);
271 rc = xc_version(xc_handle, XENVER_extraversion,
272 &xen_version->extra_version);
273 if ( rc < 0 )
274 return rc;
276 rc = xc_version(xc_handle, XENVER_compile_info,
277 &xen_version->compile_info);
278 if ( rc < 0 )
279 return rc;
281 rc = xc_version(xc_handle,
282 XENVER_capabilities, &xen_version->capabilities);
283 if ( rc < 0 )
284 return rc;
286 rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
287 if ( rc < 0 )
288 return rc;
290 rc = xc_version(xc_handle, XENVER_platform_parameters,
291 &xen_version->platform_parameters);
292 if ( rc < 0 )
293 return rc;
295 rc = xc_version(xc_handle, XENVER_pagesize, NULL);
296 if ( rc < 0 )
297 return rc;
298 xen_version->pagesize = rc;
300 return 0;
301 }
303 static void
304 elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
305 *format_version)
306 {
307 format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
308 }
310 static void
311 elfnote_init(struct elfnote *elfnote)
312 {
313 /* elf note section */
314 memset(elfnote, 0, sizeof(*elfnote));
315 elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
316 strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
317 }
319 static int
320 elfnote_dump_none(void *args, dumpcore_rtn_t dump_rtn)
321 {
322 int sts;
323 struct elfnote elfnote;
324 struct xen_dumpcore_elfnote_none_desc none;
326 elfnote_init(&elfnote);
327 memset(&none, 0, sizeof(none));
329 elfnote.descsz = sizeof(none);
330 elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
331 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
332 if ( sts != 0 )
333 return sts;
334 return dump_rtn(args, (char*)&none, sizeof(none));
335 }
337 static int
338 elfnote_dump_core_header(
339 void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
340 int nr_vcpus, unsigned long nr_pages)
341 {
342 int sts;
343 struct elfnote elfnote;
344 struct xen_dumpcore_elfnote_header_desc header;
346 elfnote_init(&elfnote);
347 memset(&header, 0, sizeof(header));
349 elfnote.descsz = sizeof(header);
350 elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
351 header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
352 header.xch_nr_vcpus = nr_vcpus;
353 header.xch_nr_pages = nr_pages;
354 header.xch_page_size = PAGE_SIZE;
355 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
356 if ( sts != 0 )
357 return sts;
358 return dump_rtn(args, (char*)&header, sizeof(header));
359 }
361 static int
362 elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle)
363 {
364 int sts;
365 struct elfnote elfnote;
366 struct xen_dumpcore_elfnote_xen_version_desc xen_version;
368 elfnote_init(&elfnote);
369 memset(&xen_version, 0, sizeof(xen_version));
371 elfnote.descsz = sizeof(xen_version);
372 elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
373 elfnote_fill_xen_version(xc_handle, &xen_version);
374 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
375 if ( sts != 0 )
376 return sts;
377 return dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
378 }
380 static int
381 elfnote_dump_format_version(void *args, dumpcore_rtn_t dump_rtn)
382 {
383 int sts;
384 struct elfnote elfnote;
385 struct xen_dumpcore_elfnote_format_version_desc format_version;
387 elfnote_init(&elfnote);
388 memset(&format_version, 0, sizeof(format_version));
390 elfnote.descsz = sizeof(format_version);
391 elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
392 elfnote_fill_format_version(&format_version);
393 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
394 if ( sts != 0 )
395 return sts;
396 return dump_rtn(args, (char*)&format_version, sizeof(format_version));
397 }
399 int
400 xc_domain_dumpcore_via_callback(int xc_handle,
401 uint32_t domid,
402 void *args,
403 dumpcore_rtn_t dump_rtn)
404 {
405 xc_dominfo_t info;
406 shared_info_t *live_shinfo = NULL;
408 int nr_vcpus = 0;
409 char *dump_mem, *dump_mem_start = NULL;
410 vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
411 struct xc_core_arch_context arch_ctxt;
412 char dummy[PAGE_SIZE];
413 int dummy_len;
414 int sts = -1;
416 unsigned long i;
417 unsigned long j;
418 unsigned long nr_pages;
420 xc_core_memory_map_t *memory_map = NULL;
421 unsigned int nr_memory_map;
422 unsigned int map_idx;
424 int auto_translated_physmap;
425 xen_pfn_t *p2m = NULL;
426 unsigned long p2m_size = 0;
427 struct xen_dumpcore_p2m *p2m_array = NULL;
429 uint64_t *pfn_array = NULL;
431 Elf64_Ehdr ehdr;
432 uint64_t filesz;
433 uint64_t offset;
434 uint64_t fixup;
436 struct xc_core_strtab *strtab = NULL;
437 uint16_t strtab_idx;
438 struct xc_core_section_headers *sheaders = NULL;
439 Elf64_Shdr *shdr;
441 xc_core_arch_context_init(&arch_ctxt);
442 if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
443 {
444 PERROR("Could not allocate dump_mem");
445 goto out;
446 }
448 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
449 {
450 PERROR("Could not get info for domain");
451 goto out;
452 }
453 /* Map the shared info frame */
454 live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
455 PROT_READ, info.shared_info_frame);
456 if ( !live_shinfo && !info.hvm )
457 {
458 PERROR("Couldn't map live_shinfo");
459 goto out;
460 }
461 auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
463 if ( domid != info.domid )
464 {
465 PERROR("Domain %d does not exist", domid);
466 goto out;
467 }
469 for ( i = 0; i <= info.max_vcpu_id; i++ )
470 {
471 if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
472 {
473 if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
474 xc_handle, domid) )
475 continue;
476 nr_vcpus++;
477 }
478 }
479 if ( nr_vcpus == 0 )
480 {
481 PERROR("No VCPU context could be grabbed");
482 goto out;
483 }
485 /* obtain memory map */
486 sts = xc_core_arch_memory_map_get(xc_handle, &arch_ctxt, &info,
487 live_shinfo, &memory_map,
488 &nr_memory_map);
489 if ( sts != 0 )
490 goto out;
492 nr_pages = info.nr_pages;
493 if ( !auto_translated_physmap )
494 {
495 /* obtain p2m table */
496 p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
497 if ( p2m_array == NULL )
498 {
499 PERROR("Could not allocate p2m array");
500 goto out;
501 }
503 sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo,
504 &p2m, &p2m_size);
505 if ( sts != 0 )
506 goto out;
507 }
508 else
509 {
510 pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
511 if ( pfn_array == NULL )
512 {
513 PERROR("Could not allocate pfn array");
514 goto out;
515 }
516 }
518 /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
519 xc_core_ehdr_init(&ehdr);
521 /* create section header */
522 strtab = xc_core_strtab_init();
523 if ( strtab == NULL )
524 {
525 PERROR("Could not allocate string table");
526 goto out;
527 }
528 sheaders = xc_core_shdr_init();
529 if ( sheaders == NULL )
530 {
531 PERROR("Could not allocate section headers");
532 goto out;
533 }
534 /* null section */
535 shdr = xc_core_shdr_get(sheaders);
536 if ( shdr == NULL )
537 {
538 PERROR("Could not get section header for null section");
539 goto out;
540 }
542 /* .shstrtab */
543 shdr = xc_core_shdr_get(sheaders);
544 if ( shdr == NULL )
545 {
546 PERROR("Could not get section header for shstrtab");
547 goto out;
548 }
549 strtab_idx = shdr - sheaders->shdrs;
550 /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
551 * fill it later
552 */
553 sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
554 if ( sts != 0 )
555 goto out;
557 /* elf note section */
558 /* here the number of section header is unknown. fix up offset later. */
559 offset = sizeof(ehdr);
560 filesz =
561 sizeof(struct xen_dumpcore_elfnote_none) + /* none */
562 sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
563 sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
564 sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
565 shdr = xc_core_shdr_get(sheaders);
566 if ( shdr == NULL )
567 {
568 PERROR("Could not get section header for note section");
569 goto out;
570 }
571 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
572 offset, filesz, 0, 0);
573 if ( sts != 0 )
574 goto out;
575 offset += filesz;
577 /* prstatus */
578 shdr = xc_core_shdr_get(sheaders);
579 if ( shdr == NULL )
580 {
581 PERROR("Could not get section header for .xen_prstatus");
582 goto out;
583 }
584 filesz = sizeof(ctxt[0]) * nr_vcpus;
585 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
586 SHT_PROGBITS, offset, filesz,
587 __alignof__(ctxt[0]), sizeof(ctxt[0]));
588 if ( sts != 0 )
589 goto out;
590 offset += filesz;
592 /* arch context */
593 sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
594 &filesz, offset);
595 if ( sts != 0 )
596 goto out;
597 offset += filesz;
599 /* shared_info */
600 if ( live_shinfo != NULL )
601 {
602 shdr = xc_core_shdr_get(sheaders);
603 if ( shdr == NULL )
604 {
605 PERROR("Could not get section header for .xen_shared_info");
606 goto out;
607 }
608 filesz = PAGE_SIZE;
609 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
610 SHT_PROGBITS, offset, filesz,
611 __alignof__(*live_shinfo), PAGE_SIZE);
612 if ( sts != 0 )
613 goto out;
614 offset += filesz;
615 }
617 /*
618 * pages and p2m/pfn are the last section to allocate section headers
619 * so that we know the number of section headers here.
620 * 2 = pages section and p2m/pfn table section
621 */
622 fixup = (sheaders->num + 2) * sizeof(*shdr);
623 /* zeroth section should have zero offset */
624 for ( i = 1; i < sheaders->num; i++ )
625 sheaders->shdrs[i].sh_offset += fixup;
626 offset += fixup;
627 dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
628 offset += dummy_len;
630 /* pages */
631 shdr = xc_core_shdr_get(sheaders);
632 if ( shdr == NULL )
633 {
634 PERROR("could not get section headers for .xen_pages");
635 goto out;
636 }
637 filesz = (uint64_t)nr_pages * PAGE_SIZE;
638 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
639 offset, filesz, PAGE_SIZE, PAGE_SIZE);
640 if ( sts != 0 )
641 goto out;
642 offset += filesz;
644 /* p2m/pfn table */
645 shdr = xc_core_shdr_get(sheaders);
646 if ( shdr == NULL )
647 {
648 PERROR("Could not get section header for .xen_{p2m, pfn} table");
649 goto out;
650 }
651 if ( !auto_translated_physmap )
652 {
653 filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
654 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
655 SHT_PROGBITS,
656 offset, filesz, __alignof__(p2m_array[0]),
657 sizeof(p2m_array[0]));
658 }
659 else
660 {
661 filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
662 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
663 SHT_PROGBITS,
664 offset, filesz, __alignof__(pfn_array[0]),
665 sizeof(pfn_array[0]));
666 }
667 if ( sts != 0 )
668 goto out;
669 offset += filesz;
671 /* fixing up section header string table section header */
672 filesz = strtab->current;
673 sheaders->shdrs[strtab_idx].sh_offset = offset;
674 sheaders->shdrs[strtab_idx].sh_size = filesz;
676 /* write out elf header */
677 ehdr.e_shnum = sheaders->num;
678 ehdr.e_shstrndx = strtab_idx;
679 sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
680 if ( sts != 0 )
681 goto out;
683 /* section headers */
684 sts = dump_rtn(args, (char*)sheaders->shdrs,
685 sheaders->num * sizeof(sheaders->shdrs[0]));
686 if ( sts != 0 )
687 goto out;
689 /* elf note section: xen core header */
690 sts = elfnote_dump_none(args, dump_rtn);
691 if ( sts != 0 )
692 goto out;
694 /* elf note section: xen core header */
695 sts = elfnote_dump_core_header(args, dump_rtn, &info, nr_vcpus, nr_pages);
696 if ( sts != 0 )
697 goto out;
699 /* elf note section: xen version */
700 sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle);
701 if ( sts != 0 )
702 goto out;
704 /* elf note section: format version */
705 sts = elfnote_dump_format_version(args, dump_rtn);
706 if ( sts != 0 )
707 goto out;
709 /* prstatus: .xen_prstatus */
710 sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus);
711 if ( sts != 0 )
712 goto out;
714 if ( live_shinfo != NULL )
715 {
716 /* shared_info: .xen_shared_info */
717 sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
718 if ( sts != 0 )
719 goto out;
720 }
722 /* arch specific context */
723 sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
724 if ( sts != 0 )
725 goto out;
727 /* Pad the output data to page alignment. */
728 memset(dummy, 0, PAGE_SIZE);
729 sts = dump_rtn(args, dummy, dummy_len);
730 if ( sts != 0 )
731 goto out;
733 /* dump pages: .xen_pages */
734 j = 0;
735 dump_mem = dump_mem_start;
736 for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
737 {
738 uint64_t pfn_start;
739 uint64_t pfn_end;
741 pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
742 pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
743 for ( i = pfn_start; i < pfn_end; i++ )
744 {
745 uint64_t gmfn;
746 void *vaddr;
748 if ( j >= nr_pages )
749 {
750 /*
751 * When live dump-mode (-L option) is specified,
752 * guest domain may increase memory.
753 */
754 IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages);
755 goto copy_done;
756 }
758 if ( !auto_translated_physmap )
759 {
760 gmfn = p2m[i];
761 if ( gmfn == INVALID_P2M_ENTRY )
762 continue;
764 p2m_array[j].pfn = i;
765 p2m_array[j].gmfn = gmfn;
766 }
767 else
768 {
769 if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
770 continue;
772 gmfn = i;
773 pfn_array[j] = i;
774 }
776 vaddr = xc_map_foreign_range(
777 xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn);
778 if ( vaddr == NULL )
779 continue;
780 memcpy(dump_mem, vaddr, PAGE_SIZE);
781 munmap(vaddr, PAGE_SIZE);
782 dump_mem += PAGE_SIZE;
783 if ( (j + 1) % DUMP_INCREMENT == 0 )
784 {
785 sts = dump_rtn(
786 args, dump_mem_start, dump_mem - dump_mem_start);
787 if ( sts != 0 )
788 goto out;
789 dump_mem = dump_mem_start;
790 }
792 j++;
793 }
794 }
796 copy_done:
797 sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
798 if ( sts != 0 )
799 goto out;
800 if ( j < nr_pages )
801 {
802 /* When live dump-mode (-L option) is specified,
803 * guest domain may reduce memory. pad with zero pages.
804 */
805 IPRINTF("j (%ld) != nr_pages (%ld)", j , nr_pages);
806 memset(dump_mem_start, 0, PAGE_SIZE);
807 for (; j < nr_pages; j++) {
808 sts = dump_rtn(args, dump_mem_start, PAGE_SIZE);
809 if ( sts != 0 )
810 goto out;
811 if ( !auto_translated_physmap )
812 {
813 p2m_array[j].pfn = XC_CORE_INVALID_PFN;
814 p2m_array[j].gmfn = XC_CORE_INVALID_GMFN;
815 }
816 else
817 pfn_array[j] = XC_CORE_INVALID_PFN;
818 }
819 }
821 /* p2m/pfn table: .xen_p2m/.xen_pfn */
822 if ( !auto_translated_physmap )
823 sts = dump_rtn(
824 args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
825 else
826 sts = dump_rtn(
827 args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
828 if ( sts != 0 )
829 goto out;
831 /* elf section header string table: .shstrtab */
832 sts = dump_rtn(args, strtab->strings, strtab->current);
833 if ( sts != 0 )
834 goto out;
836 sts = 0;
838 out:
839 if ( memory_map != NULL )
840 free(memory_map);
841 if ( p2m != NULL )
842 munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
843 if ( p2m_array != NULL )
844 free(p2m_array);
845 if ( pfn_array != NULL )
846 free(pfn_array);
847 if ( sheaders != NULL )
848 xc_core_shdr_free(sheaders);
849 if ( strtab != NULL )
850 xc_core_strtab_free(strtab);
851 if ( dump_mem_start != NULL )
852 free(dump_mem_start);
853 if ( live_shinfo != NULL )
854 munmap(live_shinfo, PAGE_SIZE);
855 xc_core_arch_context_free(&arch_ctxt);
857 return sts;
858 }
860 /* Callback args for writing to a local dump file. */
861 struct dump_args {
862 int fd;
863 };
865 /* Callback routine for writing to a local dump file. */
866 static int local_file_dump(void *args, char *buffer, unsigned int length)
867 {
868 struct dump_args *da = args;
870 if ( write_exact(da->fd, buffer, length) == -1 )
871 {
872 PERROR("Failed to write buffer");
873 return -errno;
874 }
876 if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
877 {
878 // Now dumping pages -- make sure we discard clean pages from
879 // the cache after each write
880 discard_file_cache(da->fd, 0 /* no flush */);
881 }
883 return 0;
884 }
886 int
887 xc_domain_dumpcore(int xc_handle,
888 uint32_t domid,
889 const char *corename)
890 {
891 struct dump_args da;
892 int sts;
894 if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 )
895 {
896 PERROR("Could not open corefile %s", corename);
897 return -errno;
898 }
900 sts = xc_domain_dumpcore_via_callback(
901 xc_handle, domid, &da, &local_file_dump);
903 /* flush and discard any remaining portion of the file from cache */
904 discard_file_cache(da.fd, 1/* flush first*/);
906 close(da.fd);
908 return sts;
909 }
911 /*
912 * Local variables:
913 * mode: C
914 * c-set-style: "BSD"
915 * c-basic-offset: 4
916 * tab-width: 4
917 * indent-tabs-mode: nil
918 * End:
919 */