When working with the Linux kernel — especially during custom development, module programming, or debugging kernel crashes — you’ll likely encounter a mysterious file named System.map. While it may seem cryptic at first glance, this file is an essential debugging tool. In this post, we’ll demystify it.
🧠 What is System.map
?
System.map
is a symbol table for the Linux kernel. It contains a list of all symbols (functions, global variables, etc.) used or exported by the kernel, along with their memory addresses.
It’s generated during the kernel build process and can be thought of as a “map” from memory addresses to human-readable names — which is incredibly helpful when you’re dealing with kernel panics or oops messages that spit out raw hexadecimal addresses.
📦 What Does It Contain?
✅ 1. System Calls
- Functions prefixed with
sys_
, likesys_read
,sys_open
,sys_exit
. - These are entry points from user space into the kernel.
✅ 2. Internal Kernel Functions
- Non-exported helpers used throughout the kernel but not exposed as syscalls.
- Example:
do_fork
,schedule
,do_exit
.
✅ 3. Device Driver Functions
- These may be built-in or loaded as modules.
- You’ll find names like
e1000e_probe
,snd_pcm_open
, etc.
✅ 4. Global Variables & Data Structures
- Includes important kernel-wide symbols like
init_task
,jiffies
,current
.
✅ 5. Exported Symbols for Modules
- Functions or variables marked with
EXPORT_SYMBOL()
orEXPORT_SYMBOL_GPL()
so that modules can use them.
📄 File Format
Each line in System.map
typically looks like this:
c010b860 T start_kernel
c01dfabc t local_bh_enable
c043ae20 D jiffies
c045fc84 B init_task
Column | Description |
---|---|
Address | The virtual memory address of the symbol in hex. |
Symbol Type | A single letter denoting symbol type (see below). |
Symbol Name | The name of the function, variable, or data object. |
🔤 Symbol Types
Symbol | Meaning |
---|---|
T/t |
Text (code) section — global/local |
D/d |
Initialized data — global/local |
B/b |
Uninitialized data (BSS) |
R/r |
Read-only data |
A |
Absolute symbol |
U |
Undefined — not yet linked |
🧰 Where Is It Located?
🔨 During Compilation
After building the kernel:
~/linux-<version>/System.map
📁 On Installed Systems
After make install
or distro-level install:
/boot/System.map-<kernel-version>
🧪 Why Is System.map Useful?
🚨 Debugging Kernel Panics
When the kernel crashes, you’ll often see a kernel oops message with raw addresses:
EIP: [<c010b860>] ⟶ BAD RIP VALUE
You can translate this using System.map
:
grep c010b860 /boot/System.map-$(uname -r)
c010b860 T start_kernel
Boom — now you know the crash occurred in start_kernel()
!
🔍 Reverse Lookup by Function Name
grep schedule /boot/System.map-$(uname -r)
🧑💻 Kernel Module Development
grep my_exported_function System.map
This tells you if a function is:
- Defined
- Exported
- Resolved during module loading
🔍 /proc/kallsyms
vs. System.map
Feature | /proc/kallsyms |
System.map |
---|---|---|
Dynamic | ✅ Yes | ❌ No (static at build) |
Includes Loaded Modules | ✅ Yes | ❌ No |
Human-readable? | ✅ Yes | ✅ Yes |
Root required? | ✅ Usually | ❌ No |
Live kernel data? | ✅ Yes | ❌ No |
🧠 Think of
System.map
as a build-time snapshot, while/proc/kallsyms
is live and reflects the current kernel state.
🔐 Permissions Note
/proc/kallsyms
may hide kernel symbols unless you have root access or enable:
echo 0 > /proc/sys/kernel/kptr_restrict
⚙️ Rebuilding & Matching Versions
⚠️ Very important: System.map
must match the exact kernel binary you’re analyzing.
Why?
- Address offsets shift due to config changes, compiler versions, link order, etc.
- Using the wrong map = totally wrong conclusions!
🧭 Conclusion
System.map
is a powerful tool for:
- Decoding kernel crashes
- Locating functions and variables
- Understanding symbol visibility
- Kernel module development
It’s your kernel symbol GPS — don’t navigate without it!
📚 Further Reading
- Linux Kernel Docs: Kernel Debugging
man ksymoops
/proc/kallsyms
documentation
Happy hacking, and may your symbols always resolve. 🐧🛠️