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; }
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; }