- Copy symbol-related tables (.symtab and .strtab) to the end of

relocated kernel. We use magic number to signal kernel that
    symbol data is present.
This commit is contained in:
gonzo 2010-01-24 02:59:22 +00:00
parent 6bfde02405
commit d184a1dc59
2 changed files with 64 additions and 1 deletions

View File

@ -256,4 +256,9 @@ __ElfType(Auxinfo);
#define ET_DYN_LOAD_ADDR 0x0120000
/*
* Constant to mark start of symtab/strtab saved by trampoline
*/
#define SYMTAB_MAGIC 0x64656267
#endif /* !_MACHINE_ELF_H_ */

View File

@ -96,12 +96,17 @@ load_kernel(void * kstart)
#ifdef __mips_n64
Elf64_Ehdr *eh;
Elf64_Phdr phdr[64] /* XXX */;
Elf64_Phdr shdr[64] /* XXX */;
#else
Elf32_Ehdr *eh;
Elf32_Phdr phdr[64] /* XXX */;
Elf32_Shdr shdr[64] /* XXX */;
#endif
int i;
int i, j;
void *entry_point;
vm_offset_t lastaddr = 0;
int symtabindex = -1;
int symstrindex = -1;
#ifdef __mips_n64
eh = (Elf64_Ehdr *)kstart;
@ -112,6 +117,27 @@ load_kernel(void * kstart)
memcpy(phdr, (void *)(kstart + eh->e_phoff ),
eh->e_phnum * sizeof(phdr[0]));
memcpy(shdr, (void *)(kstart + eh->e_shoff),
sizeof(*shdr) * eh->e_shnum);
if (eh->e_shnum * eh->e_shentsize != 0 && eh->e_shoff != 0) {
for (i = 0; i < eh->e_shnum; i++) {
if (shdr[i].sh_type == SHT_SYMTAB) {
/*
* XXX: check if .symtab is in PT_LOAD?
*/
if (shdr[i].sh_offset != 0 &&
shdr[i].sh_size != 0) {
symtabindex = i;
symstrindex = shdr[i].sh_link;
}
}
}
}
/*
* Copy loadable segments
*/
for (i = 0; i < eh->e_phnum; i++) {
volatile char c;
@ -120,12 +146,44 @@ load_kernel(void * kstart)
memcpy((void *)(phdr[i].p_vaddr),
(void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz);
/* Clean space from oversized segments, eg: bss. */
if (phdr[i].p_filesz < phdr[i].p_memsz)
bzero((void *)(phdr[i].p_vaddr + phdr[i].p_filesz),
phdr[i].p_memsz - phdr[i].p_filesz);
if (lastaddr < phdr[i].p_vaddr + phdr[i].p_memsz)
lastaddr = phdr[i].p_vaddr + phdr[i].p_memsz;
}
/* Now grab the symbol tables. */
if (symtabindex >= 0 && symstrindex >= 0) {
*(Elf_Size *)lastaddr = SYMTAB_MAGIC;
lastaddr += sizeof(Elf_Size);
*(Elf_Size *)lastaddr = shdr[symtabindex].sh_size +
shdr[symstrindex].sh_size + 2*sizeof(Elf_Size);
lastaddr += sizeof(Elf_Size);
/* .symtab size */
*(Elf_Size *)lastaddr = shdr[symtabindex].sh_size;
lastaddr += sizeof(shdr[symtabindex].sh_size);
/* .symtab data */
memcpy((void*)lastaddr,
shdr[symtabindex].sh_offset + kstart,
shdr[symtabindex].sh_size);
lastaddr += shdr[symtabindex].sh_size;
/* .strtab size */
*(Elf_Size *)lastaddr = shdr[symstrindex].sh_size;
lastaddr += sizeof(shdr[symstrindex].sh_size);
/* .strtab data */
memcpy((void*)lastaddr,
shdr[symstrindex].sh_offset + kstart,
shdr[symstrindex].sh_size);
} else
/* Do not take any chances */
*(Elf_Size *)lastaddr = 0;
return entry_point;
}