ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, unsigned index) { uint64_t count = elf_uval(elf, elf->ehdr, e_phnum); elf_ptrval ptr; if ( index >= count ) return ELF_INVALID_HANDLE(elf_phdr); ptr = (ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_phoff) + elf_uval(elf, elf->ehdr, e_phentsize) * index); return ELF_MAKE_HANDLE(elf_phdr, ptr); }
static char *xc_dom_guest_type(struct xc_dom_image *dom, struct elf_binary *elf) { uint64_t machine = elf_uval(elf, elf->ehdr, e_machine); if ( dom->container_type == XC_DOM_HVM_CONTAINER && dom->parms.phys_entry != UNSET_ADDR32 ) return "hvm-3.0-x86_32"; switch ( machine ) { case EM_386: switch ( dom->parms.pae ) { case XEN_PAE_BIMODAL: if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") ) return "xen-3.0-x86_32p"; return "xen-3.0-x86_32"; case XEN_PAE_EXTCR3: case XEN_PAE_YES: return "xen-3.0-x86_32p"; case XEN_PAE_NO: default: return "xen-3.0-x86_32"; } case EM_X86_64: return "xen-3.0-x86_64"; default: return "xen-3.0-unknown"; } }
static char *xc_dom_guest_type(struct xc_dom_image *dom, struct elf_binary *elf) { uint64_t machine = elf_uval(elf, elf->ehdr, e_machine); switch ( machine ) { case EM_386: switch ( dom->parms.pae ) { case 3 /* PAEKERN_bimodal */: if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") ) return "xen-3.0-x86_32p"; return "xen-3.0-x86_32"; case PAEKERN_extended_cr3: case PAEKERN_yes: return "xen-3.0-x86_32p"; case PAEKERN_no: default: return "xen-3.0-x86_32"; } case EM_X86_64: return "xen-3.0-x86_64"; case EM_IA_64: return elf_msb(elf) ? "xen-3.0-ia64be" : "xen-3.0-ia64"; case EM_PPC64: return "xen-3.0-powerpc64"; default: return "xen-3.0-unknown"; } }
static char *xc_dom_guest_type(struct xc_dom_image *dom, struct elf_binary *elf) { uint64_t machine = elf_uval(elf, elf->ehdr, e_machine); switch ( machine ) { case EM_386: switch ( dom->parms.pae ) { case XEN_PAE_BIMODAL: if ( strstr(dom->xen_caps, "xen-3.0-x86_32p") ) return "xen-3.0-x86_32p"; return "xen-3.0-x86_32"; case XEN_PAE_EXTCR3: case XEN_PAE_YES: return "xen-3.0-x86_32p"; case XEN_PAE_NO: default: return "xen-3.0-x86_32"; } case EM_X86_64: return "xen-3.0-x86_64"; default: return "xen-3.0-unknown"; } }
static void print_numeric_note(const char *prefix, struct elf_binary *elf, const elf_note *note) { uint64_t value = elf_note_numeric(elf, note); int descsz = elf_uval(elf, note, descsz); printf("%s: %#*" PRIx64 " (%d bytes)\n", prefix, 2+2*descsz, value, descsz); }
unsigned elf_shdr_count(struct elf_binary *elf) { unsigned count = elf_uval(elf, elf->ehdr, e_shnum); uint64_t max = elf->size / sizeof(Elf32_Shdr); if (max > ~(unsigned)0) max = ~(unsigned)0; /* Xen doesn't have limits.h :-/ */ if (count > max) { elf_mark_broken(elf, "far too many section headers"); count = max; } return count; }
static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf, const elf_note *note) { int descsz = elf_uval(elf, note, descsz); const uint32_t *desc32 = elf_note_desc(elf, note); const uint64_t *desc64 = elf_note_desc(elf, note); /* XXX should be able to cope with a list of values. */ switch ( descsz / 2 ) { case 8: printf("%s: mask=%#"PRIx64" value=%#"PRIx64"\n", prefix, desc64[0], desc64[1]); break; case 4: printf("%s: mask=%#"PRIx32" value=%#"PRIx32"\n", prefix, desc32[0],desc32[1]); break; } }
int __init construct_dom0( struct domain *d, unsigned long _image_start, unsigned long image_len, unsigned long _initrd_start, unsigned long initrd_len, char *cmdline) { int i, rc, compatible, compat32, order, machine; struct cpu_user_regs *regs; unsigned long pfn, mfn; unsigned long nr_pages; unsigned long nr_pt_pages; unsigned long alloc_spfn; unsigned long alloc_epfn; unsigned long count; struct page_info *page = NULL; start_info_t *si; struct vcpu *v = d->vcpu[0]; unsigned long long value; #if defined(__i386__) char *image_start = (char *)_image_start; /* use lowmem mappings */ char *initrd_start = (char *)_initrd_start; /* use lowmem mappings */ #elif defined(__x86_64__) char *image_start = __va(_image_start); char *initrd_start = __va(_initrd_start); #endif #if CONFIG_PAGING_LEVELS >= 4 l4_pgentry_t *l4tab = NULL, *l4start = NULL; #endif l3_pgentry_t *l3tab = NULL, *l3start = NULL; l2_pgentry_t *l2tab = NULL, *l2start = NULL; l1_pgentry_t *l1tab = NULL, *l1start = NULL; /* * This fully describes the memory layout of the initial domain. All * *_start address are page-aligned, except v_start (and v_end) which are * superpage-aligned. */ struct elf_binary elf; struct elf_dom_parms parms; unsigned long vkern_start; unsigned long vkern_end; unsigned long vinitrd_start; unsigned long vinitrd_end; unsigned long vphysmap_start; unsigned long vphysmap_end; unsigned long vstartinfo_start; unsigned long vstartinfo_end; unsigned long vstack_start; unsigned long vstack_end; unsigned long vpt_start; unsigned long vpt_end; unsigned long v_start; unsigned long v_end; /* Machine address of next candidate page-table page. */ unsigned long mpt_alloc; /* Sanity! */ BUG_ON(d->domain_id != 0); BUG_ON(d->vcpu[0] == NULL); BUG_ON(v->is_initialised); printk("*** LOADING DOMAIN 0 ***\n"); d->max_pages = ~0U; nr_pages = compute_dom0_nr_pages(); if ( (rc = elf_init(&elf, image_start, image_len)) != 0 ) return rc; #ifdef VERBOSE elf_set_verbose(&elf); #endif elf_parse_binary(&elf); if ( (rc = elf_xen_parse(&elf, &parms)) != 0 ) return rc; /* compatibility check */ compatible = 0; compat32 = 0; machine = elf_uval(&elf, elf.ehdr, e_machine); switch (CONFIG_PAGING_LEVELS) { case 3: /* x86_32p */ if (parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; printk(" Xen kernel: 32-bit, PAE, lsb\n"); if (elf_32bit(&elf) && parms.pae && machine == EM_386) compatible = 1; break; case 4: /* x86_64 */ printk(" Xen kernel: 64-bit, lsb, compat32\n"); if (elf_32bit(&elf) && parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; if (elf_32bit(&elf) && parms.pae && machine == EM_386) { compat32 = 1; compatible = 1; } if (elf_64bit(&elf) && machine == EM_X86_64) compatible = 1; break; } printk(" Dom0 kernel: %s%s, %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf_64bit(&elf) ? "64-bit" : "32-bit", parms.pae ? ", PAE" : "", elf_msb(&elf) ? "msb" : "lsb", elf.pstart, elf.pend); if ( elf.bsd_symtab_pstart ) printk(" Dom0 symbol map 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf.bsd_symtab_pstart, elf.bsd_symtab_pend); if ( !compatible ) { printk("Mismatch between Xen and DOM0 kernel\n"); return -EINVAL; } #if defined(__x86_64__) if ( compat32 ) { l1_pgentry_t gdt_l1e; d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 1; v->vcpu_info = (void *)&d->shared_info->compat.vcpu_info[0]; if ( nr_pages != (unsigned int)nr_pages ) nr_pages = UINT_MAX; /* * Map compatibility Xen segments into every VCPU's GDT. See * arch_domain_create() for further comments. */ gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table), PAGE_HYPERVISOR); for ( i = 0; i < MAX_VIRT_CPUS; i++ ) d->arch.mm_perdomain_pt[((i << GDT_LDT_VCPU_SHIFT) + FIRST_RESERVED_GDT_PAGE)] = gdt_l1e; flush_tlb_one_local(GDT_LDT_VIRT_START + FIRST_RESERVED_GDT_BYTE); } #endif if ( parms.pae == PAEKERN_extended_cr3 ) set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist); if ( (parms.virt_hv_start_low != UNSET_ADDR) && elf_32bit(&elf) ) { unsigned long mask = (1UL << L2_PAGETABLE_SHIFT) - 1; value = (parms.virt_hv_start_low + mask) & ~mask; BUG_ON(!is_pv_32bit_domain(d)); #if defined(__i386__) if ( value > HYPERVISOR_VIRT_START ) panic("Domain 0 expects too high a hypervisor start address.\n"); #else if ( value > __HYPERVISOR_COMPAT_VIRT_START ) panic("Domain 0 expects too high a hypervisor start address.\n"); HYPERVISOR_COMPAT_VIRT_START(d) = max_t(unsigned int, m2p_compat_vstart, value); #endif }
unsigned elf_phdr_count(struct elf_binary *elf) { return elf_uval(elf, elf->ehdr, e_phnum); }
int __init construct_dom0( struct domain *d, const module_t *image, unsigned long image_headroom, module_t *initrd, void *(*bootstrap_map)(const module_t *), char *cmdline) { int i, cpu, rc, compatible, compat32, order, machine; struct cpu_user_regs *regs; unsigned long pfn, mfn; unsigned long nr_pages; unsigned long nr_pt_pages; unsigned long alloc_spfn; unsigned long alloc_epfn; unsigned long initrd_pfn = -1, initrd_mfn = 0; unsigned long count; struct page_info *page = NULL; start_info_t *si; struct vcpu *v = d->vcpu[0]; unsigned long long value; char *image_base = bootstrap_map(image); unsigned long image_len = image->mod_end; char *image_start = image_base + image_headroom; unsigned long initrd_len = initrd ? initrd->mod_end : 0; #if CONFIG_PAGING_LEVELS < 4 module_t mpt; void *mpt_ptr; #else l4_pgentry_t *l4tab = NULL, *l4start = NULL; #endif l3_pgentry_t *l3tab = NULL, *l3start = NULL; l2_pgentry_t *l2tab = NULL, *l2start = NULL; l1_pgentry_t *l1tab = NULL, *l1start = NULL; /* * This fully describes the memory layout of the initial domain. All * *_start address are page-aligned, except v_start (and v_end) which are * superpage-aligned. */ struct elf_binary elf; struct elf_dom_parms parms; unsigned long vkern_start; unsigned long vkern_end; unsigned long vinitrd_start; unsigned long vinitrd_end; unsigned long vphysmap_start; unsigned long vphysmap_end; unsigned long vstartinfo_start; unsigned long vstartinfo_end; unsigned long vstack_start; unsigned long vstack_end; unsigned long vpt_start; unsigned long vpt_end; unsigned long v_start; unsigned long v_end; /* Machine address of next candidate page-table page. */ paddr_t mpt_alloc; /* Sanity! */ BUG_ON(d->domain_id != 0); BUG_ON(d->vcpu[0] == NULL); BUG_ON(v->is_initialised); printk("*** LOADING DOMAIN 0 ***\n"); d->max_pages = ~0U; if ( (rc = bzimage_parse(image_base, &image_start, &image_len)) != 0 ) return rc; if ( (rc = elf_init(&elf, image_start, image_len)) != 0 ) return rc; #ifdef VERBOSE elf_set_verbose(&elf); #endif elf_parse_binary(&elf); if ( (rc = elf_xen_parse(&elf, &parms)) != 0 ) return rc; /* compatibility check */ compatible = compat32 = 0; machine = elf_uval(&elf, elf.ehdr, e_machine); switch (CONFIG_PAGING_LEVELS) { case 3: /* x86_32p */ if (parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; printk(" Xen kernel: 32-bit, PAE, lsb\n"); if (elf_32bit(&elf) && parms.pae && machine == EM_386) compatible = 1; break; case 4: /* x86_64 */ printk(" Xen kernel: 64-bit, lsb, compat32\n"); if (elf_32bit(&elf) && parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; if (elf_32bit(&elf) && parms.pae && machine == EM_386) { compat32 = 1; compatible = 1; } if (elf_64bit(&elf) && machine == EM_X86_64) compatible = 1; break; } printk(" Dom0 kernel: %s%s, %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf_64bit(&elf) ? "64-bit" : "32-bit", parms.pae ? ", PAE" : "", elf_msb(&elf) ? "msb" : "lsb", elf.pstart, elf.pend); if ( elf.bsd_symtab_pstart ) printk(" Dom0 symbol map 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf.bsd_symtab_pstart, elf.bsd_symtab_pend); if ( !compatible ) { printk("Mismatch between Xen and DOM0 kernel\n"); return -EINVAL; } if ( parms.elf_notes[XEN_ELFNOTE_SUPPORTED_FEATURES].type != XEN_ENT_NONE && !test_bit(XENFEAT_dom0, parms.f_supported) ) { printk("Kernel does not support Dom0 operation\n"); return -EINVAL; } #if defined(__x86_64__) if ( compat32 ) { d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 1; v->vcpu_info = (void *)&d->shared_info->compat.vcpu_info[0]; if ( setup_compat_arg_xlat(v) != 0 ) BUG(); } #endif nr_pages = compute_dom0_nr_pages(d, &parms, initrd_len); if ( parms.pae == PAEKERN_extended_cr3 ) set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist); if ( (parms.virt_hv_start_low != UNSET_ADDR) && elf_32bit(&elf) ) { unsigned long mask = (1UL << L2_PAGETABLE_SHIFT) - 1; value = (parms.virt_hv_start_low + mask) & ~mask; BUG_ON(!is_pv_32bit_domain(d)); #if defined(__i386__) if ( value > HYPERVISOR_VIRT_START ) panic("Domain 0 expects too high a hypervisor start address.\n"); #else if ( value > __HYPERVISOR_COMPAT_VIRT_START ) panic("Domain 0 expects too high a hypervisor start address.\n"); HYPERVISOR_COMPAT_VIRT_START(d) = max_t(unsigned int, m2p_compat_vstart, value); #endif }
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, struct elf_binary *elf, int load) { struct elf_binary syms; const elf_shdr *shdr, *shdr2; xen_vaddr_t symtab, maxaddr; char *hdr; size_t size; int h, count, type, i, tables = 0; if ( elf_swap(elf) ) { xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n", __FUNCTION__); return 0; } if ( load ) { if ( !dom->bsd_symtab_start ) return 0; size = dom->kernel_seg.vend - dom->bsd_symtab_start; hdr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start); *(int *)hdr = size - sizeof(int); } else { size = sizeof(int) + elf_size(elf, elf->ehdr) + elf_shdr_count(elf) * elf_size(elf, shdr); hdr = xc_dom_malloc(dom, size); if ( hdr == NULL ) return 0; dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend); } memcpy(hdr + sizeof(int), elf->image, elf_size(elf, elf->ehdr)); memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr), elf->image + elf_uval(elf, elf->ehdr, e_shoff), elf_shdr_count(elf) * elf_size(elf, shdr)); if ( elf_64bit(elf) ) { Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int)); ehdr->e_phoff = 0; ehdr->e_phentsize = 0; ehdr->e_phnum = 0; ehdr->e_shoff = elf_size(elf, elf->ehdr); ehdr->e_shstrndx = SHN_UNDEF; } else { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int)); ehdr->e_phoff = 0; ehdr->e_phentsize = 0; ehdr->e_phnum = 0; ehdr->e_shoff = elf_size(elf, elf->ehdr); ehdr->e_shstrndx = SHN_UNDEF; } if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) ) return -1; if ( xc_dom_logfile ) elf_set_logfile(&syms, xc_dom_logfile, 1); symtab = dom->bsd_symtab_start + sizeof(int); maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) + elf_shdr_count(&syms) * elf_size(&syms, shdr)); xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64 " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n", __FUNCTION__, load ? "load" : "parse", dom->bsd_symtab_start, dom->kernel_seg.vend, symtab, maxaddr); count = elf_shdr_count(&syms); for ( h = 0; h < count; h++ ) { shdr = elf_shdr_by_index(&syms, h); type = elf_uval(&syms, shdr, sh_type); if ( type == SHT_STRTAB ) { /* Look for a strtab @i linked to symtab @h. */ for ( i = 0; i < count; i++ ) { shdr2 = elf_shdr_by_index(&syms, i); if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) && (elf_uval(&syms, shdr2, sh_link) == h) ) break; } /* Skip symtab @h if we found no corresponding strtab @i. */ if ( i == count ) { if ( elf_64bit(&syms) ) *(Elf64_Off*)(&shdr->e64.sh_offset) = 0; else *(Elf32_Off*)(&shdr->e32.sh_offset) = 0; continue; } } if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) ) { /* Mangled to be based on ELF header location. */ if ( elf_64bit(&syms) ) *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab; else *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab; size = elf_uval(&syms, shdr, sh_size); maxaddr = elf_round_up(&syms, maxaddr + size); tables++; xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n", __FUNCTION__, h, type == SHT_SYMTAB ? "symtab" : "strtab", size, maxaddr); if ( load ) { shdr2 = elf_shdr_by_index(elf, h); memcpy((void*)elf_section_start(&syms, shdr), elf_section_start(elf, shdr2), size); } } /* Name is NULL. */ if ( elf_64bit(&syms) ) *(Elf64_Half*)(&shdr->e64.sh_name) = 0; else *(Elf32_Word*)(&shdr->e32.sh_name) = 0; } if ( tables == 0 ) { xc_dom_printf("%s: no symbol table present\n", __FUNCTION__); dom->bsd_symtab_start = 0; return 0; } if ( !load ) dom->kernel_seg.vend = maxaddr; return 0; }
[XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0}, [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0}, [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1}, [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, [XEN_ELFNOTE_SUSPEND_CANCEL] = { "SUSPEND_CANCEL", 0 }, }; /* *INDENT-ON* */ const char *str = NULL; uint64_t val = 0; int type = elf_uval(elf, note, type); if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) || (note_desc[type].name == NULL) ) { elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", __FUNCTION__, type); return 0; } if ( note_desc[type].str ) { str = elf_note_desc(elf, note); elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, note_desc[type].name, str); parms->elf_notes[type].type = XEN_ENT_STR;
[XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, [XEN_ELFNOTE_SUPPORTED_FEATURES] = { "SUPPORTED_FEATURES", 0}, [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, [XEN_ELFNOTE_SUSPEND_CANCEL] = { "SUSPEND_CANCEL", 0 }, [XEN_ELFNOTE_MOD_START_PFN] = { "MOD_START_PFN", 0 }, }; /* *INDENT-ON* */ const char *str = NULL; uint64_t val = 0; unsigned int i; unsigned type = elf_uval(elf, note, type); if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) || (note_desc[type].name == NULL) ) { elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", __FUNCTION__, type); return 0; } if ( note_desc[type].str ) { str = elf_strval(elf, elf_note_desc(elf, note)); if (str == NULL) /* elf_strval will mark elf broken if it fails so no need to log */ return 0;
static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end) { const elf_note *note; int notes_found = 0; for ( note = start; note < end; note = elf_note_next(elf, note) ) { if (0 != strcmp(elf_note_name(elf, note), "Xen")) continue; notes_found++; switch(elf_uval(elf, note, type)) { case XEN_ELFNOTE_INFO: print_string_note("INFO", elf , note); break; case XEN_ELFNOTE_ENTRY: print_numeric_note("ENTRY", elf , note); break; case XEN_ELFNOTE_HYPERCALL_PAGE: print_numeric_note("HYPERCALL_PAGE", elf , note); break; case XEN_ELFNOTE_VIRT_BASE: print_numeric_note("VIRT_BASE", elf , note); break; case XEN_ELFNOTE_PADDR_OFFSET: print_numeric_note("PADDR_OFFSET", elf , note); break; case XEN_ELFNOTE_XEN_VERSION: print_string_note("XEN_VERSION", elf , note); break; case XEN_ELFNOTE_GUEST_OS: print_string_note("GUEST_OS", elf , note); break; case XEN_ELFNOTE_GUEST_VERSION: print_string_note("GUEST_VERSION", elf , note); break; case XEN_ELFNOTE_LOADER: print_string_note("LOADER", elf , note); break; case XEN_ELFNOTE_PAE_MODE: print_string_note("PAE_MODE", elf , note); break; case XEN_ELFNOTE_FEATURES: print_string_note("FEATURES", elf , note); break; case XEN_ELFNOTE_HV_START_LOW: print_numeric_note("HV_START_LOW", elf , note); break; case XEN_ELFNOTE_SUSPEND_CANCEL: print_numeric_note("SUSPEND_CANCEL", elf, note); break; case XEN_ELFNOTE_L1_MFN_VALID: print_l1_mfn_valid_note("L1_MFN_VALID", elf , note); break; default: printf("unknown note type %#x\n", (int)elf_uval(elf, note, type)); break; } } return notes_found; }
int main(int argc, char **argv) { const char *f; int fd,h,size,usize,count; void *image,*tmp; struct stat st; struct elf_binary elf; const elf_shdr *shdr; int notes_found = 0; if (argc != 2) { fprintf(stderr, "Usage: readnotes <elfimage>\n"); return 1; } f = argv[1]; fd = open(f, O_RDONLY); if (fd == -1) { fprintf(stderr, "Unable to open %s: %s\n", f, strerror(errno)); return 1; } if (fstat(fd, &st) == -1) { fprintf(stderr, "Unable to determine size of %s: %s\n", f, strerror(errno)); return 1; } image = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (image == MAP_FAILED) { fprintf(stderr, "Unable to map %s: %s\n", f, strerror(errno)); return 1; } size = st.st_size; usize = xc_dom_check_gzip(image, st.st_size); if (usize) { tmp = malloc(usize); xc_dom_do_gunzip(image, st.st_size, tmp, usize); image = tmp; size = usize; } if (0 != elf_init(&elf, image, size)) { fprintf(stderr, "File %s is not an ELF image\n", f); return 1; } elf_set_logfile(&elf, stderr, 0); count = elf_phdr_count(&elf); for ( h=0; h < count; h++) { const elf_phdr *phdr; phdr = elf_phdr_by_index(&elf, h); if (elf_uval(&elf, phdr, p_type) != PT_NOTE) continue; /* Some versions of binutils do not correctly set * p_offset for note segments. */ if (elf_uval(&elf, phdr, p_offset) == 0) continue; notes_found = print_notes(&elf, elf_segment_start(&elf, phdr), elf_segment_end(&elf, phdr)); } if ( notes_found == 0 ) { count = elf_shdr_count(&elf); for ( h=0; h < count; h++) { const elf_shdr *shdr; shdr = elf_shdr_by_index(&elf, h); if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE) continue; notes_found = print_notes(&elf, elf_section_start(&elf, shdr), elf_section_end(&elf, shdr)); if ( notes_found ) fprintf(stderr, "using notes from SHT_NOTE section\n"); } } shdr = elf_shdr_by_name(&elf, "__xen_guest"); if (shdr) printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr)); return 0; }