[Crash-utility] [PATCH v3 1/1] tools: list: create O option for specifying head node offset
HAGIO KAZUHITO(萩尾 一仁)
k-hagio-ab at nec.com
Wed May 26 01:44:46 UTC 2021
-----Original Message-----
> This -O option is very useful to specify the embedded head node's
> offset which is different to the offset of other nodes embedded,
> e.g. dentry.d_subdirs(the head node) and dentry.d_child.
>
> Signed-off-by: Firo Yang <firo.yang at suse.com>
Acked-by: Kazuhito Hagio <k-hagio-ab at nec.com>
Please wait for another ack.
Thanks,
Kazu
> ---
> defs.h | 1 +
> help.c | 32 +++++++++++++++++++++++++++++++-
> tools.c | 36 +++++++++++++++++++++++++++++++++---
> 3 files changed, 65 insertions(+), 4 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 396d61a..d5fcd37 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2613,6 +2613,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 e0c8408..1593f12 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,15 @@ 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 Only used in conjunction with -h; it specifies the offset of head",
> +" node list_head embedded within a data structure which is different",
> +" than the offset of list_head of other nodes embedded within a data",
> +" structure.",
> +" The offset may be entered in either of the following manners:",
> +"",
> +" 1. \"structure.member\" format.",
> +" 2. a number of bytes.",
> +"",
> " -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",
> @@ -6116,6 +6125,27 @@ char *help__list[] = {
> " comm = \"sudo\"",
> " ffff88005ac10180",
> " comm = \"crash\"",
> +"",
> +" To display a liked list whose head node and other nodes are embedded within ",
> +" either same or different data structures resulting in different offsets ",
> +" for head node and other nodes, e.g. dentry.d_subdirs and dentry.d_child, this",
> +" -O option can be used:",
> +"",
> +" %s> list -o dentry.d_child -s dentry.d_name.name -O dentry.d_subdirs -h ffff9c585b81a180",
> +" ffff9c585b9cb140",
> +" d_name.name = 0xffff9c585b9cb178 ccc.txt",
> +" ffff9c585b9cb980",
> +" d_name.name = 0xffff9c585b9cb9b8 bbb.txt",
> +" ffff9c585b9cb740",
> +" d_name.name = 0xffff9c585b9cb778 aaa.txt",
> +"",
> +" The dentry.d_subdirs example above is equal to the following sequence:",
> +"",
> +" %s> struct -o dentry.d_subdirs ffff9c585b81a180",
> +" struct dentry {",
> +" [ffff9c585b81a220] struct list_head d_subdirs;",
> +" }",
> +" %s> list -o dentry.d_child -s dentry.d_name.name -H ffff9c585b81a220",
> NULL
> };
>
> diff --git a/tools.c b/tools.c
> index a26b101..636adc6 100644
> --- a/tools.c
> +++ b/tools.c
> @@ -3343,6 +3343,7 @@ void
> cmd_list(void)
> {
> int c;
> + long head_member_offset = 0; /* 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,19 @@ next_arg:
> fprintf(fp, "(empty)\n");
> return;
> }
> - } else
> - ld->start += ld->list_head_offset;
> + } else {
> + if (ld->flags & LIST_HEAD_OFFSET_ENTERED) {
> + if (!ld->end)
> + ld->end = ld->start + head_member_offset;
> + readmem(ld->start + head_member_offset, KVADDR,
> + &ld->start, sizeof(void *), "LIST_HEAD contents", FAULT_ON_ERROR);
> + if (ld->start == ld->end) {
> + fprintf(fp, "(empty)\n");
> + return;
> + }
> + } else
> + ld->start += ld->list_head_offset;
> + }
> }
>
> ld->flags &= ~(LIST_OFFSET_ENTERED|LIST_START_ENTERED);
> --
> 2.31.1
More information about the Crash-utility
mailing list