Module Name: src Committed By: maxv Date: Wed Oct 18 16:29:56 UTC 2017
Modified Files: src/sys/lib/libsa: loadfile_elf32.c Log Message: Group the sections into segments, and align to KERNALIGN only between segments. Prerequisite for other changes. Unfortunately the code is not very compact, but whatever. To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 src/sys/lib/libsa/loadfile_elf32.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/lib/libsa/loadfile_elf32.c diff -u src/sys/lib/libsa/loadfile_elf32.c:1.47 src/sys/lib/libsa/loadfile_elf32.c:1.48 --- src/sys/lib/libsa/loadfile_elf32.c:1.47 Fri Oct 13 10:39:26 2017 +++ src/sys/lib/libsa/loadfile_elf32.c Wed Oct 18 16:29:56 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: loadfile_elf32.c,v 1.47 2017/10/13 10:39:26 maxv Exp $ */ +/* $NetBSD: loadfile_elf32.c,v 1.48 2017/10/18 16:29:56 maxv Exp $ */ /* * Copyright (c) 1997, 2008, 2017 The NetBSD Foundation, Inc. @@ -341,7 +341,7 @@ ELFNAMEEND(loadfile_dynamic)(int fd, Elf { const u_long offset = 0; Elf_Shdr *shdr; - Elf_Addr shpp, addr; + Elf_Addr shpp, addr, align; int i, j, loaded; size_t size, shdrsz; Elf_Addr maxp, elfp = 0; @@ -383,11 +383,22 @@ ELFNAMEEND(loadfile_dynamic)(int fd, Elf maxp += roundup(shdrsz, ELFROUND); /* - * Load the KERNEL SECTIONS. + * Load the KERNEL SECTIONS, and group them into segments. First text, + * then rodata, then data. Between sections, we align to the requested + * section alignment. Between segments, we align to KERNALIGN. */ + + /* text */ maxp = roundup(maxp, KERNALIGN); for (i = 0; i < elf->e_shnum; i++) { - addr = maxp; + if (!(shdr[i].sh_flags & SHF_EXECINSTR)) { + continue; + } + align = shdr[i].sh_addralign; + if (align == 0) { + align = ELFROUND; + } + addr = roundup(maxp, align); size = (size_t)shdr[i].sh_size; loaded = 0; @@ -411,15 +422,94 @@ ELFNAMEEND(loadfile_dynamic)(int fd, Elf } if (loaded) { - shdr[i].sh_offset = maxp - elfp; - maxp = roundup(maxp + size, KERNALIGN); + shdr[i].sh_offset = addr - elfp; + maxp = addr + size; + } + } + + /* rodata */ + maxp = roundup(maxp, KERNALIGN); + for (i = 0; i < elf->e_shnum; i++) { + if ((shdr[i].sh_flags & (SHF_EXECINSTR|SHF_WRITE))) { + continue; + } + align = shdr[i].sh_addralign; + if (align == 0) { + align = ELFROUND; + } + addr = roundup(maxp, align); + size = (size_t)shdr[i].sh_size; + + loaded = 0; + switch (shdr[i].sh_type) { + case SHT_NOBITS: + /* Zero out bss. */ + BZERO(addr, size); + loaded = 1; + break; + case SHT_PROGBITS: + ret = ELFNAMEEND(readfile_global)(fd, offset, + shdr[i].sh_offset, addr, size); + if (ret == -1) { + goto out; + } + loaded = 1; + break; + default: + loaded = 0; + break; + } + + if (loaded) { + shdr[i].sh_offset = addr - elfp; + maxp = addr + size; + } + } + + /* data */ + maxp = roundup(maxp, KERNALIGN); + for (i = 0; i < elf->e_shnum; i++) { + if (!(shdr[i].sh_flags & SHF_WRITE) || + (shdr[i].sh_flags & SHF_EXECINSTR)) { + continue; + } + align = shdr[i].sh_addralign; + if (align == 0) { + align = ELFROUND; + } + addr = roundup(maxp, align); + size = (size_t)shdr[i].sh_size; + + loaded = 0; + switch (shdr[i].sh_type) { + case SHT_NOBITS: + /* Zero out bss. */ + BZERO(addr, size); + loaded = 1; + break; + case SHT_PROGBITS: + ret = ELFNAMEEND(readfile_global)(fd, offset, + shdr[i].sh_offset, addr, size); + if (ret == -1) { + goto out; + } + loaded = 1; + break; + default: + loaded = 0; + break; + } + + if (loaded) { + shdr[i].sh_offset = addr - elfp; + maxp = addr + size; } } /* * Load the SYM+REL SECTIONS. */ - maxp = roundup(maxp, ELFROUND); + maxp = roundup(maxp, KERNALIGN); for (i = 0; i < elf->e_shnum; i++) { addr = maxp; size = (size_t)shdr[i].sh_size;