svn commit: r202908 - in head/sys/mips: include mips
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Sun Jan 24 02:59:22 UTC 2010
Author: gonzo
Date: Sun Jan 24 02:59:22 2010
New Revision: 202908
URL: http://svn.freebsd.org/changeset/base/202908
Log:
- 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.
Modified:
head/sys/mips/include/elf.h
head/sys/mips/mips/elf_trampoline.c
Modified: head/sys/mips/include/elf.h
==============================================================================
--- head/sys/mips/include/elf.h Sun Jan 24 02:33:14 2010 (r202907)
+++ head/sys/mips/include/elf.h Sun Jan 24 02:59:22 2010 (r202908)
@@ -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_ */
Modified: head/sys/mips/mips/elf_trampoline.c
==============================================================================
--- head/sys/mips/mips/elf_trampoline.c Sun Jan 24 02:33:14 2010 (r202907)
+++ head/sys/mips/mips/elf_trampoline.c Sun Jan 24 02:59:22 2010 (r202908)
@@ -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;
}
More information about the svn-src-all
mailing list