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