/proc/kcore失效,调试其文件系统相关模块,使重新正常工作
为分析内核,在有限的机器上用虚拟机装了CentOS.6.9.i386.minimal,重新编译了3.19.8内核并克隆。当使用/proc/kcore进行内核动态映像调试时,发现与kgdb远程调试端读到的内存数据不一样。运行内核的测试机上的/proc/kcore里面的数据大多都为0,几乎没有一处用途。不管我进行多少次core-file去刷新/proc/kcore,结果也是无功而返。开始以为gdb与新内核不兼容,但并不是,用hexdump去读取/proc/kcore的数据,只有开头一小段是有数据迹象,其余都基本为0。/proc/kcore大小约为1G,内核arch为x86。
新内核是按默认配置进行编译,不知道是否其中有配置影响了/proc/kcore文件系统,于是我切换到随CentOS.6.9发布的内核2.6.32-696.el6.i686。结果出来了,在CentOS官方编译的32位内核中,hexdump同样只可以读到/proc/kcore第一个页面大小的数据内容,当读取到其余空间的内容时,只返回000100(也就是一个页面的大小数值)。
那就可能跟编译选项有关,于是找遍了menuconfig,和比较/boot目录里的config-$(uname -r),再参考kconfig里面的参考说明,好像也没有找到相关的选项。最后手段就是去调试文件系统下的kcore了。
kcore模块的代码在$YourSrcDir/fs/proc/kcore.c。先去阅读代码找出有用的函数作为断点切入分析。kcore.c文件不大,只有600不到700行,只要稍为熟识文件系统就可以分析。
kcore特殊文件只实现了(虚)文件系统中的 file_operations 接口,系统调用文件IO,映射相关的接口。
static const struct file_operations proc_kcore_operations = {
.read = read_kcore,
.open = open_kcore,
.llseek = default_llseek,
};
kcore只为文件系统提供了read, open, seek三种操作服务。也就是说我们只可以通过系统调用进行kcore的这三种操作。
下面是kcore.c模块相关的数据结构和静态变量:
// kcore.h
enum kcore_type {
KCORE_TEXT,
KCORE_VMALLOC,
KCORE_RAM,
KCORE_VMEMMAP,
KCORE_OTHER,
}; struct kcore_list {
struct list_head list;
unsigned long addr;
size_t size;
int type;
}; struct vmcore {
struct list_head list;
unsigned long long paddr;
unsigned long long size;
loff_t offset;
};
// kcore.c模块的静态变量:
static LIST_HEAD(kclist_head);
static DEFINE_RWLOCK(kclist_lock);
static int kcore_need_update = ;
这里主要有两类地址,KCORE_VMALLOC和KCORE_RAM。KCORE_RAM,在32位内核中内核地址与物理地址存在一种简单的对应关系,内核地址=物理地址+3G,所以叫KCORE_RAM。但是3G到4G的地址空间中,也不是全部应用这一简单映射关系的,还有一块特殊的区域,就是KCORE_VMALLOC,它位于4G地址空间的最高256M,即0xf0000000到0xfffff000内。
VMALLOC这部分虚拟地址是用在ioremamp,也就是外部设备存储单元使用到的I/O mapped地址。这区域的VMALLOC要与内存管理mm中的vm_area区分好。vmalloc是从内核地址空间,0xc0000000到high_memory(即VMALLOC_START - VMALLOC_OFFSET)为止,进行虚拟空间分配,使用vm_struct结构和vmlist全局队列管理。进程的内存空间由mm_struct结构和vm_area_struct结构进行管理。
// pgtable_32.c
unsigned long __FIXADDR_TOP = 0xfffff000;
EXPORT_SYMBOL(__FIXADDR_TOP);
// fixmap.h
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
#define FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
// pgtable_32_types.h
#define VMALLOC_START ((unsigned long)high_memory + VMALLOC_OFFSET)
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE - * PAGE_SIZE)
#else
# define VMALLOC_END (FIXADDR_START - * PAGE_SIZE)
#endif
#define MODULES_VADDR VMALLOC_START
#define MODULES_END VMALLOC_END
#define MODULES_LEN (MODULES_VADDR - MODULES_END)
变量high_memory标志着具体物理内存的上限所对应的虚拟地址,这是在系统初始化时设置好的。通过kgdb调试,查看到high_memory为0xf0000000。
为什么我的内核只可以读到/proc/kcore的一个页面的数据,其它地址上的数据全为0呢,那么参考读操作函数read_kcore。
这个函数主要是将/proc/kcore文件尺寸的线性地址空间映射到不同的区域进行读操作,与内存(文件)映射类似。
1.read_kcore将第一个页面的地址空间的读操作,映射为一个ELF core header头结构的数据内容。
2.从这个头结构偏移后的地址,使用内核地址的简单映射规则,进行映射,即 addr + 3G - sizeof(ELF core header)。
3.分别分派到kcore_list区域进行读操作。
4.如果访问地址满足is_vmalloc_or_module_addr,则进行vread,并copy_to_user。
5.如果访问地址满足kern_addr_valid,则直接进行copy_to_user。
6.其余情况clear_user。
先来看kcore是如何将kcore文件的线性地址映射到内核地址的,下面的相关函数的反汇编代码:

