aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_core.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xensource.com>2007-02-24 14:31:42 +0000
committerKeir Fraser <keir@xensource.com>2007-02-24 14:31:42 +0000
commite3ce7ff90fbce79dbb3d5a2c82c467699dd6e57e (patch)
tree562a4377e1aae9fc4337ef026b9a4ee557335f4d /tools/libxc/xc_core.c
parent4062095bcbc7a0bf38a65ee90e8ffd2506d83950 (diff)
downloadxen-e3ce7ff90fbce79dbb3d5a2c82c467699dd6e57e.tar.gz
xen-e3ce7ff90fbce79dbb3d5a2c82c467699dd6e57e.tar.bz2
xen-e3ce7ff90fbce79dbb3d5a2c82c467699dd6e57e.zip
Xen coredump format: ELF formatified with note section.
added PFN-GMFN table for non-auto translated physmap added PFN table for auto translated physmap. HVM domain support. IA64 support Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Use the guest's own p2m table instead of xc_get_pfn_list(), which cannot handle PFNs with no MFN. Dump a zeroed page for PFNs with no MFN. Clearly deprecate xc_get_pfn_list(). Do not include a P2M table with HVM domains. Refuse to dump HVM until we can map its pages with PFNs. Signed-off-by: John Levon <john.levon@sun.com>
Diffstat (limited to 'tools/libxc/xc_core.c')
-rw-r--r--tools/libxc/xc_core.c739
1 files changed, 698 insertions, 41 deletions
diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c
index 37be5d9cd0..7ea97cd6d0 100644
--- a/tools/libxc/xc_core.c
+++ b/tools/libxc/xc_core.c
@@ -1,10 +1,62 @@
+/*
+ * Elf format, (pfn, gmfn) table, IA64 support.
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * xen dump-core file format follows ELF format specification.
+ * Analisys tools shouldn't depends on the order of sections.
+ * They should follow elf header and check section names.
+ *
+ * +--------------------------------------------------------+
+ * |ELF header |
+ * +--------------------------------------------------------+
+ * |section headers |
+ * | null section header |
+ * | .shstrtab |
+ * | .note.Xen |
+ * | .xen_prstatus |
+ * | .xen_ia64_mmapped_regs if ia64 |
+ * | .xen_shared_info if present |
+ * | .xen_p2m or .xen_pfn |
+ * | .xen_pages |
+ * +--------------------------------------------------------+
+ * |.note.Xen:note section |
+ * | "Xen" is used as note name, |
+ * | types are defined in xen/include/public/elfnote.h |
+ * | and descriptors are defined in xc_core.h. |
+ * | dumpcore none |
+ * | dumpcore header |
+ * | dumpcore xen version |
+ * | dumpcore format version |
+ * +--------------------------------------------------------+
+ * |.xen_prstatus |
+ * | vcpu_guest_context_t[nr_vcpus] |
+ * +--------------------------------------------------------+
+ * |.xen_ia64_mmapped_regs if ia64 |
+ * | mmapped_regs_t[nr_vcpus] |
+ * +--------------------------------------------------------+
+ * |.xen_shared_info if possible |
+ * +--------------------------------------------------------+
+ * |.xen_p2m or .xen_pfn |
+ * | .xen_p2m: struct xen_dumpcore_p2m[nr_pages] |
+ * | .xen_pfn: uint64_t[nr_pages] |
+ * +--------------------------------------------------------+
+ * |.xen_pages |
+ * | page * nr_pages |
+ * +--------------------------------------------------------+
+ * |.shstrtab: section header string table |
+ * +--------------------------------------------------------+
+ *
+ */
+
#include "xg_private.h"
+#include "xc_core.h"
+#include "xc_dom.h"
#include <stdlib.h>
#include <unistd.h>
/* number of pages to write at a time */
#define DUMP_INCREMENT (4 * 1024)
-#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
static int
copy_from_domain_page(int xc_handle,
@@ -21,107 +73,712 @@ copy_from_domain_page(int xc_handle,
return 0;
}
+/* string table */
+struct xc_core_strtab {
+ char *strings;
+ uint16_t current;
+ uint16_t max;
+};
+
+static struct xc_core_strtab*
+xc_core_strtab_init(void)
+{
+ struct xc_core_strtab *strtab;
+ char *strings;
+ strtab = malloc(sizeof(strtab));
+ if ( strtab == NULL )
+ return NULL;
+
+ strings = malloc(PAGE_SIZE);
+ if ( strings == NULL )
+ {
+ PERROR("Could not allocate string table init");
+ free(strtab);
+ return NULL;
+ }
+ strtab->strings = strings;
+ strtab->max = PAGE_SIZE;
+
+ /* index 0 represents none */
+ strtab->strings[0] = '\0';
+ strtab->current = 1;
+
+ return strtab;
+}
+
+static void
+xc_core_strtab_free(struct xc_core_strtab *strtab)
+{
+ free(strtab->strings);
+ free(strtab);
+}
+
+static uint16_t
+xc_core_strtab_get(struct xc_core_strtab *strtab, const char *name)
+{
+ uint16_t ret = 0;
+ uint16_t len = strlen(name) + 1;
+
+ if ( strtab->current + len > strtab->max )
+ {
+ char *tmp;
+ if ( strtab->max * 2 < strtab->max )
+ {
+ PERROR("too long string table");
+ errno = ENOMEM;
+ return ret;
+ }
+
+
+ tmp = realloc(strtab->strings, strtab->max * 2);
+ if ( tmp == NULL )
+ {
+ PERROR("Could not allocate string table");
+ return ret;
+ }
+
+ strtab->strings = tmp;
+ strtab->max *= 2;
+ }
+
+ ret = strtab->current;
+ strcpy(strtab->strings + strtab->current, name);
+ strtab->current += len;
+ return ret;
+}
+
+
+/* section headers */
+struct xc_core_section_headers {
+ uint16_t num;
+ uint16_t num_max;
+
+ Elf_Shdr *shdrs;
+};
+#define SHDR_INIT 16
+#define SHDR_INC 4
+
+static struct xc_core_section_headers*
+xc_core_shdr_init(void)
+{
+ struct xc_core_section_headers *sheaders;
+ sheaders = malloc(sizeof(*sheaders));
+ if ( sheaders == NULL )
+ return NULL;
+
+ sheaders->num = 0;
+ sheaders->num_max = SHDR_INIT;
+ sheaders->shdrs = malloc(sizeof(sheaders->shdrs[0]) * sheaders->num_max);
+ if ( sheaders->shdrs == NULL )
+ {
+ free(sheaders);
+ return NULL;
+ }
+ return sheaders;
+}
+
+static void
+xc_core_shdr_free(struct xc_core_section_headers *sheaders)
+{
+ free(sheaders->shdrs);
+ free(sheaders);
+}
+
+Elf_Shdr*
+xc_core_shdr_get(struct xc_core_section_headers *sheaders)
+{
+ Elf_Shdr *shdr;
+
+ if ( sheaders->num == sheaders->num_max )
+ {
+ Elf_Shdr *shdrs;
+ if ( sheaders->num_max + SHDR_INC < sheaders->num_max )
+ {
+ errno = E2BIG;
+ return NULL;
+ }
+ sheaders->num_max += SHDR_INC;
+ shdrs = realloc(sheaders->shdrs,
+ sizeof(sheaders->shdrs[0]) * sheaders->num_max);
+ if ( shdrs == NULL )
+ return NULL;
+ sheaders->shdrs = shdrs;
+ }
+
+ shdr = &sheaders->shdrs[sheaders->num];
+ sheaders->num++;
+ memset(shdr, 0, sizeof(*shdr));
+ return shdr;
+}
+
+int
+xc_core_shdr_set(Elf_Shdr *shdr,
+ struct xc_core_strtab *strtab,
+ const char *name, uint32_t type,
+ uint64_t offset, uint64_t size,
+ uint64_t addralign, uint64_t entsize)
+{
+ uint64_t name_idx = xc_core_strtab_get(strtab, name);
+ if ( name_idx == 0 )
+ return -1;
+
+ shdr->sh_name = name_idx;
+ shdr->sh_type = type;
+ shdr->sh_offset = offset;
+ shdr->sh_size = size;
+ shdr->sh_addralign = addralign;
+ shdr->sh_entsize = entsize;
+ return 0;
+}
+
+static int
+elfnote_fill_xen_version(int xc_handle,
+ struct xen_dumpcore_elfnote_xen_version_desc
+ *xen_version)
+{
+ int rc;
+ memset(xen_version, 0, sizeof(*xen_version));
+
+ rc = xc_version(xc_handle, XENVER_version, NULL);
+ if ( rc < 0 )
+ return rc;
+ xen_version->major_version = rc >> 16;
+ xen_version->minor_version = rc & ((1 << 16) - 1);
+
+ rc = xc_version(xc_handle, XENVER_extraversion,
+ &xen_version->extra_version);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xc_handle, XENVER_compile_info,
+ &xen_version->compile_info);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xc_handle,
+ XENVER_capabilities, &xen_version->capabilities);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xc_handle, XENVER_changeset, &xen_version->changeset);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xc_handle, XENVER_platform_parameters,
+ &xen_version->platform_parameters);
+ if ( rc < 0 )
+ return rc;
+
+ rc = xc_version(xc_handle, XENVER_pagesize, NULL);
+ if ( rc < 0 )
+ return rc;
+ xen_version->pagesize = rc;
+
+ return 0;
+}
+
+static int
+elfnote_fill_format_version(struct xen_dumpcore_elfnote_format_version_desc
+ *format_version)
+{
+ format_version->version = XEN_DUMPCORE_FORMAT_VERSION_CURRENT;
+ return 0;
+}
+
int
xc_domain_dumpcore_via_callback(int xc_handle,
uint32_t domid,
void *args,
dumpcore_rtn_t dump_rtn)
{
- unsigned long nr_pages;
- uint64_t *page_array = NULL;
xc_dominfo_t info;
- int i, nr_vcpus = 0;
+ shared_info_t *live_shinfo = NULL;
+
+ int nr_vcpus = 0;
char *dump_mem, *dump_mem_start = NULL;
- struct xc_core_header header;
vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
+ struct xc_core_arch_context arch_ctxt;
char dummy[PAGE_SIZE];
int dummy_len;
- int sts;
+ int sts = -1;
+ unsigned long i;
+ unsigned long j;
+ unsigned long nr_pages;
+
+ xc_core_memory_map_t *memory_map = NULL;
+ unsigned int nr_memory_map;
+ unsigned int map_idx;
+
+ int auto_translated_physmap;
+ xen_pfn_t *p2m = NULL;
+ unsigned long max_pfn = 0;
+ struct xen_dumpcore_p2m *p2m_array = NULL;
+
+ uint64_t *pfn_array = NULL;
+
+ Elf_Ehdr ehdr;
+ unsigned long filesz;
+ unsigned long offset;
+ unsigned long fixup;
+
+ struct xc_core_strtab *strtab = NULL;
+ uint16_t strtab_idx;
+ struct xc_core_section_headers *sheaders = NULL;
+ Elf_Shdr *shdr;
+
+ /* elf notes */
+ struct xen_elfnote elfnote;
+ struct xen_dumpcore_elfnote_none_desc none;
+ struct xen_dumpcore_elfnote_header_desc header;
+ struct xen_dumpcore_elfnote_xen_version_desc xen_version;
+ struct xen_dumpcore_elfnote_format_version_desc format_version;
+
+ xc_core_arch_context_init(&arch_ctxt);
if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
{
PERROR("Could not allocate dump_mem");
- goto error_out;
+ goto out;
}
if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
{
PERROR("Could not get info for domain");
- goto error_out;
+ goto out;
}
+ /* Map the shared info frame */
+ live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ, info.shared_info_frame);
+ if ( !live_shinfo
+#ifdef __ia64__
+ && !info.hvm
+#endif
+ )
+ {
+ PERROR("Couldn't map live_shinfo");
+ goto out;
+ }
+ auto_translated_physmap = xc_core_arch_auto_translated_physmap(&info);
if ( domid != info.domid )
{
PERROR("Domain %d does not exist", domid);
- goto error_out;
+ goto out;
}
for ( i = 0; i <= info.max_vcpu_id; i++ )
- if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0)
+ {
+ if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0 )
+ {
+ if ( xc_core_arch_context_get(&arch_ctxt, &ctxt[nr_vcpus],
+ xc_handle, domid) )
+ continue;
nr_vcpus++;
+ }
+ }
+ if ( nr_vcpus == 0 )
+ {
+ PERROR("No VCPU context could be grabbed");
+ goto out;
+ }
+
+ /* obtain memory map */
+ sts = xc_core_arch_memory_map_get(xc_handle, &info, live_shinfo,
+ &memory_map, &nr_memory_map);
+ if ( sts != 0 )
+ goto out;
nr_pages = info.nr_pages;
+ if ( !auto_translated_physmap )
+ {
+ /* obtain p2m table */
+ p2m_array = malloc(nr_pages * sizeof(p2m_array[0]));
+ if ( p2m_array == NULL )
+ {
+ PERROR("Could not allocate p2m array");
+ goto out;
+ }
+
+ sts = xc_core_arch_map_p2m(xc_handle, &info, live_shinfo,
+ &p2m, &max_pfn);
+ if ( sts != 0 )
+ goto out;
+ }
+ else
+ {
+ pfn_array = malloc(nr_pages * sizeof(pfn_array[0]));
+ if ( pfn_array == NULL )
+ {
+ PERROR("Could not allocate pfn array");
+ goto out;
+ }
+ }
+
+ /* create .xen_p2m or .xen_pfn */
+ j = 0;
+ for ( map_idx = 0; map_idx < nr_memory_map; map_idx++ )
+ {
+ uint64_t pfn_start;
+ uint64_t pfn_end;
+
+ pfn_start = memory_map[map_idx].addr >> PAGE_SHIFT;
+ pfn_end = pfn_start + (memory_map[map_idx].size >> PAGE_SHIFT);
+ for ( i = pfn_start; i < pfn_end; i++ )
+ {
+ if ( !auto_translated_physmap )
+ {
+ if ( p2m[i] == INVALID_P2M_ENTRY )
+ continue;
+ p2m_array[j].pfn = i;
+ p2m_array[j].gmfn = p2m[i];
+ }
+ else
+ {
+ /* try to map page to determin wheter it has underlying page */
+ void *vaddr = xc_map_foreign_range(xc_handle, domid,
+ PAGE_SIZE, PROT_READ, i);
+ if ( vaddr == NULL )
+ continue;
+ munmap(vaddr, PAGE_SIZE);
+ pfn_array[j] = i;
+ }
+
+ j++;
+ }
+ }
+ if ( j != nr_pages )
+ {
+ PERROR("j (%ld) != nr_pages (%ld)", j , nr_pages);
+ /* When live dump-mode (-L option) is specified,
+ * guest domain may change its mapping.
+ */
+ nr_pages = j;
+ }
+
+ memset(&ehdr, 0, sizeof(ehdr));
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELFCLASS;
+ ehdr.e_ident[EI_DATA] = ELF_ARCH_DATA;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
+ ehdr.e_ident[EI_ABIVERSION] = EV_CURRENT;
+
+ ehdr.e_type = ET_CORE;
+ ehdr.e_machine = ELF_ARCH_MACHINE;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_entry = 0;
+ ehdr.e_phoff = 0;
+ ehdr.e_shoff = sizeof(ehdr);
+ ehdr.e_flags = ELF_CORE_EFLAGS;
+ ehdr.e_ehsize = sizeof(ehdr);
+ ehdr.e_phentsize = sizeof(Elf_Phdr);
+ ehdr.e_phnum = 0;
+ ehdr.e_shentsize = sizeof(Elf_Shdr);
+ /* ehdr.e_shnum and ehdr.e_shstrndx aren't known here yet. fill it later*/
+
+ /* create section header */
+ strtab = xc_core_strtab_init();
+ if ( strtab == NULL )
+ {
+ PERROR("Could not allocate string table");
+ goto out;
+ }
+ sheaders = xc_core_shdr_init();
+ if ( sheaders == NULL )
+ {
+ PERROR("Could not allocate section headers");
+ goto out;
+ }
+ /* null section */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for null section");
+ goto out;
+ }
+
+ /* .shstrtab */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for shstrtab");
+ goto out;
+ }
+ strtab_idx = shdr - sheaders->shdrs;
+ /* strtab_shdr.sh_offset, strtab_shdr.sh_size aren't unknown.
+ * fill it later
+ */
+ sts = xc_core_shdr_set(shdr, strtab, ELF_SHSTRTAB, SHT_STRTAB, 0, 0, 0, 0);
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section */
+ /* here the number of section header is unknown. fix up offset later. */
+ offset = sizeof(ehdr);
+ filesz =
+ sizeof(struct xen_dumpcore_elfnote_none) + /* none */
+ sizeof(struct xen_dumpcore_elfnote_header) + /* core header */
+ sizeof(struct xen_dumpcore_elfnote_xen_version) + /* xen version */
+ sizeof(struct xen_dumpcore_elfnote_format_version);/* format version */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for note section");
+ goto out;
+ }
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_NOTE, SHT_NOTE,
+ offset, filesz, 0, 0);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+
+ /* prstatus */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_prstatus");
+ goto out;
+ }
+ filesz = sizeof(ctxt[0]) * nr_vcpus;
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PRSTATUS,
+ SHT_PROGBITS, offset, filesz,
+ __alignof__(ctxt[0]), sizeof(ctxt[0]));
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+ /* arch context */
+ sts = xc_core_arch_context_get_shdr(&arch_ctxt, sheaders, strtab,
+ &filesz, offset);
+ if ( sts != 0)
+ goto out;
+ offset += filesz;
+
+ /* shared_info */
+ if ( live_shinfo != NULL )
+ {
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_shared_info");
+ goto out;
+ }
+ filesz = PAGE_SIZE;
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_SHARED_INFO,
+ SHT_PROGBITS, offset, filesz,
+ __alignof__(*live_shinfo), PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+ }
+
+ /* p2m/pfn table */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("Could not get section header for .xen_{p2m, pfn} table");
+ goto out;
+ }
+ if ( !auto_translated_physmap )
+ {
+ filesz = nr_pages * sizeof(p2m_array[0]);
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_P2M,
+ SHT_PROGBITS,
+ offset, filesz, __alignof__(p2m_array[0]),
+ sizeof(p2m_array[0]));
+ if ( sts != 0 )
+ goto out;
+ }
+ else
+ {
+ filesz = nr_pages * sizeof(pfn_array[0]);
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PFN,
+ SHT_PROGBITS,
+ offset, filesz, __alignof__(pfn_array[0]),
+ sizeof(pfn_array[0]));
+ if ( sts != 0 )
+ goto out;
+ }
+ offset += filesz;
+
+ /* pages */
+ shdr = xc_core_shdr_get(sheaders);
+ if ( shdr == NULL )
+ {
+ PERROR("could not get section headers for .xen_pages");
+ goto out;
+ }
+
+ /*
+ * pages are the last section to allocate section headers
+ * so that we know the number of section headers here.
+ */
+ fixup = sheaders->num * sizeof(*shdr);
+ /* zeroth section should have zero offset */
+ for ( i = 1; i < sheaders->num; i++ )
+ sheaders->shdrs[i].sh_offset += fixup;
+ offset += fixup;
+ dummy_len = ROUNDUP(offset, PAGE_SHIFT) - offset; /* padding length */
+ offset += dummy_len;
+
+ filesz = nr_pages * PAGE_SIZE;
+ sts = xc_core_shdr_set(shdr, strtab, XEN_DUMPCORE_SEC_PAGES, SHT_PROGBITS,
+ offset, filesz, PAGE_SIZE, PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
+ offset += filesz;
+
+ /* fixing up section header string table section header */
+ filesz = strtab->current;
+ sheaders->shdrs[strtab_idx].sh_offset = offset;
+ sheaders->shdrs[strtab_idx].sh_size = filesz;
+
+ /* write out elf header */
+ ehdr.e_shnum = sheaders->num;
+ ehdr.e_shstrndx = strtab_idx;
+ sts = dump_rtn(args, (char*)&ehdr, sizeof(ehdr));
+ if ( sts != 0 )
+ goto out;
+
+ /* section headers */
+ sts = dump_rtn(args, (char*)sheaders->shdrs,
+ sheaders->num * sizeof(sheaders->shdrs[0]));
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section */
+ memset(&elfnote, 0, sizeof(elfnote));
+ elfnote.namesz = strlen(XEN_DUMPCORE_ELFNOTE_NAME) + 1;
+ strncpy(elfnote.name, XEN_DUMPCORE_ELFNOTE_NAME, sizeof(elfnote.name));
+
+ /* elf note section:xen core header */
+ elfnote.descsz = sizeof(none);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_NONE;
+ sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ goto out;
+ sts = dump_rtn(args, (char*)&none, sizeof(none));
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section:xen core header */
+ elfnote.descsz = sizeof(header);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_HEADER;
header.xch_magic = info.hvm ? XC_CORE_MAGIC_HVM : XC_CORE_MAGIC;
header.xch_nr_vcpus = nr_vcpus;
header.xch_nr_pages = nr_pages;
- header.xch_ctxt_offset = sizeof(struct xc_core_header);
- header.xch_index_offset = sizeof(struct xc_core_header) +
- sizeof(vcpu_guest_context_t)*nr_vcpus;
- dummy_len = (sizeof(struct xc_core_header) +
- (sizeof(vcpu_guest_context_t) * nr_vcpus) +
- (nr_pages * sizeof(*page_array)));
- header.xch_pages_offset = round_pgup(dummy_len);
+ header.xch_page_size = PAGE_SIZE;
+ sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ goto out;
+ sts = dump_rtn(args, (char*)&header, sizeof(header));
+ if ( sts != 0 )
+ goto out;
- sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header));
+ /* elf note section: xen version */
+ elfnote.descsz = sizeof(xen_version);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_XEN_VERSION;
+ elfnote_fill_xen_version(xc_handle, &xen_version);
+ sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ goto out;
+ sts = dump_rtn(args, (char*)&xen_version, sizeof(xen_version));
+ if ( sts != 0 )
+ goto out;
+
+ /* elf note section: format version */
+ elfnote.descsz = sizeof(format_version);
+ elfnote.type = XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION;
+ elfnote_fill_format_version(&format_version);
+ sts = dump_rtn(args, (char*)&elfnote, sizeof(elfnote));
+ if ( sts != 0 )
+ goto out;
+ sts = dump_rtn(args, (char*)&format_version, sizeof(format_version));
if ( sts != 0 )
- goto error_out;
+ goto out;
+ /* prstatus: .xen_prstatus */
sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus);
if ( sts != 0 )
- goto error_out;
+ goto out;
- if ( (page_array = malloc(nr_pages * sizeof(*page_array))) == NULL )
+ if ( live_shinfo != NULL )
{
- IPRINTF("Could not allocate memory\n");
- goto error_out;
+ /* shared_info: .xen_shared_info */
+ sts = dump_rtn(args, (char*)live_shinfo, PAGE_SIZE);
+ if ( sts != 0 )
+ goto out;
}
- if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
- {
- IPRINTF("Could not get the page frame list\n");
- goto error_out;
- }
- sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(*page_array));
+
+ /* arch specific context */
+ sts = xc_core_arch_context_dump(&arch_ctxt, args, dump_rtn);
if ( sts != 0 )
- goto error_out;
+ goto out;
+
+ /* p2m/pfn table: .xen_p2m/.xen_pfn */
+ if ( !auto_translated_physmap )
+ sts = dump_rtn(args, (char *)p2m_array,
+ sizeof(p2m_array[0]) * nr_pages);
+ else
+ sts = dump_rtn(args, (char *)pfn_array,
+ sizeof(pfn_array[0]) * nr_pages);
+ if ( sts != 0 )
+ goto out;
/* Pad the output data to page alignment. */
memset(dummy, 0, PAGE_SIZE);
- sts = dump_rtn(args, dummy, header.xch_pages_offset - dummy_len);
+ sts = dump_rtn(args, dummy, dummy_len);
if ( sts != 0 )
- goto error_out;
+ goto out;
+ /* dump pages: .xen_pages */
for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
{
- copy_from_domain_page(xc_handle, domid, page_array[i], dump_mem);
+ uint64_t gmfn;
+ if ( !auto_translated_physmap )
+ gmfn = p2m_array[i].gmfn;
+ else
+ gmfn = pfn_array[i];
+
+ copy_from_domain_page(xc_handle, domid, gmfn, dump_mem);
dump_mem += PAGE_SIZE;
if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) )
{
sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
if ( sts != 0 )
- goto error_out;
+ goto out;
dump_mem = dump_mem_start;
}
}
- free(dump_mem_start);
- free(page_array);
- return 0;
+ /* elf section header string table: .shstrtab */
+ sts = dump_rtn(args, strtab->strings, strtab->current);
+ if ( sts != 0 )
+ goto out;
+
+ sts = 0;
- error_out:
- free(dump_mem_start);
- free(page_array);
- return -1;
+out:
+ if ( p2m != NULL )
+ munmap(p2m, PAGE_SIZE * P2M_FL_ENTRIES);
+ if ( p2m_array != NULL )
+ free(p2m_array);
+ if ( pfn_array != NULL )
+ free(pfn_array);
+ if ( sheaders != NULL )
+ xc_core_shdr_free(sheaders);
+ if ( strtab != NULL )
+ xc_core_strtab_free(strtab);
+ if ( dump_mem_start != NULL )
+ free(dump_mem_start);
+ if ( live_shinfo != NULL )
+ munmap(live_shinfo, PAGE_SIZE);
+ xc_core_arch_context_free(&arch_ctxt);
+
+ return sts;
}
/* Callback args for writing to a local dump file. */