summaryrefslogtreecommitdiff
path: root/scripts/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gdb')
-rw-r--r--scripts/gdb/linux/cpus.py26
-rw-r--r--scripts/gdb/linux/symbols.py44
-rw-r--r--scripts/gdb/linux/utils.py35
3 files changed, 96 insertions, 9 deletions
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index 2f11c4f9c345..f506965ea759 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -46,7 +46,7 @@ def per_cpu(var_ptr, cpu):
# !CONFIG_SMP case
offset = 0
pointer = var_ptr.cast(utils.get_long_type()) + offset
- return pointer.cast(var_ptr.type).dereference()
+ return pointer.cast(var_ptr.type)
cpu_mask = {}
@@ -149,11 +149,29 @@ Note that VAR has to be quoted as string."""
super(PerCpu, self).__init__("lx_per_cpu")
def invoke(self, var, cpu=-1):
- return per_cpu(var.address, cpu)
+ return per_cpu(var.address, cpu).dereference()
PerCpu()
+
+class PerCpuPtr(gdb.Function):
+ """Return per-cpu pointer.
+
+$lx_per_cpu_ptr("VAR"[, CPU]): Return the per-cpu pointer called VAR for the
+given CPU number. If CPU is omitted, the CPU of the current context is used.
+Note that VAR has to be quoted as string."""
+
+ def __init__(self):
+ super(PerCpuPtr, self).__init__("lx_per_cpu_ptr")
+
+ def invoke(self, var, cpu=-1):
+ return per_cpu(var, cpu)
+
+
+PerCpuPtr()
+
+
def get_current_task(cpu):
task_ptr_type = task_type.get_type().pointer()
@@ -164,10 +182,10 @@ def get_current_task(cpu):
var_ptr = gdb.parse_and_eval("(struct task_struct *)cpu_tasks[0].task")
return var_ptr.dereference()
else:
- var_ptr = gdb.parse_and_eval("&pcpu_hot.current_task")
+ var_ptr = gdb.parse_and_eval("&current_task")
return per_cpu(var_ptr, cpu).dereference()
elif utils.is_target_arch("aarch64"):
- current_task_addr = gdb.parse_and_eval("$SP_EL0")
+ current_task_addr = gdb.parse_and_eval("(unsigned long)$SP_EL0")
if (current_task_addr >> 63) != 0:
current_task = current_task_addr.cast(task_ptr_type)
return current_task.dereference()
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index f6c1b063775a..b255177301e9 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -14,7 +14,9 @@
import gdb
import os
import re
+import struct
+from itertools import count
from linux import modules, utils, constants
@@ -53,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.
@@ -95,10 +120,14 @@ lx-symbols command."""
except gdb.error:
return str(module_addr)
- attrs = sect_attrs['attrs']
- section_name_to_address = {
- attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
- for n in range(int(sect_attrs['nsections']))}
+ section_name_to_address = {}
+ for i in count():
+ # this is a NULL terminated array
+ if sect_attrs['grp']['bin_attrs'][i] == 0x0:
+ break
+
+ attr = sect_attrs['grp']['bin_attrs'][i].dereference()
+ section_name_to_address[attr['attr']['name'].string()] = attr['private']
textaddr = section_name_to_address.get(".text", module_addr)
args = []
@@ -155,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)