内核符号表详解

news/2024/7/3 11:47:26

内核符号表详解

http://hi.baidu.com/apollon2010/blog/item/ecbe1d5a3bd2ec8a800a18dc.html

关键词:
Kernel Symbol Table、/proc/ksyms、system.map、Oops、LKM


这应该是一个很基本的内核概念,和模块、系统调用等一样基础,但牵涉的东西却一点也不窄,一毫也不浅。(但也不深:-)

【内核符号表,kernelsymbol table】

Linux的内核是个单内核monolithic,任一函数都可以访问公共数据结构和函数调用。在设计程序时,需要命名一些函数名、变量名等;同样内核中就含有很多的全局符号。
内核不是人脑皮层,要使用变量和函数-地址(指针)-来访问对应的变量和函数。
内核符号表就是为程序员通过符号来访问程序体的对应地址(指针),建立了一个动态的,可变更的映射表格。

一个符号表例子:

c03441a0 b dmi_broken
c03441a4 b is_sony_vaio_laptop


可以看出变量dmi_broken位于内核地址c03441a0处。

这和gdb的按图索骥的功能很相似,不同的是内核采用文件为载体的形式。

【/proc/ksyms】

ksyms是内核数据映像文件,在内核引导时创建,其实就是内核数据(/proc文件系统的特性及详解文末),没有实际大小的。

ksyms中的每一个表项代表着一个全局内核符号。这些符号可被LKM引用的,即可以看出LKM可以调用哪些函数(这里有一个安全问题)


【System.map】

位于/或者/boot、/usr/src/linux/下

在每次重新编译内核时,各符号名及其对应的地址指针将有所变化。(有变的,也有不变的)。所以系统需要自行更新此文件。

(关于System.map和系统出错的关系,需要额外说明)。

System.map文件作为特定内核的内核符号表,其链接了系统所使用的System.map。

一般的创建步骤:
当编译后生成内核vmlinux-2.X.Y后,存于/usr/src/linux/下,这时编译脚本将运行“nm/usr/src/linux/vmlinux-2.X.Y > System.map”,并将其拷入/boot下。

具体的生成过程可以从内核编译脚本中得到启示:

/usr/src/linux-2.X.Y/Makefile

[I]
nm vmlinux | grep -v ’(compiled)|(.o$$)|( [aUw] )|(..ng$$)|(LASH[RL]DI)’ | sort> System.map

cp /usr/src/linux/System.map /boot/System.map-2.X.Y

[/I]

注:nm vmlinux的作用是过滤掉其中不需要的符号。


值得注意的是内核本身并不真正使用System.map,但其它程序比如klogd, lsof和ps等软件需要一个正确的System.map。某些与内核头连接而非glibc库的驱动也需要System.map来解析符号(模块加载是与内核版本有关,但与内核版本一致而符号表发生变化的编译后内核无关)。


klogd 内核日志守护进程
为了执行名称-地址解析,klogd需要使用System.map。

man klogd可知,klogd将从一下路径查找System.map:
/boot/System.map
/System.map
/usr/src/linux/System.map

如:
# strace -f /sbin/klogd | grep ’System.map’
open("/boot/System.map-2.4.18",O_RDONLY|O_LARGEFILE) = 2

# strace lsof 2>&1 1> /dev/null | grep System
readlink("/proc/22711/fd/4", "/boot/System.map-2.4.18",4095) = 23

# strace ps 2>&1 1> /dev/null | grep System
open("/boot/System.map-2.4.18", O_RDONLY|O_NONBLOCK|O_NOCTTY) = 6




【/proc文件系统】
一个伪文件系统,它只存在内存当中,而不占用外存空间。为访问系统内核数据的操作提供接口。有些是动态可变的。
以数字命名的目录是进程目录,以进程的PID号为目录名,而self目录则是读取进程本身的信息接口,是一个link,proc文件系统的由来也因为此。

apm     高级电源管理信息
cmdline 内核命令行
Cpuinfo    关于Cpu信息
Devices   可以用到的设备(块设备/字符设备)
Dma    Used DMSchannels
Filesystems 支持的文件系统
Interrupts 中断的使用
Ioports    I/O端口的使用
Kcore    内核核心印象
Kmsg     内核消息
Ksyms    内核符号表
Loadavg     负载均衡
Locks     内核锁
Meminfo     内存信息
Misc    Miscellaneous
Modules    加载模块列表
Mounts    加载的文件系统
Partitions 系统识别的分区表
Rtc    Real timeclock
Slabinfo Slab pool info
Stat    全面统计状态表s
Swaps    对换空间的利用情况
Version     内核版本
Uptime    系统正常运行时间



进程目录的结构如下:
目录名称 目录内容
Cmdline    命令行参数
Environ    环境变量值
Fd  一个包含所有文件描述符的目录
Mem    进程的内存被利用情况
Stat    进程状态
Status   Processstatus in human readable form
Cwd   当前工作目录的链接
Exe   Link to theexecutable of this process
Maps    内存印象
Statm    进程内存状态信息
Root    链接此进程的root目录

查看系统信息:cat/proc/mem

修改内核参数
/proc/sys不仅提供了内核信息,而且可以通过它修改内核参数。要改变内核的参数,可用Vi编辑或echo +参数重定向到文件中即可:
# echo 8192 > /proc/sys/fs/file-max



