From 1a330eb01d1a0f21d5d1a0f0723aeaf12c76f9ac Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Mon, 17 Oct 2005 23:21:55 +0000 Subject: [PATCH] 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. --- sys/kern/link_elf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index d2809082bf34..19317ed3bd3d 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,