summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_elf.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2005-10-17 23:21:55 +0000
committerpeter <peter@FreeBSD.org>2005-10-17 23:21:55 +0000
commitc589af8f29bd5fa9cecda113a097e8149ffc5499 (patch)
treed6da7bdfc7d482f5346ad9862fa6ace2db1f5424 /sys/kern/link_elf.c
parentcba44476d8a593c7e7786fe6081a71d56abf55a4 (diff)
downloadFreeBSD-src-c589af8f29bd5fa9cecda113a097e8149ffc5499.zip
FreeBSD-src-c589af8f29bd5fa9cecda113a097e8149ffc5499.tar.gz
Add support for kernel modules with a single PT_LOAD section.
While here, support up to four sections because it was trivial to do and cheap. (One pointer per section). For amd64 with "-fpic -shared" format .ko files, using a single PT_LOAD section is important to avoid wasting about 1MB of KVM and physical ram for the 'gap' between the two PT_LOAD sections. amd64 normally uses .o format kld files and isn't affected normally. But -fpic -shared modules are actually possible to produce and load... (And with a bugfix to binutils, we can build and use plain -shared .ko files without -fpic) i386 only wastes 4K per .ko file, so that isn't such a big deal there.
Diffstat (limited to 'sys/kern/link_elf.c')
-rw-r--r--sys/kern/link_elf.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index d280908..19317ed 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -62,6 +62,8 @@ __FBSDID("$FreeBSD$");
#include "linker_if.h"
+#define MAXSEGS 4
+
typedef struct elf_file {
struct linker_file lf; /* Common fields */
int preloaded; /* Was file pre-loaded */
@@ -536,7 +538,7 @@ link_elf_load_file(linker_class_t cls, const char* filename,
int nbytes, i;
Elf_Phdr *phdr;
Elf_Phdr *phlimit;
- Elf_Phdr *segs[2];
+ Elf_Phdr *segs[MAXSEGS];
int nsegs;
Elf_Phdr *phdyn;
Elf_Phdr *phphdr;
@@ -643,7 +645,7 @@ link_elf_load_file(linker_class_t cls, const char* filename,
switch (phdr->p_type) {
case PT_LOAD:
- if (nsegs == 2) {
+ if (nsegs == MAXSEGS) {
link_elf_error("Too many sections");
error = ENOEXEC;
goto out;
@@ -676,8 +678,8 @@ link_elf_load_file(linker_class_t cls, const char* filename,
error = ENOEXEC;
goto out;
}
- if (nsegs != 2) {
- link_elf_error("Too few sections");
+ if (nsegs == 0) {
+ link_elf_error("No sections");
error = ENOEXEC;
goto out;
}
@@ -688,7 +690,8 @@ link_elf_load_file(linker_class_t cls, const char* filename,
*/
base_offset = trunc_page(segs[0]->p_offset);
base_vaddr = trunc_page(segs[0]->p_vaddr);
- base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz);
+ base_vlimit = round_page(segs[nsegs - 1]->p_vaddr +
+ segs[nsegs - 1]->p_memsz);
mapsize = base_vlimit - base_vaddr;
lf = linker_make_file(filename, &link_elf_class);
@@ -726,7 +729,7 @@ link_elf_load_file(linker_class_t cls, const char* filename,
/*
* Read the text and data sections and zero the bss.
*/
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < nsegs; i++) {
caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr;
error = vn_rdwr(UIO_READ, nd.ni_vp,
segbase, segs[i]->p_filesz, segs[i]->p_offset,
OpenPOWER on IntegriCloud