Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 1 | # |
| 2 | # gdb helper commands and functions for Linux kernel debugging |
| 3 | # |
| 4 | # kernel log buffer dump |
| 5 | # |
| 6 | # Copyright (c) Siemens AG, 2011, 2012 |
| 7 | # |
| 8 | # Authors: |
| 9 | # Jan Kiszka <jan.kiszka@siemens.com> |
| 10 | # |
| 11 | # This work is licensed under the terms of the GNU GPL version 2. |
| 12 | # |
| 13 | |
| 14 | import gdb |
Leonard Crestez | 46d10a0 | 2017-07-12 14:34:19 -0700 | [diff] [blame] | 15 | import sys |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 16 | |
| 17 | from linux import utils |
| 18 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 19 | printk_info_type = utils.CachedType("struct printk_info") |
| 20 | prb_data_blk_lpos_type = utils.CachedType("struct prb_data_blk_lpos") |
| 21 | prb_desc_type = utils.CachedType("struct prb_desc") |
| 22 | prb_desc_ring_type = utils.CachedType("struct prb_desc_ring") |
| 23 | prb_data_ring_type = utils.CachedType("struct prb_data_ring") |
| 24 | printk_ringbuffer_type = utils.CachedType("struct printk_ringbuffer") |
| 25 | atomic_long_type = utils.CachedType("atomic_long_t") |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 26 | |
| 27 | class LxDmesg(gdb.Command): |
| 28 | """Print Linux kernel log buffer.""" |
| 29 | |
| 30 | def __init__(self): |
| 31 | super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) |
| 32 | |
| 33 | def invoke(self, arg, from_tty): |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 34 | inf = gdb.inferiors()[0] |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 35 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 36 | # read in prb structure |
| 37 | prb_addr = int(str(gdb.parse_and_eval("(void *)'printk.c'::prb")).split()[0], 16) |
| 38 | sz = printk_ringbuffer_type.get_type().sizeof |
| 39 | prb = utils.read_memoryview(inf, prb_addr, sz).tobytes() |
Joel Colledge | ca210ba | 2019-10-18 20:19:26 -0700 | [diff] [blame] | 40 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 41 | # read in descriptor ring structure |
| 42 | off = printk_ringbuffer_type.get_type()['desc_ring'].bitpos // 8 |
| 43 | addr = prb_addr + off |
| 44 | sz = prb_desc_ring_type.get_type().sizeof |
| 45 | desc_ring = utils.read_memoryview(inf, addr, sz).tobytes() |
| 46 | |
| 47 | # read in descriptor array |
| 48 | off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8 |
| 49 | desc_ring_count = 1 << utils.read_u32(desc_ring, off) |
| 50 | desc_sz = prb_desc_type.get_type().sizeof |
| 51 | off = prb_desc_ring_type.get_type()['descs'].bitpos // 8 |
| 52 | addr = utils.read_ulong(desc_ring, off) |
| 53 | descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes() |
| 54 | |
John Ogness | 74caba7 | 2020-09-21 13:24:45 +0206 | [diff] [blame] | 55 | # read in info array |
| 56 | info_sz = printk_info_type.get_type().sizeof |
| 57 | off = prb_desc_ring_type.get_type()['infos'].bitpos // 8 |
| 58 | addr = utils.read_ulong(desc_ring, off) |
| 59 | infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes() |
| 60 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 61 | # read in text data ring structure |
| 62 | off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 |
| 63 | addr = prb_addr + off |
| 64 | sz = prb_data_ring_type.get_type().sizeof |
| 65 | text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes() |
| 66 | |
| 67 | # read in text data |
| 68 | off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8 |
| 69 | text_data_sz = 1 << utils.read_u32(text_data_ring, off) |
| 70 | off = prb_data_ring_type.get_type()['data'].bitpos // 8 |
| 71 | addr = utils.read_ulong(text_data_ring, off) |
| 72 | text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes() |
| 73 | |
| 74 | counter_off = atomic_long_type.get_type()['counter'].bitpos // 8 |
| 75 | |
| 76 | sv_off = prb_desc_type.get_type()['state_var'].bitpos // 8 |
| 77 | |
| 78 | off = prb_desc_type.get_type()['text_blk_lpos'].bitpos // 8 |
| 79 | begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8) |
| 80 | next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8) |
| 81 | |
John Ogness | 74caba7 | 2020-09-21 13:24:45 +0206 | [diff] [blame] | 82 | ts_off = printk_info_type.get_type()['ts_nsec'].bitpos // 8 |
| 83 | len_off = printk_info_type.get_type()['text_len'].bitpos // 8 |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 84 | |
| 85 | # definitions from kernel/printk/printk_ringbuffer.h |
John Ogness | 10dcb06 | 2020-09-14 14:39:52 +0206 | [diff] [blame] | 86 | desc_committed = 1 |
John Ogness | 4cfc725 | 2020-09-14 14:39:53 +0206 | [diff] [blame] | 87 | desc_finalized = 2 |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 88 | desc_sv_bits = utils.get_long_type().sizeof * 8 |
John Ogness | 10dcb06 | 2020-09-14 14:39:52 +0206 | [diff] [blame] | 89 | desc_flags_shift = desc_sv_bits - 2 |
| 90 | desc_flags_mask = 3 << desc_flags_shift |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 91 | desc_id_mask = ~desc_flags_mask |
| 92 | |
| 93 | # read in tail and head descriptor ids |
| 94 | off = prb_desc_ring_type.get_type()['tail_id'].bitpos // 8 |
| 95 | tail_id = utils.read_u64(desc_ring, off + counter_off) |
| 96 | off = prb_desc_ring_type.get_type()['head_id'].bitpos // 8 |
| 97 | head_id = utils.read_u64(desc_ring, off + counter_off) |
| 98 | |
| 99 | did = tail_id |
| 100 | while True: |
| 101 | ind = did % desc_ring_count |
| 102 | desc_off = desc_sz * ind |
John Ogness | 74caba7 | 2020-09-21 13:24:45 +0206 | [diff] [blame] | 103 | info_off = info_sz * ind |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 104 | |
| 105 | # skip non-committed record |
John Ogness | 10dcb06 | 2020-09-14 14:39:52 +0206 | [diff] [blame] | 106 | state = 3 & (utils.read_u64(descs, desc_off + sv_off + |
| 107 | counter_off) >> desc_flags_shift) |
John Ogness | 4cfc725 | 2020-09-14 14:39:53 +0206 | [diff] [blame] | 108 | if state != desc_committed and state != desc_finalized: |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 109 | if did == head_id: |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 110 | break |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 111 | did = (did + 1) & desc_id_mask |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 112 | continue |
| 113 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 114 | begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz |
| 115 | end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz |
| 116 | |
| 117 | # handle data-less record |
| 118 | if begin & 1 == 1: |
| 119 | text = "" |
| 120 | else: |
| 121 | # handle wrapping data block |
| 122 | if begin > end: |
| 123 | begin = 0 |
| 124 | |
| 125 | # skip over descriptor id |
| 126 | text_start = begin + utils.get_long_type().sizeof |
| 127 | |
John Ogness | 74caba7 | 2020-09-21 13:24:45 +0206 | [diff] [blame] | 128 | text_len = utils.read_u16(infos, info_off + len_off) |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 129 | |
| 130 | # handle truncated message |
| 131 | if end - text_start < text_len: |
| 132 | text_len = end - text_start |
| 133 | |
| 134 | text = text_data[text_start:text_start + text_len].decode( |
| 135 | encoding='utf8', errors='replace') |
| 136 | |
John Ogness | 74caba7 | 2020-09-21 13:24:45 +0206 | [diff] [blame] | 137 | time_stamp = utils.read_u64(infos, info_off + ts_off) |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 138 | |
Kieran Bingham | b3b0842 | 2016-05-23 16:25:21 -0700 | [diff] [blame] | 139 | for line in text.splitlines(): |
Leonard Crestez | 46d10a0 | 2017-07-12 14:34:19 -0700 | [diff] [blame] | 140 | msg = u"[{time:12.6f}] {line}\n".format( |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 141 | time=time_stamp / 1000000000.0, |
Leonard Crestez | 46d10a0 | 2017-07-12 14:34:19 -0700 | [diff] [blame] | 142 | line=line) |
| 143 | # With python2 gdb.write will attempt to convert unicode to |
| 144 | # ascii and might fail so pass an utf8-encoded str instead. |
| 145 | if sys.hexversion < 0x03000000: |
| 146 | msg = msg.encode(encoding='utf8', errors='replace') |
| 147 | gdb.write(msg) |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 148 | |
John Ogness | e607683 | 2020-08-14 23:31:25 +0206 | [diff] [blame] | 149 | if did == head_id: |
| 150 | break |
| 151 | did = (did + 1) & desc_id_mask |
Jan Kiszka | ae7dbaa | 2015-02-17 13:47:04 -0800 | [diff] [blame] | 152 | |
| 153 | |
| 154 | LxDmesg() |