[Crash-utility] [PATCH 1/1] tools: list: create O option for specifying head node offset

Firo Yang firo.yang at suse.com
Mon Apr 26 05:03:51 UTC 2021


The 04/20/2021 13:44, Firo Yang wrote:
Hi Kazu-san,

> This new O option is very useful to specify the head node
> offset for listing linked list whose head node embedded has a
> different offset to other node, e.g. dentry.d_subdirs(the head node)
> and dentry.d_child.
> 
> Signed-off-by: Firo Yang <firo.yang at suse.com>
> ---
>  defs.h  |  1 +
>  help.c  | 12 +++++++++++-
>  tools.c | 30 +++++++++++++++++++++++++++---
>  3 files changed, 39 insertions(+), 4 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index 35b983a..764facf 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2605,6 +2605,7 @@ struct list_data {             /* generic structure used by do_list() to walk */
>  #define LIST_PARSE_MEMBER   (VERBOSE << 13)
>  #define LIST_READ_MEMBER    (VERBOSE << 14)
>  #define LIST_BRENT_ALGO     (VERBOSE << 15)
> +#define LIST_HEAD_OFFSET_ENTERED  (VERBOSE << 16)
>  
>  struct tree_data {
>  	ulong flags;
> diff --git a/help.c b/help.c
> index 531f50a..b561f3b 100644
> --- a/help.c
> +++ b/help.c
> @@ -5716,7 +5716,7 @@ char *help__list[] = {
>  "list",
>  "linked list",
>  "[[-o] offset][-e end][-[s|S] struct[.member[,member] [-l offset]] -[x|d]]"
> -"\n       [-r|-B] [-h|-H] start",
> +"\n       [-r|-B] [-h [-O head_offset]|-H] start",
>  " ",
>  "  This command dumps the contents of a linked list.  The entries in a linked",
>  "  list are typically data structures that are tied together in one of two",
> @@ -5800,6 +5800,16 @@ char *help__list[] = {
>  "    -S struct  Similar to -s, but instead of parsing gdb output, member values",
>  "               are read directly from memory, so the command works much faster",
>  "               for 1-, 2-, 4-, and 8-byte members.",
> +"    -O offset  The -O option works only with -h option.",
> +"               It is used for specifying the offset of head node embedded in a",
> +"               structure, like dentry.d_subdirs or cgroup_subsys_state.children.",
> +"               The offset may be entered in either of two manners:",
> +"",
> +"               1. \"structure.member\" format.",
> +"               2. a number of bytes.",
> +"",
> +"               You can use it like the following:",
> +"               list -O <head node offset> -o <node offset> -h start -s <...>",
>  "    -l offset  Only used in conjunction with -s, if the start address argument",
>  "               is a pointer to an embedded list head (or any other similar list",
>  "               linkage structure whose first member points to the next linkage",
> diff --git a/tools.c b/tools.c
> index a26b101..792a567 100644
> --- a/tools.c
> +++ b/tools.c
> @@ -3343,6 +3343,7 @@ void
>  cmd_list(void)
>  {
>  	int c;
> +	long head_member_offset; /* offset for head like denty.d_subdirs */
>  	struct list_data list_data, *ld;
>  	struct datatype_member struct_member, *sm;
>  	struct syment *sp;
> @@ -3353,7 +3354,7 @@ cmd_list(void)
>  	BZERO(ld, sizeof(struct list_data));
>  	struct_list_offset = 0;
>  
> -	while ((c = getopt(argcnt, args, "BHhrs:S:e:o:xdl:")) != EOF) {
> +	while ((c = getopt(argcnt, args, "BHhrs:S:e:o:O:xdl:")) != EOF) {
>                  switch(c)
>  		{
>  		case 'B':
> @@ -3394,6 +3395,24 @@ cmd_list(void)
>  					optarg);
>  			break;
>  
> +		case 'O':
> +			if (ld->flags & LIST_HEAD_OFFSET_ENTERED)
> +                               error(FATAL,
> +                                "offset value %d (0x%lx) already entered\n",
> +                                        head_member_offset, head_member_offset);
> +			else if (IS_A_NUMBER(optarg))
> +				head_member_offset = stol(optarg,
> +					FAULT_ON_ERROR, NULL);
> +			else if (arg_to_datatype(optarg,
> +				sm, RETURN_ON_ERROR) > 1)
> +				head_member_offset = sm->member_offset;
> +			else
> +				error(FATAL, "invalid -O argument: %s\n",
> +					optarg);
> +
> +			ld->flags |= LIST_HEAD_OFFSET_ENTERED;
> +			break;
> +
>  		case 'o':
>  			if (ld->flags & LIST_OFFSET_ENTERED) 
>                                 error(FATAL,
> @@ -3599,8 +3618,13 @@ next_arg:
>  				fprintf(fp, "(empty)\n");
>  				return;
>  			}
> -		} else
> -			ld->start += ld->list_head_offset;
> +		} else {
> +			if (ld->flags & LIST_HEAD_OFFSET_ENTERED)
> +				readmem(ld->start + head_member_offset, KVADDR,
> +					&ld->start, sizeof(void *), "LIST_HEAD contents", FAULT_ON_ERROR);
> +			else
> +				ld->start += ld->list_head_offset;
> +		}
>  	}
>  
>  	ld->flags &= ~(LIST_OFFSET_ENTERED|LIST_START_ENTERED);
> -- 
> 2.30.2
> 

I am not sure whether this patch is considered helpful or not.
Could you please share some thoughts?

Thanks, 
Firo




More information about the Crash-utility mailing list