命令字!dmesg

基本功能:dmesg基本功能为打印所用linux中消息缓冲区中的信息。兼容linux4.0与linux5.0。
基本用法:!ndx.dmesg,!ndx.dmesg -a [address],!ndx.dmesg -f [*filename]

基本实现:

1.提取符号,定位地址:

linux的许多信息都是存放在/symbol/kernel/目录下,若想要提取所需信息,需要先加载该符号。新版本中的缓冲区的信息都与printk_rb_dynamic,printk_rb_static结构体强关联,所以我们得先在nanocode加载prb,因为在linux内核中有两个结构体储存缓冲区信息,分别是printk_rb_dynamic与printk_rb_static,而prb是一个指针,储存的是存有信息的那个结构体的地址。

上图中,我们可以看到,prb的所指向的地址与printk_rb_static的地址是一样的。

以上是详细的prb_desc_ring的详细结构图。我们想要的日志数据都是在text_data_ring的data指针所指向的对象当中。但我们无法直接获取数据,这是因为每一条日志的位置都不一样。需要其他数据辅以计算得到精确的位置,再加以输出。
我们需要读取其中的head_id,tail_id作为end_id和id,用于运算每个prb_desc_ring结构体与printk_info结构体的地址用于后续操作。


通过一些数值计算,计算出地址的正确位置。保存为desc和info,并将其传入dump_record函数中进行执行
我们通过state判断该条日志要不要输出,若是要输出,那我们就将prb_desc_ring和printk_info的地址传入dump_record函数中。

2.计算日志具体位置,打印信息:

之后我们就需要获取日志信息的具体位置了,我们需要用到
text_blk_lpos中的begin和next。原始的tbl_begin,tbl_next是不能用的,需要进行处理。

将tbl_begin与tbl_next进行一个取余运算,我们将得到该条日志在data中的准确位置。

我们将其记作log,该位置就是其实就是该条日志的位置,其长度为text_len,该值在printk_info中。
我们用ReadMemory函数去读取该地址的日志信息,且指定长度为text_len。

以下为第一版实现效果:

可以看到日志信息正常打印。

在项目初期,我们出现了这样的错误。如图所见,打印的信息全是乱码。

这是因为初期的代码在取的偏移上有所问题,初期取的地址所读出来的前四位是结束符,这会导致在读取该数据块时直接遇到结束符而结束。

解决方法,目前是手动加上偏移,对地址进行读取,略过前面的四位结束符。将地址直接改到日志的开始地点,这样再用函数去读取的时候,就不会因为读取到结束符而提前结束。

在上图中我们可以看到,出现了乱码。这是由于系统崩溃造成的,在系统崩溃是,Linux会将原本data中的日志立即转出,并将崩溃时的信息载入其中。由于text_len还是能正常读取的,所以其会强制输出text_len长度的信息。而乱码的部分则是由于读到了结束符。导致读取强制结束。输出时由于长度不够,需要弥补,故出现了乱码。

还有一个比较致命的错误,就是在计算begin与next的偏移值的时候犯了错。


上图为我们最初的设定,我们将上图四个变量都定义为了有符号整数类型。这就导致在取余运算的时候往往取不到有效值。在最初的版本中tbl_begin在经过运算之后只是等于begin的相反数,完全起不到一个下标的作用。

故我们尝试了将原来的四个变量改为无符号的64位整数,之后再通过运算,就可以渠取到正确的下标。

第二版中:我们加入了命令行参数,使用户可以自己选择使用的
方式。

-f可以指定文件,用于老版本的的文件指定。而-a可指定想要读取的地址。

作者:施国瑞  创建时间:2023-10-19 09:53
最后编辑:施国瑞  更新时间:2024-04-26 11:16