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