Resolving Undefined Symbol Errors in Linux Kernel Module Linking: A Step-by-Step Guide

Resolving Undefined Symbol Errors in Linux Kernel Module Linking: A Step-by-Step Guide

When developing Linux kernel modules, developers often encounter undefined symbol errors during the linking phase. This article explains how to resolve such issues through a systematic approach, using generic examples to illustrate key concepts. We'll explore two common solutions: symbol export configuration and header inclusion correction.


Scenario Overview

Imagine two kernel modules:

  1. helper_module: Defines a symbol example_symbol (function/variable)
  2. main_module: Depends on example_symbol from helper_module

During main_module compilation, we encounter:

ERROR: "example_symbol" [main_module.ko] undefined!        

Visual Flow of Module Dependencies

Article content

Problem Analysis

The kernel build system fails to resolve example_symbol because:

  1. Symbol Export Missing: helper_module's symbol information isn't available to main_module
  2. Header Misconfiguration: main_module might not be locating the proper declaration


Solution 1: Exporting Symbols Correctly

Step 1: Verify Symbol Export in Helper Module

helper_module.c should export the symbol:

// Important: Must be in global scope
void example_symbol(void) {
    // Function implementation
}
EXPORT_SYMBOL(example_symbol);        

Step 2: Configure Module.symvers Sharing

The kernel build system generates Module.symvers containing symbol information. main_module needs access to this file from helper_module.

Original (Broken) Makefile:

obj-m += main_module.o        

Fixed Makefile:

obj-m += main_module.o

# Path to helper_module's build directory
KBUILD_EXTRA_SYMBOLS += /path/to/helper_module/Module.symvers
        

Solution 2: Correct Header Inclusion

Step 1: Header File Structure

Ensure proper header organization:

project_root/
├── helper_module/
│   ├── helper_module.h   # Contains example_symbol declaration
│   └── Makefile
└── main_module/
    ├── main_module.c
    └── Makefile        

Step 2: Fix Inclusion Syntax

Original (Problematic):

#include "helper_module.h"   // Looks in local directory only        

Fixed Code:

#include <helper_module.h>   // Searches system include paths        

Step 3: Update Makefile Paths

ccflags-y += -I$(src)/../helper_module        

Complete Workflow Example

  1. Build Helper Module

cd helper_module/
make -C /lib/modules/$(uname -r)/build M=$PWD modules        

  1. Build Main Module

cd ../main_module/
make -C /lib/modules/$(uname -r)/build M=$PWD modules        

Key Concepts Explained

1. Symbol Export System

  • Module.symvers: Database of exported symbols (name, address, module)
  • KBUILD_EXTRA_SYMBOLS: Build directive to include external symbol tables

2. Header Inclusion Types

Article content

Troubleshooting Checklist

  • Verify symbol export with:

nm helper_module.ko | grep example_symbol        

  • Check Module.symvers contains the symbol:

grep example_symbol Module.symvers        

  • Confirm header file paths in build output
  • Ensure build order: helper_module → main_module


Conclusion

Resolving undefined symbol errors in kernel modules requires attention to:

  1. Symbol Visibility: Properly export and share symbol information via Module.symvers
  2. Build System Configuration: Correct Makefile settings for symbol sharing and header paths
  3. Code Organization: Appropriate header inclusion syntax and path management

By following these patterns, developers can effectively manage cross-module dependencies in complex kernel projects.

To view or add a comment, sign in

Others also viewed

Explore topics