[PATCH v2][makedumpfile 05/14] eppic dwarf: support anonymous structs member resolving

Tao Liu ltao at redhat.com
Mon Oct 20 15:24:01 PDT 2025


Previously, apimember cannot dive into members which belongs to anonymous
structs. E.g. mm_struct has structure as follows:

0x000027bc:   DW_TAG_structure_type
                DW_AT_name      ("mm_struct")
0x000027cb:     DW_TAG_member
                  DW_AT_type    (0x00008dde "structure ")
0x000027d2:     DW_TAG_member
                  DW_AT_name    ("cpu_bitmap")

0x00008dde:   DW_TAG_structure_type
0x00008deb:     DW_TAG_member
                  DW_AT_type    (0x00008d8e "structure ")
0x00008df2:     DW_TAG_member
                  DW_AT_name    ("mm_mt")
0x00008e00:     DW_TAG_member
                  DW_AT_name    ("mmap_base")
0x00008e0e:     DW_TAG_member
                  DW_AT_name    ("mmap_legacy_base")

GET_DIE_NFIELDS_ALL() for mm_struct will only iterate 2 members, it will
not dive into the anonymous structure and iterate members as mm_mt,
mmap_base etc. In other words, there is no way to reference members as
mm_struct.mm_mt.

This patch will make apimember recursive, when anonymous struct/union found,
it will dive deeper to discover further members to make mm_struct.mm_mt
reference possible.

E.g for the following eppic program:
    int main()
    {
	    struct mm_struct *m = (struct mm_struct *)0xffff96b7d1afa680;
	    printf("%lx\n", &m->mm_mt);
	    return 0;
    }

Before the patch:
    File /tmp/test.c, line 4, Error: Unknown member name [mm_mt]

After the patch:
    ffff96b7d1afa6c0
---
 extension_eppic.c | 73 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 26 deletions(-)

diff --git a/extension_eppic.c b/extension_eppic.c
index c4a13b9..ebace25 100644
--- a/extension_eppic.c
+++ b/extension_eppic.c
@@ -223,13 +223,16 @@ out:
  * Get the type, size and position information for a member of a structure.
  */
 static char *
-apimember(char *mname, ull idx, type_t *tm, member_t *m, ull *last_index)
+apimember_internal(char *mname, ull idx, type_t *tm, member_t *m,
+		long offset_base, ull *target_index, ull *global_index)
 {
-	int index, nfields = -1, size;
+	int index = 0, nfields = -1, size;
 	int nbits = 0, fbits = 0;
 	long offset;
 	unsigned long long m_die, die_off = idx;
-	char *name = NULL;
+	int type_flag;
+	unsigned long long t_die_off;
+	char *name;
 
 	nfields = GET_DIE_NFIELDS_ALL(die_off);
 	/*
@@ -239,43 +242,61 @@ apimember(char *mname, ull idx, type_t *tm, member_t *m, ull *last_index)
 	if (nfields <= 0)
 		return NULL;
 
-	/* if we're being asked the next member in a getfirst/getnext
-	 * sequence
-	 */
-	if (mname && !mname[0] && last_index && (*last_index))
-		index = *last_index;
-	else
-		index = 0;
-
 	while (index < nfields) {
+		name = NULL;
 		size = GET_DIE_MEMBER_ALL(die_off, index, &offset, &name,
 					&nbits, &fbits, &m_die);
 
 		if (size < 0)
 			return NULL;
 
-		if (!mname || !mname[0] || !strcmp(mname, name)) {
-			eppic_member_ssize(m, size);
-			if (name) {
-				eppic_member_sname(m, name);
-				/*
-				 * Free the memory allocated by makedumpfile.
-				 */
-				free(name);
+		if (!name && GET_DIE_ATTR_TYPE(m_die, &type_flag, &t_die_off)) {
+			char *ret;
+			ret = apimember_internal(mname, t_die_off, tm, m,
+						offset_base + offset, target_index, global_index);
+			if (ret)
+				return ret;
+			else {
+				index++;
+				continue;
 			}
-			else
-				eppic_member_sname(m, "");
-			eppic_member_soffset(m, offset);
-			eppic_member_snbits(m, nbits);
-			eppic_member_sfbit(m, fbits);
-			*last_index = index + 1;
-			return drilldown(m_die, tm);
+		}
+
+		if (*target_index == *global_index) {
+			if (!mname || !mname[0] || !strcmp(mname, name)) {
+				eppic_member_ssize(m, size);
+				if (name) {
+					eppic_member_sname(m, name);
+					/*
+					* Free the memory allocated by makedumpfile.
+					*/
+					free(name);
+				}
+				else
+					eppic_member_sname(m, "");
+				eppic_member_soffset(m, offset + offset_base);
+				eppic_member_snbits(m, nbits);
+				eppic_member_sfbit(m, fbits);
+				return drilldown(m_die, tm);
+			} else
+				return eppic_strdup("");
 		}
 		index++;
+		(*global_index)++;
 	}
 	return NULL;
 }
 
+static char *
+apimember(char *mname, ull idx, type_t *tm, member_t *m, ull *target_index)
+{
+	char *ret;
+	ull global_index = 0;
+	ret = apimember_internal(mname, idx, tm, m, 0, target_index, &global_index);
+	(*target_index)++;
+	return ret;
+}
+
 static int
 apigetctype(int ctype, char *name, type_t *tout)
 {
-- 
2.47.0




More information about the kexec mailing list