ia64/xen-unstable

changeset 14112:e2e6830269f7

xc_ptrace_core.c new elf format support
The old format is still supported and the old implementation is left
as is with the slight adjustment to coexist with new implementation.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Keir Fraser <keir@xensource.com>
date Sat Feb 24 14:32:43 2007 +0000 (2007-02-24)
parents 3dac99b6034e
children 0147ef7c3cd7
files tools/libxc/xc_ptrace_core.c
line diff
     1.1 --- a/tools/libxc/xc_ptrace_core.c	Sat Feb 24 14:31:42 2007 +0000
     1.2 +++ b/tools/libxc/xc_ptrace_core.c	Sat Feb 24 14:32:43 2007 +0000
     1.3 @@ -1,32 +1,41 @@
     1.4 +/*
     1.5 + * New elf format support.
     1.6 + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
     1.7 + *                    VA Linux Systems Japan K.K.
     1.8 + */
     1.9 +
    1.10  #include <sys/ptrace.h>
    1.11  #include <sys/wait.h>
    1.12  #include "xc_private.h"
    1.13  #include "xg_private.h"
    1.14  #include "xc_ptrace.h"
    1.15  #include <time.h>
    1.16 +#include <inttypes.h>
    1.17  
    1.18 +/* Leave the code for the old format as is. */
    1.19 +/* --- compatible layer for old format ------------------------------------- */
    1.20  /* XXX application state */
    1.21  
    1.22 -static int    current_is_hvm = 0;
    1.23 -static long   nr_pages = 0;
    1.24 -static unsigned long  *p2m_array = NULL;
    1.25 -static unsigned long  *m2p_array = NULL;
    1.26 -static unsigned long   pages_offset;
    1.27 -static unsigned long   cr3[MAX_VIRT_CPUS];
    1.28 +static int    current_is_hvm_compat = 0;
    1.29 +static long   nr_pages_compat = 0;
    1.30 +static unsigned long  *p2m_array_compat = NULL;
    1.31 +static unsigned long  *m2p_array_compat = NULL;
    1.32 +static unsigned long   pages_offset_compat;
    1.33 +static unsigned long   cr3_compat[MAX_VIRT_CPUS];
    1.34  
    1.35  /* --------------------- */
    1.36  
    1.37  static unsigned long
    1.38 -map_mtop_offset(unsigned long ma)
    1.39 +map_mtop_offset_compat(unsigned long ma)
    1.40  {
    1.41 -    return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT);
    1.42 +    return pages_offset_compat + (m2p_array_compat[ma >> PAGE_SHIFT] << PAGE_SHIFT);
    1.43      return 0;
    1.44  }
    1.45  
    1.46  
    1.47 -void *
    1.48 -map_domain_va_core(unsigned long domfd, int cpu, void *guest_va,
    1.49 -                   vcpu_guest_context_t *ctxt)
    1.50 +static void *
    1.51 +map_domain_va_core_compat(unsigned long domfd, int cpu, void *guest_va,
    1.52 +                          vcpu_guest_context_t *ctxt)
    1.53  {
    1.54      unsigned long pde, page;
    1.55      unsigned long va = (unsigned long)guest_va;
    1.56 @@ -39,14 +48,14 @@ map_domain_va_core(unsigned long domfd, 
    1.57      static unsigned long  page_phys[MAX_VIRT_CPUS];
    1.58      static unsigned long *page_virt[MAX_VIRT_CPUS];
    1.59  
    1.60 -    if (cr3[cpu] != cr3_phys[cpu])
    1.61 +    if (cr3_compat[cpu] != cr3_phys[cpu])
    1.62      {
    1.63 -        cr3_phys[cpu] = cr3[cpu];
    1.64 +        cr3_phys[cpu] = cr3_compat[cpu];
    1.65          if (cr3_virt[cpu])
    1.66              munmap(cr3_virt[cpu], PAGE_SIZE);
    1.67          v = mmap(
    1.68              NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
    1.69 -            map_mtop_offset(xen_cr3_to_pfn(cr3_phys[cpu])));
    1.70 +            map_mtop_offset_compat(xen_cr3_to_pfn(cr3_phys[cpu])));
    1.71          if (v == MAP_FAILED)
    1.72          {
    1.73              perror("mmap failed");
    1.74 @@ -56,8 +65,8 @@ map_domain_va_core(unsigned long domfd, 
    1.75      }
    1.76      if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */
    1.77          return NULL;
    1.78 -    if (current_is_hvm)
    1.79 -        pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
    1.80 +    if (current_is_hvm_compat)
    1.81 +        pde = p2m_array_compat[pde >> PAGE_SHIFT] << PAGE_SHIFT;
    1.82      if (pde != pde_phys[cpu])
    1.83      {
    1.84          pde_phys[cpu] = pde;
    1.85 @@ -65,15 +74,15 @@ map_domain_va_core(unsigned long domfd, 
    1.86              munmap(pde_virt[cpu], PAGE_SIZE);
    1.87          v = mmap(
    1.88              NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
    1.89 -            map_mtop_offset(pde_phys[cpu]));
    1.90 +            map_mtop_offset_compat(pde_phys[cpu]));
    1.91          if (v == MAP_FAILED)
    1.92              return NULL;
    1.93          pde_virt[cpu] = v;
    1.94      }
    1.95      if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */
    1.96          return NULL;
    1.97 -    if (current_is_hvm)
    1.98 -        page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
    1.99 +    if (current_is_hvm_compat)
   1.100 +        page = p2m_array_compat[page >> PAGE_SHIFT] << PAGE_SHIFT;
   1.101      if (page != page_phys[cpu])
   1.102      {
   1.103          page_phys[cpu] = page;
   1.104 @@ -81,10 +90,10 @@ map_domain_va_core(unsigned long domfd, 
   1.105              munmap(page_virt[cpu], PAGE_SIZE);
   1.106          v = mmap(
   1.107              NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd,
   1.108 -            map_mtop_offset(page_phys[cpu]));
   1.109 +            map_mtop_offset_compat(page_phys[cpu]));
   1.110          if (v == MAP_FAILED)
   1.111          {
   1.112 -            IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, l1_table_offset_i386(va));
   1.113 +            IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n", cr3_compat[cpu], pde, page, l1_table_offset_i386(va));
   1.114              page_phys[cpu] = 0;
   1.115              return NULL;
   1.116          }
   1.117 @@ -93,8 +102,8 @@ map_domain_va_core(unsigned long domfd, 
   1.118      return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
   1.119  }
   1.120  
   1.121 -int
   1.122 -xc_waitdomain_core(
   1.123 +static int
   1.124 +xc_waitdomain_core_compat(
   1.125      int xc_handle,
   1.126      int domfd,
   1.127      int *status,
   1.128 @@ -105,13 +114,13 @@ xc_waitdomain_core(
   1.129      int i;
   1.130      xc_core_header_t header;
   1.131  
   1.132 -    if ( nr_pages == 0 )
   1.133 +    if ( nr_pages_compat == 0 )
   1.134      {
   1.135          if (read(domfd, &header, sizeof(header)) != sizeof(header))
   1.136              return -1;
   1.137  
   1.138 -        current_is_hvm = (header.xch_magic == XC_CORE_MAGIC_HVM);
   1.139 -        if ( !current_is_hvm && (header.xch_magic != XC_CORE_MAGIC) )
   1.140 +        current_is_hvm_compat = (header.xch_magic == XC_CORE_MAGIC_HVM);
   1.141 +        if ( !current_is_hvm_compat && (header.xch_magic != XC_CORE_MAGIC) )
   1.142          {
   1.143              IPRINTF("Magic number missmatch: 0x%08x (file) != "
   1.144                      " 0x%08x (code)\n", header.xch_magic,
   1.145 @@ -119,40 +128,544 @@ xc_waitdomain_core(
   1.146              return -1;
   1.147          }
   1.148  
   1.149 -        nr_pages = header.xch_nr_pages;
   1.150 +        nr_pages_compat = header.xch_nr_pages;
   1.151          nr_vcpus = header.xch_nr_vcpus;
   1.152 -        pages_offset = header.xch_pages_offset;
   1.153 +        pages_offset_compat = header.xch_pages_offset;
   1.154  
   1.155          if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
   1.156              sizeof(vcpu_guest_context_t)*nr_vcpus)
   1.157              return -1;
   1.158  
   1.159          for (i = 0; i < nr_vcpus; i++)
   1.160 -            cr3[i] = ctxt[i].ctrlreg[3];
   1.161 +            cr3_compat[i] = ctxt[i].ctrlreg[3];
   1.162  
   1.163 -        if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL)
   1.164 +        if ((p2m_array_compat = malloc(nr_pages_compat * sizeof(unsigned long))) == NULL)
   1.165          {
   1.166              IPRINTF("Could not allocate p2m_array\n");
   1.167              return -1;
   1.168          }
   1.169  
   1.170 -        if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) !=
   1.171 -            sizeof(unsigned long)*nr_pages)
   1.172 +        if (read(domfd, p2m_array_compat, sizeof(unsigned long)*nr_pages_compat) !=
   1.173 +            sizeof(unsigned long)*nr_pages_compat)
   1.174              return -1;
   1.175  
   1.176 -        if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL)
   1.177 +        if ((m2p_array_compat = malloc((1<<20) * sizeof(unsigned long))) == NULL)
   1.178          {
   1.179              IPRINTF("Could not allocate m2p array\n");
   1.180              return -1;
   1.181          }
   1.182 -        bzero(m2p_array, sizeof(unsigned long)* 1 << 20);
   1.183 +        bzero(m2p_array_compat, sizeof(unsigned long)* 1 << 20);
   1.184 +
   1.185 +        for (i = 0; i < nr_pages_compat; i++)
   1.186 +            m2p_array_compat[p2m_array_compat[i]] = i;
   1.187 +    }
   1.188 +    return 0;
   1.189 +}
   1.190 +
   1.191 +
   1.192 +/* --- new format based on ELF -------------------------------------------- */
   1.193 +#include "xc_core.h"
   1.194 +
   1.195 +static int
   1.196 +pread_exact(int fd, void* buffer, size_t size, off_t offset)
   1.197 +{
   1.198 +    off_t ret;
   1.199 +    unsigned char *buf = buffer;
   1.200 +    size_t done = 0;
   1.201 +    ret = lseek(fd, offset, SEEK_SET);
   1.202 +    if (ret < 0 || ret != offset)
   1.203 +        return -1;
   1.204 +
   1.205 +    while (done < size) {
   1.206 +        ssize_t s = read(fd, buf, size - done);
   1.207 +        if (s == -1 && errno == EINTR)
   1.208 +            continue;
   1.209 +        if (s <= 0)
   1.210 +            return -1;
   1.211 +
   1.212 +        done += s;
   1.213 +        buf += s;
   1.214 +    }
   1.215 +    return 0;
   1.216 +}
   1.217 +
   1.218 +struct elf_core
   1.219 +{
   1.220 +    int         domfd;
   1.221 +    Elf_Ehdr    ehdr;
   1.222 +
   1.223 +    char*       shdr;
   1.224 +    
   1.225 +    char*       shstrtab;
   1.226 +    uint64_t    shstrtab_size;
   1.227 +
   1.228 +    char*       note_sec;
   1.229 +    uint64_t    note_sec_size;
   1.230 +};
   1.231 +
   1.232 +static int
   1.233 +elf_core_alloc_read_sec_by_index(struct elf_core* ecore, uint16_t index,
   1.234 +                                 char** buf, uint64_t* size);
   1.235 +static int
   1.236 +elf_core_alloc_read_sec_by_name(struct elf_core* ecore, const char* name,
   1.237 +                                char** buf, uint64_t* size);
   1.238 +
   1.239 +static void
   1.240 +elf_core_free(struct elf_core* ecore)
   1.241 +{
   1.242 +    if (ecore->shdr != NULL) {
   1.243 +        free(ecore->shdr);
   1.244 +        ecore->shdr = NULL;
   1.245 +    }
   1.246 +    if (ecore->shstrtab != NULL) {
   1.247 +        free(ecore->shstrtab);
   1.248 +        ecore->shstrtab = NULL;
   1.249 +    }
   1.250 +    if (ecore->note_sec != NULL) {
   1.251 +        free(ecore->note_sec);
   1.252 +        ecore->note_sec = NULL;
   1.253 +    }
   1.254 +}
   1.255 +
   1.256 +static int
   1.257 +elf_core_init(struct elf_core* ecore, int domfd)
   1.258 +{
   1.259 +    uint64_t sh_size;
   1.260 +    ecore->domfd = domfd;
   1.261 +    ecore->shdr = NULL;
   1.262 +    ecore->shstrtab = NULL;
   1.263 +    ecore->note_sec = NULL;
   1.264 +    
   1.265 +    if (pread_exact(ecore->domfd, &ecore->ehdr, sizeof(ecore->ehdr), 0) < 0)
   1.266 +        goto out;
   1.267 +    
   1.268 +    /* check elf header */
   1.269 +    if (!IS_ELF(ecore->ehdr) || ecore->ehdr.e_type != ET_CORE)
   1.270 +        goto out;
   1.271 +    /* check elf header more: EI_DATA, EI_VERSION, e_machine... */
   1.272 +
   1.273 +    /* read section headers */
   1.274 +    sh_size = ecore->ehdr.e_shentsize * ecore->ehdr.e_shnum;
   1.275 +    ecore->shdr = malloc(sh_size);
   1.276 +    if (ecore->shdr == NULL)
   1.277 +        goto out;
   1.278 +    if (pread_exact(ecore->domfd, ecore->shdr, sh_size,
   1.279 +                    ecore->ehdr.e_shoff) < 0)
   1.280 +        goto out;
   1.281 +
   1.282 +    /* read shstrtab */
   1.283 +    if (elf_core_alloc_read_sec_by_index(ecore, ecore->ehdr.e_shstrndx,
   1.284 +                                         &ecore->shstrtab,
   1.285 +                                         &ecore->shstrtab_size) < 0)
   1.286 +        goto out;
   1.287 +
   1.288 +    /* read .note.Xen section */
   1.289 +    if (elf_core_alloc_read_sec_by_name(ecore, XEN_DUMPCORE_SEC_NOTE,
   1.290 +                                        &ecore->note_sec,
   1.291 +                                        &ecore->note_sec_size) < 0)
   1.292 +        goto out;
   1.293 +
   1.294 +    return 0;
   1.295 +out:
   1.296 +    elf_core_free(ecore);
   1.297 +    return -1;
   1.298 +}
   1.299 +
   1.300 +static int
   1.301 +elf_core_search_note(struct elf_core* ecore, const char* name, uint32_t type,
   1.302 +                     void** elfnotep)
   1.303 +{
   1.304 +    const char* note_sec_end = ecore->note_sec + ecore->note_sec_size;
   1.305 +    const char* n;
   1.306  
   1.307 -        for (i = 0; i < nr_pages; i++)
   1.308 -            m2p_array[p2m_array[i]] = i;
   1.309 +    n = ecore->note_sec;
   1.310 +    while (n < note_sec_end) {
   1.311 +        const struct xen_elfnote *elfnote = (const struct xen_elfnote*)n;
   1.312 +        if (elfnote->namesz == strlen(name) + 1 &&
   1.313 +            strncmp(elfnote->name, name, elfnote->namesz) == 0 &&
   1.314 +            elfnote->type == type) {
   1.315 +            *elfnotep = (void*)elfnote;
   1.316 +            return 0;
   1.317 +        }
   1.318 +
   1.319 +        n += sizeof(*elfnote) + elfnote->descsz;
   1.320 +    }
   1.321 +    return -1;
   1.322 +}
   1.323 +
   1.324 +static int
   1.325 +elf_core_alloc_read_sec(struct elf_core* ecore, const Elf_Shdr* shdr,
   1.326 +                        char** buf)
   1.327 +{
   1.328 +    int ret;
   1.329 +    *buf = malloc(shdr->sh_size);
   1.330 +    if (*buf == NULL)
   1.331 +        return -1;
   1.332 +    ret = pread_exact(ecore->domfd, *buf, shdr->sh_size, shdr->sh_offset);
   1.333 +    if (ret < 0) {
   1.334 +        free(*buf);
   1.335 +        *buf = NULL;
   1.336 +    }
   1.337 +    return ret;
   1.338 +}
   1.339 +
   1.340 +static Elf_Shdr*
   1.341 +elf_core_shdr_by_index(struct elf_core* ecore, uint16_t index)
   1.342 +{
   1.343 +    if (index >= ecore->ehdr.e_shnum)
   1.344 +        return NULL;
   1.345 +    return (Elf_Shdr*)(ecore->shdr + ecore->ehdr.e_shentsize * index);
   1.346 +}
   1.347 +
   1.348 +static int
   1.349 +elf_core_alloc_read_sec_by_index(struct elf_core* ecore, uint16_t index,
   1.350 +                                 char** buf, uint64_t* size)
   1.351 +{
   1.352 +    Elf_Shdr* shdr = elf_core_shdr_by_index(ecore, index);
   1.353 +    if (shdr == NULL)
   1.354 +        return -1;
   1.355 +    if (size != NULL)
   1.356 +        *size = shdr->sh_size;
   1.357 +    return elf_core_alloc_read_sec(ecore, shdr, buf);
   1.358 +}
   1.359 +
   1.360 +static Elf_Shdr*
   1.361 +elf_core_shdr_by_name(struct elf_core* ecore, const char* name)
   1.362 +{
   1.363 +    const char* s;
   1.364 +    for (s = ecore->shdr;
   1.365 +         s < ecore->shdr + ecore->ehdr.e_shentsize * ecore->ehdr.e_shnum;
   1.366 +         s += ecore->ehdr.e_shentsize) {
   1.367 +        Elf_Shdr* shdr = (Elf_Shdr*)s;
   1.368 +
   1.369 +        if (strncmp(ecore->shstrtab + shdr->sh_name, name, strlen(name)) == 0)
   1.370 +            return shdr;
   1.371 +    }
   1.372 +
   1.373 +    return NULL;
   1.374 +}
   1.375 +
   1.376 +static int
   1.377 +elf_core_read_sec_by_name(struct elf_core* ecore, const char* name, char* buf)
   1.378 +{
   1.379 +    Elf_Shdr* shdr = elf_core_shdr_by_name(ecore, name);
   1.380 +    return pread_exact(ecore->domfd, buf, shdr->sh_size, shdr->sh_offset);
   1.381 +    
   1.382 +}
   1.383 +
   1.384 +static int
   1.385 +elf_core_alloc_read_sec_by_name(struct elf_core* ecore, const char* name,
   1.386 +                                char** buf, uint64_t* size)
   1.387 +{
   1.388 +    Elf_Shdr* shdr = elf_core_shdr_by_name(ecore, name);
   1.389 +    if (shdr == NULL)
   1.390 +        return -1;
   1.391 +    if (size != NULL)
   1.392 +        *size = shdr->sh_size;
   1.393 +    return elf_core_alloc_read_sec(ecore, shdr, buf);
   1.394 +}
   1.395 +
   1.396 +/* XXX application state */
   1.397 +static int current_is_auto_translated_physmap = 0;
   1.398 +static struct xen_dumpcore_p2m* p2m_array = NULL; /* for non auto translated physmap mode */
   1.399 +static uint64_t p2m_array_size = 0;
   1.400 +static uint64_t* pfn_array = NULL; /* for auto translated physmap mode */
   1.401 +static uint64_t pfn_array_size = 0;
   1.402 +static long nr_pages = 0;
   1.403 +static uint64_t pages_offset;
   1.404 +static unsigned long cr3[MAX_VIRT_CPUS];
   1.405 +
   1.406 +static const struct xen_dumpcore_elfnote_format_version_desc
   1.407 +known_format_version[] =
   1.408 +{
   1.409 +    {XEN_DUMPCORE_FORMAT_VERSION((uint64_t)0, (uint64_t)1)},
   1.410 +};
   1.411 +#define KNOWN_FORMAT_VERSION_NR \
   1.412 +    (sizeof(known_format_version)/sizeof(known_format_version[0]))
   1.413 +
   1.414 +static unsigned long
   1.415 +map_gmfn_to_offset_elf(unsigned long gmfn)
   1.416 +{
   1.417 +    /* 
   1.418 +     * linear search
   1.419 +     * There is no gurantee that those tables are sorted.
   1.420 +     */
   1.421 +    unsigned long i;
   1.422 +    if (current_is_auto_translated_physmap) {
   1.423 +        if (pfn_array == NULL)
   1.424 +            return 0;
   1.425 +        for (i = 0; i < pfn_array_size; i++) {
   1.426 +            if (pfn_array[i] == gmfn) {
   1.427 +                return pages_offset + (i << PAGE_SHIFT);
   1.428 +            }
   1.429 +        }
   1.430 +    } else {
   1.431 +        if (p2m_array == NULL)
   1.432 +            return 0;
   1.433 +        for (i = 0; i < p2m_array_size; i++) {
   1.434 +            if (p2m_array[i].gmfn == gmfn) {
   1.435 +                return pages_offset + (i << PAGE_SHIFT);
   1.436 +            }
   1.437 +        }
   1.438      }
   1.439      return 0;
   1.440  }
   1.441  
   1.442 +static void *
   1.443 +map_domain_va_core_elf(unsigned long domfd, int cpu, void *guest_va,
   1.444 +                       vcpu_guest_context_t *ctxt)
   1.445 +{
   1.446 +    unsigned long pde, page;
   1.447 +    unsigned long va = (unsigned long)guest_va;
   1.448 +    unsigned long offset;
   1.449 +    void *v;
   1.450 +
   1.451 +    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
   1.452 +    static unsigned long *cr3_virt[MAX_VIRT_CPUS];
   1.453 +    static unsigned long  pde_phys[MAX_VIRT_CPUS];
   1.454 +    static unsigned long *pde_virt[MAX_VIRT_CPUS];
   1.455 +    static unsigned long  page_phys[MAX_VIRT_CPUS];
   1.456 +    static unsigned long *page_virt[MAX_VIRT_CPUS];
   1.457 +
   1.458 +    if (cr3[cpu] != cr3_phys[cpu])
   1.459 +    {
   1.460 +        if (cr3_virt[cpu])
   1.461 +        {
   1.462 +            munmap(cr3_virt[cpu], PAGE_SIZE);
   1.463 +            cr3_virt[cpu] = NULL;
   1.464 +            cr3_phys[cpu] = 0;
   1.465 +        }
   1.466 +        offset = map_gmfn_to_offset_elf(xen_cr3_to_pfn(cr3[cpu]));
   1.467 +        if (offset == 0)
   1.468 +            return NULL;
   1.469 +        v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset);
   1.470 +        if (v == MAP_FAILED)
   1.471 +        {
   1.472 +            perror("mmap failed");
   1.473 +            return NULL;
   1.474 +        }
   1.475 +        cr3_phys[cpu] = cr3[cpu];
   1.476 +        cr3_virt[cpu] = v;
   1.477 +    }
   1.478 +    if ((pde = cr3_virt[cpu][l2_table_offset_i386(va)]) == 0) /* logical address */
   1.479 +        return NULL;
   1.480 +    if (pde != pde_phys[cpu])
   1.481 +    {
   1.482 +        if (pde_virt[cpu])
   1.483 +        {
   1.484 +            munmap(pde_virt[cpu], PAGE_SIZE);
   1.485 +            pde_virt[cpu] = NULL;
   1.486 +            pde_phys[cpu] = 0;
   1.487 +        }
   1.488 +        offset = map_gmfn_to_offset_elf(pde >> PAGE_SHIFT);
   1.489 +        if (offset == 0)
   1.490 +            return NULL;
   1.491 +        v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset);
   1.492 +        if (v == MAP_FAILED)
   1.493 +            return NULL;
   1.494 +        pde_phys[cpu] = pde;
   1.495 +        pde_virt[cpu] = v;
   1.496 +    }
   1.497 +    if ((page = pde_virt[cpu][l1_table_offset_i386(va)]) == 0) /* logical address */
   1.498 +        return NULL;
   1.499 +    if (page != page_phys[cpu])
   1.500 +    {
   1.501 +        if (page_virt[cpu])
   1.502 +        {
   1.503 +            munmap(page_virt[cpu], PAGE_SIZE);
   1.504 +            page_virt[cpu] = NULL;
   1.505 +            page_phys[cpu] = 0;
   1.506 +        }
   1.507 +        offset = map_gmfn_to_offset_elf(page >> PAGE_SHIFT);
   1.508 +        if (offset == 0)
   1.509 +            return NULL;
   1.510 +        v = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, domfd, offset);
   1.511 +        if (v == MAP_FAILED)
   1.512 +        {
   1.513 +            IPRINTF("cr3 %lx pde %lx page %lx pti %lx\n",
   1.514 +                    cr3[cpu], pde, page, l1_table_offset_i386(va));
   1.515 +            return NULL;
   1.516 +        }
   1.517 +        page_phys[cpu] = page;
   1.518 +        page_virt[cpu] = v;
   1.519 +    }
   1.520 +    return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
   1.521 +}
   1.522 +
   1.523 +static int
   1.524 +xc_waitdomain_core_elf(
   1.525 +    int xc_handle,
   1.526 +    int domfd,
   1.527 +    int *status,
   1.528 +    int options,
   1.529 +    vcpu_guest_context_t *ctxt)
   1.530 +{
   1.531 +    int i;
   1.532 +    struct elf_core ecore;
   1.533 +
   1.534 +    struct xen_dumpcore_elfnote_none *none;
   1.535 +    struct xen_dumpcore_elfnote_header *header;
   1.536 +    struct xen_dumpcore_elfnote_xen_version *xen_version;
   1.537 +    struct xen_dumpcore_elfnote_format_version *format_version;
   1.538 +
   1.539 +    Elf_Shdr* table_shdr;
   1.540 +    Elf_Shdr* pages_shdr;
   1.541 +
   1.542 +    if (elf_core_init(&ecore, domfd) < 0)
   1.543 +        goto out;
   1.544 +    
   1.545 +    /* .note.Xen: none */
   1.546 +    if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME,
   1.547 +                             XEN_ELFNOTE_DUMPCORE_NONE, (void**)&none) < 0)
   1.548 +        goto out;
   1.549 +    
   1.550 +    /* .note.Xen: header */
   1.551 +    if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME,
   1.552 +                             XEN_ELFNOTE_DUMPCORE_HEADER, (void**)&header) < 0)
   1.553 +        goto out;
   1.554 +    if ((header->header.xch_magic != XC_CORE_MAGIC &&
   1.555 +         header->header.xch_magic != XC_CORE_MAGIC_HVM) ||
   1.556 +        header->header.xch_nr_vcpus == 0 ||
   1.557 +        header->header.xch_nr_vcpus >= MAX_VIRT_CPUS ||
   1.558 +        header->header.xch_nr_pages == 0 ||
   1.559 +        header->header.xch_page_size != PAGE_SIZE)
   1.560 +        goto out;
   1.561 +    current_is_auto_translated_physmap =
   1.562 +        (header->header.xch_magic == XC_CORE_MAGIC_HVM);
   1.563 +    nr_pages = header->header.xch_nr_pages;
   1.564 +    
   1.565 +    /* .note.Xen: xen_version */
   1.566 +    if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME,
   1.567 +                             XEN_ELFNOTE_DUMPCORE_XEN_VERSION,
   1.568 +                             (void**)&xen_version) < 0)
   1.569 +        goto out;
   1.570 +    if (xen_version->xen_version.pagesize != PAGE_SIZE)
   1.571 +        goto out;
   1.572 +
   1.573 +    /* .note.Xen: format_version */
   1.574 +    if (elf_core_search_note(&ecore, XEN_DUMPCORE_ELFNOTE_NAME, 
   1.575 +                             XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION,
   1.576 +                             (void**)&format_version) < 0)
   1.577 +        goto out;
   1.578 +    for (i = 0; i < KNOWN_FORMAT_VERSION_NR; i++) {
   1.579 +        if (format_version->format_version.version ==
   1.580 +            known_format_version[i].version)
   1.581 +            break;
   1.582 +    }
   1.583 +    if (i == KNOWN_FORMAT_VERSION_NR) {
   1.584 +        /* complain if unknown format */
   1.585 +        IPRINTF("warning:unknown format version. %"PRIx64"\n",
   1.586 +                format_version->format_version.version);
   1.587 +    }
   1.588 +
   1.589 +    /* .xen_prstatus: read vcpu_guest_context_t*/
   1.590 +    if (elf_core_read_sec_by_name(&ecore, XEN_DUMPCORE_SEC_PRSTATUS,
   1.591 +                                  (char*)ctxt) < 0)
   1.592 +        goto out;
   1.593 +    for (i = 0; i < header->header.xch_nr_vcpus; i++)
   1.594 +        cr3[i] = ctxt[i].ctrlreg[3];
   1.595 +
   1.596 +    /* read .xen_p2m or .xen_pfn */
   1.597 +    if (current_is_auto_translated_physmap) {
   1.598 +        table_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_PFN);
   1.599 +        if (table_shdr == NULL)
   1.600 +            goto out;
   1.601 +        pfn_array_size = table_shdr->sh_size / table_shdr->sh_entsize;
   1.602 +        if (pfn_array != NULL)
   1.603 +            free(pfn_array);
   1.604 +        if (elf_core_alloc_read_sec(&ecore, table_shdr,
   1.605 +                                    (char**)&pfn_array) < 0)
   1.606 +            goto out;
   1.607 +        if (table_shdr->sh_entsize != sizeof(pfn_array[0]))
   1.608 +            goto out;
   1.609 +    } else {
   1.610 +        table_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_P2M);
   1.611 +        if (table_shdr == NULL)
   1.612 +            goto out;
   1.613 +        p2m_array_size = table_shdr->sh_size / table_shdr->sh_entsize;
   1.614 +        if (p2m_array != NULL)
   1.615 +            free(p2m_array);
   1.616 +        if (elf_core_alloc_read_sec(&ecore, table_shdr,
   1.617 +                                    (char**)&p2m_array) < 0)
   1.618 +            goto out;
   1.619 +        if (table_shdr->sh_entsize != sizeof(p2m_array[0]))
   1.620 +            goto out;
   1.621 +    }
   1.622 +    if (table_shdr->sh_size / table_shdr->sh_entsize != nr_pages)
   1.623 +        goto out;
   1.624 +
   1.625 +    /* pages_offset and check the file size */
   1.626 +    pages_shdr = elf_core_shdr_by_name(&ecore, XEN_DUMPCORE_SEC_PAGES);
   1.627 +    if (pages_shdr == NULL)
   1.628 +        goto out;
   1.629 +    pages_offset = pages_shdr->sh_offset;
   1.630 +    if ((pages_shdr->sh_size / pages_shdr->sh_entsize) != nr_pages ||
   1.631 +        pages_shdr->sh_entsize != PAGE_SIZE ||
   1.632 +        (pages_shdr->sh_addralign % PAGE_SIZE) != 0 ||
   1.633 +        (pages_offset % PAGE_SIZE) != 0)
   1.634 +        goto out;
   1.635 +    
   1.636 +    elf_core_free(&ecore);
   1.637 +    return 0;
   1.638 +
   1.639 +out:
   1.640 +    elf_core_free(&ecore);
   1.641 +    return -1;
   1.642 +}
   1.643 +
   1.644 +/* --- interface ----------------------------------------------------------- */
   1.645 +
   1.646 +typedef int (*xc_waitdomain_core_t)(int xc_handle,
   1.647 +                                    int domfd,
   1.648 +                                    int *status,
   1.649 +                                    int options,
   1.650 +                                    vcpu_guest_context_t *ctxt);
   1.651 +typedef void *(*map_domain_va_core_t)(unsigned long domfd,
   1.652 +                                      int cpu,
   1.653 +                                      void *guest_va,
   1.654 +                                      vcpu_guest_context_t *ctxt);
   1.655 +struct xc_core_format_type {
   1.656 +    xc_waitdomain_core_t waitdomain_core;
   1.657 +    map_domain_va_core_t map_domain_va_core;
   1.658 +};
   1.659 +
   1.660 +static const struct xc_core_format_type format_type[] = {
   1.661 +    {xc_waitdomain_core_elf,    map_domain_va_core_elf},
   1.662 +    {xc_waitdomain_core_compat, map_domain_va_core_compat},
   1.663 +};
   1.664 +#define NR_FORMAT_TYPE (sizeof(format_type)/sizeof(format_type[0]))
   1.665 +
   1.666 +/* XXX application state */
   1.667 +static const struct xc_core_format_type* current_format_type = NULL;
   1.668 +
   1.669 +void *
   1.670 +map_domain_va_core(unsigned long domfd, int cpu, void *guest_va,
   1.671 +                   vcpu_guest_context_t *ctxt)
   1.672 +{
   1.673 +    if (current_format_type == NULL)
   1.674 +        return NULL;
   1.675 +    return (current_format_type->map_domain_va_core)(domfd, cpu, guest_va,
   1.676 +                                                     ctxt);
   1.677 +}
   1.678 +
   1.679 +int
   1.680 +xc_waitdomain_core(int xc_handle, int domfd, int *status, int options,
   1.681 +                   vcpu_guest_context_t *ctxt)
   1.682 +{
   1.683 +    int ret;
   1.684 +    int i;
   1.685 +
   1.686 +    for (i = 0; i < NR_FORMAT_TYPE; i++) {
   1.687 +        ret = (format_type[i].waitdomain_core)(xc_handle, domfd, status,
   1.688 +                                               options, ctxt);
   1.689 +        if (ret == 0) {
   1.690 +            current_format_type = &format_type[i];
   1.691 +            break;
   1.692 +        }
   1.693 +    }
   1.694 +    return ret;
   1.695 +}
   1.696 +
   1.697  /*
   1.698   * Local variables:
   1.699   * mode: C