[Pdbg] [PATCH v3 09/22] libpdbg: Parent retrieval should handle virtual nodes correctly

Amitay Isaacs amitay at ozlabs.org
Mon Sep 23 18:48:28 AEST 2019


When traversing system device tree view (system == true), parent of a
node can be a virtual node.

When traversing backend device tree, parent of a node will not be a
virtual node unless it's part of the backend device tree itself.

Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
 libpdbg/libpdbg.c | 51 +++++++++++++++++++++++++++++++++++++++++------
 libpdbg/libpdbg.h | 10 +++++-----
 libpdbg/target.c  |  2 +-
 libpdbg/target.h  |  1 +
 src/thread.c      |  4 ++--
 5 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/libpdbg/libpdbg.c b/libpdbg/libpdbg.c
index 1f23208..1c3fdb6 100644
--- a/libpdbg/libpdbg.c
+++ b/libpdbg/libpdbg.c
@@ -6,7 +6,41 @@
 
 static pdbg_progress_tick_t progress_tick;
 
-struct pdbg_target *__pdbg_next_target(const char *class, struct pdbg_target *parent, struct pdbg_target *last)
+struct pdbg_target *get_parent(struct pdbg_target *target, bool system)
+{
+	struct pdbg_target *parent;
+
+	if (!target)
+		return NULL;
+
+	/*
+	 * In system tree:
+	 *  - virtual targets are mapped to real targets
+	 *
+	 * To find a parent in the system tree:
+	 *   - If a target is real, map it to possible virtual target
+	 *   - Calculate the parent
+	 *   - If the parent is virtual, map it to real target
+	 */
+	if (system) {
+		if (target->vnode && target->compatible)
+			target = target->vnode;
+	}
+
+	parent = target->parent;
+
+	if (!parent)
+		return NULL;
+
+	if (system) {
+		if (parent->vnode && !parent->compatible)
+			parent = parent->vnode;
+	}
+
+	return parent;
+}
+
+struct pdbg_target *__pdbg_next_target(const char *class, struct pdbg_target *parent, struct pdbg_target *last, bool system)
 {
 	struct pdbg_target *next, *tmp;
 	struct pdbg_target_class *target_class;
@@ -33,7 +67,7 @@ retry:
 		return next;
 	else {
 		/* Check if this target is a child of the given parent */
-		for (tmp = next; tmp && next->parent && tmp != parent; tmp = tmp->parent) {}
+		for (tmp = next; tmp && get_parent(tmp, system) && tmp != parent; tmp = get_parent(tmp, system)) {}
 		if (tmp == parent)
 			return next;
 		else {
@@ -160,7 +194,7 @@ uint32_t pdbg_target_index(struct pdbg_target *target)
 {
 	struct pdbg_target *dn;
 
-	for (dn = target; dn && dn->index == -1; dn = dn->parent);
+	for (dn = target; dn && dn->index == -1; dn = get_parent(dn, true));
 
 	if (!dn)
 		return -1;
@@ -174,10 +208,15 @@ struct pdbg_target *pdbg_target_parent(const char *class, struct pdbg_target *ta
 	struct pdbg_target *parent;
 
 	if (!class)
-		return target->parent;
+		return get_parent(target, true);
+
+	for (parent = get_parent(target, true); parent && get_parent(parent, true); parent = get_parent(parent, true)) {
+		const char *tclass = pdbg_target_class_name(parent);
+
+		if (!tclass)
+			continue;
 
-	for (parent = target->parent; parent && parent->parent; parent = parent->parent) {
-		if (!strcmp(class, pdbg_target_class_name(parent)))
+		if (!strcmp(class, tclass))
 			return parent;
 	}
 
diff --git a/libpdbg/libpdbg.h b/libpdbg/libpdbg.h
index 2ae29cc..de3fc17 100644
--- a/libpdbg/libpdbg.h
+++ b/libpdbg/libpdbg.h
@@ -19,7 +19,7 @@ struct pdbg_target_class;
 struct pdbg_target *__pdbg_next_compatible_node(struct pdbg_target *root,
                                                 struct pdbg_target *prev,
                                                 const char *compat);
-struct pdbg_target *__pdbg_next_target(const char *klass, struct pdbg_target *parent, struct pdbg_target *last);
+struct pdbg_target *__pdbg_next_target(const char *klass, struct pdbg_target *parent, struct pdbg_target *last, bool system);
 struct pdbg_target *__pdbg_next_child_target(struct pdbg_target *parent, struct pdbg_target *last, bool system);
 
 /*
@@ -61,14 +61,14 @@ enum pdbg_backend { PDBG_DEFAULT_BACKEND = 0, PDBG_BACKEND_FSI, PDBG_BACKEND_I2C
              (target = __pdbg_next_compatible_node(parent, target, compat)) != NULL;)
 
 #define pdbg_for_each_target(class, parent, target)			\
-	for (target = __pdbg_next_target(class, parent, NULL);		\
+	for (target = __pdbg_next_target(class, parent, NULL, true);	\
 	     target;							\
-	     target = __pdbg_next_target(class, parent, target))
+	     target = __pdbg_next_target(class, parent, target, true))
 
 #define pdbg_for_each_class_target(class, target)		\
-	for (target = __pdbg_next_target(class, NULL, NULL);	\
+	for (target = __pdbg_next_target(class, NULL, NULL, true);	\
 	     target;						\
-	     target = __pdbg_next_target(class, NULL, target))
+	     target = __pdbg_next_target(class, NULL, target, true))
 
 #define pdbg_for_each_child_target(parent, target)	      \
 	for (target = __pdbg_next_child_target(parent, NULL, true); \
diff --git a/libpdbg/target.c b/libpdbg/target.c
index da24ba0..e5aa92b 100644
--- a/libpdbg/target.c
+++ b/libpdbg/target.c
@@ -27,7 +27,7 @@ static struct pdbg_target *get_class_target_addr(struct pdbg_target *target, con
 			*addr += pdbg_target_address(target, NULL);
 
 		/* Keep walking the tree translating addresses */
-		target = target->parent;
+		target = get_parent(target, false);
 
 		/* The root node doesn't have an address space so it's
 		 * an error in the device tree if we hit this. */
diff --git a/libpdbg/target.h b/libpdbg/target.h
index 7e08ac3..7419ce5 100644
--- a/libpdbg/target.h
+++ b/libpdbg/target.h
@@ -53,6 +53,7 @@ struct pdbg_target {
 	struct pdbg_target *vnode;
 };
 
+struct pdbg_target *get_parent(struct pdbg_target *target, bool system);
 struct pdbg_target *require_target_parent(struct pdbg_target *target);
 struct pdbg_target_class *find_target_class(const char *name);
 struct pdbg_target_class *require_target_class(const char *name);
diff --git a/src/thread.c b/src/thread.c
index 663f290..8ddf4ae 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -277,10 +277,10 @@ static int thread_status_print(void)
 		assert(path_target_add(pib));
 	}
 
-	pib = __pdbg_next_target("pib", pdbg_target_root(), NULL);
+	pib = __pdbg_next_target("pib", pdbg_target_root(), NULL, true);
 	assert(pib);
 
-	core = __pdbg_next_target("core", pib, NULL);
+	core = __pdbg_next_target("core", pib, NULL, true);
 	assert(core);
 
 	pdbg_for_each_target("thread", core, thread)
-- 
2.21.0



More information about the Pdbg mailing list