Module Name:    src
Committed By:   maxv
Date:           Mon Nov 13 21:14:04 UTC 2017

Modified Files:
        src/sys/arch/amd64/stand/prekern: elf.c mm.c prekern.h

Log Message:
Change the mapping logic: don't group sections of the same type into
segments, and rather map each section independently at a random VA.

In particular, .data and .bss are not merged anymore and reside at
different addresses.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/amd64/stand/prekern/elf.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/amd64/stand/prekern/mm.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/amd64/stand/prekern/prekern.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/stand/prekern/elf.c
diff -u src/sys/arch/amd64/stand/prekern/elf.c:1.9 src/sys/arch/amd64/stand/prekern/elf.c:1.10
--- src/sys/arch/amd64/stand/prekern/elf.c:1.9	Thu Nov  9 15:56:56 2017
+++ src/sys/arch/amd64/stand/prekern/elf.c	Mon Nov 13 21:14:04 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: elf.c,v 1.9 2017/11/09 15:56:56 maxv Exp $	*/
+/*	$NetBSD: elf.c,v 1.10 2017/11/13 21:14:04 maxv Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc. All rights reserved.
@@ -258,184 +258,41 @@ elf_build_head(vaddr_t headva)
 	}
 }
 
-static bool
-elf_section_is_text(Elf_Shdr *shdr)
-{
-	if (shdr->sh_type != SHT_NOBITS &&
-	    shdr->sh_type != SHT_PROGBITS) {
-		return false;
-	}
-	if (!(shdr->sh_flags & SHF_EXECINSTR)) {
-		return false;
-	}
-	return true;
-}
-
-static bool
-elf_section_is_rodata(Elf_Shdr *shdr)
-{
-	if (shdr->sh_type != SHT_NOBITS &&
-	    shdr->sh_type != SHT_PROGBITS) {
-		return false;
-	}
-	if (shdr->sh_flags & (SHF_EXECINSTR|SHF_WRITE)) {
-		return false;
-	}
-	return true;
-}
-
-static bool
-elf_section_is_data(Elf_Shdr *shdr)
-{
-	if (shdr->sh_type != SHT_NOBITS &&
-	    shdr->sh_type != SHT_PROGBITS) {
-		return false;
-	}
-	if (!(shdr->sh_flags & SHF_WRITE) ||
-	    (shdr->sh_flags & SHF_EXECINSTR)) {
-		return false;
-	}
-	return true;
-}
-
 void
-elf_get_text(paddr_t *pa, size_t *sz)
-{
-	const paddr_t basepa = kernpa_start;
-	paddr_t minpa, maxpa, secpa;
-	size_t i, secsz;
-
-	minpa = 0xFFFFFFFFFFFFFFFF, maxpa = 0;
-	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_text(&eif.shdr[i])) {
-			continue;
-		}
-		secpa = basepa + eif.shdr[i].sh_offset;
-		secsz = eif.shdr[i].sh_size;
-		if (secpa < minpa) {
-			minpa = secpa;
-		}
-		if (secpa + secsz > maxpa) {
-			maxpa = secpa + secsz;
-		}
-	}
-	ASSERT(minpa % PAGE_SIZE == 0);
-
-	*pa = minpa;
-	*sz = maxpa - minpa;
-}
-
-void
-elf_build_text(vaddr_t textva, paddr_t textpa)
+elf_map_sections()
 {
 	const paddr_t basepa = kernpa_start;
 	const vaddr_t headva = (vaddr_t)eif.ehdr;
-	size_t i, offtext;
-
-	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_text(&eif.shdr[i])) {
-			continue;
-		}
-
-		/* Offset of the section within the text segment. */
-		offtext = basepa + eif.shdr[i].sh_offset - textpa;
-
-		/* We want (headva + sh_offset) to be the VA of the section. */
-		eif.shdr[i].sh_offset = (textva + offtext - headva);
-	}
-}
-
-void
-elf_get_rodata(paddr_t *pa, size_t *sz)
-{
-	const paddr_t basepa = kernpa_start;
-	paddr_t minpa, maxpa, secpa;
+	Elf_Shdr *shdr;
+	int segtype;
+	vaddr_t secva;
+	paddr_t secpa;
 	size_t i, secsz;
 
-	minpa = 0xFFFFFFFFFFFFFFFF, maxpa = 0;
-	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_rodata(&eif.shdr[i])) {
-			continue;
-		}
-		secpa = basepa + eif.shdr[i].sh_offset;
-		secsz = eif.shdr[i].sh_size;
-		if (secpa < minpa) {
-			minpa = secpa;
-		}
-		if (secpa + secsz > maxpa) {
-			maxpa = secpa + secsz;
-		}
-	}
-	ASSERT(minpa % PAGE_SIZE == 0);
-
-	*pa = minpa;
-	*sz = maxpa - minpa;
-}
-
-void
-elf_build_rodata(vaddr_t rodatava, paddr_t rodatapa)
-{
-	const paddr_t basepa = kernpa_start;
-	const vaddr_t headva = (vaddr_t)eif.ehdr;
-	size_t i, offrodata;
-
 	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_rodata(&eif.shdr[i])) {
-			continue;
-		}
-
-		/* Offset of the section within the rodata segment. */
-		offrodata = basepa + eif.shdr[i].sh_offset - rodatapa;
-
-		/* We want (headva + sh_offset) to be the VA of the section. */
-		eif.shdr[i].sh_offset = (rodatava + offrodata - headva);
-	}
-}
-
-void
-elf_get_data(paddr_t *pa, size_t *sz)
-{
-	const paddr_t basepa = kernpa_start;
-	paddr_t minpa, maxpa, secpa;
-	size_t i, secsz;
+		shdr = &eif.shdr[i];
 
-	minpa = 0xFFFFFFFFFFFFFFFF, maxpa = 0;
-	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_data(&eif.shdr[i])) {
+		if (shdr->sh_type != SHT_NOBITS &&
+		    shdr->sh_type != SHT_PROGBITS) {
 			continue;
 		}
-		secpa = basepa + eif.shdr[i].sh_offset;
-		secsz = eif.shdr[i].sh_size;
-		if (secpa < minpa) {
-			minpa = secpa;
-		}
-		if (secpa + secsz > maxpa) {
-			maxpa = secpa + secsz;
-		}
-	}
-	ASSERT(minpa % PAGE_SIZE == 0);
-
-	*pa = minpa;
-	*sz = maxpa - minpa;
-}
-
-void
-elf_build_data(vaddr_t datava, paddr_t datapa)
-{
-	const paddr_t basepa = kernpa_start;
-	const vaddr_t headva = (vaddr_t)eif.ehdr;
-	size_t i, offdata;
 
-	for (i = 0; i < eif.ehdr->e_shnum; i++) {
-		if (!elf_section_is_data(&eif.shdr[i])) {
-			continue;
+		if (shdr->sh_flags & SHF_EXECINSTR) {
+			segtype = BTSEG_TEXT;
+		} else if (shdr->sh_flags & SHF_WRITE) {
+			segtype = BTSEG_DATA;
+		} else {
+			segtype = BTSEG_RODATA;
 		}
+		secpa = basepa + shdr->sh_offset;
+		secsz = shdr->sh_size;
+		ASSERT(shdr->sh_offset != 0);
+		ASSERT(secpa % PAGE_SIZE == 0);
 
-		/* Offset of the section within the data segment. */
-		offdata = basepa + eif.shdr[i].sh_offset - datapa;
+		secva = mm_map_segment(segtype, secpa, secsz);
 
 		/* We want (headva + sh_offset) to be the VA of the section. */
-		eif.shdr[i].sh_offset = (datava + offdata - headva);
+		shdr->sh_offset = secva - headva;
 	}
 }
 

Index: src/sys/arch/amd64/stand/prekern/mm.c
diff -u src/sys/arch/amd64/stand/prekern/mm.c:1.11 src/sys/arch/amd64/stand/prekern/mm.c:1.12
--- src/sys/arch/amd64/stand/prekern/mm.c:1.11	Sat Nov 11 13:50:57 2017
+++ src/sys/arch/amd64/stand/prekern/mm.c	Mon Nov 13 21:14:04 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mm.c,v 1.11 2017/11/11 13:50:57 maxv Exp $	*/
+/*	$NetBSD: mm.c,v 1.12 2017/11/13 21:14:04 maxv Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc. All rights reserved.
@@ -313,75 +313,34 @@ bootspace_addseg(int type, vaddr_t va, p
 	fatal("bootspace_addseg: segments full");
 }
 
-static void
-mm_map_segments()
+vaddr_t
+mm_map_segment(int segtype, paddr_t pa, size_t elfsz)
 {
-	size_t i, npages, size, elfsz;
+	size_t i, npages, size;
 	vaddr_t randva;
-	paddr_t pa;
-
-	/*
-	 * Kernel text segment.
-	 */
-	elf_get_text(&pa, &elfsz);
-	size = roundup(elfsz, PAGE_SIZE);
-	randva = mm_randva_kregion(size);
-	npages = size / PAGE_SIZE;
-
-	/* Enter the area and build the ELF info */
-	for (i = 0; i < npages; i++) {
-		mm_enter_pa(pa + i * PAGE_SIZE,
-		    randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
-	}
-	elf_build_text(randva, pa);
-
-	/* Fill in the padding */
-	memset((void *)(randva + elfsz), PAD_TEXT, size - elfsz);
-
-	/* Register the values in bootspace */
-	bootspace_addseg(BTSEG_TEXT, randva, pa, size);
+	char pad;
 
-	/*
-	 * Kernel rodata segment.
-	 */
-	elf_get_rodata(&pa, &elfsz);
 	size = roundup(elfsz, PAGE_SIZE);
 	randva = mm_randva_kregion(size);
 	npages = size / PAGE_SIZE;
 
-	/* Enter the area and build the ELF info */
 	for (i = 0; i < npages; i++) {
 		mm_enter_pa(pa + i * PAGE_SIZE,
 		    randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
 	}
-	elf_build_rodata(randva, pa);
-
-	/* Fill in the padding */
-	memset((void *)(randva + elfsz), PAD_RODATA, size - elfsz);
-
-	/* Register the values in bootspace */
-	bootspace_addseg(BTSEG_RODATA, randva, pa, size);
-
-	/*
-	 * Kernel data segment.
-	 */
-	elf_get_data(&pa, &elfsz);
-	size = roundup(elfsz, PAGE_SIZE);
-	randva = mm_randva_kregion(size);
-	npages = size / PAGE_SIZE;
 
-	/* Enter the area and build the ELF info */
-	for (i = 0; i < npages; i++) {
-		mm_enter_pa(pa + i * PAGE_SIZE,
-		    randva + i * PAGE_SIZE, MM_PROT_READ|MM_PROT_WRITE);
+	if (segtype == BTSEG_TEXT) {
+		pad = PAD_TEXT;
+	} else if (segtype == BTSEG_RODATA) {
+		pad = PAD_RODATA;
+	} else {
+		pad = PAD_DATA;
 	}
-	elf_build_data(randva, pa);
+	memset((void *)(randva + elfsz), pad, size - elfsz);
 
-	/* Fill in the padding */
-	memset((void *)(randva + elfsz), PAD_DATA, size - elfsz);
+	bootspace_addseg(segtype, randva, pa, size);
 
-	/* Register the values in bootspace */
-	bootspace_addseg(BTSEG_DATA, randva, pa, size);
+	return randva;
 }
 
 static void
@@ -447,7 +406,7 @@ mm_map_kernel()
 	memset(&bootspace, 0, sizeof(bootspace));
 	mm_map_head();
 	print_state(true, "Head region mapped");
-	mm_map_segments();
+	elf_map_sections();
 	print_state(true, "Segments mapped");
 	mm_map_boot();
 	print_state(true, "Boot region mapped");

Index: src/sys/arch/amd64/stand/prekern/prekern.h
diff -u src/sys/arch/amd64/stand/prekern/prekern.h:1.10 src/sys/arch/amd64/stand/prekern/prekern.h:1.11
--- src/sys/arch/amd64/stand/prekern/prekern.h:1.10	Mon Nov 13 20:03:26 2017
+++ src/sys/arch/amd64/stand/prekern/prekern.h	Mon Nov 13 21:14:03 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: prekern.h,v 1.10 2017/11/13 20:03:26 maxv Exp $	*/
+/*	$NetBSD: prekern.h,v 1.11 2017/11/13 21:14:03 maxv Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc. All rights reserved.
@@ -96,12 +96,7 @@ void print_banner();
 /* elf.c */
 size_t elf_get_head_size(vaddr_t);
 void elf_build_head(vaddr_t);
-void elf_get_text(paddr_t *, size_t *);
-void elf_build_text(vaddr_t, paddr_t);
-void elf_get_rodata(paddr_t *, size_t *);
-void elf_build_rodata(vaddr_t, paddr_t);
-void elf_get_data(paddr_t *, size_t *);
-void elf_build_data(vaddr_t, paddr_t);
+void elf_map_sections();
 void elf_build_boot(vaddr_t, paddr_t);
 vaddr_t elf_kernel_reloc();
 
@@ -116,6 +111,7 @@ void jump_kernel();
 void mm_init(paddr_t);
 paddr_t mm_vatopa(vaddr_t);
 void mm_bootspace_mprotect();
+vaddr_t mm_map_segment(int, paddr_t, size_t);
 void mm_map_kernel();
 
 /* prekern.c */

Reply via email to