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


Reply via email to