forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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. [[email protected]: v2] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]> Cc: Douglas Anderson <[email protected]> Cc: Nikolay Borisov <[email protected]> Cc: Kieran Bingham <[email protected]> Cc: Jan Kiszka <[email protected]> Cc: Jackie Liu <[email protected]> Cc: Jason Wessel <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
2 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters