• DUMP kernel log_buf以及解析log_buf字符的办法。


    多数情况下,Linux出问题时都可以打印出错误log,但是有些情形却又不能,这时就要自己来dump出还没来得及打印的log了。

    1. dump log_buf

    a. 需要找到 _text字段的虚拟地址,可以 nm vmlinux | grep _text

    b. 需要找到 _log_buf字段的虚拟地址,可以 nm vmlinux | grep _log_buf

    c. 需要找到kernel在内存的起始位置 PA。

    找到以上部分,那么可以算出_log_buf在物理内存中的地址了。

    PA_log_buf = _log_buf - _text + PA

    一般来说,_text会有0x8000/0x80000的偏移,如果要算上的话,PA也会有这个偏移,要一同算上比如:

    c0dd480c b __log_buf

    PA_log_buf = c0dd480c - c0008000 + 20208000

    还有另外一种情况就是,我们在bootargs中添加了log_buf_len,这时会使用新的地址,_log_buf就可能不适用了。

    这时需要找到 log_buf 的地址,然后看这个地址上的值是多少,新的log_buf会保存在这里。

    2.解析dump出来的数据。

    #! /usr/bin/python
    
    import sys
    import os
    from ctypes import *
    
    # struct printk_log {
    #           u64 ts_nsec;
    #           u16 len;
    #           u16 text_len;
    #           u16 dict_len;
    #           u8 facility;
    #           u8 flags:5;
    #           u8 level:3;
    # }
    class PHEAD(LittleEndianStructure):
        _pack_ = 1
        _fields_ = [
            ('ts_nsec', c_uint64),
            ('len',     c_uint16),
            ('text_len',c_uint16),
            ('dict_len',c_uint16),
            ('facility',c_uint8),
            ('flags',   c_uint8,5),
            ('level',   c_uint8,3),
        ]
        def encode(self):
            return string_at(addressof(self), sizeof(self))
        def decode(self, data):
            memmove(addressof(self), data, sizeof(self))
            return len(data)
    
    headsize = 16
    
    if __name__ == "__main__":
        fd = open(sys.argv[1], "rb")
        line = fd.read(headsize)
        while line:
            ss = PHEAD()
            ss.decode(line)
            if (ss.level > 7 or ss.len > 1024 or ss.text_len > ss.len or ss.len == 0 or ss.text_len == 0):
                fd.seek(-15, 1)
                line = fd.read(headsize)
                if (len(line) != headsize):
                    break
                continue
            tel = fd.tell()
            stream = fd.read(ss.text_len)
            check_byte = True
            for i in range(ss.text_len):
                if (ord(stream[i]) > 0x7f or ord(stream[i]) < 0x10):
                    fd.seek(tel, 0)
                    fd.seek(-15, 1)
                    line = fd.read(headsize)
                    check_byte = False
                    break
            print ("[ %05d.%06d ] ")%(ss.ts_nsec/1000000000,(ss.ts_nsec%1000000000)/1000),
            print stream
            if (check_byte == False):
                continue
            offset = 4 - ss.len%4
            if (offset >= 4):
                offset = 0
            offset += ss.len - ss.text_len - headsize
            if (offset < 0 ):
                offset = 0
            fd.seek(offset, 1)
            line = fd.read(headsize)
        fd.close()
  • 相关阅读:
    Vue 监听子组件事件
    延时队列
    AES加密
    centos7.9 iftop 工具源码安装
    angular pass get paragrams by router
    Android chrome console in PC
    powershell 运行带路径的exe
    win下 nrm ls报错
    windows10 安装 node 16 解决node-sass node-gyp报错
    位图和布隆过滤器
  • 原文地址:https://www.cnblogs.com/smilingsusu/p/14188477.html
Copyright © 2020-2023  润新知