mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
bitkeeper revision 1.1159.1.131 (413ddc610qK3tZi2_2-e23mt5avoNA)
Load (Net)BSD symbol table from ELF image if requested.
This commit is contained in:
1 parent
2a23966f2b
commit
f11bc5a8fc
3 files changed
+145
-22
No files matched your search
@@ -180,7 +180,12 @@
|
||||
* Xen guest identifier and loader selection
|
||||
*/
|
||||
.section __xen_guest
|
||||
.asciz "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0,LOADER=generic"
|
||||
.ascii "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0"
|
||||
.ascii ",LOADER=generic"
|
||||
#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
|
||||
.ascii ",BSD_SYMTAB"
|
||||
#endif
|
||||
.byte 0
|
||||
|
||||
|
||||
/*
|
||||
@@ -189,7 +194,7 @@
|
||||
.data
|
||||
|
||||
.globl _C_LABEL(cpu)
|
||||
.globl _C_LABEL(esym),_C_LABEL(boothowto)
|
||||
.globl _C_LABEL(boothowto)
|
||||
.globl _C_LABEL(bootinfo),_C_LABEL(atdevbase)
|
||||
#ifdef COMPAT_OLDBOOT
|
||||
.globl _C_LABEL(bootdev)
|
||||
@@ -228,7 +233,6 @@ _C_LABEL(lapic_tpr):
|
||||
|
||||
_C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486,
|
||||
# or Pentium, or..
|
||||
_C_LABEL(esym): .long 0 # ptr to end of syms
|
||||
_C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual
|
||||
_C_LABEL(proc0paddr): .long 0
|
||||
_C_LABEL(PTDpaddr): .long 0 # paddr of PTD, for libkvm
|
||||
@@ -254,11 +258,6 @@ tmpstk:
|
||||
#define _RELOC(x) ((x))
|
||||
#define RELOC(x) _RELOC(_C_LABEL(x))
|
||||
|
||||
/* XXX assym.h */
|
||||
#define MOD_START 48
|
||||
#define MOD_LEN 56
|
||||
/* XXX assym.h */
|
||||
|
||||
.text
|
||||
.globl _C_LABEL(kernel_text)
|
||||
.set _C_LABEL(kernel_text),KERNTEXTOFF
|
||||
@@ -271,13 +270,6 @@ start:
|
||||
|
||||
movl %esi,%ebx # save start_info pointer
|
||||
|
||||
#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
|
||||
/* Save the symbol locations. */
|
||||
movl MOD_START(%ebx),%esi
|
||||
addl MOD_LEN(%ebx),%esi
|
||||
movl %esi,RELOC(esym)
|
||||
#endif
|
||||
|
||||
/* Clear BSS first so that there are no surprises... */
|
||||
xorl %eax,%eax
|
||||
movl $RELOC(__bss_start),%edi
|
||||
|
||||
@@ -2061,7 +2061,6 @@ init386(paddr_t first_avail)
|
||||
#if NKSYMS || defined(DDB) || defined(LKM)
|
||||
{
|
||||
extern int end;
|
||||
extern int *esym;
|
||||
struct btinfo_symtab *symtab;
|
||||
|
||||
#ifdef DDB
|
||||
@@ -2077,7 +2076,10 @@ init386(paddr_t first_avail)
|
||||
(int *)symtab->esym);
|
||||
}
|
||||
else
|
||||
ksyms_init(*(int *)&end, ((int *)&end) + 1, esym);
|
||||
ksyms_init(*(int *)&end, ((int *)&end) + 1,
|
||||
xen_start_info.mod_start ?
|
||||
(void *)xen_start_info.mod_start :
|
||||
(void *)xen_start_info.mfn_list);
|
||||
}
|
||||
#endif
|
||||
#ifdef DDB
|
||||
|
||||
@@ -17,11 +17,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;
|
||||
};
|
||||
|
||||
static int parseelfimage(char *elfbase,
|
||||
@@ -29,6 +34,8 @@ static int parseelfimage(char *elfbase,
|
||||
struct domain_setup_info *dsi);
|
||||
static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
|
||||
unsigned long vstart);
|
||||
static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
|
||||
struct domain_setup_info *dsi);
|
||||
|
||||
static long get_tot_pages(int xc_handle, u32 domid)
|
||||
{
|
||||
@@ -125,6 +132,9 @@ static int setup_guestos(int xc_handle,
|
||||
xc_domain_setvmassist(xc_handle, dom, VMASST_CMD_enable,
|
||||
VMASST_TYPE_writable_pagetables);
|
||||
|
||||
if (dsi.load_bsd_symtab)
|
||||
loadelfsymtab(image, NULL, NULL, &dsi);
|
||||
|
||||
if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
|
||||
{
|
||||
PERROR("Guest OS must load to a page boundary.\n");
|
||||
@@ -138,13 +148,13 @@ static int setup_guestos(int xc_handle,
|
||||
* read-only). We have a pair of simultaneous equations in two unknowns,
|
||||
* which we solve by exhaustive search.
|
||||
*/
|
||||
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));
|
||||
vpt_start = round_pgup(vphysmap_end);
|
||||
for ( nr_pt_pages = 2; ; nr_pt_pages++ )
|
||||
{
|
||||
vinitrd_start = round_pgup(dsi.v_kernend);
|
||||
vinitrd_end = vinitrd_start + initrd_len;
|
||||
vphysmap_start = round_pgup(vinitrd_end);
|
||||
vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
|
||||
vpt_start = round_pgup(vphysmap_end);
|
||||
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
|
||||
vstartinfo_start = vpt_end;
|
||||
vstartinfo_end = vstartinfo_start + PAGE_SIZE;
|
||||
@@ -200,6 +210,9 @@ static int setup_guestos(int xc_handle,
|
||||
|
||||
loadelfimage(image, pm_handle, page_array, dsi.v_start);
|
||||
|
||||
if (dsi.load_bsd_symtab)
|
||||
loadelfsymtab(image, pm_handle, page_array, &dsi);
|
||||
|
||||
/* Load the initial ramdisk image. */
|
||||
if ( initrd_len != 0 )
|
||||
{
|
||||
@@ -656,10 +669,15 @@ static int parseelfimage(char *elfbase,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -706,3 +724,114 @@ static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void map_memcpy(unsigned long dst, char *src, unsigned long size,
|
||||
void *pmh, unsigned long *parray, unsigned long vstart)
|
||||
{
|
||||
char *va;
|
||||
unsigned long chunksz, done, pa;
|
||||
|
||||
for ( done = 0; done < size; done += chunksz )
|
||||
{
|
||||
pa = dst + done - vstart;
|
||||
va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
|
||||
chunksz = size - done;
|
||||
if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
|
||||
chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
|
||||
memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
|
||||
unmap_pfn(pmh, va);
|
||||
}
|
||||
}
|
||||
|
||||
#define ELFROUND (ELFSIZE / 8)
|
||||
|
||||
static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
|
||||
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;
|
||||
|
||||
p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
|
||||
ehdr->e_shnum * sizeof(Elf_Shdr));
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
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);
|
||||
|
||||
shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
|
||||
memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
|
||||
|
||||
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 )
|
||||
{
|
||||
shdr[h].sh_offset = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (shdr[h].sh_type == SHT_STRTAB) ||
|
||||
(shdr[h].sh_type == SHT_SYMTAB) )
|
||||
{
|
||||
if ( pmh != NULL )
|
||||
map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
|
||||
pmh, parray, dsi->v_start);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
shdr[h].sh_name = 0; /* Name is NULL. */
|
||||
}
|
||||
|
||||
if ( dsi->symtab_len == 0 )
|
||||
{
|
||||
dsi->symtab_addr = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( pmh != NULL ) {
|
||||
*(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;
|
||||
|
||||
/* Copy total length, crafted ELF header and section header table */
|
||||
map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
|
||||
ehdr->e_shnum * sizeof(Elf_Shdr), pmh, parray,
|
||||
dsi->v_start);
|
||||
}
|
||||
|
||||
dsi->symtab_len = maxva - dsi->symtab_addr;
|
||||
dsi->v_end = round_pgup(maxva);
|
||||
|
||||
out:
|
||||
if ( p != NULL )
|
||||
free(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||