1ae7dbaadSJan Kiszka# 2ae7dbaadSJan Kiszka# gdb helper commands and functions for Linux kernel debugging 3ae7dbaadSJan Kiszka# 4ae7dbaadSJan Kiszka# kernel log buffer dump 5ae7dbaadSJan Kiszka# 6ae7dbaadSJan Kiszka# Copyright (c) Siemens AG, 2011, 2012 7ae7dbaadSJan Kiszka# 8ae7dbaadSJan Kiszka# Authors: 9ae7dbaadSJan Kiszka# Jan Kiszka <[email protected]> 10ae7dbaadSJan Kiszka# 11ae7dbaadSJan Kiszka# This work is licensed under the terms of the GNU GPL version 2. 12ae7dbaadSJan Kiszka# 13ae7dbaadSJan Kiszka 14ae7dbaadSJan Kiszkaimport gdb 1546d10a09SLeonard Crestezimport sys 16ae7dbaadSJan Kiszka 17ae7dbaadSJan Kiszkafrom linux import utils 18ae7dbaadSJan Kiszka 19e6076831SJohn Ognessprintk_info_type = utils.CachedType("struct printk_info") 20e6076831SJohn Ognessprb_data_blk_lpos_type = utils.CachedType("struct prb_data_blk_lpos") 21e6076831SJohn Ognessprb_desc_type = utils.CachedType("struct prb_desc") 22e6076831SJohn Ognessprb_desc_ring_type = utils.CachedType("struct prb_desc_ring") 23e6076831SJohn Ognessprb_data_ring_type = utils.CachedType("struct prb_data_ring") 24e6076831SJohn Ognessprintk_ringbuffer_type = utils.CachedType("struct printk_ringbuffer") 25ae7dbaadSJan Kiszka 26ae7dbaadSJan Kiszkaclass LxDmesg(gdb.Command): 27ae7dbaadSJan Kiszka """Print Linux kernel log buffer.""" 28ae7dbaadSJan Kiszka 29ae7dbaadSJan Kiszka def __init__(self): 30ae7dbaadSJan Kiszka super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) 31ae7dbaadSJan Kiszka 32ae7dbaadSJan Kiszka def invoke(self, arg, from_tty): 33ae7dbaadSJan Kiszka inf = gdb.inferiors()[0] 34ae7dbaadSJan Kiszka 35e6076831SJohn Ogness # read in prb structure 36e6076831SJohn Ogness prb_addr = int(str(gdb.parse_and_eval("(void *)'printk.c'::prb")).split()[0], 16) 37e6076831SJohn Ogness sz = printk_ringbuffer_type.get_type().sizeof 38e6076831SJohn Ogness prb = utils.read_memoryview(inf, prb_addr, sz).tobytes() 39ca210ba3SJoel Colledge 40e6076831SJohn Ogness # read in descriptor ring structure 41e6076831SJohn Ogness off = printk_ringbuffer_type.get_type()['desc_ring'].bitpos // 8 42e6076831SJohn Ogness addr = prb_addr + off 43e6076831SJohn Ogness sz = prb_desc_ring_type.get_type().sizeof 44e6076831SJohn Ogness desc_ring = utils.read_memoryview(inf, addr, sz).tobytes() 45e6076831SJohn Ogness 46deaee270SJohn Ogness # read in descriptor count, size, and address 47e6076831SJohn Ogness off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8 48e6076831SJohn Ogness desc_ring_count = 1 << utils.read_u32(desc_ring, off) 49e6076831SJohn Ogness desc_sz = prb_desc_type.get_type().sizeof 50e6076831SJohn Ogness off = prb_desc_ring_type.get_type()['descs'].bitpos // 8 51deaee270SJohn Ogness desc_addr = utils.read_ulong(desc_ring, off) 52e6076831SJohn Ogness 53deaee270SJohn Ogness # read in info size and address 5474caba7fSJohn Ogness info_sz = printk_info_type.get_type().sizeof 5574caba7fSJohn Ogness off = prb_desc_ring_type.get_type()['infos'].bitpos // 8 56deaee270SJohn Ogness info_addr = utils.read_ulong(desc_ring, off) 5774caba7fSJohn Ogness 58e6076831SJohn Ogness # read in text data ring structure 59e6076831SJohn Ogness off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 60e6076831SJohn Ogness addr = prb_addr + off 61e6076831SJohn Ogness sz = prb_data_ring_type.get_type().sizeof 62e6076831SJohn Ogness text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes() 63e6076831SJohn Ogness 64deaee270SJohn Ogness # read in text data size and address 65e6076831SJohn Ogness off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8 66e6076831SJohn Ogness text_data_sz = 1 << utils.read_u32(text_data_ring, off) 67e6076831SJohn Ogness off = prb_data_ring_type.get_type()['data'].bitpos // 8 68deaee270SJohn Ogness text_data_addr = utils.read_ulong(text_data_ring, off) 69e6076831SJohn Ogness 70e6076831SJohn Ogness sv_off = prb_desc_type.get_type()['state_var'].bitpos // 8 71e6076831SJohn Ogness 72e6076831SJohn Ogness off = prb_desc_type.get_type()['text_blk_lpos'].bitpos // 8 73e6076831SJohn Ogness begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8) 74e6076831SJohn Ogness next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8) 75e6076831SJohn Ogness 7674caba7fSJohn Ogness ts_off = printk_info_type.get_type()['ts_nsec'].bitpos // 8 7774caba7fSJohn Ogness len_off = printk_info_type.get_type()['text_len'].bitpos // 8 78e6076831SJohn Ogness 79e6076831SJohn Ogness # definitions from kernel/printk/printk_ringbuffer.h 8010dcb06dSJohn Ogness desc_committed = 1 814cfc7258SJohn Ogness desc_finalized = 2 82e6076831SJohn Ogness desc_sv_bits = utils.get_long_type().sizeof * 8 8310dcb06dSJohn Ogness desc_flags_shift = desc_sv_bits - 2 8410dcb06dSJohn Ogness desc_flags_mask = 3 << desc_flags_shift 85e6076831SJohn Ogness desc_id_mask = ~desc_flags_mask 86e6076831SJohn Ogness 87e6076831SJohn Ogness # read in tail and head descriptor ids 88e6076831SJohn Ogness off = prb_desc_ring_type.get_type()['tail_id'].bitpos // 8 89*e3c8d33eSAntonio Borneo tail_id = utils.read_atomic_long(desc_ring, off) 90e6076831SJohn Ogness off = prb_desc_ring_type.get_type()['head_id'].bitpos // 8 91*e3c8d33eSAntonio Borneo head_id = utils.read_atomic_long(desc_ring, off) 92e6076831SJohn Ogness 93e6076831SJohn Ogness did = tail_id 94e6076831SJohn Ogness while True: 95e6076831SJohn Ogness ind = did % desc_ring_count 96e6076831SJohn Ogness desc_off = desc_sz * ind 9774caba7fSJohn Ogness info_off = info_sz * ind 98e6076831SJohn Ogness 99deaee270SJohn Ogness desc = utils.read_memoryview(inf, desc_addr + desc_off, desc_sz).tobytes() 100deaee270SJohn Ogness 101e6076831SJohn Ogness # skip non-committed record 102*e3c8d33eSAntonio Borneo state = 3 & (utils.read_atomic_long(desc, sv_off) >> desc_flags_shift) 1034cfc7258SJohn Ogness if state != desc_committed and state != desc_finalized: 104e6076831SJohn Ogness if did == head_id: 105ae7dbaadSJan Kiszka break 106e6076831SJohn Ogness did = (did + 1) & desc_id_mask 107ae7dbaadSJan Kiszka continue 108ae7dbaadSJan Kiszka 109deaee270SJohn Ogness begin = utils.read_ulong(desc, begin_off) % text_data_sz 110deaee270SJohn Ogness end = utils.read_ulong(desc, next_off) % text_data_sz 111deaee270SJohn Ogness 112deaee270SJohn Ogness info = utils.read_memoryview(inf, info_addr + info_off, info_sz).tobytes() 113e6076831SJohn Ogness 114e6076831SJohn Ogness # handle data-less record 115e6076831SJohn Ogness if begin & 1 == 1: 116e6076831SJohn Ogness text = "" 117e6076831SJohn Ogness else: 118e6076831SJohn Ogness # handle wrapping data block 119e6076831SJohn Ogness if begin > end: 120e6076831SJohn Ogness begin = 0 121e6076831SJohn Ogness 122e6076831SJohn Ogness # skip over descriptor id 123e6076831SJohn Ogness text_start = begin + utils.get_long_type().sizeof 124e6076831SJohn Ogness 125deaee270SJohn Ogness text_len = utils.read_u16(info, len_off) 126e6076831SJohn Ogness 127e6076831SJohn Ogness # handle truncated message 128e6076831SJohn Ogness if end - text_start < text_len: 129e6076831SJohn Ogness text_len = end - text_start 130e6076831SJohn Ogness 131deaee270SJohn Ogness text_data = utils.read_memoryview(inf, text_data_addr + text_start, 132deaee270SJohn Ogness text_len).tobytes() 133deaee270SJohn Ogness text = text_data[0:text_len].decode(encoding='utf8', errors='replace') 134e6076831SJohn Ogness 135deaee270SJohn Ogness time_stamp = utils.read_u64(info, ts_off) 136ae7dbaadSJan Kiszka 137b3b08429SKieran Bingham for line in text.splitlines(): 13846d10a09SLeonard Crestez msg = u"[{time:12.6f}] {line}\n".format( 139ae7dbaadSJan Kiszka time=time_stamp / 1000000000.0, 14046d10a09SLeonard Crestez line=line) 14146d10a09SLeonard Crestez # With python2 gdb.write will attempt to convert unicode to 14246d10a09SLeonard Crestez # ascii and might fail so pass an utf8-encoded str instead. 14346d10a09SLeonard Crestez if sys.hexversion < 0x03000000: 14446d10a09SLeonard Crestez msg = msg.encode(encoding='utf8', errors='replace') 14546d10a09SLeonard Crestez gdb.write(msg) 146ae7dbaadSJan Kiszka 147e6076831SJohn Ogness if did == head_id: 148e6076831SJohn Ogness break 149e6076831SJohn Ogness did = (did + 1) & desc_id_mask 150ae7dbaadSJan Kiszka 151ae7dbaadSJan Kiszka 152ae7dbaadSJan KiszkaLxDmesg() 153