这里要注意的是,代码是被-O2优化过的,反汇编并不能与代码很好地对应,开头两行可能是承着某处的跳转的。从行文来看%esi优化为变量elf_buflen。
将图的下面4行汇编逆向为 0xc0000000 - elf_buflen + *fpos。 也就是 offset + 3G - sizeof(ELF core header)。
再来看kcore一共有几个映射区间,只要walk through一下kclist_head队列就可以知道。自己写一下调试脚本就可以得到。

kclist_head有两个区间,地址区间与info files查看到映像区间一致。分别是0xf0800000开始的KCORE_VMALLOC区间,和0xc0000000开始的KCORE_RAM区间。 这两个区间下面还会进行说明。
这就好办了,断点设置在read_kcore跑一次。结果发现在头部分偏移之后的地址量的读操作一切都被clear_user,也就是填0。对应高地址(即vmalloc,ioremap)的读操作则是正常的。代码已经被-O2优化过,用混合反汇编出来的代码和汇编对应也是乱七八糟的。不过好在符号信息还在,那就设断点到kern_addr_valid,却发现找不到符号。经过汇编分析后发现,代码在判断is_vmalloc_or_module_addr失败后直接进行clear_user。按代码的逻辑应该是先进行kern_addr_valid判断。也就是访问地址不在最高 处的vamlloc,再判断是否在内核有效的地址空间内。但实际的反汇编代码却根本找不到这个判断逻辑。查阅kern_addr_valid在不同arch下实现后,发现x86下这个函数只是一个开关。
// arch/x86/include/asm/pgtable_32.h
#ifdef CONFIG_FLATMEM
#define kern_addr_valid(addr) (1)
#else
#define kern_addr_valid(kaddr) (0)
#endif
终于发现在arch x86中,内存管理模型影响了/proc/kcore特殊文件的运作。只有在FLAT模型下的内存管理,/proc/kcore才能提供正常的服务。内核中默认配置是使用SPARSE模型的,不管理是什么arch的处理器。CentOS的32位内核也使用了这一默认配置,经过/boot/config-2.6.32-696.el6.i686核实。
内核3.19.8重新进行menuconfig配置,选用FLAT内存管理模型,再次编译后。OK!/proc/kcore特殊文件正常读出内核内存映像的数据。x86 32位的内核必须使用FLAT内存管理模型,即CONFIG_FLATMEM_ENABLE=y,才可以正常使用/proc/kcore。
在重编译后,我懒得编译modules,使用原来SPARSE内存模型编译出来的modules进行安装。安装时提示许多mm_section符号缺失的warning,实际运行内核时也就杯具了。幸好是虚拟机,回退重新全部编译就是了,机器配置有限,至少就一个半小时。
现在大家都用arch x86_64的内核,内核不会出现这个问题,arch arm和arch arm64也不会有这个问题,只是我机器资源有限只能使用32位的内核,所以碰上了这个问题。
x86 32位的内核必须使用FLAT内存管理模型,即CONFIG_FLATMEM_ENABLE=y,才可以正常使用/proc/kcore。
/proc/kcore失效,调试其文件系统相关模块,使重新正常工作的更多相关文章
- python 加密算法及其相关模块的学习(hashlib,random,string,math)
加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...
- python加密算法及其相关模块的学习(hashlib,RSA,random,string,math)
加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...
- Python——电子邮件、Internet协议相关模块
一.电子邮件相关模块 email:用于处理电子邮件 smtpd:SMTP服务器 base64:Base-16.32.64数据编码 mhlib:处理MH文件格式解析的类 mailcap:mailcap文 ...
- 【转】Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历))
Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历)) 本文由 Luzhuo 编写,转发请保留该信息. 原文: http://blog. ...
- nodeJS---URL相关模块用法(url和querystring)
nodeJS---URL相关模块用法(url和querystring) 一: URL模块: URL模块用于解析和处理URL的字符串,提供了如下三个方法: 1. parse 2. format 3. r ...
- Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历))
Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历)) 本文由 Luzhuo 编写,转发请保留该信息. 原文: http://blog. ...
- python 相关模块安装 国内镜像地址
python 相关模块安装 国内镜像地址 pipy国内镜像目前有: http://pypi.douban.com/ 豆瓣 http://pypi.hustunique.com/ 华中理工大学 ht ...
- Android开发环境——调试器 DDMS相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT ...
- /proc/kcore
[root@b proc]# ls -lh /proc/kcore-r-------- 1 root root 128T Sep 29 09:39 /proc/kcore[root@b proc]# ...
随机推荐
- 微软 深度学习 cntk ,我目前见过 安装方式最简单的一个框架,2.0之后开始支持C# 咯
嗨,你也是我这种手残党么?之前试着安装着mxnet和tensorflow,但是因为时间比较短所以往往来不及安装完就失去兴趣,今天看到微软的cntk可以用了,一次性安装好了,并且测试通过 本人环境: W ...
- Liferay中利用URL传参数
业务场景:现在有一个新闻系统,有两个页面,A是新闻列表页面/web/guest/home,B是新闻的详情页面/web/guest/newsview. 业务逻辑为:在A页面中,点击新闻的标题进入B页面, ...
- 跨web浏览器的IC卡读卡器解决方案
BS结构的程序,如果要与IC卡读卡器通信本身就是件不容易解决的事情.微软的activex ocx技术将这种应用限制在IE浏览器上了,不兼容其它的浏览器.而Chrome使用插件也不兼容IE和其他的浏览器 ...
- 【Shell】使用Shell脚本发布项目
第一次写Shell脚本,没经验,是直接写呢,还是要走流程( ̄▽ ̄)~* ---------------------------------------------------------------- ...
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(十一)数据层优化-druid监控及慢sql记录
本文提要 前文也提到过druid不仅仅是一个连接池技术,因此在将整合druid到项目中后,这一篇文章将去介绍druid的其他特性和功能,作为一个辅助工具帮助提升项目的性能,本文的重点就是两个字:监控. ...
- JS自定义对象,正则表达式,JQuery中的一些知识点
一:自定义对象 1.基本概念:①对象:包含一系列无序属性和方法的集合.②键值对:对象中的数据是以键值对的形式存在的,以键取值.③属性:描述对象特征的一系列变量.[对象中的变量]④方法:描述对象行为的一 ...
- Android事件分发机制详解
事件分发机制详解 一.基础知识介绍 1.经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等 2 ...
- Arraylist动态扩容详解
ArrayList 概述 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长. ArrayList不是线程安全的,只能用在单线程环境下. 实现了Serializable接口,因此它支 ...
- Python 基础三 文件 函数
今天回顾一下之前学的文件操作相关知识点,对于文件的操作,主要有一下几部分构成: 一.文件的基础知识 1.文件操作的基本流程 文件操作其实可以分成三大部分: 1.打开文件,获取文件句柄并赋予一个变量 2 ...
- php超时任务处理
首先,不知道fastcgi_finish_request是啥的点这里. 一直知道php有个fastcgi_finish_request可以用来针对web应用处理耗时任务,但我一直以为直接fastcg ...