scripts/gdb/linux/symbols.py | 31 ++++++++++++++++++++++++++++++- scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-)
Use QEMU's qemu.PhyMemMode [1] functionality to read vmcore from the
physical memory the same way the existing dump tooling does this.
Gracefully handle non-QEMU targets, early boot, and memory corruptions;
print a warning if such situation is detected.
[1] https://qemu-project.gitlab.io/qemu/system/gdb.html#examining-physical-memory
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
scripts/gdb/linux/symbols.py | 31 ++++++++++++++++++++++++++++++-
scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index f6c1b063775a..3126329c7f26 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -14,6 +14,7 @@
import gdb
import os
import re
+import struct
from linux import modules, utils, constants
@@ -53,6 +54,29 @@ if hasattr(gdb, 'Breakpoint'):
return False
+def get_vmcore_s390():
+ with utils.qemu_phy_mem_mode():
+ vmcore_info = 0x0e0c
+ paddr_vmcoreinfo_note = gdb.parse_and_eval("*(unsigned long long *)" +
+ hex(vmcore_info))
+ inferior = gdb.selected_inferior()
+ elf_note = inferior.read_memory(paddr_vmcoreinfo_note, 12)
+ n_namesz, n_descsz, n_type = struct.unpack(">III", elf_note)
+ desc_paddr = paddr_vmcoreinfo_note + len(elf_note) + n_namesz + 1
+ return gdb.parse_and_eval("(char *)" + hex(desc_paddr)).string()
+
+
+def get_kerneloffset():
+ if utils.is_target_arch('s390'):
+ try:
+ vmcore_str = get_vmcore_s390()
+ except gdb.error as e:
+ gdb.write("{}\n".format(e))
+ return None
+ return utils.parse_vmcore(vmcore_str).kerneloffset
+ return None
+
+
class LxSymbols(gdb.Command):
"""(Re-)load symbols of Linux kernel and currently loaded modules.
@@ -155,7 +179,12 @@ lx-symbols command."""
obj.filename.endswith('vmlinux.debug')):
orig_vmlinux = obj.filename
gdb.execute("symbol-file", to_string=True)
- gdb.execute("symbol-file {0}".format(orig_vmlinux))
+ kerneloffset = get_kerneloffset()
+ if kerneloffset is None:
+ offset_arg = ""
+ else:
+ offset_arg = " -o " + hex(kerneloffset)
+ gdb.execute("symbol-file {0}{1}".format(orig_vmlinux, offset_arg))
self.loaded_modules = []
module_list = modules.module_list()
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 245ab297ea84..03ebdccf5f69 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -11,6 +11,11 @@
# This work is licensed under the terms of the GNU GPL version 2.
#
+import contextlib
+import dataclasses
+import re
+import typing
+
import gdb
@@ -216,3 +221,33 @@ def gdb_eval_or_none(expresssion):
return gdb.parse_and_eval(expresssion)
except gdb.error:
return None
+
+
+@contextlib.contextmanager
+def qemu_phy_mem_mode():
+ connection = gdb.selected_inferior().connection
+ orig = connection.send_packet("qqemu.PhyMemMode")
+ if orig not in b"01":
+ raise gdb.error("Unexpected qemu.PhyMemMode")
+ orig = orig.decode()
+ if connection.send_packet("Qqemu.PhyMemMode:1") != b"OK":
+ raise gdb.error("Failed to set qemu.PhyMemMode")
+ try:
+ yield
+ finally:
+ if connection.send_packet("Qqemu.PhyMemMode:" + orig) != b"OK":
+ raise gdb.error("Failed to restore qemu.PhyMemMode")
+
+
+@dataclasses.dataclass
+class VmCore:
+ kerneloffset: typing.Optional[int]
+
+
+def parse_vmcore(s):
+ match = re.search(r"KERNELOFFSET=([0-9a-f]+)", s)
+ if match is None:
+ kerneloffset = None
+ else:
+ kerneloffset = int(match.group(1), 16)
+ return VmCore(kerneloffset=kerneloffset)
--
2.48.1
On Mon, Mar 03, 2025 at 12:03:58PM +0100, Ilya Leoshkevich wrote: > Use QEMU's qemu.PhyMemMode [1] functionality to read vmcore from the > physical memory the same way the existing dump tooling does this. > Gracefully handle non-QEMU targets, early boot, and memory corruptions; > print a warning if such situation is detected. > > [1] https://qemu-project.gitlab.io/qemu/system/gdb.html#examining-physical-memory > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > scripts/gdb/linux/symbols.py | 31 ++++++++++++++++++++++++++++++- > scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++ > 2 files changed, 65 insertions(+), 1 deletion(-) Can not tell for the gdb part, but for the s390 bits: Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
On 03.03.25 12:03, Ilya Leoshkevich wrote:
> Use QEMU's qemu.PhyMemMode [1] functionality to read vmcore from the
> physical memory the same way the existing dump tooling does this.
> Gracefully handle non-QEMU targets, early boot, and memory corruptions;
> print a warning if such situation is detected.
>
> [1] https://qemu-project.gitlab.io/qemu/system/gdb.html#examining-physical-memory
>
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
> scripts/gdb/linux/symbols.py | 31 ++++++++++++++++++++++++++++++-
> scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++
> 2 files changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
> index f6c1b063775a..3126329c7f26 100644
> --- a/scripts/gdb/linux/symbols.py
> +++ b/scripts/gdb/linux/symbols.py
> @@ -14,6 +14,7 @@
> import gdb
> import os
> import re
> +import struct
>
> from linux import modules, utils, constants
>
> @@ -53,6 +54,29 @@ if hasattr(gdb, 'Breakpoint'):
> return False
>
>
> +def get_vmcore_s390():
> + with utils.qemu_phy_mem_mode():
> + vmcore_info = 0x0e0c
> + paddr_vmcoreinfo_note = gdb.parse_and_eval("*(unsigned long long *)" +
> + hex(vmcore_info))
> + inferior = gdb.selected_inferior()
> + elf_note = inferior.read_memory(paddr_vmcoreinfo_note, 12)
> + n_namesz, n_descsz, n_type = struct.unpack(">III", elf_note)
> + desc_paddr = paddr_vmcoreinfo_note + len(elf_note) + n_namesz + 1
> + return gdb.parse_and_eval("(char *)" + hex(desc_paddr)).string()
> +
> +
> +def get_kerneloffset():
> + if utils.is_target_arch('s390'):
> + try:
> + vmcore_str = get_vmcore_s390()
> + except gdb.error as e:
> + gdb.write("{}\n".format(e))
> + return None
> + return utils.parse_vmcore(vmcore_str).kerneloffset
> + return None
> +
> +
> class LxSymbols(gdb.Command):
> """(Re-)load symbols of Linux kernel and currently loaded modules.
>
> @@ -155,7 +179,12 @@ lx-symbols command."""
> obj.filename.endswith('vmlinux.debug')):
> orig_vmlinux = obj.filename
> gdb.execute("symbol-file", to_string=True)
> - gdb.execute("symbol-file {0}".format(orig_vmlinux))
> + kerneloffset = get_kerneloffset()
> + if kerneloffset is None:
> + offset_arg = ""
> + else:
> + offset_arg = " -o " + hex(kerneloffset)
> + gdb.execute("symbol-file {0}{1}".format(orig_vmlinux, offset_arg))
>
> self.loaded_modules = []
> module_list = modules.module_list()
> diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
> index 245ab297ea84..03ebdccf5f69 100644
> --- a/scripts/gdb/linux/utils.py
> +++ b/scripts/gdb/linux/utils.py
> @@ -11,6 +11,11 @@
> # This work is licensed under the terms of the GNU GPL version 2.
> #
>
> +import contextlib
> +import dataclasses
> +import re
> +import typing
> +
> import gdb
>
>
> @@ -216,3 +221,33 @@ def gdb_eval_or_none(expresssion):
> return gdb.parse_and_eval(expresssion)
> except gdb.error:
> return None
> +
> +
> +@contextlib.contextmanager
> +def qemu_phy_mem_mode():
> + connection = gdb.selected_inferior().connection
> + orig = connection.send_packet("qqemu.PhyMemMode")
> + if orig not in b"01":
> + raise gdb.error("Unexpected qemu.PhyMemMode")
> + orig = orig.decode()
> + if connection.send_packet("Qqemu.PhyMemMode:1") != b"OK":
> + raise gdb.error("Failed to set qemu.PhyMemMode")
> + try:
> + yield
> + finally:
> + if connection.send_packet("Qqemu.PhyMemMode:" + orig) != b"OK":
> + raise gdb.error("Failed to restore qemu.PhyMemMode")
> +
> +
> +@dataclasses.dataclass
> +class VmCore:
> + kerneloffset: typing.Optional[int]
> +
> +
> +def parse_vmcore(s):
> + match = re.search(r"KERNELOFFSET=([0-9a-f]+)", s)
> + if match is None:
> + kerneloffset = None
> + else:
> + kerneloffset = int(match.group(1), 16)
> + return VmCore(kerneloffset=kerneloffset)
Nice trick with qemu. Can't comment on the s390-specifics in this, but
the rest looks fine to me. Just wish there was something similar for
other the archs.
Acked-by: Jan Kiszka <jan.kiszka@siemens.com>
Jan
--
Siemens AG, Foundational Technologies
Linux Expert Center
© 2016 - 2026 Red Hat, Inc.