v2: limit example to 80 columns and fill -l in synopsis as well
---
defs.h | 1 +
help.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
tools.c | 20 ++++++++++++++++++--
3 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/defs.h b/defs.h
index adddb9f2748d..ec298cbd70be 100644
--- a/defs.h
+++ b/defs.h
@@ -2480,6 +2480,7 @@ struct tree_data {
#define TREE_STRUCT_RADIX_16 (VERBOSE << 6)
#define TREE_PARSE_MEMBER (VERBOSE << 7)
#define TREE_READ_MEMBER (VERBOSE << 8)
+#define TREE_LINEAR_ORDER (VERBOSE << 9)
#define ALIAS_RUNTIME (1)
#define ALIAS_RCLOCAL (2)
diff --git a/help.c b/help.c
index c5cec5365962..3f9a404ee3c0 100644
--- a/help.c
+++ b/help.c
@@ -5658,7 +5658,7 @@ NULL
char *help_tree[] = {
"tree",
"display radix tree or red-black tree",
-"-t [radix|rbtree] [-r offset] [-[s|S] struct[.member[,member]] -[x|d]]\n
[-o offset] [-p] [-N] start",
+"-t [radix|rbtree] [-r offset] [-[s|S] struct[.member[,member]] -[x|d]]\n
[-o offset] [-p] [-l] [-N] start",
" This command dumps the contents of a radix tree or a red-black tree.",
" The arguments are as follows:\n",
" -t type The type of tree to dump; the type string can be either ",
@@ -5698,6 +5699,8 @@ char *help_tree[] = {
" indicates \"root/l/r\" means that the node is the right
child",
" of the left child of the root node. For radix trees, the
height",
" and slot index values are shown with respect to the root.",
+" -l Dump the tree sorted in linear order starting with the
leftmost",
+" node and progressing to the right.",
" ",
" The meaning of the \"start\" argument, which can be expressed either
in",
" hexadecimal format or symbolically, depends upon whether the -N option",
@@ -5823,6 +5826,59 @@ char *help_tree[] = {
" ffffea000407de58",
" position: root/3/28",
"",
+" Given the mm_struct address of 0xffff880074b5be80 list the VMA tree in
linear",
+" order from the leftmost node progressing to the right using the -l
option:\n",
+" %s> tree -ls vm_area_struct.vm_start -o vm_area_struct.vm_rb \\",
+" -r mm_struct.mm_rb 0xffff880074b5be80 | paste - -",
+" ffff88001f2c50e0 vm_start = 0x400000",
+" ffff88001f2c5290 vm_start = 0xceb000",
+" ffff880074bfc6c0 vm_start = 0xcec000",
+" ffff88001f2c4bd0 vm_start = 0xd10000",
+" ffff880074bfc948 vm_start = 0x1fe9000",
+" ffff880036e54510 vm_start = 0x7ff6aa296000",
+" ffff88001f2c5bd8 vm_start = 0x7ff6aa298000",
+" ffff880036e54af8 vm_start = 0x7ff6aa497000",
+" ffff880036e54f30 vm_start = 0x7ff6aa498000",
+" ffff88000e06aa20 vm_start = 0x7ff6aa499000",
+" ffff88000e06b368 vm_start = 0x7ff6ab95f000",
+" ...",
+" ffff88001f2c5e60 vm_start = 0x7ff6bc1af000",
+" ffff88001f2c4ca8 vm_start = 0x7ff6bc1b6000",
+" ffff88001f2c5008 vm_start = 0x7ff6bc200000",
+" ffff88001f2c5d88 vm_start = 0x7ff6bc205000",
+" ffff880074bfd6c8 vm_start = 0x7ff6bc206000",
+" ffff88001f2c4288 vm_start = 0x7ff6bc207000",
+" ffff88001f2c4510 vm_start = 0x7ffc7a5fc000",
+" ffff88001f2c5b00 vm_start = 0x7ffc7a6d1000",
+"",
+" Compared to the top/down root/leaves order:\n",
+" %s> tree -s vm_area_struct.vm_start -o vm_area_struct.vm_rb \\",
+" -r mm_struct.mm_rb 0xffff880074b5be80 | paste - -",
+" ffff88001f2c5a28 vm_start = 0x7ff6bbbb9000",
+" ffff88001f2c55f0 vm_start = 0x7ff6bb252000",
+" ffff88000e06a360 vm_start = 0x7ff6ac6c3000",
+" ffff88001f2c4bd0 vm_start = 0xd10000",
+" ffff88001f2c5290 vm_start = 0xceb000",
+" ffff88001f2c50e0 vm_start = 0x400000",
+" ffff880074bfc6c0 vm_start = 0xcec000",
+" ffff88000e06b368 vm_start = 0x7ff6ab95f000",
+" ffff88001f2c5bd8 vm_start = 0x7ff6aa298000",
+" ffff880074bfc948 vm_start = 0x1fe9000",
+" ffff880036e54510 vm_start = 0x7ff6aa296000",
+" ffff880036e54f30 vm_start = 0x7ff6aa498000",
+" ffff880036e54af8 vm_start = 0x7ff6aa497000",
+" ffff88000e06aa20 vm_start = 0x7ff6aa499000",
+" ffff88000e06ae58 vm_start = 0x7ff6ac1df000",
+" ffff88000e06ba28 vm_start = 0x7ff6abefc000",
+" ffff88000e06a6c0 vm_start = 0x7ff6ac41b000",
+" ffff88001f2c4000 vm_start = 0x7ff6bac75000",
+" ffff88000e06bd88 vm_start = 0x7ff6b2d00000",
+" ffff88000e06b440 vm_start = 0x7ff6b28de000",
+" ...",
+" ffff880074bfd6c8 vm_start = 0x7ff6bc206000",
+" ffff88001f2c4510 vm_start = 0x7ffc7a5fc000",
+" ffff88001f2c5b00 vm_start = 0x7ffc7a6d1000",
+"",
" Alternatively, take the address of the radix_tree_node from the",
" radix_tree_root structure in the address_space structure above,",
" and display the tree with the -N option:\n",
diff --git a/tools.c b/tools.c
index 7c7f65ac558b..b8e19e4284c5 100644
--- a/tools.c
+++ b/tools.c
@@ -3926,7 +3926,7 @@ cmd_tree()
td = &tree_data;
BZERO(td, sizeof(struct tree_data));
- while ((c = getopt(argcnt, args, "xdt:r:o:s:S:pN")) != EOF) {
+ while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plN")) != EOF) {
switch (c)
{
case 't':
@@ -3993,6 +3993,10 @@ cmd_tree()
td->flags |= TREE_POSITION_DISPLAY;
break;
+ case 'l':
+ td->flags |= TREE_LINEAR_ORDER;
+ break;
+
case 'N':
td->flags |= TREE_NODE_POINTER;
break;
@@ -4397,6 +4401,17 @@ rbtree_iteration(ulong node_p, struct tree_data *td, char *pos)
else
error(FATAL, "\nduplicate tree entry: %lx\n", node_p);
+ if (td->flags & TREE_LINEAR_ORDER &&
+ readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
+ sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR) && new_p)
+ if (readmem(new_p+OFFSET(rb_node_rb_left), KVADDR, &test_p,
+ sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR|QUIET)) {
+ sprintf(new_pos, "%s/l", pos);
+ rbtree_iteration(new_p, td, new_pos);
+ } else
+ error(INFO, "rb_node: %lx: corrupted rb_left pointer: %lx\n",
+ node_p, new_p);
+
struct_p = node_p - td->node_member_offset;
if (td->flags & VERBOSE)
@@ -4430,7 +4445,8 @@ rbtree_iteration(ulong node_p, struct tree_data *td, char *pos)
}
}
- if ( readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
+ if (!(td->flags & TREE_LINEAR_ORDER) &&
+ readmem(node_p+OFFSET(rb_node_rb_left), KVADDR, &new_p,
sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR) && new_p)
if (readmem(new_p+OFFSET(rb_node_rb_left), KVADDR, &test_p,
sizeof(void *), "rb_node rb_left", RETURN_ON_ERROR|QUIET)) {
--
2.17.0