Using struct -r allows much faster execution when iterating through a file;
on 3909 elements struct struct.member takes 192s vs. 3s with -r
---
Sorry for the delay, here's another take at allowing struct -r with a
specific field specified.

I didn't post that v2 back in Feb because I wasn't totally happy with
it; I can't say I now am but might as well get your take on it...
Thanks!

 defs.h    |  2 ++
 symbols.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/defs.h b/defs.h
index e852ddf..a3f828d 100644
--- a/defs.h
+++ b/defs.h
@@ -2283,6 +2283,7 @@ struct array_table {
 #define MEMBER_TYPE_REQUEST ((struct datatype_member *)(-3))
 #define STRUCT_SIZE_REQUEST ((struct datatype_member *)(-4))
 #define MEMBER_TYPE_NAME_REQUEST ((struct datatype_member *)(-5))
+#define ANON_MEMBER_SIZE_REQUEST ((struct datatype_member *)(-6))
 
 #define STRUCT_SIZE(X)      datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
 #define UNION_SIZE(X)       datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
@@ -2294,6 +2295,7 @@ struct array_table {
 #define MEMBER_TYPE(X,Y)    datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
 #define MEMBER_TYPE_NAME(X,Y)    ((char *)datatype_info((X), (Y), 
MEMBER_TYPE_NAME_REQUEST))
 #define ANON_MEMBER_OFFSET(X,Y)    datatype_info((X), (Y), 
ANON_MEMBER_OFFSET_REQUEST)
+#define ANON_MEMBER_SIZE(X,Y)    datatype_info((X), (Y), 
ANON_MEMBER_SIZE_REQUEST)
 
 /*
  *  The following set of macros can only be used with pre-intialized fields
diff --git a/symbols.c b/symbols.c
index 9c3032d..b32e480 100644
--- a/symbols.c
+++ b/symbols.c
@@ -145,6 +145,7 @@ static void print_union(char *, ulong);
 static void dump_datatype_member(FILE *, struct datatype_member *);
 static void dump_datatype_flags(ulong, FILE *);
 static long anon_member_offset(char *, char *);
+static long anon_member_size(char *, char *);
 static int gdb_whatis(char *);
 static void do_datatype_declaration(struct datatype_member *, ulong);
 static int member_to_datatype(char *, struct datatype_member *, ulong);
@@ -5604,14 +5605,17 @@ long
 datatype_info(char *name, char *member, struct datatype_member *dm)
 {
        struct gnu_request *req;
-        long offset, size, member_size;
+       long offset, size, member_size;
        int member_typecode;
-        ulong type_found;
+       ulong type_found;
        char buf[BUFSIZE];
 
-        if (dm == ANON_MEMBER_OFFSET_REQUEST)
+       if (dm == ANON_MEMBER_OFFSET_REQUEST)
                return anon_member_offset(name, member);
 
+       if (dm == ANON_MEMBER_SIZE_REQUEST)
+               return anon_member_size(name, member);
+
        strcpy(buf, name);
 
        req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
@@ -5828,6 +5832,46 @@ retry:
        return value;
 }
 
+/*
+ *  Determine the size of a member in an anonymous union
+ *  in a structure or union.
+ */
+static long
+anon_member_size(char *name, char *member)
+{
+       char buf[BUFSIZE];
+       ulong value;
+       int type;
+
+       value = -1;
+       type = STRUCT_REQUEST;
+       sprintf(buf, "printf \"%%ld\", (u64)(&((struct %s*)0)->%s + 1) - 
(u64)&((struct %s*)0)->%s",
+               name, member, name, member);
+       open_tmpfile2();
+retry:
+       if (gdb_pass_through(buf, pc->tmpfile2, GNU_RETURN_ON_ERROR)) {
+               rewind(pc->tmpfile2);
+               if (fgets(buf, BUFSIZE, pc->tmpfile2)) {
+                       if (hexadecimal(buf, 0))
+                               value = htol(buf, RETURN_ON_ERROR|QUIET, NULL);
+                       else if (STRNEQ(buf, "(nil)"))
+                               value = 0;
+               }
+       }
+
+       if ((value == -1) && (type == STRUCT_REQUEST)) {
+               type = UNION_REQUEST;
+               sprintf(buf, "printf \"%%ld\", (u64)(&((union %s*)0)->%s + 1) - 
(u64)&((union %s*)0)->%s",
+                       name, member, name, member);
+               rewind(pc->tmpfile2);
+               goto retry;
+       }
+
+       close_tmpfile2();
+
+       return value;
+}
+
 /*
  *  Get the basic type info for a symbol.  Let the caller pass in the 
  *  gnu_request structure to have access to the full response; in either
@@ -6617,6 +6661,9 @@ do_datatype_addr(struct datatype_member *dm, ulong addr, 
int count,
                i = 0;
                do {
                        if (argc_members) {
+                               if (argc_members > 1 && flags & SHOW_RAW_DATA)
+                                       error(FATAL,
+                                             "only up to one member-specific 
output allowed with -r\n");
                                /* This call works fine with fields
                                 * of the second, third, ... levels.
                                 * There is no need to fix it
@@ -6625,9 +6672,6 @@ do_datatype_addr(struct datatype_member *dm, ulong addr, 
int count,
                                                        ANON_MEMBER_QUERY))
                                        error(FATAL, "invalid data structure 
reference: %s.%s\n",
                                              dm->name, memberlist[i]);
-                               if (flags & SHOW_RAW_DATA)
-                                       error(FATAL, 
-                                             "member-specific output not 
allowed with -r\n");
                        }
 
                        /*
@@ -6636,9 +6680,18 @@ do_datatype_addr(struct datatype_member *dm, ulong addr, 
int count,
                        if (flags & SHOW_OFFSET) {
                                dm->vaddr = addr;
                                do_datatype_declaration(dm, flags | (dm->flags 
& TYPEDEF));
-                       } else if (flags & SHOW_RAW_DATA)
+                       } else if (flags & SHOW_RAW_DATA) {
+                               if (dm->member) {
+                                       addr += dm->member_offset;
+                                       len = MEMBER_SIZE(dm->name, dm->member);
+                                       if (len < 0)
+                                               len = 
ANON_MEMBER_SIZE(dm->name, dm->member);
+                                       if (len < 0)
+                                               error(FATAL, "invalid data 
structure reference: %s.%s\n",
+                                                     dm->name, dm->member);
+                               }
                                raw_data_dump(addr, len, flags & 
STRUCT_VERBOSE);
-                       else if ((flags & DEREF_POINTERS) && !dm->member) {
+                       } else if ((flags & DEREF_POINTERS) && !dm->member) {
                                print_struct_with_dereference(addr, dm, flags);
                        } else {
                                if (dm->member)
-- 
2.26.0


--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to