debuggers.hg

view tools/libxc/xc_core.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents 3e4a70d6c50a
children 779c0ef9682c
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 /* string table */
62 struct xc_core_strtab {
63 char *strings;
64 uint16_t length;
65 uint16_t max;
66 };
68 static struct xc_core_strtab*
69 xc_core_strtab_init(void)
70 {
71 struct xc_core_strtab *strtab;
72 char *strings;
73 strtab = malloc(sizeof(*strtab));
74 if ( strtab == NULL )
75 return NULL;
77 strings = malloc(PAGE_SIZE);
78 if ( strings == NULL )
79 {
80 PERROR("Could not allocate string table init");
81 free(strtab);
82 return NULL;
83 }
84 strtab->strings = strings;
85 strtab->max = PAGE_SIZE;
87 /* index 0 represents none */
88 strtab->strings[0] = '\0';
89 strtab->length = 1;
91 return strtab;
92 }
94 static void
95 xc_core_strtab_free(struct xc_core_strtab *strtab)
96 {
97 free(strtab->strings);
98 free(strtab);
99 }
101 static uint16_t
102 xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name)
103 {
104 uint16_t ret = 0;
105 uint16_t len = strlen(name) + 1;
107 if ( strtab->length > UINT16_MAX - len )
108 {
109 PERROR("too long string table");
110 errno = E2BIG;
111 return ret;
112 }
114 if ( strtab->length + len > strtab->max )
115 {
116 char *tmp;
117 if ( strtab->max > UINT16_MAX / 2 )
118 {
119 PERROR("too long string table");
120 errno = ENOMEM;
121 return ret;
122 }
124 tmp = realloc(strtab->strings, strtab->max * 2);
125 if ( tmp == NULL )
126 {
127 PERROR("Could not allocate string table");
128 return ret;
129 }
131 strtab->strings = tmp;
132 strtab->max *= 2;
133 }
135 ret = strtab->length;
136 strcpy(strtab->strings + strtab->length, name);
137 strtab->length += len;
138 return ret;
139 }
142 /* section headers */
143 struct xc_core_section_headers {
144 uint16_t num;
145 uint16_t num_max;
147 Elf64_Shdr *shdrs;
148 };
149 #define SHDR_INIT ((uint16_t)16)
150 #define SHDR_INC ((uint16_t)4)
152 static struct xc_core_section_headers*
153 xc_core_shdr_init(void)
154 {
155 struct xc_core_section_headers *sheaders;
156 sheaders = malloc(sizeof(*sheaders));
157 if ( sheaders == NULL )
158 return NULL;
160 sheaders->num = 0;
161 sheaders->num_max = SHDR_INIT;
162 sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
163 if ( sheaders->shdrs == NULL )
164 {
165 free(sheaders);
166 return NULL;
167 }
168 return sheaders;
169 }
171 static void
172 xc_core_shdr_free(struct xc_core_section_headers *sheaders)
173 {
174 free(sheaders->shdrs);
175 free(sheaders);
176 }
178 Elf64_Shdr*
179 xc_core_shdr_get(struct xc_core_section_headers *sheaders)
180 {
181 Elf64_Shdr *shdr;
183 if ( sheaders->num == sheaders->num_max )
184 {
185 Elf64_Shdr *shdrs;
186 if ( sheaders->num_max > UINT16_MAX - SHDR_INC )
187 {
188 errno = E2BIG;
189 return NULL;
190 }
191 sheaders->num_max += SHDR_INC;
192 shdrs = realloc(sheaders->shdrs,
193 sizeof(sheaders->shdrs[0]) * sheaders->num_max);
194 if ( shdrs == NULL )
195 return NULL;
196 sheaders->shdrs = shdrs;
197 }
199 shdr = &sheaders->shdrs[sheaders->num];
200 sheaders->num++;
201 memset(shdr, 0, sizeof(*shdr));
202 return shdr;
203 }
205 int
206 xc_core_shdr_set(Elf64_Shdr *shdr,
207 struct xc_core_strtab *strtab,
208 const char *name, uint32_t type,
209 uint64_t offset, uint64_t size,
210 uint64_t addralign, uint64_t entsize)
211 {
212 uint64_t name_idx = xc_core_strtab_get(strtab, name);
213 if ( name_idx == 0 )
214 return -1;
216 shdr->sh_name = name_idx;
217 shdr->sh_type = type;
218 shdr->sh_offset = offset;
219 shdr->sh_size = size;
220 shdr->sh_addralign = addralign;
221 shdr->sh_entsize = entsize;
222 return 0;
223 }
225 static void
226 xc_core_ehdr_init(Elf64_Ehdr *ehdr)
227 {
228 memset(ehdr, 0, sizeof(*ehdr));
229 ehdr->e_ident[EI_MAG0] = ELFMAG0;
230 ehdr->e_ident[EI_MAG1] = ELFMAG1;
231 ehdr->e_ident[EI_MAG2] = ELFMAG2;
232 ehdr->e_ident[EI_MAG3] = ELFMAG3;
233 ehdr->e_ident[EI_CLASS] = ELFCLASS64;
234 ehdr->e_ident[EI_DATA] = ELF_ARCH_DATA;
235 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
236 ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
237 ehdr->e_ident[EI_ABIVERSION] = EV_CURRENT;
239 ehdr->e_type = ET_CORE;
240 /* e_machine will be filled in later */
241 ehdr->e_version = EV_CURRENT;
242 ehdr->e_entry = 0;
243 ehdr->e_phoff = 0;
244 ehdr->e_shoff = sizeof(*ehdr);
245 ehdr->e_flags = ELF_CORE_EFLAGS;
246 ehdr->e_ehsize = sizeof(*ehdr);
247 ehdr->e_phentsize = sizeof(Elf64_Phdr);
248 ehdr->e_phnum = 0;
249 ehdr->e_shentsize = sizeof(Elf64_Shdr);
250 /* ehdr->e_shnum and ehdr->e_shstrndx aren't known here yet.
251 * fill it later */
252 }
254 static int
255 elfnote_fill_xen_version(int xc_handle,
256 struct xen_dumpcore_elfnote_xen_version_desc
257 *xen_version)
258 {
259 int rc;
260 memset(xen_version, 0, sizeof(*xen_version));
262 rc = xc_version(xc_handle, XENVER_version, NULL);
263 if ( rc < 0 )
264 return rc;
265 xen_version->major_version = rc >> 16;
266 xen_version->minor_version = rc & ((1 << 16) - 1);
268 rc = xc_version(xc_handle, XENVER_extraversion,
269 &xen_version->extra_version);
270 if ( rc < 0 )
271 return rc;
273 rc = xc_version(xc_handle, XENVER_compile_info,
274 &xen_version->compile_info);
275 if ( rc < 0 )
276 return rc;
278 rc = xc_version(xc_handle,
279 XENVER_capabilities, &xen_version->capabilities);
280 if ( rc < 0 )
281 return rc;
283 rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
284 if ( rc < 0 )
285 return rc;
287 rc = xc_version(xc_handle, XENVER_platform_parameters,
288 &xen_version->platform_parameters);
289 if ( rc < 0 )
290 return rc;
292 rc = xc_version(xc_handle, XENVER_pagesize, NULL);
293 if ( rc < 0 )
294 return rc;
295 xen_version->pagesize = rc;
297 return 0;
298 }
300 static void
301 elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
302 *format_version)
303 {
304 format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
305 }
307 static void
308 elfnote_init(struct elfnote *elfnote)
309 {
310 /* elf note section */
311 memset(elfnote, 0, sizeof(*elfnote));
312 elfnote->namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
313 strncpy(elfnote->name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote->name));
314 }
316 static int
317 elfnote_dump_none(void *args, dumpcore_rtn_t dump_rtn)
318 {
319 int sts;
320 struct elfnote elfnote;
321 struct xen_dumpcore_elfnote_none_desc none;
323 elfnote_init(&elfnote);
324 /* Avoid compile warning about constant-zero-sized memset(). */
325 /*memset(&none, 0, sizeof(none));*/
327 elfnote.descsz = sizeof(none);
328 elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
329 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
330 if ( sts != 0 )
331 return sts;
332 return dump_rtn(args, (char*)&none, sizeof(none));
333 }
335 static int
336 elfnote_dump_core_header(
337 void *args, dumpcore_rtn_t dump_rtn, const xc_dominfo_t *info,
338 int nr_vcpus, unsigned long nr_pages)
339 {
340 int sts;
341 struct elfnote elfnote;
342 struct xen_dumpcore_elfnote_header_desc header;
344 elfnote_init(&elfnote);
345 memset(&header, 0, sizeof(header));
347 elfnote.descsz = sizeof(header);
348 elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
349 header.xch_magic = info->hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
350 header.xch_nr_vcpus = nr_vcpus;
351 header.xch_nr_pages = nr_pages;
352 header.xch_page_size = PAGE_SIZE;
353 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
354 if ( sts != 0 )
355 return sts;
356 return dump_rtn(args, (char*)&header, sizeof(header));
357 }
359 static int
360 elfnote_dump_xen_version(void *args, dumpcore_rtn_t dump_rtn, int xc_handle,
361 unsigned int guest_width)
362 {
363 int sts;
364 struct elfnote elfnote;
365 struct xen_dumpcore_elfnote_xen_version_desc xen_version;
367 elfnote_init(&elfnote);
368 memset(&xen_version, 0, sizeof(xen_version));
370 elfnote.descsz = sizeof(xen_version);
371 elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
372 elfnote_fill_xen_version(xc_handle, &xen_version);
373 if (guest_width < sizeof(unsigned long))
374 {
375 // 32 bit elf file format differs in pagesize's alignment
376 char *p = (char *)&xen_version.pagesize;
377 memmove(p - 4, p, sizeof(xen_version.pagesize));
378 }
379 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
380 if ( sts != 0 )
381 return sts;
382 return dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
383 }
385 static int
386 elfnote_dump_format_version(void *args, dumpcore_rtn_t dump_rtn)
387 {
388 int sts;
389 struct elfnote elfnote;
390 struct xen_dumpcore_elfnote_format_version_desc format_version;
392 elfnote_init(&elfnote);
393 memset(&format_version, 0, sizeof(format_version));
395 elfnote.descsz = sizeof(format_version);
396 elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
397 elfnote_fill_format_version(&format_version);
398 sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
399 if ( sts != 0 )
400 return sts;
401 return dump_rtn(args, (char*)&format_version, sizeof(format_version));
402 }
404 static int
405 get_guest_width(int xc_handle,
406 uint32_t domid,
407 unsigned int *guest_width)
408 {
409 DECLARE_DOMCTL;
411 memset(&domctl, 0, sizeof(domctl));
412 domctl.domain = domid;
413 domctl.cmd = XEN_DOMCTL_get_address_size;
415 if ( do_domctl(xc_handle, &domctl) != 0 )
416 return 1;
418 *guest_width = domctl.u.address_size.size / 8;
419 return 0;
420 }
422 int
423 xc_domain_dumpcore_via_callback(int xc_handle,
424 uint32_t domid,
425 void *args,
426 dumpcore_rtn_t dump_rtn)
427 {
428 xc_dominfo_t info;
429 shared_info_any_t *live_shinfo = NULL;
430 struct domain_info_context _dinfo = {};
431 struct domain_info_context *dinfo = &_dinfo;
433 int nr_vcpus = 0;
434 char *dump_mem, *dump_mem_start = NULL;
435 vcpu_guest_context_any_t *ctxt = NULL;
436 struct xc_core_arch_context arch_ctxt;
437 char dummy[PAGE_SIZE];
438 int dummy_len;
439 int sts = -1;
441 unsigned long i;
442 unsigned long j;
443 unsigned long nr_pages;
445 xc_core_memory_map_t *memory_map = NULL;
446 unsigned int nr_memory_map;
447 unsigned int map_idx;
449 int auto_translated_physmap;
450 xen_pfn_t *p2m = NULL;
451 unsigned long p2m_size = 0;
452 struct xen_dumpcore_p2m *p2m_array = NULL;
454 uint64_t *pfn_array = NULL;
456 Elf64_Ehdr ehdr;
457 uint64_t filesz;
458 uint64_t offset;
459 uint64_t fixup;
461 struct xc_core_strtab *strtab = NULL;
462 uint16_t strtab_idx;
463 struct xc_core_section_headers *sheaders = NULL;
464 Elf64_Shdr *shdr;
466 if ( get_guest_width(xc_handle, domid, &dinfo->guest_width) != 0 )
467 {
468 PERROR("Could not get address size for domain");
469 return sts;
470 }
472 xc_core_arch_context_init(&arch_ctxt);
473 if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
474 {
475 PERROR("Could not allocate dump_mem");
476 goto out;
477 }
479 if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
480 {
481 PERROR("Could not get info for domain");
482 goto out;
483 }
484 /* Map the shared info frame */
485 live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
486 PROT_READ, info.shared_info_frame);
487 if ( !live_shinfo && !info.hvm )
488 {
489 PERROR("Couldn't map live_shinfo");
490 goto out;
491 }
492 auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
494 if ( domid != info.domid )
495 {
496 PERROR("Domain %d does not exist", domid);
497 goto out;
498 }
500 ctxt = calloc(sizeof(*ctxt), info.max_vcpu_id + 1);
501 if ( !ctxt )
502 {
503 PERROR("Could not allocate vcpu context array", domid);
504 goto out;
505 }
507 for ( i = 0; i <= info.max_vcpu_id; i++ )
508 {
509 if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
510 {
511 if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
512 xc_handle, domid) )
513 continue;
514 nr_vcpus++;
515 }
516 }
517 if ( nr_vcpus == 0 )
518 {
519 PERROR("No VCPU context could be grabbed");
520 goto out;
521 }
523 /* obtain memory map */
524 sts = xc_core_arch_memory_map_get(xc_handle, &arch_ctxt, &info,
525 live_shinfo, &memory_map,
526 &nr_memory_map);
527 if ( sts != 0 )
528 goto out;
530 /*
531 * Note: this is the *current* number of pages and may change under
532 * a live dump-core. We'll just take this value, and if more pages
533 * exist, we'll skip them. If there's less, then we'll just not use
534 * all the array...
535 *
536 * We don't want to use the total potential size of the memory map
537 * since that is usually much higher than info.nr_pages.
538 */
539 nr_pages = info.nr_pages;
541 if ( !auto_translated_physmap )
542 {
543 /* obtain p2m table */
544 p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
545 if ( p2m_array == NULL )
546 {
547 PERROR("Could not allocate p2m array");
548 goto out;
549 }
551 sts = xc_core_arch_map_p2m(xc_handle, dinfo->guest_width, &info, live_shinfo,
552 &p2m, &p2m_size);
553 if ( sts != 0 )
554 goto out;
555 }
556 else
557 {
558 pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
559 if ( pfn_array == NULL )
560 {
561 PERROR("Could not allocate pfn array");
562 goto out;
563 }
564 }
566 /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
567 xc_core_ehdr_init(&ehdr);
569 /* create section header */
570 strtab = xc_core_strtab_init();
571 if ( strtab == NULL )
572 {
573 PERROR("Could not allocate string table");
574 goto out;
575 }
576 sheaders = xc_core_shdr_init();
577 if ( sheaders == NULL )
578 {
579 PERROR("Could not allocate section headers");
580 goto out;
581 }
582 /* null section */
583 shdr = xc_core_shdr_get(sheaders);
584 if ( shdr == NULL )
585 {
586 PERROR("Could not get section header for null section");
587 goto out;
588 }
590 /* .shstrtab */
591 shdr = xc_core_shdr_get(sheaders);
592 if ( shdr == NULL )
593 {
594 PERROR("Could not get section header for shstrtab");
595 goto out;
596 }
597 strtab_idx = shdr - sheaders->shdrs;
598 /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
599 * fill it later
600 */
601 sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
602 if ( sts != 0 )
603 goto out;
605 /* elf note section */
606 /* here the number of section header is unknown. fix up offset later. */
607 offset = sizeof(ehdr);
608 filesz =
609 sizeof(struct xen_dumpcore_elfnote_none) + /* none */
610 sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
611 sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
612 sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
613 shdr = xc_core_shdr_get(sheaders);
614 if ( shdr == NULL )
615 {
616 PERROR("Could not get section header for note section");
617 goto out;
618 }
619 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
620 offset, filesz, 0, 0);
621 if ( sts != 0 )
622 goto out;
623 offset += filesz;
625 /* prstatus */
626 shdr = xc_core_shdr_get(sheaders);
627 if ( shdr == NULL )
628 {
629 PERROR("Could not get section header for .xen_prstatus");
630 goto out;
631 }
632 filesz = sizeof(*ctxt) * nr_vcpus;
633 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
634 SHT_PROGBITS, offset, filesz,
635 __alignof__(*ctxt), sizeof(*ctxt));
636 if ( sts != 0 )
637 goto out;
638 offset += filesz;
640 /* arch context */
641 sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
642 &filesz, offset);
643 if ( sts != 0 )
644 goto out;
645 offset += filesz;
647 /* shared_info */
648 if ( live_shinfo != NULL )
649 {
650 shdr = xc_core_shdr_get(sheaders);
651 if ( shdr == NULL )
652 {
653 PERROR("Could not get section header for .xen_shared_info");
654 goto out;
655 }
656 filesz = PAGE_SIZE;
657 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
658 SHT_PROGBITS, offset, filesz,
659 __alignof__(*live_shinfo), PAGE_SIZE);
660 if ( sts != 0 )
661 goto out;
662 offset += filesz;
663 }
665 /*
666 * pages and p2m/pfn are the last section to allocate section headers
667 * so that we know the number of section headers here.
668 * 2 = pages section and p2m/pfn table section
669 */
670 fixup = (sheaders->num + 2) * sizeof(*shdr);
671 /* zeroth section should have zero offset */
672 for ( i = 1; i < sheaders->num; i++ )
673 sheaders->shdrs[i].sh_offset += fixup;
674 offset += fixup;
675 dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
676 offset += dummy_len;
678 /* pages */
679 shdr = xc_core_shdr_get(sheaders);
680 if ( shdr == NULL )
681 {
682 PERROR("could not get section headers for .xen_pages");
683 goto out;
684 }
685 filesz = (uint64_t)nr_pages * PAGE_SIZE;
686 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
687 offset, filesz, PAGE_SIZE, PAGE_SIZE);
688 if ( sts != 0 )
689 goto out;
690 offset += filesz;
692 /* p2m/pfn table */
693 shdr = xc_core_shdr_get(sheaders);
694 if ( shdr == NULL )
695 {
696 PERROR("Could not get section header for .xen_{p2m, pfn} table");
697 goto out;
698 }
699 if ( !auto_translated_physmap )
700 {
701 filesz = (uint64_t)nr_pages * sizeof(p2m_array[0]);
702 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
703 SHT_PROGBITS,
704 offset, filesz, __alignof__(p2m_array[0]),
705 sizeof(p2m_array[0]));
706 }
707 else
708 {
709 filesz = (uint64_t)nr_pages * sizeof(pfn_array[0]);
710 sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
711 SHT_PROGBITS,
712 offset, filesz, __alignof__(pfn_array[0]),
713 sizeof(pfn_array[0]));
714 }
715 if ( sts != 0 )
716 goto out;
717 offset += filesz;
719 /* fixing up section header string table section header */
720 filesz = strtab->length;
721 sheaders->shdrs[strtab_idx].sh_offset = offset;
722 sheaders->shdrs[strtab_idx].sh_size = filesz;
724 /* write out elf header */
725 ehdr.e_shnum = sheaders->num;
726 ehdr.e_shstrndx = strtab_idx;
727 ehdr.e_machine = ELF_ARCH_MACHINE;
728 sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
729 if ( sts != 0 )
730 goto out;
732 /* section headers */
733 sts = dump_rtn(args, (char*)sheaders->shdrs,
734 sheaders->num * sizeof(sheaders->shdrs[0]));
735 if ( sts != 0 )
736 goto out;
738 /* elf note section: xen core header */
739 sts = elfnote_dump_none(args, dump_rtn);
740 if ( sts != 0 )
741 goto out;
743 /* elf note section: xen core header */
744 sts = elfnote_dump_core_header(args, dump_rtn, &info, nr_vcpus, nr_pages);
745 if ( sts != 0 )
746 goto out;
748 /* elf note section: xen version */
749 sts = elfnote_dump_xen_version(args, dump_rtn, xc_handle, dinfo->guest_width);
750 if ( sts != 0 )
751 goto out;
753 /* elf note section: format version */
754 sts = elfnote_dump_format_version(args, dump_rtn);
755 if ( sts != 0 )
756 goto out;
758 /* prstatus: .xen_prstatus */
759 sts = dump_rtn(args, (char *)ctxt, sizeof(*ctxt) * nr_vcpus);
760 if ( sts != 0 )
761 goto out;
763 if ( live_shinfo != NULL )
764 {
765 /* shared_info: .xen_shared_info */
766 sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
767 if ( sts != 0 )
768 goto out;
769 }
771 /* arch specific context */
772 sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
773 if ( sts != 0 )
774 goto out;
776 /* Pad the output data to page alignment. */
777 memset(dummy, 0, PAGE_SIZE);
778 sts = dump_rtn(args, dummy, dummy_len);
779 if ( sts != 0 )
780 goto out;
782 /* dump pages: .xen_pages */
783 j = 0;
784 dump_mem = dump_mem_start;
785 for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
786 {
787 uint64_t pfn_start;
788 uint64_t pfn_end;
790 pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
791 pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
792 for ( i = pfn_start; i < pfn_end; i++ )
793 {
794 uint64_t gmfn;
795 void *vaddr;
797 if ( j >= nr_pages )
798 {
799 /*
800 * When live dump-mode (-L option) is specified,
801 * guest domain may increase memory.
802 */
803 IPRINTF("exceeded nr_pages (%ld) losing pages", nr_pages);
804 goto copy_done;
805 }
807 if ( !auto_translated_physmap )
808 {
809 if ( dinfo->guest_width >= sizeof(unsigned long) )
810 {
811 if ( dinfo->guest_width == sizeof(unsigned long) )
812 gmfn = p2m[i];
813 else
814 gmfn = ((uint64_t *)p2m)[i];
815 if ( gmfn == INVALID_P2M_ENTRY )
816 continue;
817 }
818 else
819 {
820 gmfn = ((uint32_t *)p2m)[i];
821 if ( gmfn == (uint32_t)INVALID_P2M_ENTRY )
822 continue;
823 }
825 p2m_array[j].pfn = i;
826 p2m_array[j].gmfn = gmfn;
827 }
828 else
829 {
830 if ( !xc_core_arch_gpfn_may_present(&arch_ctxt, i) )
831 continue;
833 gmfn = i;
834 pfn_array[j] = i;
835 }
837 vaddr = xc_map_foreign_range(
838 xc_handle, domid, PAGE_SIZE, PROT_READ, gmfn);
839 if ( vaddr == NULL )
840 continue;
841 memcpy(dump_mem, vaddr, PAGE_SIZE);
842 munmap(vaddr, PAGE_SIZE);
843 dump_mem += PAGE_SIZE;
844 if ( (j + 1) % DUMP_INCREMENT == 0 )
845 {
846 sts = dump_rtn(
847 args, dump_mem_start, dump_mem - dump_mem_start);
848 if ( sts != 0 )
849 goto out;
850 dump_mem = dump_mem_start;
851 }
853 j++;
854 }
855 }
857 copy_done:
858 sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
859 if ( sts != 0 )
860 goto out;
861 if ( j < nr_pages )
862 {
863 /* When live dump-mode (-L option) is specified,
864 * guest domain may reduce memory. pad with zero pages.
865 */
866 IPRINTF("j (%ld) != nr_pages (%ld)", j, nr_pages);
867 memset(dump_mem_start, 0, PAGE_SIZE);
868 for (; j < nr_pages; j++) {
869 sts = dump_rtn(args, dump_mem_start, PAGE_SIZE);
870 if ( sts != 0 )
871 goto out;
872 if ( !auto_translated_physmap )
873 {
874 p2m_array[j].pfn = XC_CORE_INVALID_PFN;
875 p2m_array[j].gmfn = XC_CORE_INVALID_GMFN;
876 }
877 else
878 pfn_array[j] = XC_CORE_INVALID_PFN;
879 }
880 }
882 /* p2m/pfn table: .xen_p2m/.xen_pfn */
883 if ( !auto_translated_physmap )
884 sts = dump_rtn(
885 args, (char *)p2m_array, sizeof(p2m_array[0]) * nr_pages);
886 else
887 sts = dump_rtn(
888 args, (char *)pfn_array, sizeof(pfn_array[0]) * nr_pages);
889 if ( sts != 0 )
890 goto out;
892 /* elf section header string table: .shstrtab */
893 sts = dump_rtn(args, strtab->strings, strtab->length);
894 if ( sts != 0 )
895 goto out;
897 sts = 0;
899 out:
900 if ( memory_map != NULL )
901 free(memory_map);
902 if ( p2m != NULL )
903 munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
904 if ( p2m_array != NULL )
905 free(p2m_array);
906 if ( pfn_array != NULL )
907 free(pfn_array);
908 if ( sheaders != NULL )
909 xc_core_shdr_free(sheaders);
910 if ( strtab != NULL )
911 xc_core_strtab_free(strtab);
912 if ( ctxt != NULL )
913 free(ctxt);
914 if ( dump_mem_start != NULL )
915 free(dump_mem_start);
916 if ( live_shinfo != NULL )
917 munmap(live_shinfo, PAGE_SIZE);
918 xc_core_arch_context_free(&arch_ctxt);
920 return sts;
921 }
923 /* Callback args for writing to a local dump file. */
924 struct dump_args {
925 int fd;
926 };
928 /* Callback routine for writing to a local dump file. */
929 static int local_file_dump(void *args, char *buffer, unsigned int length)
930 {
931 struct dump_args *da = args;
933 if ( write_exact(da->fd, buffer, length) == -1 )
934 {
935 PERROR("Failed to write buffer");
936 return -errno;
937 }
939 if ( length >= (DUMP_INCREMENT * PAGE_SIZE) )
940 {
941 // Now dumping pages -- make sure we discard clean pages from
942 // the cache after each write
943 discard_file_cache(da->fd, 0 /* no flush */);
944 }
946 return 0;
947 }
949 int
950 xc_domain_dumpcore(int xc_handle,
951 uint32_t domid,
952 const char *corename)
953 {
954 struct dump_args da;
955 int sts;
957 if ( (da.fd = open(corename, O_CREAT|O_RDWR|O_TRUNC, S_IWUSR|S_IRUSR)) < 0 )
958 {
959 PERROR("Could not open corefile %s", corename);
960 return -errno;
961 }
963 sts = xc_domain_dumpcore_via_callback(
964 xc_handle, domid, &da, &local_file_dump);
966 /* flush and discard any remaining portion of the file from cache */
967 discard_file_cache(da.fd, 1/* flush first*/);
969 close(da.fd);
971 return sts;
972 }
974 /*
975 * Local variables:
976 * mode: C
977 * c-set-style: "BSD"
978 * c-basic-offset: 4
979 * tab-width: 4
980 * indent-tabs-mode: nil
981 * End:
982 */