Understanding Linux's System.map File: The Kernel's Debugging Rosetta Stone.

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_, like sys_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() or EXPORT_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


Happy hacking, and may your symbols always resolve. 🐧🛠️