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:
parent
8a56f26607
commit
28939c3e99
@ -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()
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user