mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
scripts/gdb: add rb tree iterating utilities
Implement gdb functions for rb_first(), rb_last(), rb_next(), and rb_prev(). These can be useful to iterate through the kernel's red-black trees. [swboyd@chromium.org: v2] Link: http://lkml.kernel.org/r/20190329220844.38234-4-swboyd@chromium.org Link: http://lkml.kernel.org/r/20190325184522.260535-4-swboyd@chromium.org Signed-off-by: Stephen Boyd <swboyd@chromium.org> Cc: Douglas Anderson <dianders@chromium.org> Cc: Nikolay Borisov <n.borisov.lkml@gmail.com> Cc: Kieran Bingham <kbingham@kernel.org> Cc: Jan Kiszka <jan.kiszka@siemens.com> Cc: Jackie Liu <liuyun01@kylinos.cn> Cc: Jason Wessel <jason.wessel@windriver.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
90cf83dbd2
commit
449ca0c95e
177
scripts/gdb/linux/rbtree.py
Normal file
177
scripts/gdb/linux/rbtree.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
#
|
||||||
|
# Copyright 2019 Google LLC.
|
||||||
|
|
||||||
|
import gdb
|
||||||
|
|
||||||
|
from linux import utils
|
||||||
|
|
||||||
|
rb_root_type = utils.CachedType("struct rb_root")
|
||||||
|
rb_node_type = utils.CachedType("struct rb_node")
|
||||||
|
|
||||||
|
|
||||||
|
def rb_first(root):
|
||||||
|
if root.type == rb_root_type.get_type():
|
||||||
|
node = node.address.cast(rb_root_type.get_type().pointer())
|
||||||
|
elif root.type != rb_root_type.get_type().pointer():
|
||||||
|
raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
|
||||||
|
|
||||||
|
node = root['rb_node']
|
||||||
|
if node is 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
while node['rb_left']:
|
||||||
|
node = node['rb_left']
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def rb_last(root):
|
||||||
|
if root.type == rb_root_type.get_type():
|
||||||
|
node = node.address.cast(rb_root_type.get_type().pointer())
|
||||||
|
elif root.type != rb_root_type.get_type().pointer():
|
||||||
|
raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
|
||||||
|
|
||||||
|
node = root['rb_node']
|
||||||
|
if node is 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
while node['rb_right']:
|
||||||
|
node = node['rb_right']
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def rb_parent(node):
|
||||||
|
parent = gdb.Value(node['__rb_parent_color'] & ~3)
|
||||||
|
return parent.cast(rb_node_type.get_type().pointer())
|
||||||
|
|
||||||
|
|
||||||
|
def rb_empty_node(node):
|
||||||
|
return node['__rb_parent_color'] == node.address
|
||||||
|
|
||||||
|
|
||||||
|
def rb_next(node):
|
||||||
|
if node.type == rb_node_type.get_type():
|
||||||
|
node = node.address.cast(rb_node_type.get_type().pointer())
|
||||||
|
elif node.type != rb_node_type.get_type().pointer():
|
||||||
|
raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
|
||||||
|
|
||||||
|
if rb_empty_node(node):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if node['rb_right']:
|
||||||
|
node = node['rb_right']
|
||||||
|
while node['rb_left']:
|
||||||
|
node = node['rb_left']
|
||||||
|
return node
|
||||||
|
|
||||||
|
parent = rb_parent(node)
|
||||||
|
while parent and node == parent['rb_right']:
|
||||||
|
node = parent
|
||||||
|
parent = rb_parent(node)
|
||||||
|
|
||||||
|
return parent
|
||||||
|
|
||||||
|
|
||||||
|
def rb_prev(node):
|
||||||
|
if node.type == rb_node_type.get_type():
|
||||||
|
node = node.address.cast(rb_node_type.get_type().pointer())
|
||||||
|
elif node.type != rb_node_type.get_type().pointer():
|
||||||
|
raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
|
||||||
|
|
||||||
|
if rb_empty_node(node):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if node['rb_left']:
|
||||||
|
node = node['rb_left']
|
||||||
|
while node['rb_right']:
|
||||||
|
node = node['rb_right']
|
||||||
|
return node.dereference()
|
||||||
|
|
||||||
|
parent = rb_parent(node)
|
||||||
|
while parent and node == parent['rb_left'].dereference():
|
||||||
|
node = parent
|
||||||
|
parent = rb_parent(node)
|
||||||
|
|
||||||
|
return parent
|
||||||
|
|
||||||
|
|
||||||
|
class LxRbFirst(gdb.Function):
|
||||||
|
"""Lookup and return a node from an RBTree
|
||||||
|
|
||||||
|
$lx_rb_first(root): Return the node at the given index.
|
||||||
|
If index is omitted, the root node is dereferenced and returned."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(LxRbFirst, self).__init__("lx_rb_first")
|
||||||
|
|
||||||
|
def invoke(self, root):
|
||||||
|
result = rb_first(root)
|
||||||
|
if result is None:
|
||||||
|
raise gdb.GdbError("No entry in tree")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
LxRbFirst()
|
||||||
|
|
||||||
|
|
||||||
|
class LxRbLast(gdb.Function):
|
||||||
|
"""Lookup and return a node from an RBTree.
|
||||||
|
|
||||||
|
$lx_rb_last(root): Return the node at the given index.
|
||||||
|
If index is omitted, the root node is dereferenced and returned."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(LxRbLast, self).__init__("lx_rb_last")
|
||||||
|
|
||||||
|
def invoke(self, root):
|
||||||
|
result = rb_last(root)
|
||||||
|
if result is None:
|
||||||
|
raise gdb.GdbError("No entry in tree")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
LxRbLast()
|
||||||
|
|
||||||
|
|
||||||
|
class LxRbNext(gdb.Function):
|
||||||
|
"""Lookup and return a node from an RBTree.
|
||||||
|
|
||||||
|
$lx_rb_next(node): Return the node at the given index.
|
||||||
|
If index is omitted, the root node is dereferenced and returned."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(LxRbNext, self).__init__("lx_rb_next")
|
||||||
|
|
||||||
|
def invoke(self, node):
|
||||||
|
result = rb_next(node)
|
||||||
|
if result is None:
|
||||||
|
raise gdb.GdbError("No entry in tree")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
LxRbNext()
|
||||||
|
|
||||||
|
|
||||||
|
class LxRbPrev(gdb.Function):
|
||||||
|
"""Lookup and return a node from an RBTree.
|
||||||
|
|
||||||
|
$lx_rb_prev(node): Return the node at the given index.
|
||||||
|
If index is omitted, the root node is dereferenced and returned."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(LxRbPrev, self).__init__("lx_rb_prev")
|
||||||
|
|
||||||
|
def invoke(self, node):
|
||||||
|
result = rb_prev(node)
|
||||||
|
if result is None:
|
||||||
|
raise gdb.GdbError("No entry in tree")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
LxRbPrev()
|
@ -30,5 +30,6 @@ else:
|
|||||||
import linux.config
|
import linux.config
|
||||||
import linux.cpus
|
import linux.cpus
|
||||||
import linux.lists
|
import linux.lists
|
||||||
|
import linux.rbtree
|
||||||
import linux.proc
|
import linux.proc
|
||||||
import linux.constants
|
import linux.constants
|
||||||
|
Loading…
Reference in New Issue
Block a user