Re: [Crash-utility] [PATCH v2] struct: Allow -r with a single member-specific output
- Original Message - > Hi Dave, > > Dave Anderson wrote on Wed, Apr 01, 2020: > > > 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... > > > > What part of this patch aren't you happy about? > > It's mostly style really - I don't like that we're calling in twice in > datatype_info(), because member_to_datatype() doesn't really fill in the > datatype_member struct and only fills in dm->member and offset. > At a naive read, I would expect member_to_datatype to fill in the whole dm... > > Functionally I tested it, it's a bit slower than my original version but > not enough to be a valid argument here; it's much better than nothing so > if you're happy with this let's go with it :) Works for me -- queued for crash-7.2.9: https://github.com/crash-utility/crash/commit/42fba6524ce01b6cecb4cd2cac8f0a50d79b1420 Thanks, Dave > > I will probably want to follow up with a second patch for raw_data_dump > to add DISPLAY_32/16 flags if the len requested is < word size but it's > not directly related to this patch... > > > Cheers, > -- > Dominique > > > -- > Crash-utility mailing list > Crash-utility@redhat.com > https://www.redhat.com/mailman/listinfo/crash-utility > -- Crash-utility mailing list Crash-utility@redhat.com https://www.redhat.com/mailman/listinfo/crash-utility
Re: [Crash-utility] [PATCH v2] struct: Allow -r with a single member-specific output
Hi Dave, Dave Anderson wrote on Wed, Apr 01, 2020: > > 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... > > What part of this patch aren't you happy about? It's mostly style really - I don't like that we're calling in twice in datatype_info(), because member_to_datatype() doesn't really fill in the datatype_member struct and only fills in dm->member and offset. At a naive read, I would expect member_to_datatype to fill in the whole dm... Functionally I tested it, it's a bit slower than my original version but not enough to be a valid argument here; it's much better than nothing so if you're happy with this let's go with it :) I will probably want to follow up with a second patch for raw_data_dump to add DISPLAY_32/16 flags if the len requested is < word size but it's not directly related to this patch... Cheers, -- Dominique -- Crash-utility mailing list Crash-utility@redhat.com https://www.redhat.com/mailman/listinfo/crash-utility
Re: [Crash-utility] [PATCH v2] struct: Allow -r with a single member-specific output
- Original Message - > 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... What part of this patch aren't you happy about? Dave > 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 >
[Crash-utility] [PATCH v2] struct: Allow -r with a single member-specific output
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,