【关于ksyms被LKM调用的安全问题】
可以绕过LKM调用的符号表声明


/*定义自己的符号表!!*/

static struct symbol_table module_syms= {

#include <linux/symtab_begin.h>    

/*我们想引用的符号表*/

...                  

};

register_symtab(&module_syms);    

/*实际的注册工作,并不需要对外公开这里的符号,只要用如下的语句*/

register_symtab(NULL);

/*放在init_module()函数中*/



【关于System.map和内核出错Oops的关系】
※内核出错(oops)※

编程最常见的出错情况是段出错(segfault),信号11。

Linux内核中最常见的bug也是段出错。不过当内核引用了一个无效指针时,并不称其为段出错 -- 而被称为"oops"。一个oops表明内核存在一个bug。

当出现一个oops时,并不意味着内核肯定处于不稳定的状态;一个oops可能仅杀死了当前进程,并使余下的内核处于一个良好的、稳定的状态。 -健壮的Linux

一个oops并非是内核死循环(panic)
在内核调用了panic()函数后,内核将停止运行,必须重启;
如果系统中关键部分遭到破坏,如关键的驱动等, 那么一个oops也可能会导致内核进入死循环(panic)。

当出现一个oops时,系统就会显示出用于调试问题的相关信息,比如所有CPU寄存器中的内容以及页描述符表的位置等,尤其会象下面那样打印出EIP(指令指针)的内容:

EIP: 0010:[<00000000>]
Call Trace: []


※与System.map的关系※

Linux使用klogd截取内核oops并且使用syslogd将其记录下来。klogd是一个内核消息记录器(logger), 它可以通过System.map文件进行名字-地址之间的解析。通常是使用syslogd记录器。

深入说明: 其实klogd会执行两类地址解析活动。
静态转换,将使用System.map文件。
动态转换,该方式用于可加载模块,不使用System.map

Klogd动态转换

假设你加载了一个产生oops的内核模块。klogd就会截获消息。并解析出地址。如果该地址属于动态加载模块,在System.map文件中没有对应条目。此时klogd就会向内核查询该可加载模块输出的符号。


http://www.niftyadmin.cn/n/4645236.html

相关文章

如何读取被禁用的网卡信息

http://topic.csdn.net/u/20080310/19/5fa9b49d-c7f5-42be-986f-4cb46fb4e0b0.html?2079547956 比如&#xff0c;有两张网卡&#xff0c;一张启用&#xff0c;一张禁用&#xff0c;如何获取被禁用的网卡的信息&#xff0c;如网卡MAC&#xff0c;网卡名称等。GetAdaptersInfo…

如何在IDA中找到MFC程序的消息处理函数

比起用Win32SDK写的程序&#xff0c;要分析MFC应用程序要麻烦不少。在前者&#xff0c;只要找到注册窗口类的地方就知道其WinProc的位置。那里是程序的控制中心&#xff0c;只要顺藤摸瓜就可以找到你感兴趣的地方。对于用MFC写的程序&#xff0c;这一切都变得复杂起来了。这时&…

距离矢量路由协议通用属性

一、路由分类大多的路由协议都属于两个类别1、距离矢量&#xff08;Distance Ventor&#xff09;、2、链路状态&#xff08;Link State&#xff09;二、距离矢量路由协议因为路由是以矢量&#xff08;距离&#xff0c;方向&#xff09;的方式被通告出去的&#xff0c;其中距离是…

JSR 299 建议草案第二版已提交

昨天 Gavin King 提交了 JSR 299 &#xff08;Contexts and Dependency Injection for the Java EE platform&#xff09;的第二个建议草案 给 JCP。相比上一个建议草案&#xff0c;主要有如下四个大的修订&#xff1a; 在依赖注射注解&#xff08;annotation&#xff09;上全面…

csdn博客集

逆向 http://blog.csdn.net/pll621/article/category/138401 http://blog.csdn.net/cattom/article/category/220275

锂电池知识

一&#xff0e;锂电池保护 一般用户接触到手机锂离子电池,在外面看到的除了电池外壳,还有就是几个五金触片了,如图中"电池正极,电池负极"就是的电池正负极输出. ┏━━Fuse━━━━━┳━━━━━━━━━┫电池正极 ┃ R1 ┃ ┃ ┇ ┏┻━━┓ ┏┻┓ ┃保护IC┃…

MoveFileEx 的特殊应用

了解MoveFileEx (2012-01-18 11:01:36) 转载▼标签&#xff1a; 杂谈 分类&#xff1a; 技术文章 当dwFlags被设为MOVEFILE_DELAY_UNTIL_REBOOT时&#xff0c;函数直到系统重启后才移动文件。注意文件的移动是发生在AUTOCHK执行之后&#xff0c;在页面文件创建之前。而此时…

分析了一下360安全卫士的 HOOK(二)——架构与实现(zt)

连接&#xff1a;http://blog.csdn.net/lionzl/article/details/7738182 上一篇的分析中漏掉了三个函数&#xff0c;现补上&#xff1a; NtSetSystemInformation 024 ProcessNotify 045 //这个并非Hook,只是HookPort安装的一个Notify KeUserModeCallback 04…