diff options
author | Ilya Leoshkevich <iii@linux.ibm.com> | 2025-03-03 12:03:58 +0100 |
---|---|---|
committer | Andrew Morton <akpm@linux-foundation.org> | 2025-03-17 12:17:00 -0700 |
commit | 28939c3e9925735166e7b6e42f9e1dc828093510 (patch) | |
tree | 19c774d4e67f4c7bb7e78edcda0a8f8a75033e88 /scripts | |
parent | 8a56f26607418ab517476de4a27e38be51f6fbca (diff) |
scripts/gdb/symbols: determine KASLR offset on s390
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
Link: https://lkml.kernel.org/r/20250303110437.79070-1-iii@linux.ibm.com
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Acked-by: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Andrew Donnellan <ajd@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Kieran Bingham <kbingham@kernel.org>
Cc: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/gdb/linux/symbols.py | 31 | ||||
-rw-r--r-- | scripts/gdb/linux/utils.py | 35 |
2 files changed, 65 insertions, 1 deletions
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index 15d76f7d8ebc..b255177301e9 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 itertools import count from linux import modules, utils, constants @@ -54,6 +55,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. @@ -160,7 +184,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) |