diff -r 7c5c3aa858cc xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Tue Jul 31 15:09:45 2007 +0100 +++ b/xen/arch/x86/domain_build.c Wed Aug 01 14:26:49 2007 +0200 @@ -316,6 +316,9 @@ int __init construct_dom0( parms.pae ? ", PAE" : "", elf_msb(&elf) ? "msb" : "lsb", elf.pstart, elf.pend); + if (parms.bsd_symtab) + printk(" Dom0 symbol map 0x%" PRIx64 " -> 0x%" PRIx64 "\n", + elf.sstart, elf.send); if ( !compatible ) { @@ -385,7 +388,7 @@ int __init construct_dom0( v_start = parms.virt_base; vkern_start = parms.virt_kstart; vkern_end = parms.virt_kend; - vinitrd_start = round_pgup(vkern_end); + vinitrd_start = round_pgup(parms.virt_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); vphysmap_end = vphysmap_start + (nr_pages * (!is_pv_32on64_domain(d) ? @@ -795,7 +798,7 @@ int __init construct_dom0( /* Copy the OS image and free temporary buffer. */ elf.dest = (void*)vkern_start; - elf_load_binary(&elf); + elf_xen_dom_load_binary(&elf, &parms); if ( UNSET_ADDR != parms.virt_hypercall ) { diff -r 7c5c3aa858cc xen/common/libelf/libelf-dominfo.c --- a/xen/common/libelf/libelf-dominfo.c Tue Jul 31 15:09:45 2007 +0100 +++ b/xen/common/libelf/libelf-dominfo.c Wed Aug 01 15:12:14 2007 +0200 @@ -333,6 +333,100 @@ static int elf_xen_note_check(struct elf return 0; } + +static int elf_xen_loadsymtab(struct elf_binary *elf, + struct elf_dom_parms *parms) +{ + unsigned long maxva, len; + + if (!parms->bsd_symtab) + return -1; + + /* Calculate the required additional kernel space for the elf image */ + + /* The absolute base address of the elf image */ + maxva = elf_round_up(elf, parms->virt_kend); + maxva += sizeof(long); /* Space to store the size of the elf image */ + /* Space for the elf and elf section headers */ + maxva += elf_uval(elf, elf->ehdr, e_ehsize) + + elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize); + maxva = elf_round_up(elf, maxva); + + /* Space for the symbol and string tabs */ + len = (unsigned long)elf->send - (unsigned long)elf->sstart; + maxva = elf_round_up(elf, maxva + len); + + /* The address the kernel must expanded to */ + parms->virt_end = maxva; + + return 0; +} + +int elf_xen_dom_load_binary(struct elf_binary *elf, + struct elf_dom_parms *parms) +{ + elf_ehdr *sym_ehdr; + unsigned long shdr, symtab_addr; + unsigned long maxva, symbase; + uint8_t i; + char *p; + + elf_load_binary(elf); + + if (!parms->bsd_symtab) + return 0; + +#define elf_hdr_elm(_elf, _hdr, _elm, _val) \ + if (elf_64bit(_elf)) \ + (_hdr)->e64._elm = _val; \ + else \ + (_hdr)->e32._elm = _val; + + + /* ehdr right after the kernel image (4 byte aligned) */ + symbase = elf_round_up(elf, parms->virt_kend); /* abs. start of the ELF image */ + symtab_addr = maxva = symbase + sizeof(long); + + /* setup elf header */ + sym_ehdr = (elf_ehdr *)symtab_addr; + maxva = elf_copy_ehdr(elf, sym_ehdr); + + elf_hdr_elm(elf, sym_ehdr, e_phoff, 0); + elf_hdr_elm(elf, sym_ehdr, e_shoff, elf_uval(elf, elf->ehdr, e_ehsize)); + elf_hdr_elm(elf, sym_ehdr, e_phentsize, 0); + elf_hdr_elm(elf, sym_ehdr, e_phnum, 0); + + /* copy elf section headers */ + shdr = maxva; + maxva = elf_copy_shdr(elf, (elf_shdr *)shdr); /* copy section entries */ + + for (i = 0; i < elf_shdr_count(elf); i++) { + uint8_t type; + unsigned long tmp; + + type = elf_uval(elf, (elf_shdr *)shdr, sh_type); + if ((type == SHT_STRTAB) || (type == SHT_SYMTAB)) { + elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i, + elf_section_start(elf, (elf_shdr *)shdr), (void *)maxva); + /* copy section */ + tmp = elf_copy_section(elf, (elf_shdr *)shdr, (void *)maxva); + /* Mangled to be based on ELF header location. */ + elf_hdr_elm(elf, (elf_shdr *)shdr, sh_offset, + maxva - symtab_addr); + maxva = tmp; + } + shdr += elf_uval(elf, elf->ehdr, e_shentsize); + } + + /* write down the actual sym size */ + p = (char *)symbase; + *(long *)p = maxva - symtab_addr; /* sym size */ + +#undef elf_ehdr_elm + + return 0; +} + static int elf_xen_addr_calc_check(struct elf_binary *elf, struct elf_dom_parms *parms) { @@ -374,9 +468,13 @@ static int elf_xen_addr_calc_check(struc parms->virt_offset = parms->virt_base - parms->elf_paddr_offset; parms->virt_kstart = elf->pstart + parms->virt_offset; parms->virt_kend = elf->pend + parms->virt_offset; + parms->virt_end = parms->virt_kend; if ( parms->virt_entry == UNSET_ADDR ) parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry); + + if (parms->bsd_symtab) + elf_xen_loadsymtab(elf, parms); elf_msg(elf, "%s: addresses:\n", __FUNCTION__); elf_msg(elf, " virt_base = 0x%" PRIx64 "\n", parms->virt_base); @@ -384,12 +482,14 @@ static int elf_xen_addr_calc_check(struc elf_msg(elf, " virt_offset = 0x%" PRIx64 "\n", parms->virt_offset); elf_msg(elf, " virt_kstart = 0x%" PRIx64 "\n", parms->virt_kstart); elf_msg(elf, " virt_kend = 0x%" PRIx64 "\n", parms->virt_kend); + elf_msg(elf, " virt_end = 0x%" PRIx64 "\n", parms->virt_end); elf_msg(elf, " virt_entry = 0x%" PRIx64 "\n", parms->virt_entry); if ( (parms->virt_kstart > parms->virt_kend) || (parms->virt_entry < parms->virt_kstart) || (parms->virt_entry > parms->virt_kend) || - (parms->virt_base > parms->virt_kstart) ) + (parms->virt_base > parms->virt_kstart) || + (parms->virt_kend > parms->virt_end) ) { elf_err(elf, "%s: ERROR: ELF start or entries are out of bounds.\n", __FUNCTION__); diff -r 7c5c3aa858cc xen/common/libelf/libelf-loader.c --- a/xen/common/libelf/libelf-loader.c Tue Jul 31 15:09:45 2007 +0100 +++ b/xen/common/libelf/libelf-loader.c Wed Aug 01 15:18:47 2007 +0200 @@ -10,6 +10,8 @@ int elf_init(struct elf_binary *elf, con { const elf_shdr *shdr; uint64_t i, count, section, offset; + uint64_t low = -1; + uint64_t high = 0; if ( !elf_is_elfbinary(image) ) { @@ -24,6 +26,10 @@ int elf_init(struct elf_binary *elf, con elf->class = elf->ehdr->e32.e_ident[EI_CLASS]; elf->data = elf->ehdr->e32.e_ident[EI_DATA]; +#ifdef VERBOSE + elf_set_verbose(elf); +#endif + /* sanity check phdr */ offset = elf_uval(elf, elf->ehdr, e_phoff) + elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); @@ -54,19 +60,46 @@ int elf_init(struct elf_binary *elf, con count = elf_shdr_count(elf); for ( i = 0; i < count; i++ ) { + const char * sh_symend, *sh_strend; + shdr = elf_shdr_by_index(elf, i); if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB ) continue; elf->sym_tab = shdr; + sh_symend = (const char *)elf_section_end(elf, shdr); shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); if ( shdr == NULL ) { elf->sym_tab = NULL; + sh_symend = 0; continue; } elf->sym_strtab = elf_section_start(elf, shdr); + sh_strend = (const char *)elf_section_end(elf, shdr); + + if (low > (unsigned long)elf->sym_tab) + low = (unsigned long)elf->sym_tab; + if (low > (unsigned long)shdr) + low = (unsigned long)shdr; + + if (high < ((unsigned long)sh_symend)) + high = (unsigned long)sh_symend; + if (high < ((unsigned long)sh_strend)) + high = (unsigned long)sh_strend; + + elf_msg(elf, "%s: shdr: sym_tab=%p size=0x%" PRIx64 "\n", + __FUNCTION__, + elf->sym_tab, elf_uval(elf, elf->sym_tab, sh_size)); + elf_msg(elf, "%s: shdr: str_tab=%p size=0x%" PRIx64 "\n", + __FUNCTION__, + elf->sym_strtab, elf_uval(elf, shdr, sh_size)); break; } + elf->sstart = low; + elf->send = high; + + elf_msg(elf, "%s: symbol map: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", + __FUNCTION__, elf->sstart, elf->send); return 0; } diff -r 7c5c3aa858cc xen/common/libelf/libelf-tools.c --- a/xen/common/libelf/libelf-tools.c Tue Jul 31 15:09:45 2007 +0100 +++ b/xen/common/libelf/libelf-tools.c Wed Aug 01 14:17:59 2007 +0200 @@ -238,6 +238,110 @@ int elf_phdr_is_loadable(struct elf_bina return ((p_type == PT_LOAD) && (p_flags & (PF_W | PF_X)) != 0); } +unsigned long +elf_copy_ehdr(struct elf_binary *elf, void *dest) +{ + uint64_t size; + + size = elf_uval(elf, elf->ehdr, e_ehsize); + memcpy(dest, elf->ehdr, size); + return elf_round_up(elf, (unsigned long)(dest) + size); +} + +unsigned long +elf_copy_shdr(struct elf_binary *elf, void *dest) +{ + uint64_t size; + + size = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize); + memcpy(dest, elf->image + elf_uval(elf, elf->ehdr, e_shoff), size); + return elf_round_up(elf, (unsigned long)(dest) + size); +} + +unsigned long +elf_copy_section(struct elf_binary *elf, const elf_shdr *shdr, void *dest) +{ + uint64_t size; + + size = elf_uval(elf, shdr, sh_size); + memcpy(dest, elf_section_start(elf, shdr), size); + return elf_round_up(elf, (unsigned long)(dest) + size); +} + +#ifndef NDEBUG +void elf_ehdr_dump(struct elf_binary *elf, unsigned long addr) +{ + elf_ehdr *ehdr; + +#define elm(_elm) elf_uval(elf, ehdr, _elm) +#define elm8(_elm) (uint8_t)elm(_elm) + + ehdr = (elf_ehdr *)addr; + + printk("elf header at address 0x%lx\n", addr); + + printk("e_ident (MAGIC): %x%c%c%c\n", elm8(e_ident[EI_MAG0]), + elm8(e_ident[EI_MAG1]), elm8(e_ident[EI_MAG2]), elm8(e_ident[EI_MAG3])); + printk("e_ident (class): %x %s\n", + elm8(e_ident[EI_CLASS]), + (elm8(e_ident[EI_CLASS]) == ELFCLASS64) ? + "64bit class" : (elm8(e_ident[EI_CLASS]) == ELFCLASS32) ? + "32bit class" : "invalid class"); + printk("e_ident (DATA): %x %s\n", + elm8(e_ident[EI_DATA]), + (elm8(e_ident[EI_DATA]) == ELFDATA2MSB) ? + "msb data" : (elm8(e_ident[EI_DATA]) == ELFDATA2LSB) ? + "lsb data" : "invalid data encoding"); + + printk("e_type: %x\n", elm8(e_type)); + printk("e_machine: %x\n", elm8(e_machine)); + printk("e_version: %x\n", elm8(e_version)); + printk("e_entry: %lx\n", (unsigned long)elm(e_entry)); + printk("e_phoff: %lx\n", (unsigned long)elm(e_phoff)); + printk("e_shoff: %lx\n", (unsigned long)elm(e_shoff)); + printk("e_flags: %x\n", elm8(e_flags)); + printk("e_ehsize: %x\n", elm8(e_ehsize)); + printk("e_phentsize: %x\n", elm8(e_phentsize)); + printk("e_phnum: %x\n", elm8(e_phnum)); + printk("e_shentsize: %x\n", elm8(e_shentsize)); + printk("e_shnum: %x\n", elm8(e_shnum)); + printk("e_shstrndx: %x\n", elm8(e_shstrndx)); + +#undef elm +#undef elm8 + +} + +void elf_shdr_dump(struct elf_binary *elf, unsigned long addr) +{ + elf_shdr *shdr; + +#define elm(_elm) elf_uval(elf, shdr, _elm) +#define elm8(_elm) (uint8_t)elm(_elm) + + shdr = (elf_shdr *)addr; + + printk("section header at 0x%lx\n", addr); + + printk("sh_name: %x\n", elm8(sh_name)); + printk("sh_type: %x %s\n", elm8(sh_type), + (elm8(sh_type) == SHT_SYMTAB) ? "SHT_SYMTAB" : + (elm8(sh_type) == SHT_STRTAB) ? "SHT_STRTAB" : ""); + printk("sh_flags: %x\n", elm8(sh_flags)); + printk("sh_addr: %lx\n", (unsigned long)elm(sh_addr)); + printk("sh_offset: %lx\n", (unsigned long)elm(sh_offset)); + printk("sh_size: %x\n", elm8(sh_size)); + printk("sh_link: %x\n", elm8(sh_link)); + printk("sh_info: %x\n", elm8(sh_info)); + printk("sh_addralign: %x\n", elm8(sh_addralign)); + printk("sh_entsize: %x\n", elm8(sh_entsize)); + +#undef elm +#undef elm8 + +} +#endif /* NDEBUG */ + /* * Local variables: * mode: C diff -r 7c5c3aa858cc xen/include/public/libelf.h --- a/xen/include/public/libelf.h Tue Jul 31 15:09:45 2007 +0100 +++ b/xen/include/public/libelf.h Wed Aug 01 14:47:47 2007 +0200 @@ -65,6 +65,8 @@ struct elf_binary { /* loaded to */ char *dest; + uint64_t sstart; + uint64_t send; uint64_t pstart; uint64_t pend; uint64_t reloc_offset; @@ -148,6 +150,16 @@ const elf_note *elf_note_next(struct elf int elf_is_elfbinary(const void *image); int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr); + +unsigned long elf_copy_ehdr(struct elf_binary *elf, void *dest); +unsigned long elf_copy_shdr(struct elf_binary *elf, void *dest); +unsigned long elf_copy_section(struct elf_binary *elf, + const elf_shdr *shdr, void *dest); + +#ifndef NDEBUG +void elf_ehdr_dump(struct elf_binary *elf, unsigned long addr); +void elf_shdr_dump(struct elf_binary *elf, unsigned long addr); +#endif /* ------------------------------------------------------------------------ */ /* xc_libelf_loader.c */ @@ -215,7 +227,8 @@ struct elf_dom_parms { /* calculated */ uint64_t virt_offset; uint64_t virt_kstart; - uint64_t virt_kend; + uint64_t virt_kend; /* end of kernel image */ + uint64_t virt_end; /* = virt_kend + sizeof symtab */ }; static inline void elf_xen_feature_set(int nr, uint32_t * addr) @@ -238,4 +251,7 @@ int elf_xen_parse(struct elf_binary *elf int elf_xen_parse(struct elf_binary *elf, struct elf_dom_parms *parms); +int elf_xen_dom_load_binary(struct elf_binary *elf, + struct elf_dom_parms *parms); + #endif /* __XC_LIBELF__ */