Bug 291273 - p9fs module missing symbol exports -- dependent modules fail to load with module loader local symbol resolution disabled
Summary: p9fs module missing symbol exports -- dependent modules fail to load with mod...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 16.0-CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks: 207898
  Show dependency treegraph
 
Reported: 2025-11-28 18:17 UTC by Ed Maste
Modified: 2025-12-04 16:51 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Maste freebsd_committer freebsd_triage 2025-11-28 18:17:42 UTC
See https://lists.freebsd.org/archives/freebsd-current/2025-November/009500.html for background.

To reproduce, set
debug.link_elf_leak_locals=0
debug.link_elf_obj_leak_locals=0
then

# kldload virtio_p9fs.ko
link_elf_obj: symbol p9_init_zones undefined
linker_load_file: /boot/kernel/virtio_p9fs.ko - unsupported file type
kldload: an error occurred while loading module virtio_p9fs.ko. Please check dmesg(8) for more details.

The module's Makefile should have an EXPORT_SYMS= line that lists all of the symbols to be intentionally exported.

Another option is to just set EXPORT_SYMS=YES.  An explicit export list is preferred over EXPORT_SYMS=YES, unless we actually want all symbols exported.
Comment 1 Ed Maste freebsd_committer freebsd_triage 2025-11-30 20:01:56 UTC
We can find the symbols needed by virtio_p9fs.ko with something like

% nm obj/virtio_p9fs.ko | sed -n 's/^.* U U//p' | sort > undef.syms
% nm /boot/kernel/kernel | sed -n 's/^.* T //p' | sort > kernel.syms
% comm -23 undef.syms kernel.syms

The p9 symbols this reveals are:

p9_debug_level
p9_destroy_zones
p9_init_zones
p9_register_trans
Comment 2 Rupesh Pilania 2025-12-02 17:16:26 UTC
I’ve tested the fixes by disabling symbol-leak suppression (debug.link_elf_leak_locals=0 and debug.link_elf_obj_leak_locals=0) to ensure unresolved symbols become visible. With the updated EXPORT_SYMS entries added to sys/modules/p9fs/Makefile, both modules now load successfully without any undefined symbol errors.

Patch Used:
diff --git a/sys/modules/p9fs/Makefile b/sys/modules/p9fs/Makefile
index ae90cb3a46d7..08a5b3ec0fa2 100644
--- a/sys/modules/p9fs/Makefile
+++ b/sys/modules/p9fs/Makefile
@@ -5,4 +5,10 @@ SRCS=  vnode_if.h \
        p9_client.c p9_protocol.c p9_transport.c \
        p9fs_subr.c p9fs_vfsops.c p9fs_vnops.c

+ EXPORT_SYMS=  \
+        p9_debug_level \
+        p9_destroy_zones \
+        p9_init_zones \
+        p9_register_trans
+
 .include <bsd.kmod.mk>

Test Logs:

root@freebsd16:~ # cat /boot/loader.conf
debug.link_elf_leak_locals=0
debug.link_elf_obj_leak_locals=0
root@freebsd16:~ # sysctl debug.link_elf_leak_locals
debug.link_elf_leak_locals: 0
root@freebsd16:~ # sysctl debug.link_elf_obj_leak_locals
debug.link_elf_obj_leak_locals: 0
root@freebsd16:~ # kldstat
Id Refs Address                Size Name
 1    8 0xffffffff80200000  2126750 kernel
 2    1 0xffffffff82d10000     3220 intpm.ko
 3    1 0xffffffff82d14000     2178 smbus.ko
 4    1 0xffffffff82d17000     2a80 mac_ntpd.ko
root@freebsd16:~ # kldload /boot/kernel/virtio_p9fs.ko
root@freebsd16:~ # kldstat
Id Refs Address                Size Name
 1   14 0xffffffff80200000  2126750 kernel
 2    1 0xffffffff82d10000     3220 intpm.ko
 3    1 0xffffffff82d14000     2178 smbus.ko
 4    1 0xffffffff82d17000     2a80 mac_ntpd.ko
 5    1 0xffffffff82d1a000     24e0 virtio_p9fs.ko
 6    1 0xffffffff82d1d000     a888 p9fs.ko

