[PATCH 5.15 521/779] scripts/gdb: lx-dmesg: read records individually

From: Greg Kroah-Hartman
Date: Mon Aug 15 2022 - 15:23:53 EST


From: John Ogness <john.ogness@xxxxxxxxxxxxx>

[ Upstream commit deaee2704a157dfcca77301ddaa10c62a9840952 ]

For the gdb command lx-dmesg, the entire descriptor, info, and text
data regions are read into memory before printing any records. For
large kernel log buffers, this not only causes a huge delay before
seeing any records, but it may also lead to python errors of too
much memory allocation.

Rather than reading in all these regions in advance, read them as
needed and only read the regions for the particular record that is
being printed.

The gdb macro "dmesg" in Documentation/admin-guide/kdump/gdbmacros.txt
already prints out the kernel log buffer like this.

Signed-off-by: John Ogness <john.ogness@xxxxxxxxxxxxx>
Signed-off-by: Petr Mladek <pmladek@xxxxxxxx>
Link: https://lore.kernel.org/r/874k79c3a9.fsf@xxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
scripts/gdb/linux/dmesg.py | 35 ++++++++++++++++++-----------------
1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py
index a92c55bd8de5..d5983cf3db7d 100644
--- a/scripts/gdb/linux/dmesg.py
+++ b/scripts/gdb/linux/dmesg.py
@@ -44,19 +44,17 @@ class LxDmesg(gdb.Command):
sz = prb_desc_ring_type.get_type().sizeof
desc_ring = utils.read_memoryview(inf, addr, sz).tobytes()

- # read in descriptor array
+ # read in descriptor count, size, and address
off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8
desc_ring_count = 1 << utils.read_u32(desc_ring, off)
desc_sz = prb_desc_type.get_type().sizeof
off = prb_desc_ring_type.get_type()['descs'].bitpos // 8
- addr = utils.read_ulong(desc_ring, off)
- descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes()
+ desc_addr = utils.read_ulong(desc_ring, off)

- # read in info array
+ # read in info size and address
info_sz = printk_info_type.get_type().sizeof
off = prb_desc_ring_type.get_type()['infos'].bitpos // 8
- addr = utils.read_ulong(desc_ring, off)
- infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes()
+ info_addr = utils.read_ulong(desc_ring, off)

# read in text data ring structure
off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8
@@ -64,12 +62,11 @@ class LxDmesg(gdb.Command):
sz = prb_data_ring_type.get_type().sizeof
text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes()

- # read in text data
+ # read in text data size and address
off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8
text_data_sz = 1 << utils.read_u32(text_data_ring, off)
off = prb_data_ring_type.get_type()['data'].bitpos // 8
- addr = utils.read_ulong(text_data_ring, off)
- text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes()
+ text_data_addr = utils.read_ulong(text_data_ring, off)

counter_off = atomic_long_type.get_type()['counter'].bitpos // 8

@@ -102,17 +99,20 @@ class LxDmesg(gdb.Command):
desc_off = desc_sz * ind
info_off = info_sz * ind

+ desc = utils.read_memoryview(inf, desc_addr + desc_off, desc_sz).tobytes()
+
# skip non-committed record
- state = 3 & (utils.read_u64(descs, desc_off + sv_off +
- counter_off) >> desc_flags_shift)
+ state = 3 & (utils.read_u64(desc, sv_off + counter_off) >> desc_flags_shift)
if state != desc_committed and state != desc_finalized:
if did == head_id:
break
did = (did + 1) & desc_id_mask
continue

- begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz
- end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz
+ begin = utils.read_ulong(desc, begin_off) % text_data_sz
+ end = utils.read_ulong(desc, next_off) % text_data_sz
+
+ info = utils.read_memoryview(inf, info_addr + info_off, info_sz).tobytes()

# handle data-less record
if begin & 1 == 1:
@@ -125,16 +125,17 @@ class LxDmesg(gdb.Command):
# skip over descriptor id
text_start = begin + utils.get_long_type().sizeof

- text_len = utils.read_u16(infos, info_off + len_off)
+ text_len = utils.read_u16(info, len_off)

# handle truncated message
if end - text_start < text_len:
text_len = end - text_start

- text = text_data[text_start:text_start + text_len].decode(
- encoding='utf8', errors='replace')
+ text_data = utils.read_memoryview(inf, text_data_addr + text_start,
+ text_len).tobytes()
+ text = text_data[0:text_len].decode(encoding='utf8', errors='replace')

- time_stamp = utils.read_u64(infos, info_off + ts_off)
+ time_stamp = utils.read_u64(info, ts_off)

for line in text.splitlines():
msg = u"[{time:12.6f}] {line}\n".format(
--
2.35.1