ksyms is one of those commands that trips people up precisely because it’s mostly gone. If you’ve stumbled across a reference to it in an old book, a legacy script, or a decades-old forum thread, and then typed it into a modern Linux box only to get “command not found,” you’re not doing anything wrong — the tool genuinely doesn’t exist on modern systems anymore. I want to explain exactly what it was, why it disappeared, and what you should actually use today, because that history matters for understanding how the kernel symbol table works in the first place.
What ksyms Actually Was
ksyms was a utility from the old modutils package (the predecessor to today’s module-init-tools and, later, kmod), used on Linux kernels from the 2.0.x/2.2.x/early 2.4.x era. Its job was to print the kernel’s exported symbol table — the list of kernel function and variable names, along with their addresses, that loadable kernel modules are permitted to reference when they’re loaded.
ksyms [options]
It would print output resembling:
c0123456 do_fork
c0123abc printk
c0234567 vfs_read
Each line: a hexadecimal kernel address, and the exported symbol name at that address.
Why It Existed
Back in that era, the kernel exposed this data through a special file, /proc/ksyms, and ksyms was simply a formatting front-end for reading and displaying it — conceptually very similar to how lsmod today is just a formatter for /proc/modules. Module loading tools of that generation (insmod from modutils, specifically) needed to resolve symbol references inside a module against this exported table at load time, and ksyms gave administrators and developers a way to inspect that table directly, which was useful for debugging module load failures (“undefined symbol” errors) and for kernel/driver development work.
Why It’s Gone
Two things happened that made ksyms obsolete:
/proc/ksymswas removed and replaced. As the kernel module subsystem was substantially reworked, the symbol table exposure moved to a new, far more complete file:/proc/kallsyms. This file covers not just exported symbols usable by modules, but the entire kernel symbol table, including static/internal symbols (subject to kernel configuration and, on modern systems, permission restrictions).modutilswas replaced. The wholemodutilspackage (insmod,rmmod,depmod,modprobe,ksymsas it then existed) was superseded first bymodule-init-tools, then by the modernkmodpackage that essentially every current distribution uses.kmod‘s toolset never included aksymsequivalent, because/proc/kallsyms(readable directly withcat, or via companion tools) made a dedicated symbol-dumping command largely redundant.
If you try it on any current distribution:
ksyms
bash: ksyms: command not found
That’s expected — it isn’t packaged anywhere in current Debian, Ubuntu, RHEL, Fedora, SUSE, or Arch repositories.
What to Use Instead Today
/proc/kallsyms — The Direct Modern Equivalent
cat /proc/kallsyms | head
0000000000000000 A fixed_percpu_data
0000000000000000 A __per_cpu_start
0000000000000000 A cpu_debug_store
ffffffff81000000 T startup_64
ffffffff81000040 T secondary_startup_64
Format: address, symbol type letter, symbol name, and (for module-provided symbols) the owning module name in brackets. The type letter follows the same convention as nm:
T/t— a text (code) symbol, global/local respectively.D/d— an initialized data symbol.B/b— an uninitialized (BSS) data symbol.A— an absolute symbol, value won’t change.- Uppercase = globally visible (exported); lowercase = local to that compilation unit.
Searching for a specific kernel function:
grep " do_fork\| vfs_read" /proc/kallsyms
Listing only symbols provided by loaded modules (shown with the module name in brackets):
grep '\[' /proc/kallsyms | head
ffffffffc0912000 t fat_add_new_entry [fat]
ffffffffc0912100 t fat_bmap [fat]
Security Note: kptr_restrict
On most modern, security-conscious systems, /proc/kallsyms addresses are deliberately zeroed out for unprivileged users:
cat /proc/kallsyms | head -3
0000000000000000 T startup_64
0000000000000000 T secondary_startup_64
This is controlled by the kernel.kptr_restrict sysctl:
sysctl kernel.kptr_restrict
kernel.kptr_restrict = 1
- 0 — addresses shown to everyone (legacy, insecure default from older kernels).
- 1 — addresses hidden from unprivileged users, visible to root.
- 2 — addresses hidden from everyone, including root, unless
CAP_SYSLOGis explicitly granted.
This exists specifically because leaking real kernel addresses to unprivileged userspace materially helps attackers bypass kernel ASLR (KASLR) when exploiting kernel vulnerabilities — so what ksyms historically exposed freely and unconditionally is now deliberately access-controlled, which is itself a good example of how Linux kernel security posture has hardened significantly since the ksyms-era tooling was written.
To see real addresses for debugging as root:
sudo cat /proc/kallsyms | grep do_fork
Companion Tools Worth Knowing
nm — for inspecting symbols in an individual, not-yet-loaded module file (equivalent to what modinfo/objdump can also partially show):
nm -D /lib/modules/$(uname -r)/kernel/fs/fat/fat.ko
objdump -t — a lower-level alternative for the same purpose, useful in kernel/driver development contexts:
objdump -t fat.ko | less
/sys/kernel/tracing/available_filter_functions — on kernels with ftrace enabled, this lists functions available for kernel function tracing, a very different but related use case (tracing execution rather than resolving module symbol references).
Real-World Use Cases (Historical and Modern-Equivalent)
Debugging a module load failure with an “unknown symbol” error (modern equivalent):
sudo modprobe my_custom_driver
modprobe: ERROR: could not insert 'my_custom_driver': Unknown symbol in module
dmesg | tail -5
my_custom_driver: Unknown symbol some_kernel_function (err -22)
grep " some_kernel_function$" /proc/kallsyms
If nothing is found, that symbol genuinely isn’t exported by the running kernel — the module was likely built against a different kernel version/config, or references a symbol that’s GPL-only while the module itself isn’t GPL-licensed (see EXPORT_SYMBOL_GPL vs EXPORT_SYMBOL in kernel source).
Kernel/driver development — confirming a function you want to call from a module is actually exported:
grep -w "vfs_read" /proc/kallsyms
If it only appears with lowercase t/d (local) rather than uppercase T/D (global/exported), it isn’t usable from an external module at all, regardless of what ksyms-style inspection shows.
Troubleshooting
“ksyms: command not found” — expected on any current distribution; this command has been removed from all actively maintained package repositories. Use /proc/kallsyms instead, as shown above.
/proc/kallsyms shows all-zero addresses — kernel.kptr_restrict is enabled (the modern default); either run as root, or accept that this is intentional hardening rather than a malfunction.
Symbol appears in a module’s exports but not in /proc/kallsyms — the module providing it isn’t currently loaded; /proc/kallsyms only reflects symbols from modules that are actually loaded right now, plus the core kernel’s built-in symbols.
Comparison to Modern Tools
/proc/kallsyms— the direct functional successor; richer, covers the whole kernel and all loaded modules, not just the exported subset.lsmod— shows loaded modules themselves, not their individual symbols.modinfo— shows a module’s own metadata and dependencies, not the live kernel symbol table.nm/objdump— inspect symbols within an individual.kofile directly, independent of whether it’s currently loaded.crash— a full kernel-crash-analysis utility that, among many other things, can browse kernel symbols interactively against a live system or a crash dump, going far beyond whatksymsever offered.
Summary
ksyms is a genuinely retired command — you won’t find it on any actively maintained Linux distribution, and there’s no reason to install it even if you somehow could. Its job has been fully absorbed by /proc/kallsyms, which is more complete, more current, and — importantly — protected by kptr_restrict against the very real security risk that unrestricted kernel address disclosure represents on a modern, internet-facing system. If you’re maintaining old documentation, scripts, or training material that still references ksyms, it’s worth updating those references to /proc/kallsyms directly.
References
man 5 proc(documents/proc/kallsymsandkptr_restrict)- Linux kernel source:
kernel/kallsyms.c - Linux Kernel Module Programming Guide (kernel.org)
- Historical
modutilspackage documentation/changelogs (Debian and kernel.org archives)
