mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
Merge tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull non-MM updates from Andrew Morton: "Mainly singleton patches all over the place. Series of note are: - updates to scripts/gdb from Glenn Washburn - kexec cleanups from Bjorn Helgaas" * tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (50 commits) mailmap: add entries for Paul Mackerras libgcc: add forward declarations for generic library routines mailmap: add entry for Oleksandr ocfs2: reduce ioctl stack usage fs/proc: add Kthread flag to /proc/$pid/status ia64: fix an addr to taddr in huge_pte_offset() checkpatch: introduce proper bindings license check epoll: rename global epmutex scripts/gdb: add GDB convenience functions $lx_dentry_name() and $lx_i_dentry() scripts/gdb: create linux/vfs.py for VFS related GDB helpers uapi/linux/const.h: prefer ISO-friendly __typeof__ delayacct: track delays from IRQ/SOFTIRQ scripts/gdb: timerlist: convert int chunks to str scripts/gdb: print interrupts scripts/gdb: raise error with reduced debugging information scripts/gdb: add a Radix Tree Parser lib/rbtree: use '+' instead of '|' for setting color. proc/stat: remove arch_idle_time() checkpatch: check for misuse of the link tags checkpatch: allow Closes tags with links ...
This commit is contained in:
@@ -41,6 +41,8 @@ are cached and potentially out of date"""
|
||||
self.show_subtree(child, level + 1)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
if utils.gdb_eval_or_none("clk_root_list") is None:
|
||||
raise gdb.GdbError("No clocks registered")
|
||||
gdb.write(" enable prepare protect \n")
|
||||
gdb.write(" clock count count count rate \n")
|
||||
gdb.write("------------------------------------------------------------------------\n")
|
||||
|
@@ -15,8 +15,10 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/threads.h>
|
||||
|
||||
/* We need to stringify expanded macros so that they can be parsed */
|
||||
@@ -39,6 +41,8 @@
|
||||
|
||||
import gdb
|
||||
|
||||
LX_CONFIG(CONFIG_DEBUG_INFO_REDUCED)
|
||||
|
||||
/* linux/clk-provider.h */
|
||||
if IS_BUILTIN(CONFIG_COMMON_CLK):
|
||||
LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
|
||||
@@ -54,6 +58,10 @@ LX_VALUE(SB_NODIRATIME)
|
||||
/* linux/htimer.h */
|
||||
LX_GDBPARSED(hrtimer_resolution)
|
||||
|
||||
/* linux/irq.h */
|
||||
LX_GDBPARSED(IRQD_LEVEL)
|
||||
LX_GDBPARSED(IRQ_HIDDEN)
|
||||
|
||||
/* linux/module.h */
|
||||
LX_GDBPARSED(MOD_TEXT)
|
||||
|
||||
@@ -71,6 +79,13 @@ LX_VALUE(NR_CPUS)
|
||||
/* linux/of_fdt.h> */
|
||||
LX_VALUE(OF_DT_HEADER)
|
||||
|
||||
/* linux/radix-tree.h */
|
||||
LX_GDBPARSED(RADIX_TREE_ENTRY_MASK)
|
||||
LX_GDBPARSED(RADIX_TREE_INTERNAL_NODE)
|
||||
LX_GDBPARSED(RADIX_TREE_MAP_SIZE)
|
||||
LX_GDBPARSED(RADIX_TREE_MAP_SHIFT)
|
||||
LX_GDBPARSED(RADIX_TREE_MAP_MASK)
|
||||
|
||||
/* Kernel Configs */
|
||||
LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
|
||||
LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
|
||||
@@ -78,3 +93,12 @@ LX_CONFIG(CONFIG_HIGH_RES_TIMERS)
|
||||
LX_CONFIG(CONFIG_NR_CPUS)
|
||||
LX_CONFIG(CONFIG_OF)
|
||||
LX_CONFIG(CONFIG_TICK_ONESHOT)
|
||||
LX_CONFIG(CONFIG_GENERIC_IRQ_SHOW_LEVEL)
|
||||
LX_CONFIG(CONFIG_X86_LOCAL_APIC)
|
||||
LX_CONFIG(CONFIG_SMP)
|
||||
LX_CONFIG(CONFIG_X86_THERMAL_VECTOR)
|
||||
LX_CONFIG(CONFIG_X86_MCE_THRESHOLD)
|
||||
LX_CONFIG(CONFIG_X86_MCE_AMD)
|
||||
LX_CONFIG(CONFIG_X86_MCE)
|
||||
LX_CONFIG(CONFIG_X86_IO_APIC)
|
||||
LX_CONFIG(CONFIG_HAVE_KVM)
|
||||
|
@@ -163,16 +163,22 @@ def get_current_task(cpu):
|
||||
task_ptr_type = task_type.get_type().pointer()
|
||||
|
||||
if utils.is_target_arch("x86"):
|
||||
var_ptr = gdb.parse_and_eval("&pcpu_hot.current_task")
|
||||
return per_cpu(var_ptr, cpu).dereference()
|
||||
if gdb.lookup_global_symbol("cpu_tasks"):
|
||||
# This is a UML kernel, which stores the current task
|
||||
# differently than other x86 sub architectures
|
||||
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")
|
||||
return per_cpu(var_ptr, cpu).dereference()
|
||||
elif utils.is_target_arch("aarch64"):
|
||||
current_task_addr = gdb.parse_and_eval("$SP_EL0")
|
||||
if((current_task_addr >> 63) != 0):
|
||||
current_task = current_task_addr.cast(task_ptr_type)
|
||||
return current_task.dereference()
|
||||
else:
|
||||
raise gdb.GdbError("Sorry, obtaining the current task is not allowed "
|
||||
"while running in userspace(EL0)")
|
||||
current_task_addr = gdb.parse_and_eval("$SP_EL0")
|
||||
if (current_task_addr >> 63) != 0:
|
||||
current_task = current_task_addr.cast(task_ptr_type)
|
||||
return current_task.dereference()
|
||||
else:
|
||||
raise gdb.GdbError("Sorry, obtaining the current task is not allowed "
|
||||
"while running in userspace(EL0)")
|
||||
else:
|
||||
raise gdb.GdbError("Sorry, obtaining the current task is not yet "
|
||||
"supported with this arch")
|
||||
|
@@ -5,7 +5,7 @@
|
||||
import gdb
|
||||
import sys
|
||||
|
||||
from linux.utils import CachedType
|
||||
from linux.utils import CachedType, gdb_eval_or_none
|
||||
from linux.lists import list_for_each_entry
|
||||
|
||||
generic_pm_domain_type = CachedType('struct generic_pm_domain')
|
||||
@@ -70,6 +70,8 @@ Output is similar to /sys/kernel/debug/pm_genpd/pm_genpd_summary'''
|
||||
gdb.write(' %-50s %s\n' % (kobj_path, rtpm_status_str(dev)))
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
if gdb_eval_or_none("&gpd_list") is None:
|
||||
raise gdb.GdbError("No power domain(s) registered")
|
||||
gdb.write('domain status children\n');
|
||||
gdb.write(' /device runtime status\n');
|
||||
gdb.write('----------------------------------------------------------------------\n');
|
||||
|
232
scripts/gdb/linux/interrupts.py
Normal file
232
scripts/gdb/linux/interrupts.py
Normal file
@@ -0,0 +1,232 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Copyright 2023 Broadcom
|
||||
|
||||
import gdb
|
||||
|
||||
from linux import constants
|
||||
from linux import cpus
|
||||
from linux import utils
|
||||
from linux import radixtree
|
||||
|
||||
irq_desc_type = utils.CachedType("struct irq_desc")
|
||||
|
||||
def irq_settings_is_hidden(desc):
|
||||
return desc['status_use_accessors'] & constants.LX_IRQ_HIDDEN
|
||||
|
||||
def irq_desc_is_chained(desc):
|
||||
return desc['action'] and desc['action'] == gdb.parse_and_eval("&chained_action")
|
||||
|
||||
def irqd_is_level(desc):
|
||||
return desc['irq_data']['common']['state_use_accessors'] & constants.LX_IRQD_LEVEL
|
||||
|
||||
def show_irq_desc(prec, irq):
|
||||
text = ""
|
||||
|
||||
desc = radixtree.lookup(gdb.parse_and_eval("&irq_desc_tree"), irq)
|
||||
if desc is None:
|
||||
return text
|
||||
|
||||
desc = desc.cast(irq_desc_type.get_type())
|
||||
if desc is None:
|
||||
return text
|
||||
|
||||
if irq_settings_is_hidden(desc):
|
||||
return text
|
||||
|
||||
any_count = 0
|
||||
if desc['kstat_irqs']:
|
||||
for cpu in cpus.each_online_cpu():
|
||||
any_count += cpus.per_cpu(desc['kstat_irqs'], cpu)
|
||||
|
||||
if (desc['action'] == 0 or irq_desc_is_chained(desc)) and any_count == 0:
|
||||
return text;
|
||||
|
||||
text += "%*d: " % (prec, irq)
|
||||
for cpu in cpus.each_online_cpu():
|
||||
if desc['kstat_irqs']:
|
||||
count = cpus.per_cpu(desc['kstat_irqs'], cpu)
|
||||
else:
|
||||
count = 0
|
||||
text += "%10u" % (count)
|
||||
|
||||
name = "None"
|
||||
if desc['irq_data']['chip']:
|
||||
chip = desc['irq_data']['chip']
|
||||
if chip['name']:
|
||||
name = chip['name'].string()
|
||||
else:
|
||||
name = "-"
|
||||
|
||||
text += " %8s" % (name)
|
||||
|
||||
if desc['irq_data']['domain']:
|
||||
text += " %*lu" % (prec, desc['irq_data']['hwirq'])
|
||||
else:
|
||||
text += " %*s" % (prec, "")
|
||||
|
||||
if constants.LX_CONFIG_GENERIC_IRQ_SHOW_LEVEL:
|
||||
text += " %-8s" % ("Level" if irqd_is_level(desc) else "Edge")
|
||||
|
||||
if desc['name']:
|
||||
text += "-%-8s" % (desc['name'].string())
|
||||
|
||||
""" Some toolchains may not be able to provide information about irqaction """
|
||||
try:
|
||||
gdb.lookup_type("struct irqaction")
|
||||
action = desc['action']
|
||||
if action is not None:
|
||||
text += " %s" % (action['name'].string())
|
||||
while True:
|
||||
action = action['next']
|
||||
if action is not None:
|
||||
break
|
||||
if action['name']:
|
||||
text += ", %s" % (action['name'].string())
|
||||
except:
|
||||
pass
|
||||
|
||||
text += "\n"
|
||||
|
||||
return text
|
||||
|
||||
def show_irq_err_count(prec):
|
||||
cnt = utils.gdb_eval_or_none("irq_err_count")
|
||||
text = ""
|
||||
if cnt is not None:
|
||||
text += "%*s: %10u\n" % (prec, "ERR", cnt['counter'])
|
||||
return text
|
||||
|
||||
def x86_show_irqstat(prec, pfx, field, desc):
|
||||
irq_stat = gdb.parse_and_eval("&irq_stat")
|
||||
text = "%*s: " % (prec, pfx)
|
||||
for cpu in cpus.each_online_cpu():
|
||||
stat = cpus.per_cpu(irq_stat, cpu)
|
||||
text += "%10u " % (stat[field])
|
||||
text += " %s\n" % (desc)
|
||||
return text
|
||||
|
||||
def x86_show_mce(prec, var, pfx, desc):
|
||||
pvar = gdb.parse_and_eval(var)
|
||||
text = "%*s: " % (prec, pfx)
|
||||
for cpu in cpus.each_online_cpu():
|
||||
text += "%10u " % (cpus.per_cpu(pvar, cpu))
|
||||
text += " %s\n" % (desc)
|
||||
return text
|
||||
|
||||
def x86_show_interupts(prec):
|
||||
text = x86_show_irqstat(prec, "NMI", '__nmi_count', 'Non-maskable interrupts')
|
||||
|
||||
if constants.LX_CONFIG_X86_LOCAL_APIC:
|
||||
text += x86_show_irqstat(prec, "LOC", 'apic_timer_irqs', "Local timer interrupts")
|
||||
text += x86_show_irqstat(prec, "SPU", 'irq_spurious_count', "Spurious interrupts")
|
||||
text += x86_show_irqstat(prec, "PMI", 'apic_perf_irqs', "Performance monitoring interrupts")
|
||||
text += x86_show_irqstat(prec, "IWI", 'apic_irq_work_irqs', "IRQ work interrupts")
|
||||
text += x86_show_irqstat(prec, "RTR", 'icr_read_retry_count', "APIC ICR read retries")
|
||||
if utils.gdb_eval_or_none("x86_platform_ipi_callback") is not None:
|
||||
text += x86_show_irqstat(prec, "PLT", 'x86_platform_ipis', "Platform interrupts")
|
||||
|
||||
if constants.LX_CONFIG_SMP:
|
||||
text += x86_show_irqstat(prec, "RES", 'irq_resched_count', "Rescheduling interrupts")
|
||||
text += x86_show_irqstat(prec, "CAL", 'irq_call_count', "Function call interrupts")
|
||||
text += x86_show_irqstat(prec, "TLB", 'irq_tlb_count', "TLB shootdowns")
|
||||
|
||||
if constants.LX_CONFIG_X86_THERMAL_VECTOR:
|
||||
text += x86_show_irqstat(prec, "TRM", 'irq_thermal_count', "Thermal events interrupts")
|
||||
|
||||
if constants.LX_CONFIG_X86_MCE_THRESHOLD:
|
||||
text += x86_show_irqstat(prec, "THR", 'irq_threshold_count', "Threshold APIC interrupts")
|
||||
|
||||
if constants.LX_CONFIG_X86_MCE_AMD:
|
||||
text += x86_show_irqstat(prec, "DFR", 'irq_deferred_error_count', "Deferred Error APIC interrupts")
|
||||
|
||||
if constants.LX_CONFIG_X86_MCE:
|
||||
text += x86_show_mce(prec, "&mce_exception_count", "MCE", "Machine check exceptions")
|
||||
text == x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls")
|
||||
|
||||
text += show_irq_err_count(prec)
|
||||
|
||||
if constants.LX_CONFIG_X86_IO_APIC:
|
||||
cnt = utils.gdb_eval_or_none("irq_mis_count")
|
||||
if cnt is not None:
|
||||
text += "%*s: %10u\n" % (prec, "MIS", cnt['counter'])
|
||||
|
||||
if constants.LX_CONFIG_HAVE_KVM:
|
||||
text += x86_show_irqstat(prec, "PIN", 'kvm_posted_intr_ipis', 'Posted-interrupt notification event')
|
||||
text += x86_show_irqstat(prec, "NPI", 'kvm_posted_intr_nested_ipis', 'Nested posted-interrupt event')
|
||||
text += x86_show_irqstat(prec, "PIW", 'kvm_posted_intr_wakeup_ipis', 'Posted-interrupt wakeup event')
|
||||
|
||||
return text
|
||||
|
||||
def arm_common_show_interrupts(prec):
|
||||
text = ""
|
||||
nr_ipi = utils.gdb_eval_or_none("nr_ipi")
|
||||
ipi_desc = utils.gdb_eval_or_none("ipi_desc")
|
||||
ipi_types = utils.gdb_eval_or_none("ipi_types")
|
||||
if nr_ipi is None or ipi_desc is None or ipi_types is None:
|
||||
return text
|
||||
|
||||
if prec >= 4:
|
||||
sep = " "
|
||||
else:
|
||||
sep = ""
|
||||
|
||||
for ipi in range(nr_ipi):
|
||||
text += "%*s%u:%s" % (prec - 1, "IPI", ipi, sep)
|
||||
desc = ipi_desc[ipi].cast(irq_desc_type.get_type().pointer())
|
||||
if desc == 0:
|
||||
continue
|
||||
for cpu in cpus.each_online_cpu():
|
||||
text += "%10u" % (cpus.per_cpu(desc['kstat_irqs'], cpu))
|
||||
text += " %s" % (ipi_types[ipi].string())
|
||||
text += "\n"
|
||||
return text
|
||||
|
||||
def aarch64_show_interrupts(prec):
|
||||
text = arm_common_show_interrupts(prec)
|
||||
text += "%*s: %10lu\n" % (prec, "ERR", gdb.parse_and_eval("irq_err_count"))
|
||||
return text
|
||||
|
||||
def arch_show_interrupts(prec):
|
||||
text = ""
|
||||
if utils.is_target_arch("x86"):
|
||||
text += x86_show_interupts(prec)
|
||||
elif utils.is_target_arch("aarch64"):
|
||||
text += aarch64_show_interrupts(prec)
|
||||
elif utils.is_target_arch("arm"):
|
||||
text += arm_common_show_interrupts(prec)
|
||||
elif utils.is_target_arch("mips"):
|
||||
text += show_irq_err_count(prec)
|
||||
else:
|
||||
raise gdb.GdbError("Unsupported architecture: {}".format(target_arch))
|
||||
|
||||
return text
|
||||
|
||||
class LxInterruptList(gdb.Command):
|
||||
"""Print /proc/interrupts"""
|
||||
|
||||
def __init__(self):
|
||||
super(LxInterruptList, self).__init__("lx-interruptlist", gdb.COMMAND_DATA)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
nr_irqs = gdb.parse_and_eval("nr_irqs")
|
||||
prec = 3
|
||||
j = 1000
|
||||
while prec < 10 and j <= nr_irqs:
|
||||
prec += 1
|
||||
j *= 10
|
||||
|
||||
gdb.write("%*s" % (prec + 8, ""))
|
||||
for cpu in cpus.each_online_cpu():
|
||||
gdb.write("CPU%-8d" % cpu)
|
||||
gdb.write("\n")
|
||||
|
||||
if utils.gdb_eval_or_none("&irq_desc_tree") is None:
|
||||
return
|
||||
|
||||
for irq in range(nr_irqs):
|
||||
gdb.write(show_irq_desc(prec, irq))
|
||||
gdb.write(arch_show_interrupts(prec))
|
||||
|
||||
|
||||
LxInterruptList()
|
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# gdb helper commands and functions for Linux kernel debugging
|
||||
#
|
||||
@@ -16,6 +17,7 @@ from linux import constants
|
||||
from linux import utils
|
||||
from linux import tasks
|
||||
from linux import lists
|
||||
from linux import vfs
|
||||
from struct import *
|
||||
|
||||
|
||||
@@ -170,16 +172,16 @@ values of that process namespace"""
|
||||
gdb.write("{:^18} {:^15} {:>9} {} {} options\n".format(
|
||||
"mount", "super_block", "devname", "pathname", "fstype"))
|
||||
|
||||
for vfs in lists.list_for_each_entry(namespace['list'],
|
||||
for mnt in lists.list_for_each_entry(namespace['list'],
|
||||
mount_ptr_type, "mnt_list"):
|
||||
devname = vfs['mnt_devname'].string()
|
||||
devname = mnt['mnt_devname'].string()
|
||||
devname = devname if devname else "none"
|
||||
|
||||
pathname = ""
|
||||
parent = vfs
|
||||
parent = mnt
|
||||
while True:
|
||||
mntpoint = parent['mnt_mountpoint']
|
||||
pathname = utils.dentry_name(mntpoint) + pathname
|
||||
pathname = vfs.dentry_name(mntpoint) + pathname
|
||||
if (parent == parent['mnt_parent']):
|
||||
break
|
||||
parent = parent['mnt_parent']
|
||||
@@ -187,14 +189,14 @@ values of that process namespace"""
|
||||
if (pathname == ""):
|
||||
pathname = "/"
|
||||
|
||||
superblock = vfs['mnt']['mnt_sb']
|
||||
superblock = mnt['mnt']['mnt_sb']
|
||||
fstype = superblock['s_type']['name'].string()
|
||||
s_flags = int(superblock['s_flags'])
|
||||
m_flags = int(vfs['mnt']['mnt_flags'])
|
||||
m_flags = int(mnt['mnt']['mnt_flags'])
|
||||
rd = "ro" if (s_flags & constants.LX_SB_RDONLY) else "rw"
|
||||
|
||||
gdb.write("{} {} {} {} {} {}{}{} 0 0\n".format(
|
||||
vfs.format_string(), superblock.format_string(), devname,
|
||||
mnt.format_string(), superblock.format_string(), devname,
|
||||
pathname, fstype, rd, info_opts(FS_INFO, s_flags),
|
||||
info_opts(MNT_INFO, m_flags)))
|
||||
|
||||
|
90
scripts/gdb/linux/radixtree.py
Normal file
90
scripts/gdb/linux/radixtree.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Radix Tree Parser
|
||||
#
|
||||
# Copyright (c) 2016 Linaro Ltd
|
||||
# Copyright (c) 2023 Broadcom
|
||||
#
|
||||
# Authors:
|
||||
# Kieran Bingham <kieran.bingham@linaro.org>
|
||||
# Florian Fainelli <f.fainelli@gmail.com>
|
||||
|
||||
import gdb
|
||||
|
||||
from linux import utils
|
||||
from linux import constants
|
||||
|
||||
radix_tree_root_type = utils.CachedType("struct xarray")
|
||||
radix_tree_node_type = utils.CachedType("struct xa_node")
|
||||
|
||||
def is_internal_node(node):
|
||||
long_type = utils.get_long_type()
|
||||
return ((node.cast(long_type) & constants.LX_RADIX_TREE_ENTRY_MASK) == constants.LX_RADIX_TREE_INTERNAL_NODE)
|
||||
|
||||
def entry_to_node(node):
|
||||
long_type = utils.get_long_type()
|
||||
node_type = node.type
|
||||
indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INTERNAL_NODE
|
||||
return indirect_ptr.cast(radix_tree_node_type.get_type().pointer())
|
||||
|
||||
def node_maxindex(node):
|
||||
return (constants.LX_RADIX_TREE_MAP_SIZE << node['shift']) - 1
|
||||
|
||||
def lookup(root, index):
|
||||
if root.type == radix_tree_root_type.get_type().pointer():
|
||||
node = root.dereference()
|
||||
elif root.type != radix_tree_root_type.get_type():
|
||||
raise gdb.GdbError("must be {} not {}"
|
||||
.format(radix_tree_root_type.get_type(), root.type))
|
||||
|
||||
node = root['xa_head']
|
||||
if node == 0:
|
||||
return None
|
||||
|
||||
if not (is_internal_node(node)):
|
||||
if (index > 0):
|
||||
return None
|
||||
return node
|
||||
|
||||
node = entry_to_node(node)
|
||||
maxindex = node_maxindex(node)
|
||||
|
||||
if (index > maxindex):
|
||||
return None
|
||||
|
||||
shift = node['shift'] + constants.LX_RADIX_TREE_MAP_SHIFT
|
||||
|
||||
while True:
|
||||
offset = (index >> node['shift']) & constants.LX_RADIX_TREE_MAP_MASK
|
||||
slot = node['slots'][offset]
|
||||
|
||||
if slot == 0:
|
||||
return None
|
||||
|
||||
node = slot.cast(node.type.pointer()).dereference()
|
||||
if node == 0:
|
||||
return None
|
||||
|
||||
shift -= constants.LX_RADIX_TREE_MAP_SHIFT
|
||||
if (shift <= 0):
|
||||
break
|
||||
|
||||
return node
|
||||
|
||||
class LxRadixTree(gdb.Function):
|
||||
""" Lookup and return a node from a RadixTree.
|
||||
|
||||
$lx_radix_tree_lookup(root_node [, index]): Return the node at the given index.
|
||||
If index is omitted, the root node is dereference and returned."""
|
||||
|
||||
def __init__(self):
|
||||
super(LxRadixTree, self).__init__("lx_radix_tree_lookup")
|
||||
|
||||
def invoke(self, root, index=0):
|
||||
result = lookup(root, index)
|
||||
if result is None:
|
||||
raise gdb.GdbError("No entry in tree at index {}".format(index))
|
||||
|
||||
return result
|
||||
|
||||
LxRadixTree()
|
@@ -43,8 +43,7 @@ def print_timer(rb_node, idx):
|
||||
|
||||
|
||||
def print_active_timers(base):
|
||||
curr = base['active']['next']['node']
|
||||
curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
|
||||
curr = base['active']['rb_root']['rb_leftmost']
|
||||
idx = 0
|
||||
while curr:
|
||||
yield print_timer(curr, idx)
|
||||
@@ -73,7 +72,7 @@ def print_cpu(hrtimer_bases, cpu, max_clock_bases):
|
||||
ts = cpus.per_cpu(tick_sched_ptr, cpu)
|
||||
|
||||
text = "cpu: {}\n".format(cpu)
|
||||
for i in xrange(max_clock_bases):
|
||||
for i in range(max_clock_bases):
|
||||
text += " clock {}:\n".format(i)
|
||||
text += print_base(cpu_base['clock_base'][i])
|
||||
|
||||
@@ -158,6 +157,8 @@ def pr_cpumask(mask):
|
||||
num_bytes = (nr_cpu_ids + 7) / 8
|
||||
buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
|
||||
buf = binascii.b2a_hex(buf)
|
||||
if type(buf) is not str:
|
||||
buf=buf.decode()
|
||||
|
||||
chunks = []
|
||||
i = num_bytes
|
||||
@@ -173,7 +174,7 @@ def pr_cpumask(mask):
|
||||
if 0 < extra <= 4:
|
||||
chunks[0] = chunks[0][0] # Cut off the first 0
|
||||
|
||||
return "".join(chunks)
|
||||
return "".join(str(chunks))
|
||||
|
||||
|
||||
class LxTimerList(gdb.Command):
|
||||
@@ -187,7 +188,8 @@ class LxTimerList(gdb.Command):
|
||||
max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
|
||||
|
||||
text = "Timer List Version: gdb scripts\n"
|
||||
text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
|
||||
text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(
|
||||
max_clock_bases.type.fields()[max_clock_bases].enumval)
|
||||
text += "now at {} nsecs\n".format(ktime_get())
|
||||
|
||||
for cpu in cpus.each_online_cpu():
|
||||
|
@@ -88,7 +88,10 @@ def get_target_endianness():
|
||||
|
||||
|
||||
def read_memoryview(inf, start, length):
|
||||
return memoryview(inf.read_memory(start, length))
|
||||
m = inf.read_memory(start, length)
|
||||
if type(m) is memoryview:
|
||||
return m
|
||||
return memoryview(m)
|
||||
|
||||
|
||||
def read_u16(buffer, offset):
|
||||
@@ -193,11 +196,3 @@ def gdb_eval_or_none(expresssion):
|
||||
return gdb.parse_and_eval(expresssion)
|
||||
except gdb.error:
|
||||
return None
|
||||
|
||||
|
||||
def dentry_name(d):
|
||||
parent = d['d_parent']
|
||||
if parent == d or parent == 0:
|
||||
return ""
|
||||
p = dentry_name(d['d_parent']) + "/"
|
||||
return p + d['d_iname'].string()
|
||||
|
59
scripts/gdb/linux/vfs.py
Normal file
59
scripts/gdb/linux/vfs.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# gdb helper commands and functions for Linux kernel debugging
|
||||
#
|
||||
# VFS tools
|
||||
#
|
||||
# Copyright (c) 2023 Glenn Washburn
|
||||
# Copyright (c) 2016 Linaro Ltd
|
||||
#
|
||||
# Authors:
|
||||
# Glenn Washburn <development@efficientek.com>
|
||||
# Kieran Bingham <kieran.bingham@linaro.org>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPL version 2.
|
||||
#
|
||||
|
||||
import gdb
|
||||
from linux import utils
|
||||
|
||||
|
||||
def dentry_name(d):
|
||||
parent = d['d_parent']
|
||||
if parent == d or parent == 0:
|
||||
return ""
|
||||
p = dentry_name(d['d_parent']) + "/"
|
||||
return p + d['d_iname'].string()
|
||||
|
||||
class DentryName(gdb.Function):
|
||||
"""Return string of the full path of a dentry.
|
||||
|
||||
$lx_dentry_name(PTR): Given PTR to a dentry struct, return a string
|
||||
of the full path of the dentry."""
|
||||
|
||||
def __init__(self):
|
||||
super(DentryName, self).__init__("lx_dentry_name")
|
||||
|
||||
def invoke(self, dentry_ptr):
|
||||
return dentry_name(dentry_ptr)
|
||||
|
||||
DentryName()
|
||||
|
||||
|
||||
dentry_type = utils.CachedType("struct dentry")
|
||||
|
||||
class InodeDentry(gdb.Function):
|
||||
"""Return dentry pointer for inode.
|
||||
|
||||
$lx_i_dentry(PTR): Given PTR to an inode struct, return a pointer to
|
||||
the associated dentry struct, if there is one."""
|
||||
|
||||
def __init__(self):
|
||||
super(InodeDentry, self).__init__("lx_i_dentry")
|
||||
|
||||
def invoke(self, inode_ptr):
|
||||
d_u = inode_ptr["i_dentry"]["first"]
|
||||
if d_u == 0:
|
||||
return ""
|
||||
return utils.container_of(d_u, dentry_type.get_type().pointer(), "d_u")
|
||||
|
||||
InodeDentry()
|
@@ -22,6 +22,10 @@ except:
|
||||
gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
|
||||
"work.\n")
|
||||
else:
|
||||
import linux.constants
|
||||
if linux.constants.LX_CONFIG_DEBUG_INFO_REDUCED:
|
||||
raise gdb.GdbError("Reduced debug information will prevent GDB "
|
||||
"from having complete types.\n")
|
||||
import linux.utils
|
||||
import linux.symbols
|
||||
import linux.modules
|
||||
@@ -32,9 +36,11 @@ else:
|
||||
import linux.lists
|
||||
import linux.rbtree
|
||||
import linux.proc
|
||||
import linux.constants
|
||||
import linux.timerlist
|
||||
import linux.clk
|
||||
import linux.genpd
|
||||
import linux.device
|
||||
import linux.vfs
|
||||
import linux.mm
|
||||
import linux.radixtree
|
||||
import linux.interrupts
|
||||
|
Reference in New Issue
Block a user