#include #include #include #include #include #include #include #include #include #include #include #include #include /* gunzip bits */ #include static xc_interface *xch; static void print_string_note(const char *prefix, struct elf_binary *elf, const elf_note *note) { printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note)); } 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); } 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; } } 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 \n"); return 1; } f = argv[1]; xch = xc_interface_open(0,0,XC_OPENFLAG_DUMMY); 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(xch, image, st.st_size); if (usize) { tmp = malloc(usize); xc_dom_do_gunzip(xch, 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; } xc_elf_set_logfile(xch, &elf, 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; }