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-head mailing list