[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] From: YAMAMOTO Takashi <yamt@xxxxxxxxxxxxxxxxx>
ChangeSet 1.1822, 2005/04/02 22:21:29+01:00, cl349@xxxxxxxxxxxxxxxxxxxx From: YAMAMOTO Takashi <yamt@xxxxxxxxxxxxxxxxx> Add support to domain0 builder to load a (Net)BSD symtab for domain0. Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> arch/x86/domain.c | 8 +++- common/elf.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/xen/elf.h | 1 include/xen/sched.h | 5 ++ 4 files changed, 113 insertions(+), 1 deletion(-) diff -Nru a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c 2005-04-05 05:04:52 -04:00 +++ b/xen/arch/x86/domain.c 2005-04-05 05:04:52 -04:00 @@ -667,6 +667,9 @@ if ( rc != 0 ) return rc; + if (dsi.load_bsd_symtab) + loadelfsymtab(image_start, 0, &dsi); + /* Set up domain options */ if ( dsi.use_writable_pagetables ) vm_assist(p, VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); @@ -684,7 +687,7 @@ * read-only). We have a pair of simultaneous equations in two unknowns, * which we solve by exhaustive search. */ - vinitrd_start = round_pgup(dsi.v_kernend); + vinitrd_start = round_pgup(dsi.v_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long)); @@ -883,6 +886,9 @@ /* Copy the OS image. */ (void)loadelfimage(image_start); + + if (dsi.load_bsd_symtab) + loadelfsymtab(image_start, 1, &dsi); /* Copy the initial ramdisk. */ if ( initrd_len != 0 ) diff -Nru a/xen/common/elf.c b/xen/common/elf.c --- a/xen/common/elf.c 2005-04-05 05:04:52 -04:00 +++ b/xen/common/elf.c 2005-04-05 05:04:52 -04:00 @@ -125,12 +125,18 @@ if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL ) dsi->use_writable_pagetables = 1; + + if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) + dsi->load_bsd_symtab = 1; + } dsi->v_kernstart = kernstart; dsi->v_kernend = kernend; dsi->v_kernentry = ehdr->e_entry; + dsi->v_end = dsi->v_kernend; + return 0; } @@ -152,6 +158,100 @@ memset((char *)phdr->ELF_ADDR + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } + + return 0; +} + +#define ELFROUND (ELFSIZE / 8) + +int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) +{ + Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr; + Elf_Shdr *shdr; + unsigned long maxva, symva; + char *p; + int h, i; + + maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1); + symva = maxva; + maxva += sizeof(int); + dsi->symtab_addr = maxva; + dsi->symtab_len = 0; + maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr); + maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); + if (doload) { + p = (void *)symva; + + shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); + memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr)); + } else { + shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff); + p = NULL; /* XXX: gcc */ + } + + for ( h = 0; h < ehdr->e_shnum; h++ ) + { + if ( shdr[h].sh_type == SHT_STRTAB ) + { + /* Look for a strtab @i linked to symtab @h. */ + for ( i = 0; i < ehdr->e_shnum; i++ ) + if ( (shdr[i].sh_type == SHT_SYMTAB) && + (shdr[i].sh_link == h) ) + break; + /* Skip symtab @h if we found no corresponding strtab @i. */ + if ( i == ehdr->e_shnum ) + { + if (doload) { + shdr[h].sh_offset = 0; + } + continue; + } + } + + if ( (shdr[h].sh_type == SHT_STRTAB) || + (shdr[h].sh_type == SHT_SYMTAB) ) + { + if (doload) { + memcpy((void *)maxva, elfbase + shdr[h].sh_offset, + shdr[h].sh_size); + + /* Mangled to be based on ELF header location. */ + shdr[h].sh_offset = maxva - dsi->symtab_addr; + + } + dsi->symtab_len += shdr[h].sh_size; + maxva += shdr[h].sh_size; + maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); + } + + if (doload) { + shdr[h].sh_name = 0; /* Name is NULL. */ + } + } + + if ( dsi->symtab_len == 0 ) + { + dsi->symtab_addr = 0; + goto out; + } + + if (doload) { + *(int *)p = maxva - dsi->symtab_addr; + sym_ehdr = (Elf_Ehdr *)(p + sizeof(int)); + memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr)); + sym_ehdr->e_phoff = 0; + sym_ehdr->e_shoff = sizeof(Elf_Ehdr); + sym_ehdr->e_phentsize = 0; + sym_ehdr->e_phnum = 0; + sym_ehdr->e_shstrndx = SHN_UNDEF; + } + +#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) /* XXX */ + + dsi->symtab_len = maxva - dsi->symtab_addr; + dsi->v_end = round_pgup(maxva); + + out: return 0; } diff -Nru a/xen/include/xen/elf.h b/xen/include/xen/elf.h --- a/xen/include/xen/elf.h 2005-04-05 05:04:52 -04:00 +++ b/xen/include/xen/elf.h 2005-04-05 05:04:52 -04:00 @@ -526,6 +526,7 @@ struct domain_setup_info; extern int loadelfimage(char *); +extern int loadelfsymtab(char *, int, struct domain_setup_info *); extern int parseelfimage(char *, unsigned long, struct domain_setup_info *); #endif /* __XEN_ELF_H__ */ diff -Nru a/xen/include/xen/sched.h b/xen/include/xen/sched.h --- a/xen/include/xen/sched.h 2005-04-05 05:04:52 -04:00 +++ b/xen/include/xen/sched.h 2005-04-05 05:04:52 -04:00 @@ -119,11 +119,16 @@ struct domain_setup_info { unsigned long v_start; + unsigned long v_end; unsigned long v_kernstart; unsigned long v_kernend; unsigned long v_kernentry; unsigned int use_writable_pagetables; + unsigned int load_bsd_symtab; + + unsigned long symtab_addr; + unsigned long symtab_len; }; #include <asm/uaccess.h> /* for KERNEL_DS */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |