0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

(信息量有点大)基于RK3576深入解读kernel-6.1/System.map:内核开发调试的“地址-功能”导航图

jf_44130326 来源:Linux1024 2026-02-04 16:18 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

Linux内核开发与调试场景中,你是否遇到过这些困惑?内核panic时打印的pc: ffffffc00801c400究竟对应哪个函数?编写模块时引用的foo符号为何提示未定义?优化内核时如何判断某个功能是否被编译进去?

答案都藏在kernel-6.1/System.map——它不是内核代码,却是连接机器地址人类可读功能的核心桥梁,是kernel开发者调试字典开发指南针

本文将从以下5个维度,带你吃透kernel-6.1 System.map的价值,让内核开发调试效率翻倍:

1.本质定位:System.map是什么?kernel-6.1中的结构如何解读?

2.核心知识点:符号类型、地址空间、内核段关联的底层逻辑(附kernel-6.1实例)

3.调试实战:查看该文件能解决哪些痛点?(Oops定位、栈回溯等案例)

4.开发意义:对模块编写、内核裁剪、版本兼容的实际帮助

5.流程可视化:用流程图梳理实战场景(崩溃调试、模块开发)

一、System.map本质:kernel-6.1地址-符号映射字典

kernel-6.1/System.map是内核编译过程中由链接器ld生成的符号表文件,核心作用是将内核运行时的虚拟地址可读符号(函数/变量)建立映射。

它就像内核的身份证系统”——每个符号(如函数die、变量jiffies_64)都有唯一的地址身份证,开发者通过地址查符号,就能快速定位功能归属。

1.1生成路径与核心作用

默认路径kernel-6.1编译后,默认存放在kernel-6.1/System.map

核心价值

破解地址黑盒:将Oops/panic打印的虚拟地址(如ffffffc00801c400)翻译成可读符号(如die);

验证符号有效性:判断模块引用的符号是否存在、是否可导出(如T类型符号可被外部调用);

反推内核配置:通过符号是否存在,判断功能是否编译(如smp_send_reschedule存在开启SMP)。

1.2 kernel-6.1符号结构解析(一行看懂)

System.map的每一行都遵循固定格式,以kernel-6.1ffffffc00801c400 T die为例,拆解3个关键字段:

字段

示例值

说明(结合kernel-6.1

虚拟地址

ffffffc00801c400

符号在内存中的虚拟地址(ARM64内核地址多以ffffffc0开头,用户空间地址以00000000开头)

符号类型

T

区分符号属性:大写为全局符号(可被外部模块引用),小写为局部符号(仅内核内部使用)

符号名

die

可读符号名(diekernel-6.1中内核崩溃的核心处理函数,定义在kernel/exit.c

1.3 kernel-6.1常见符号类型对照表

符号类型直接反映符号的归属段(代码段/数据段)和可见性kernel-6.1中高频出现的类型如下:

符号类型

含义

kernel-6.1实例

对应内核段

T

全局代码段符号(可导出)

T _text(内核代码段起始地址)

.text(代码段)

t

局部代码段符号(仅内部使用)

t __bad_stack(异常栈处理函数)

.text(代码段)

A

绝对符号(地址编译时固定)

A PECOFF_FILE_ALIGNMENTPECOFF对齐值)

绝对段

W

弱符号(可被重定义)

W calibrate_delay_is_known(延迟校准标志)

.data(数据段)

B

全局数据段符号(已初始化)

B jiffies_64(系统滴答计数器)

.data(数据段)

二、必须掌握的4个核心知识点(结合kernel-6.1

看懂System.map不只是查地址,更要通过符号反推kernel-6.1内存布局、功能模块、配置状态——这才是它的深层价值。

2.1符号类型内核段归属:快速定位功能区域

kernel-6.1的内存被划分为多个功能段,符号类型+地址范围可直接判断归属,帮你快速定位功能场景:

代码段(.textT/t类型符号的聚集地,存放内核所有执行函数,例如:

T _textffffffc008000000):kernel-6.1代码段起始地址,内核启动后第一个执行的代码段;

T __irqentry_text_start~T __irqentry_text_end:中断入口代码段,包含gic_handle_irqARM64 GIC中断处理函数);

T vectorsffffffc008010800):ARM64异常向量表,是内核处理中断、系统调用、异常的入口网关

wKgZO2kamRaAV4NhAACyZI2JQ5Q148.png

数据段(.dataW/B类型符号所在,存放已初始化的全局变量,例如:

W calibration_delay_done:延迟校准完成标志,内核启动时用于判断是否跳过校准流程;

B jiffies_64:系统滴答计数器,记录内核运行时间,是定时器、调度的核心变量。

绝对段A类型符号,地址编译时固定,不随内存布局变化,例如A _kernel_size_le_lo32kernel-6.1内核大小低32位)。

2.2 ARM64地址空间符号的居住区域

kernel-6.1ARM64架构)的符号地址主要分两类,对应Linux内核的地址空间隔离设计:

1.内核虚拟地址(ffffffc0开头)

示例:ffffffc00801c400 T die(崩溃处理)、ffffffc008010628 T __entry_text_start(系统调用入口段起始);

特点:与用户空间地址(00000000~ffff0000)完全隔离,保障内核安全性,仅内核态可访问。

1.早期/特定段地址(00000000开头)

示例:00000000 A _kernel_flags_le_hi32(内核标志高32位)、00000000 A __pecoff_data_rawsizePECOFF数据原始大小);

特点:地址编译时固定,多用于内核早期启动(如EFI stub初始化)或文件格式相关(PECOFFWindows可执行文件格式,内核用于兼容引导)。

2.3符号名内核子系统映射:一眼识别功能

kernel-6.1的符号名遵循功能前缀规则,通过符号名可直接对应内核子系统,减少查源码的时间:

内核子系统

符号名前缀/关键词

kernel-6.1实例

功能说明

中断处理

gic_irq_do_undef

t gic_handle_irqT do_undefinstr

GIC中断处理、未定义指令异常处理

进程调度

sched_cpu_switch

T cpu_switch_tot pick_next_task_fair

进程切换、CFS调度器选任务

内存管理

pgd_do_page_fault

T pgd_alloct do_page_fault

页表分配、页错误处理

系统调用

__arm64_sys_

T __arm64_sys_mmapT __arm64_sys_exit

ARM64架构的mmap/exit系统调用

EFI引导

__efistub_efi_

A __efistub_primary_entry_offset

EFI stub启动入口偏移量

2.4符号存在性内核配置判断

kernel-6.1中某个符号是否存在,直接反映内核编译时的配置(.config):

若存在T smp_send_reschedule开启CONFIG_SMP(对称多处理器);

若存在T __arm64_sys_fanotify_init开启CONFIG_FANOTIFY(文件系统事件通知);

若不存在t has_no_fpsimd开启CONFIG_FPSIMDARM64浮点/向量支持)。

这对内核裁剪优化非常有用:若不需要SMP功能,编译时关闭CONFIG_SMPsmp_send_reschedule等符号会消失,减少内核体积。

三、调试时关注System.map:解决4大核心痛点

kernel-6.1调试中,System.map效率工具”——没有它,你可能需要花几小时猜地址;有了它,几分钟就能定位问题。

3.1 Oops崩溃定位:从地址到函数的一秒翻译

内核Oops是最常见的调试场景,例如打印:

Oops:0000000000000005[#1] PREEMPT SMPPCisat ffffffc00801c400

此时查System.map即可快速定位:

1.打开kernel-6.1/System.map,搜索ffffffc00801c400

2.找到对应行:ffffffc00801c400 T die确认崩溃发生在die函数;

3.查看die源码(kernel/exit.c),结合Oops上下文(如寄存器值、调用链),判断是空指针访问还是非法内存地址

wKgZO2kamRaARWZwAAAGXTTy754087.png

流程图

wKgZO2kamRaAVFHBAACEPmNZadc777.jpg


3.2内核恐慌栈回溯:补全函数调用链

当内核panic打印栈回溯(Backtrace)时,会输出一串函数地址,例如:

Backtrace:ffffffc00801c400 → ffffffc00801c680 → ffffffc00801d8e0

通过System.map翻译地址:

ffffffc00801c400 → die(崩溃处理);

ffffffc00801c680 → arm64_force_sig_fault(强制发送信号);

ffffffc00801d8e0 → do_serror(系统错误处理)。

瞬间补全调用链:do_serrorarm64_force_sig_faultdie,快速定位错误传播路径。

wKgZO2kamRaAcEztAAAqGb7Xe_E678.png

3.3模块开发符号验证:避免未定义引用

编写kernel-6.1内核模块时,若引用foo函数却提示“undefined reference tofoo,可通过System.map排查:

1.搜索foo符号:

若不存在内核未编译foo对应的功能,需开启相关配置(如CONFIG_FOO=y);

若存在但类型为tfoo是局部符号(仅内核内部使用),无法被模块引用,需修改内核源码将foo导出(添加EXPORT_SYMBOL(foo));

若存在且类型为Tfoo是全局符号,模块中声明extern int foo();即可正常编译。

3.4性能分析地址翻译:perf采样结果落地

perf record -g采样内核性能时,结果会包含大量地址,例如:

Samples:100 of event 'cycles', Event count (approx.):123456ffffffc0080164a420%ffffffc0080165d015%

通过System.map翻译:

ffffffc0080164a4 T cpu_switch_to(进程切换);

ffffffc0080165d0 T fpsimd_thread_switch(浮点上下文切换)。

wKgZO2kamRaAP-v3AAAcv-M-hzQ565.png

可快速判断性能瓶颈在进程切换,进而优化调度策略。

四、对开发的意义:从试错精准

kernel-6.1/System.map不只是调试工具,更是kernel开发的正确性保障效率加速器

4.1提升内核调试效率

没有System.map时,调试需通过addr2line工具(需带调试信息的内核镜像vmlinux),且依赖内核编译时保留调试符号;有了System.map,直接查地址符号,无需额外工具,尤其适合无调试信息的release版本内核。

4.2保障模块开发正确性

kernel-6.1模块开发中,符号引用错误是常见问题(如引用不存在的符号、引用局部符号)。System.map可提前验证符号有效性,避免模块加载时因符号未定义被内核拒绝(insmod: ERROR: could not insert module xxx.ko: Unknown symbol in module)。

模块开发流程图

wKgZO2kamReADQXGAACng1Nxtrc619.png

4.3辅助内核裁剪与优化

kernel-6.1支持按需裁剪功能,System.map可验证裁剪效果:

若不需要EFI引导,关闭CONFIG_EFI后,__efistub_前缀的符号会消失,说明裁剪成功;

若不需要浮点支持,关闭CONFIG_FPSIMD后,fpsimd_前缀的符号会消失,减少内核体积。

4.4验证版本兼容性

不同内核版本(如kernel-6.1kernel-6.2)的符号地址可能变化,若模块硬编码地址,会导致加载失败。通过对比System.map

foo符号在kernel-6.1中地址为ffffffc0080164a4,在kernel-6.2中为ffffffc008016500,说明地址偏移,需修改模块为符号引用而非地址硬编码

五、总结:System.mapkernel-6.1开发的基础设施

kernel-6.1/System.map看似是简单的地址-符号列表,实则是内核的功能导航图”——它连接了机器可识别的地址与人类可理解的功能,解决了调试中的地址黑盒问题,保障了开发中的符号正确性

无论是内核崩溃定位、模块开发,还是性能优化、版本兼容,System.map都能帮你从盲目试错转向精准操作,是 linux开发者必须掌握的核心工具。

下次遇到内核问题时,先打开System.map——它或许能帮你省下几小时的调试时间。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    4

    文章

    1475

    浏览量

    43089
  • 开发调试
    +关注

    关注

    0

    文章

    7

    浏览量

    8319
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于RK3576开发板的PWN使用说明

    RK3576开发板使用PWN教程及Demo
    的头像 发表于 05-07 14:07 2490次阅读
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>开发</b>板的PWN使用说明

    基于RK3576开发板的RTC使用说明

    文章主要展示RK3576开发板的RTC信息和快速上手例程
    的头像 发表于 05-07 15:04 2552次阅读
    基于<b class='flag-5'>RK3576</b><b class='flag-5'>开发</b>板的RTC使用说明

    如何移植EtherCAT Igh--基于米尔RK3576开发

    本文将介绍基于米尔电子MYD-LR3576开发板(米尔基于瑞芯微RK3576开发板)的板端移植EtherCATIgh方案的开发测试。摘自优秀
    的头像 发表于 09-26 08:04 1w次阅读
    如何移植EtherCAT Igh--基于米尔<b class='flag-5'>RK3576</b><b class='flag-5'>开发</b>板

    RK3576 Android 14.0 SDK开发指南(第一集)

    kernelkernel源码在工程中kernel-6.1目录下 Lunch项说明 一键编译命令 ./build.sh -UKAupSoc RK3576 SDK默认没有开启GK
    发表于 05-20 08:43

    RK3576 vs RK3588:为何越来越多的开发者转向RK3576

    瑞芯微(Rockchip)最新发布的 RK3576 一经推出,就吸引了大量原本关注 RK3588 的开发者。RK3588 作为旗舰级芯片,性能固然强大,但
    发表于 05-30 08:46

    【米尔RK3576开发板免费体验】3、移植EtherCAT Igh

    6.1.75,将文件夹中的Kernel-6.1下的补丁应用到内核配置中。 cd /path/to/kernel-6.1/ patch中存在重定义问题 serial8250_set_IER
    发表于 07-21 10:35

    【作品合集】米尔RK3576开发板测评

    米尔RK3576开发板测评作品合集 产品介绍: RK3576 是瑞芯微一款面向AI市场推出的高性能处理器,它配备了四核Cortex-A72和四 核Cortex-A53 的 CPU,集成了6TOPS
    发表于 09-11 10:19

    【作品合集】灵眸科技EASY EAI Orin Nano(RK3576开发板测评

    6Tops,支持INT4/INT8/INT16/FP16混合运算。提供完整的Linux开发包供客户二次开发。 活动详情地址:【RISC-V专题】EASY EAI Orin Nano(RK357
    发表于 09-09 09:59

    如何米尔RK3576开发板上移植EtherCAT Igh

    本文将介绍基于米尔电子MYD-LR3576开发板(米尔基于瑞芯微 RK3576开发板)的板端移植EtherCAT Igh方案的开发测试。摘自
    发表于 09-26 16:02

    新品体验 | RK3576开发

    前言:RK3576作为瑞芯微第二代8nm高性能AIOT平台,一经推出便获得了极大的关注。广州眺望电子科技有限公司是一家专注于嵌入式处理器模组研发与应用的国家高新技术企业,目前公司已推出的相关型号有
    的头像 发表于 11-01 08:08 3397次阅读
    新品体验 | <b class='flag-5'>RK3576</b><b class='flag-5'>开发</b>板

    RK3576单板发布倒计时:RK3399与RK3576对比

    好多人说RK3576RK3399的升级版,某种程度上也可以这么说,RK3576在强大的多媒体功能的基础上,性能和接口都进行了升级 一、工艺 性能
    的头像 发表于 12-03 16:59 2767次阅读
    <b class='flag-5'>RK3576</b>单板发布倒计时:<b class='flag-5'>RK</b>3399与<b class='flag-5'>RK3576</b>对比

    初次编译rk3568(rk3576)Linux 6.1内核踩坑记录:从报错终止到成功解决的完整流程

    很多刚接触瑞芯微 rk 系列芯片开发的小伙伴,在初次编译基于 Linux 6.1 内核的系统时,很容易因为环境依赖问题卡壳。最近我在编译 rk357
    的头像 发表于 02-06 16:47 3182次阅读
    初次编译<b class='flag-5'>rk</b>3568(<b class='flag-5'>rk3576</b>)Linux <b class='flag-5'>6.1</b><b class='flag-5'>内核</b>踩坑记录:从报错终止到成功解决的完整流程

    RK3576音频调试全纪录

    在嵌入式设备开发中,音频调试往往是“牵一发而动全身” 的环节 —— 既需要对齐硬件原理图的信号定义,又要适配软件层的 codec 配置、引脚映射和驱动逻辑。本文基于 RK3576 平台的实际
    的头像 发表于 02-02 17:13 1832次阅读
    <b class='flag-5'>RK3576</b>音频<b class='flag-5'>调试</b>全纪录

    迅为如何在RK3576上部署YOLOv5;基于RK3576构建智能门禁系统

    迅为如何在RK3576开发板上部署YOLOv5;基于RK3576构建智能门禁系统
    的头像 发表于 11-25 14:06 1971次阅读
    迅为如何在<b class='flag-5'>RK3576</b>上部署YOLOv5;基于<b class='flag-5'>RK3576</b>构建智能门禁系统

    迅为电子RK系列开发板SDK内核正式升级至6.1 LTS版本

    迅为RK3568、RK3588、RK3576RK3562系列开发板,SDK内核从5.10版本正
    的头像 发表于 03-16 16:18 513次阅读