*scopes = data.scopes;
        return data.nr;
 }
+
+static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg)
+{
+       Dwarf_Die type_die;
+       Dwarf_Word size, loc;
+       Dwarf_Word offset = (long)arg;
+       int tag = dwarf_tag(die_mem);
+
+       if (tag != DW_TAG_member)
+               return DIE_FIND_CB_SIBLING;
+
+       /* Unions might not have location */
+       if (die_get_data_member_location(die_mem, &loc) < 0)
+               loc = 0;
+
+       if (offset == loc)
+               return DIE_FIND_CB_END;
+
+       if (die_get_real_type(die_mem, &type_die) == NULL) {
+               // TODO: add a pr_debug_dtp() later for this unlikely failure
+               return DIE_FIND_CB_SIBLING;
+       }
+
+       if (dwarf_aggregate_size(&type_die, &size) < 0)
+               size = 0;
+
+       if (loc < offset && offset < (loc + size))
+               return DIE_FIND_CB_END;
+
+       return DIE_FIND_CB_SIBLING;
+}
+
+/**
+ * die_get_member_type - Return type info of struct member
+ * @type_die: a type DIE
+ * @offset: offset in the type
+ * @die_mem: a buffer to save the resulting DIE
+ *
+ * This function returns a type of a member in @type_die where it's located at
+ * @offset if it's a struct.  For now, it just returns the first matching
+ * member in a union.  For other types, it'd return the given type directly
+ * if it's within the size of the type or NULL otherwise.
+ */
+Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset,
+                              Dwarf_Die *die_mem)
+{
+       Dwarf_Die *member;
+       Dwarf_Die mb_type;
+       int tag;
+
+       tag = dwarf_tag(type_die);
+       /* If it's not a compound type, return the type directly */
+       if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
+               Dwarf_Word size;
+
+               if (dwarf_aggregate_size(type_die, &size) < 0)
+                       size = 0;
+
+               if ((unsigned)offset >= size)
+                       return NULL;
+
+               *die_mem = *type_die;
+               return die_mem;
+       }
+
+       mb_type = *type_die;
+       /* TODO: Handle union types better? */
+       while (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) {
+               member = die_find_child(&mb_type, __die_find_member_offset_cb,
+                                       (void *)(long)offset, die_mem);
+               if (member == NULL)
+                       return NULL;
+
+               if (die_get_real_type(member, &mb_type) == NULL)
+                       return NULL;
+
+               tag = dwarf_tag(&mb_type);
+
+               if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) {
+                       Dwarf_Word loc;
+
+                       /* Update offset for the start of the member struct */
+                       if (die_get_data_member_location(member, &loc) == 0)
+                               offset -= loc;
+               }
+       }
+       *die_mem = mb_type;
+       return die_mem;
+}
+
+/**
+ * die_deref_ptr_type - Return type info for pointer access
+ * @ptr_die: a pointer type DIE
+ * @offset: access offset for the pointer
+ * @die_mem: a buffer to save the resulting DIE
+ *
+ * This function follows the pointer in @ptr_die with given @offset
+ * and saves the resulting type in @die_mem.  If the pointer points
+ * a struct type, actual member at the offset would be returned.
+ */
+Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset,
+                             Dwarf_Die *die_mem)
+{
+       Dwarf_Die type_die;
+
+       if (dwarf_tag(ptr_die) != DW_TAG_pointer_type)
+               return NULL;
+
+       if (die_get_real_type(ptr_die, &type_die) == NULL)
+               return NULL;
+
+       return die_get_member_type(&type_die, offset, die_mem);
+}