2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

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>
This commit is contained in:
Ilya Leoshkevich 2025-03-03 12:03:58 +01:00 committed by Andrew Morton
parent 8a56f26607
commit 28939c3e99
2 changed files with 65 additions and 1 deletions

View File

@ -14,6 +14,7 @@
import gdb import gdb
import os import os
import re import re
import struct
from itertools import count from itertools import count
from linux import modules, utils, constants from linux import modules, utils, constants
@ -54,6 +55,29 @@ if hasattr(gdb, 'Breakpoint'):
return False 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): class LxSymbols(gdb.Command):
"""(Re-)load symbols of Linux kernel and currently loaded modules. """(Re-)load symbols of Linux kernel and currently loaded modules.
@ -160,7 +184,12 @@ lx-symbols command."""
obj.filename.endswith('vmlinux.debug')): obj.filename.endswith('vmlinux.debug')):
orig_vmlinux = obj.filename orig_vmlinux = obj.filename
gdb.execute("symbol-file", to_string=True) 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 = [] self.loaded_modules = []
module_list = modules.module_list() module_list = modules.module_list()

View File

@ -11,6 +11,11 @@
# This work is licensed under the terms of the GNU GPL version 2. # This work is licensed under the terms of the GNU GPL version 2.
# #
import contextlib
import dataclasses
import re
import typing
import gdb import gdb
@ -216,3 +221,33 @@ def gdb_eval_or_none(expresssion):
return gdb.parse_and_eval(expresssion) return gdb.parse_and_eval(expresssion)
except gdb.error: except gdb.error:
return None 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)