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(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/crash-utility