diff options
author | gonzo <gonzo@FreeBSD.org> | 2010-01-24 02:59:22 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2010-01-24 02:59:22 +0000 |
commit | d184a1dc591e220ab469cf09ad53989e6d347422 (patch) | |
tree | 2ef8b97f66a86a0cffa295fb4ee6dafdbeb095a9 | |
parent | 6bfde02405eb8939b3afcbdae9de37471c7bb79e (diff) | |
download | FreeBSD-src-d184a1dc591e220ab469cf09ad53989e6d347422.zip FreeBSD-src-d184a1dc591e220ab469cf09ad53989e6d347422.tar.gz |
- 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.
-rw-r--r-- | sys/mips/include/elf.h | 5 | ||||
-rw-r--r-- | sys/mips/mips/elf_trampoline.c | 60 |
2 files changed, 64 insertions, 1 deletions
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h index de12b5b..2d6ca3e 100644 --- a/sys/mips/include/elf.h +++ b/sys/mips/include/elf.h @@ -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_ */ diff --git a/sys/mips/mips/elf_trampoline.c b/sys/mips/mips/elf_trampoline.c index d98b846..5bd100c 100644 --- a/sys/mips/mips/elf_trampoline.c +++ b/sys/mips/mips/elf_trampoline.c @@ -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; } |