Both virtio_p9fs.ko and p9fs.ko now load without reporting undefined symbols.
Comment 3 Ed Maste freebsd_committer freebsd_triage 2025-12-04 16:51:12 UTC
Some developers have expressed a desire to avoid using per-symbol export lists and generally use EXPORT_SYMS=YES, possibly adding missing `static` declarations where necessary. I took a look at this module with that in mind:

With the four explicit EXPORT_SYMS, as expected `readelf -s | grep GLOBAL | grep -v UND` reports:
 
   159: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    10 p9_debug_level
   169: 00000000000008b0   132 FUNC    GLOBAL DEFAULT     1 p9_init_zones
   171: 0000000000000940    41 FUNC    GLOBAL DEFAULT     1 p9_destroy_zones
   186: 00000000000036d0    34 FUNC    GLOBAL DEFAULT     1 p9_register_trans

With EXPORT_SYMS=YES many symbols are GLOBAL:

    98: 0000000000000000    15 FUNC    GLOBAL DEFAULT     1 p9_is_proto_dotl
    99: 0000000000000010    15 FUNC    GLOBAL DEFAULT     1 p9_is_proto_dotu
   100: 0000000000000020    59 FUNC    GLOBAL DEFAULT     1 p9_client_disconnect
   101: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    10 p9_debug_level
   103: 0000000000000060    59 FUNC    GLOBAL DEFAULT     1 p9_client_begin_disconnect
   104: 00000000000000a0    72 FUNC    GLOBAL DEFAULT     1 p9_tag_create
   106: 00000000000000f0    68 FUNC    GLOBAL DEFAULT     1 p9_tag_destroy
   108: 0000000000000140   130 FUNC    GLOBAL DEFAULT     1 p9_fid_create
   111: 00000000000001d0    80 FUNC    GLOBAL DEFAULT     1 p9_fid_destroy
   112: 0000000000000220   364 FUNC    GLOBAL DEFAULT     1 p9_client_version
   113: 0000000000002ae0  2561 FUNC    GLOBAL DEFAULT     1 p9_buf_readf
   116: 0000000000003560    35 FUNC    GLOBAL DEFAULT     1 p9_buf_prepare
   117: 00000000000020f0  2452 FUNC    GLOBAL DEFAULT     1 p9_buf_vwritef
   118: 0000000000003590    93 FUNC    GLOBAL DEFAULT     1 p9_buf_finalize
   121: 00000000000008b0   132 FUNC    GLOBAL DEFAULT     1 p9_init_zones
   123: 0000000000000940    41 FUNC    GLOBAL DEFAULT     1 p9_destroy_zones
   125: 0000000000000970   461 FUNC    GLOBAL DEFAULT     1 p9_client_create
   130: 0000000000003730    64 FUNC    GLOBAL DEFAULT     1 p9_get_trans_by_name
   132: 0000000000000b40   160 FUNC    GLOBAL DEFAULT     1 p9_client_destroy
   134: 0000000000000be0   498 FUNC    GLOBAL DEFAULT     1 p9_client_attach
   135: 0000000000000de0   141 FUNC    GLOBAL DEFAULT     1 p9_client_remove
   136: 0000000000000e70   124 FUNC    GLOBAL DEFAULT     1 p9_client_unlink
   137: 0000000000000ef0   249 FUNC    GLOBAL DEFAULT     1 p9_client_clunk
   138: 0000000000000ff0   766 FUNC    GLOBAL DEFAULT     1 p9_client_walk
   139: 00000000000012f0   316 FUNC    GLOBAL DEFAULT     1 p9_client_open
   140: 0000000000001430   345 FUNC    GLOBAL DEFAULT     1 p9_client_readdir
   142: 0000000000001590   460 FUNC    GLOBAL DEFAULT     1 p9_client_read
   143: 0000000000001760   454 FUNC    GLOBAL DEFAULT     1 p9_client_write
   144: 0000000000001930   279 FUNC    GLOBAL DEFAULT     1 p9_client_file_create
   145: 0000000000001a50   300 FUNC    GLOBAL DEFAULT     1 p9_client_statfs
   146: 0000000000001b80   155 FUNC    GLOBAL DEFAULT     1 p9_client_renameat
   147: 0000000000001c20   256 FUNC    GLOBAL DEFAULT     1 p9_create_symlink
   148: 0000000000001d20   144 FUNC    GLOBAL DEFAULT     1 p9_create_hardlink
   149: 0000000000001db0   213 FUNC    GLOBAL DEFAULT     1 p9_readlink
   150: 0000000000001e90   394 FUNC    GLOBAL DEFAULT     1 p9_client_getattr
   151: 0000000000002020   193 FUNC    GLOBAL DEFAULT     1 p9_client_setattr
   154: 0000000000000140   112 OBJECT  GLOBAL DEFAULT     4 sysctl___vfs_p9fs
   158: 00000000000034f0    97 FUNC    GLOBAL DEFAULT     1 p9stat_read
   159: 00000000000035f0    20 FUNC    GLOBAL DEFAULT     1 p9_buf_reset
   160: 0000000000003610   181 FUNC    GLOBAL DEFAULT     1 p9_dirent_read
   162: 00000000000036d0    34 FUNC    GLOBAL DEFAULT     1 p9_register_trans
   163: 0000000000000020    16 OBJECT  GLOBAL DEFAULT    10 transports
   164: 0000000000003700    37 FUNC    GLOBAL DEFAULT     1 p9_unregister_trans
   166: 0000000000003790    12 FUNC    GLOBAL DEFAULT     1 p9fs_proto_dotl
   167: 00000000000037a0   551 FUNC    GLOBAL DEFAULT     1 p9fs_init_session
   169: 00000000000039d0   104 FUNC    GLOBAL DEFAULT     1 p9fs_prepare_to_close
   171: 0000000000003a40    24 FUNC    GLOBAL DEFAULT     1 p9fs_complete_close
   172: 0000000000003a60    95 FUNC    GLOBAL DEFAULT     1 p9fs_close_session
   174: 0000000000003ac0   225 FUNC    GLOBAL DEFAULT     1 p9fs_fid_remove_all
   175: 0000000000003bb0   276 FUNC    GLOBAL DEFAULT     1 p9fs_fid_remove
   178: 0000000000003cd0   176 FUNC    GLOBAL DEFAULT     1 p9fs_fid_add
   179: 0000000000003d80   914 FUNC    GLOBAL DEFAULT     1 p9fs_get_fid
   182: 0000000000004250   153 FUNC    GLOBAL DEFAULT     1 p9fs_dispose_node
   183: 00000000000042f0    62 FUNC    GLOBAL DEFAULT     1 p9fs_node_cmp
   184: 0000000000004330    55 FUNC    GLOBAL DEFAULT     1 p9fs_destroy_node
   185: 0000000000004370  1172 FUNC    GLOBAL DEFAULT     1 p9fs_vget_common
   187: 0000000000004fd0   261 FUNC    GLOBAL DEFAULT     1 p9fs_reload_stats_dotl
   190: 0000000000000480   680 OBJECT  GLOBAL DEFAULT     4 p9fs_vnops
   204: 0000000000000040     8 OBJECT  GLOBAL DEFAULT    10 p9fs_getattr_zone
   205: 0000000000000048     8 OBJECT  GLOBAL DEFAULT    10 p9fs_setattr_zone
   208: 0000000000000050     8 OBJECT  GLOBAL DEFAULT    10 p9fs_pbuf_zone
   209: 0000000000000038     8 OBJECT  GLOBAL DEFAULT    10 p9fs_io_buffer_zone
   211: 00000000000001f0   208 OBJECT  GLOBAL DEFAULT     4 p9fs_vfsops
   214: 0000000000004ea0   303 FUNC    GLOBAL DEFAULT     1 p9fs_cleanup
   217: 00000000000050e0   263 FUNC    GLOBAL DEFAULT     1 p9fs_stat_vnode_dotl

Will update again here after more discussion