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 */