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
|