Re: Link modules to DYN type
- In reply to: Zhenlei Huang : "Re: Link modules to DYN type"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 04 May 2023 10:11:06 UTC
> On Apr 28, 2023, at 12:32 AM, Zhenlei Huang <zlei@FreeBSD.org> wrote: > > > >> On Apr 26, 2023, at 7:12 PM, Konstantin Belousov <kostikbel@gmail.com <mailto:kostikbel@gmail.com>> wrote: >> >> On Wed, Apr 26, 2023 at 12:55:02PM +0200, Hans Petter Selasky wrote: >>> On 4/26/23 12:36, Zhenlei Huang wrote: >>>> Hi, >>>> >>>> I'm recently working on https://reviews.freebsd.org/D39638 <https://reviews.freebsd.org/D39638> (sysctl(9): Enable vnet sysctl variables be loader tunable), >>>> the changes to `sys/kern/link_elf_obj.c` are runtime tested, but not those to `sys/kern/link_elf.c` . >>>> >>>> After some hacking I realized that `link_elf.c` is for EXEC (Executable file) or DYN (Shared object file), and `link_elf_obj.c` is >>>> for REL (Relocatable file). >>>> >>>> ``` >>>> /* link_elf.c */ >>>> static int >>>> link_elf_load_file(linker_class_t cls, const char* filename, >>>> linker_file_t* result) >>>> { >>>> ... >>>> if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { >>>> error = ENOSYS; >>>> goto out; >>>> } >>>> ... >>>> } >>>> >>>> >>>> /* link_elf_obj.c */ >>>> static int >>>> link_elf_load_file(linker_class_t cls, const char *filename, >>>> linker_file_t *result) >>>> { >>>> ... >>>> if (hdr->e_type != ET_REL) { >>>> error = ENOSYS; >>>> goto out; >>>> } >>>> ... >>>> } >>>> ``` >>>> >>>> Run the following snip: >>>> ``` >>>> # find /boot/kernel -type f -name "*.ko" -exec readelf -h {} \; | grep Type >>>> ``` >>>> shows that all the kernel modules' types are `REL (Relocatable file)`. >>>> >>>> I guess if some module such as if_bridge is linked to DYN type, then I can do runtime for the changes to `sys/kern/link_elf.c`. >>>> >>>> I'm not familiar with elf and linkers, is that ( compile module and link it to DYN type ) possible ? >> >> Module file type (shared object vs. object file) depends on architecture. >> For amd64 modules are objects, while kernel is shared library. >> For arm64 (and all other arches, I believe) modules and kernels are shared >> libraries. >> >> I think you can link amd64 module as shared object, but this require enough >> hacking of the build infrastructure. At least I am not aware of a simple >> knob to switch the produced type. > > I did some hack on `sys/conf/kmod.mk` and finally produced DYN kernel modules. > The good news is I do some basic sysctl tests, but the bad news is the module does not function correctly. > > For exampe the if_disc.c > > ``` > static void > vnet_disc_init(const void *unused __unused) > { > /* Reference V_disc_cloner will immediately trigger page fault panic */ > V_disc_cloner = if_clone_simple(discname, disc_clone_create, > disc_clone_destroy, 0); > } > VNET_SYSINIT(vnet_disc_init, SI_SUB_PSEUDO, SI_ORDER_ANY, > vnet_disc_init, NULL); > ``` > > I suspect the relocation is not done correctly for DYN elf kmod on amd64. > > My local patch to kmod.mk: > > ``` > diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk > index 134b150af1d9..1fc5386204a5 100644 > --- a/sys/conf/kmod.mk > +++ b/sys/conf/kmod.mk > @@ -84,6 +84,7 @@ __KLD_SHARED=yes > .else > __KLD_SHARED=no > .endif > +__KLD_SHARED=yes > > .if !empty(CFLAGS:M-O[23s]) && empty(CFLAGS:M-fno-strict-aliasing) > CFLAGS+= -fno-strict-aliasing > @@ -167,6 +168,7 @@ CFLAGS+= -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer > ${MACHINE_CPUARCH} == "powerpc" > CFLAGS+= -fPIC > .endif > +CFLAGS+= -fPIC > > # Temporary workaround for PR 196407, which contains the fascinating details. > # Don't allow clang to use fpu instructions or registers in kernel modules. > ``` > > > As for https://reviews.freebsd.org/D39638 <https://reviews.freebsd.org/D39638>, for other platform such as arm, I think the `link_elf_propagate_vnets()` should work if `parse_vnet()` works. > > I'll appreciate if someone can test it on platforms those have DYN type kernel modules. Good news on this! I've managed to test the change for `link_elf.c` on QEMU RISCV . It works as expected and solid ! > >> >> >>>> >>> >>> Hi, >>> >>> I don't have an answer for you either, but I have seen in the past, loading >>> kernel modules behaves a bit like libraries, in the following regard: >>> >>> If two kernel modules define the same global symbol, then no warning is >>> given and the first loaded symbol definition (I think) is used to resolve >>> that symbol for all kernel modules, regardless of the prototype. Probably we >>> should not allow this. That's why building LINT is a good thing, to avoid >>> this issue. >> No, in-kernel linker does not behave this way. >> Modules need to contain explicit reference to all modules they depend upon, >> using the MODULE_DEPEND() macro. Only symbols from the dependencies are >> resolved. >> >> All modules get an implicit reference to kernel. >> >>> >>> Even if we don't have C++ support in the FreeBSD kernel, defining symbol >>> names the way C++ does for C could be nice for the kernel too, also with >>> regards to debugging systems. >>> >>> Many times when I don't know what is going on, I do like this: >>> >>> #include <sys/kdb.h> >>> >>> .... >>> >>> if (not too fast or my sysctl debug) { >>> printf("My tracer\n"); >>> kdb_backtrace(); >>> } >>> >>> Dtrace can also do this, but not during boot. Just track who is calling >>> those functions, and you'll probably find the answer to your question! >>> >>> --HPS >>> >>>> >>>> Best regards, >>>> Zhenlei