[Crash-utility] [PATCH v2] struct: Fix handing of percpu symbols (when symbolic argument only)
Dave Anderson
anderson at redhat.com
Thu Sep 29 15:46:20 UTC 2016
Aaron,
First things first:
$ make warn
... [ cut ] ...
cc -c -g -DX86_64 -DLZO -DSNAPPY -DGDB_7_6 symbols.c -I./gdb-7.6/bfd -I./gdb-7.6/include -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wformat-security
symbols.c: In function ‘cmd_datatype_common’:
symbols.c:6119:15: warning: unused variable ‘tmpfp’ [-Wunused-variable]
FILE *tmpfp;
^
In file included from symbols.c:18:0:
defs.h:4819:28: warning: ‘typename’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#define FREEBUF(X) freebuf((char *)(X))
^
symbols.c:6116:15: note: ‘typename’ was declared here
char *typename;
^
...
Dave
----- Original Message -----
> Hi Dave,
>
> Sorry about the delay. I completely forgot about this one!
> Please note I have only addressed the case when the argument to the
> 'struct' command is not an address:
>
> When a percpu symbol is of type pointer, the 'struct' command does
> not generate the expected output. For example:
>
> Note: The correct value of 'exec_start' should be
> 0x15b070b28b0c27 not 0x0
>
> crash> struct task_struct.se.exec_start softlockup_watchdog:0
> [0]: ffff880214e55a00
> se.exec_start = 0x0,
>
> crash> px softlockup_watchdog:0-1
> per_cpu(softlockup_watchdog, 0) = $1 = (struct task_struct *)
> 0xffff880fe97e2e00
>
> crash> px ((struct task_struct *)0xffff880fe97e2e00)->se.exec_start
> $2 = 0x15b070b28b0c27
>
> Currently, the 'struct' and 'p' command simply calculates 'cpuaddr' as
> follows -- where 'addr' is a percpu's value:
>
> cpuaddr = addr + __per_cpu_offset
>
> This is correct if the percpu symbol or offset
> (i.e. [percpu symbol:cpu-specifier] or [percpu value:cpu-specifier])
> is not of type pointer. If a given percpu symbol is of type pointer such as
> in 'static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog)', we
> need to dereference the pointer to obtain the above correct kernel virtual
> address.
>
> For instance, using the above example, we need to pass the following to gdb
> to resolve appropriately:
>
> kernel virtual addresses for the cpus specified.
>
> crash> set gdb on
> gdb: on
>
> gdb> p *(struct task_struct **) 0xffff880fffc0ddc0
> $1 = (struct task_struct *) 0xffff880fe97e2e00
> gdb>
>
> With this patch, we now obtain the expected output:
>
> crash> struct task_struct.se.exec_start softlockup_watchdog:0
> [0]: ffff880214e55a00
> se.exec_start = 0x15b070b28b0c27,
>
> Signed-off-by: Aaron Tomlin <atomlin at redhat.com>
> ---
> symbols.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/symbols.c b/symbols.c
> index 8b0d8b9..b68d0d3 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -81,6 +81,7 @@ static void cmd_datatype_common(ulong);
> static void do_datatype_addr(struct datatype_member *, ulong, int,
> ulong, char **, int);
> static void process_gdb_output(char *, unsigned, const char *, int);
> +static char *expr_type_name(const char *);
> static int display_per_cpu_info(struct syment *, int, char *);
> static struct load_module *get_module_percpu_sym_owner(struct syment *);
> static int is_percpu_symbol(struct syment *);
> @@ -6112,6 +6113,11 @@ cmd_datatype_common(ulong flags)
> char *separator;
> char *structname, *members;
> char *memberlist[MAXARGS];
> + char *typename;
> + char buf[BUFSIZE];
> + char *argv[MAXARGS];
> + FILE *tmpfp;
> + ushort ptype;
>
> dm = &datatype_member;
> count = 0xdeadbeef;
> @@ -6122,6 +6128,7 @@ cmd_datatype_common(ulong flags)
> separator = members = NULL;
> cpuspec = NULL;
> cpus = NULL;
> + ptype = 0;
>
> while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) {
> switch (c)
> @@ -6262,6 +6269,12 @@ cmd_datatype_common(ulong flags)
> SET_BIT(cpus, CURRENT_CONTEXT()->processor);
> else
> make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
> +
> + if (sp) {
> + typename = expr_type_name(sp->name);
> + ptype = typename &&
> + LASTCHAR(typename) == '*' ? 1 : 0;
> + }
> }
>
> optind = optind_save;
> @@ -6346,6 +6359,19 @@ cmd_datatype_common(ulong flags)
> continue;
> }
>
> + if (ptype) {
> + open_tmpfile();
> + snprintf(buf, sizeof buf, "p *(%s*) 0x%lx",
> + typename, cpuaddr);
> + gdb_pass_through(buf, pc->tmpfile, GNU_RETURN_ON_ERROR);
> +
> + rewind(pc->tmpfile);
> + fgets(buf, BUFSIZE, pc->tmpfile);
> + parse_line(buf, argv);
> + cpuaddr = htol(argv[3], FAULT_ON_ERROR, NULL);
> + close_tmpfile();
> + }
> +
> fprintf(fp, "%lx\n", cpuaddr);
> do_datatype_addr(dm, cpuaddr , count,
> flags, memberlist, argc_members);
> @@ -6364,6 +6390,9 @@ freebuf:
>
> if (cpus)
> FREEBUF(cpus);
> +
> + if (typename)
> + FREEBUF(typename);
> }
>
> static void
> --
> 2.5.5
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
More information about the Crash-utility
mailing list