[ANNOUNCE] crash version 7.1.1 is available
by Dave Anderson
Download from: http://people.redhat.com/anderson
or
https://github.com/crash-utility/crash/releases
The master branch serves as a development branch that will contain all
patches that are queued for the next release:
$ git clone git://github.com/crash-utility/crash.git
Changelog:
- Fix for two minor issues with the "net" command. Without the patch,
the "net -a" option appends its correct output with the command's
"Usage:" message; and if either the "net -x" or "net -d" options are
used without also specifying "-s" or "-S", the error message would
indicate "net: illegal flag: 800000" or "net: illegal flag: 1000000"
instead of showing the command's "Usage:" message.
(anderson(a)redhat.com)
- If the kernel (live or dumpfile) has the TAINT_LIVEPATCH bit set, or
if the Red Hat "kpatch" module is installed, the tag "[LIVEPATCH]"
will be displayed next to the kernel name in the initial system
banner and by the "sys" command. This new tag replaces the
"[KPATCH]" tag that was introduced in crash-7.0.7.
(anderson(a)redhat.com)
- Addressed three Coverity Scan complaints in vmware_vmss.c:
50:leaked_storage: Variable "fp" going out of scope leaks the
storage it points to.
53:leaked_storage: Variable "fp" going out of scope leaks the
storage it points to.
256:warning: Use of memory after it is freed
(anderson(a)redhat.com)
- Remove the LKCD-only "propeller spinner" seen when a dumpfile read
requires more than 2048 page header accesses. This was put in place
because of the non-random-access design of LKCD dumpfiles. Without
the patch, the spinner display is intermingled with command output,
which complicates the parsing of the output.
(watters.sam(a)gmail.com)
- Fix to support the Linux version increment from 3 to 4. Without the
patch, both dumpfile and live sessions fail during initialization,
issuing the message "WARNING: kernel version inconsistency between
vmlinux and dumpfile" or "WARNING: kernel version inconsistency
between vmlinux and live memory", followed by the nonsensical fatal
error message "crash: incompatible arguments: vmlinux is not SMP --
vmcore is SMP" or "crash: incompatible arguments: vmlinux is not
SMP -- live system is SMP". To prevent unexpected kernel version
bumps in the future, support has been added for version 5.
(anderson(a)redhat.com)
- Add support for more than 16TB of physical memory space in the SADUMP
dumpfile format. Without the patch, there is a limitation caused
by several 32-bit members of dump_header structure, in particular
the max_mapnr member, which overflows if the dumpfile contains more
than 16TB of physical memory space. The header_version member of
the dump_header structure has been increased from 0 to 1 in this
extended new format, and the new 64-bit members will be used.
(d.hatayama(a)jp.fujitsu.com)
- Fix for command lines that are redirected to a pipe. Without the
patch, if an external piped-to command contains a quoted string that
includes a "|" character, the command fails with the message "crash:
pipe operation failed".
(anderson(a)redhat.com)
- Fix for insecure temporary file usage in _rl_tropen() as reported by
readline library CVE-2014-2524.
(anderson(a)redhat.com)
- When the gdb-<version>.patch file has changed and a rebuild is
done from within a previously-existing build tree, the "patch -N"
option is used to ignore patches that have been previously applied;
this patch also applies the "patch -r-" option to prevent unnecessary
.rej files from being created.
(anderson(a)redhat.com)
- Fix to account for Xen hypervisor's "domain" structure member name
change from "is_paused_by_controller" to "controller_pause_count".
Without the patch, in Xen 4.2.5 and later, the crash session fails
during initialization with the error message 'crash: invalid
structure member offset: domain_is_paused_by_controller".
(dietmar.hahn(a)ts.fujitsu.com)
- During initialization, reject useless ARM64 "(A)" and "(a)" absolute
symbols that are below the text region. Without the patch, several
recently-introduced absolute symbols have been introduced into the
kernel, which will be displayed by "sym -l" prior to the first kernel
virtual address symbol, and will show up in command output where
memory values are translated into kernel symbol references.
(anderson(a)redhat.com)
- Fix for ARM64 kernels to account for changes in the virtual memory
layout introduced in Linux 3.17. The vmalloc region end address, and
the vmemmap start and end addresses are now calculated at kernel
build time, because they depend upon the size of a struct page.
Accordingly, the crash utility needs to calculate those three address
values dynamically, after the embedded gdb module has initialized.
Without the patch, reads of page structures return invalid data due
to incorrect virtual-to-physical translations of memory in the
vmemmap range. This in turn causes commands that require page
structure contents to fail or show invalid data, such as "kmem -p",
"kmem -[sS]", and the "kmem -[fF]" options.
(anderson(a)redhat.com)
- Fix to support ELF vmcore dumpfiles whose PT_LOAD file offset values
of their respective memory segments are not laid out sequentially
from low to high in the dumpfile. This has only been seen in ELF
dumpfiles created by VMware's "vmss2core -M" facility. Without the
patch, the crash session may fail during initialization, either with
the message "cannot malloc ELF header buffer", or "crash: <dumpfile>:
not a supported file format".
(anderson(a)redhat.com)
- Enhancement to the support of VMware .vmss suspended state dumpfiles.
There may be holes in the memory address saved for PCI, etc. In such
cases, the memory dump is divided into regions. With this patch, up
to 3 memory regions are supported.
(hfu(a)vmware.com)
- Fortified the error handling of task gathering from the pid_hash[]
chains during session initialization. If a chain has been corrupted,
the patch prevents the sequence from entering an infinite loop, and
the error messages associated with corrupt/invalid chains have been
updated to report the pid_hash[] index number.
(anderson(a)redhat.com)
- Implemented a new STRDUPBUF() utility that will duplicate an existing
string into a buffer allocated with GETBUF(). As is the case with
any buffer allocated with GETBUF(), it is only meant to exist during
the life-span of the current command. If it is not explicitly freed
via FREEBUF(), then it will be freed automatically prior to the next
command.
(anderson(a)redhat.com)
- Implemented a new fill_struct_member_data() function that gathers
a bundle of data that describes a structure member. The function
receives a pointer to a struct_member_data structure, in which the
caller has initialized the "structure" and "member" name pointers:
struct struct_member_data {
char *structure;
char *member;
long type;
long unsigned_type;
long length;
long offset;
long bitpos;
long bitsize;
};
A gdb "printm" command is crafted using those two fields, and the
output of the command is used to initialize the remaining six fields.
Adapted from Qiao Nuohan's "pstruct" extension module.
(anderson(a)redhat.com, qiaonuohan(a)cn.fujitsu.com)
- Implemented a new "runq -c cpu(s)" option to display the run queue
data of specified cpus. It can be used in conjunction with all runq
command options. The cpus must be specified in a comma- and/or
dash-separated list; for examples, "3", "1,8,9", "1-23", or "1,8-15".
(anderson(a)redhat.com)
- Build extension modules that utilize the generic extensions/Makefile
with -g. In addition, build the snap.c extension module with -g.
(rabinv(a)axis.com)
- Several fixes, updates, and enhancements for 32-bit MIPS support:
(1) The MIPS general purpose registers in the elf_gregset_t
don't start at index 0 but at index 6.
(2) Adjust for the kernel's pt_regs structure changes between
kernel versions. For example, fields are inserted into the
middle based on build time options, and the amount of padding
at the head of the structure was changed relatively recently.
To handle this, split the structure definition into two parts
and get the offsets of these two parts dynamically.
(3) Do not display each parsed kernel symbol during initialization
when invoked with "crash -d8".
(4) Add support for loading raw MIPS ramdump dumpfiles.
(5) Add support for compressed kdump dumpfiles.
(rabinv(a)axis.com)
- Fix for a typo in "help foreach", and a fix for a spelling error in
"help input".
(weijg.fnst(a)cn.fujitsu.com)
- Fix for "and and" and "the the" typos in the README file.
(weijg.fnst(a)cn.fujitsu.com)
- Fix to address the Xen 4.5.0 hypervisor symbol name change from
"dom0" to "hardware_domain". Without the patch, the crash session
fails with the error message "crash: cannot resolve: dom0".
(dslutz(a)verizon.com)
- Fix for a regression in crash-7.1.0 that causes failures when the
"crash -t" option is run on a live system, and when analyzing remote
Linux kernels. Without the patch, "crash -t" on a live system fails
with the message "crash: cannot open remote memory source: /dev/mem",
and attempts to analyze a Linux kernel remotely just shows the kernel
timestamp and exits immediately.
(dslutz(a)verizon.com, anderson(a)redhat.com)
- Speed up the session invocation time of "flattened" format dumpfiles
created by the makedumpfile(8) facility. When sorting the blocks of
memory by their intended ELF or compressed kdump file offsets, the
patch replaces the bubble-sort method that is currently used with an
insertion sort method.
(dslutz(a)verizon.com)
- Remove the non-existent "-L" option from the "ps" command's mutually-
exclusive options error message.
(vvs(a)parallels.com)
- Fix for the "irq", "mount", "kmem -p" and "kmem -v" commands when
they are used in an input file. If more than one of any of those
four commands are used in an input file, the output of the second
and subsequent command instances will not display their respective
command headers.
(anderson(a)redhat.com)
- Implemented a new "kmem -m" option that is similar to "kmem -p",
but it allows the user to specify the page struct members to be
displayed. The option takes a comma-separated list of one or
more page struct members, which will be displayed following the
page structure address. The "flags" member will always be expressed
in hexadecimal format, and the "_count" and "_mapcount" members will
always be expressed in decimal format. Otherwise, all other members
will be displayed in hexadecimal format unless the current output
radix is 10 and the member is a signed/unsigned integer. Members
that are data structures may be specified by the data structure's
member name, or expanded to specify a member of that data structure.
For example, "-m lru" refers to a list_head data structure, in which
case both the list_head.next and list_head.prev pointer values will
be displayed; if "-m lru.next" is specified, just the list_head.next
value will be displayed.
(atomlin(a)redhat.com, anderson(a)redhat.com)
- Support enhancement for the 32-bit MIPS architecture that retrieves
the per-cpu registers from the NT_PRSTATUS notes stored in the header
of compressed kdump dumpfiles.
(rabinv(a)axis.com)
- Fix to remove an invalid warning message on ARM64 if a crash session
is invoked with the "-d<number>" debug flag. Without the patch,
the invalid message is "WARNING: SPARSEMEM_EX: questionable section
values".
(anderson(a)redhat.com)
- Remove the leftover ".constructor" build file in the extensions
subdirectory when "make extensions" is complete, and update the
top-level .gitignore file to ignore post-build extensions
subdirectory files.
(anderson(a)redhat.com)
- Fix for a segmentation violation generated by the "help -[n|D]"
options on ARM64 compressed kdumps.
(anderson(a)redhat.com)
- Additional output for the "help [-D|-n]" options on ARM64. For ELF
kdump vmcores and compressed kdumps, the elf_prstatus structure in
each NT_PRSTATUS note will be translated.
(anderson(a)redhat.com)
- The "help -r" option has been extended to dump the ARM64 registers
stored in each per-cpu NT_PRSTATUS note in compressed kdump and
ELF kdump dumpfiles.
(anderson(a)redhat.com)
- Fix for the ARM64 page size determination on Linux 4.1 and later
kernels. Without the patch, the crash session fails during
initialization with the message "crash: invalid/unsupported page
size: 98304" on kernels with 64K pages. On kernels with 4K pages,
the message is "crash: invalid/unsupported page size: 6144". In
addition, the "-p <page-size>" command line override option
had no effect on ARM64; that has been fixed as well.
(anderson(a)redhat.com)
- Fix for the DATE display in the initial system banner and by the
"sys" command to account for the Linux 3.17 change that moved
the "timekeeper" symbol and structure into a containing tk_core
structure; the "shadow_timekeeper" timekeeper will be used as an
alternative. Without the patch, the DATE shows something within
a few hours of the Linux epoch, such as "Wed Dec 31 18:00:00 1969".
(kmcmartin(a)redhat.com)
- Fixes for the translation of ARM64 PTEs, as displayed by the "vm -p"
and "vtop" commands. Without the patch, if "vm -p" references a
swapped-out page on Linux 4.0 and later kernels, the SWAP location
may indicate "(unknown swap location)", and will show an invalid
OFFSET value; on Linux 3.13 and later kernels, running "vtop" on a
user virtual address incorrectly translates the PTE contents of
swapped out pages by showing a PHYSICAL address and FLAGS translation
instead of the SWAP device and OFFSET. It is possible that there may
be PTE bit translation errors on other kernel versions; the patch
addresses the changes in ARM64 PTE bit definitions made in Linux
3.11, 3.13, and 4.0 kernels.
(anderson(a)redhat.com)
- Enhanced the "struct.member" display capability of the "struct",
"union", "task", "list" and "tree" commands. If a specified
structure member contains an embedded structure, the output may
be restricted to just the embedded structure by expressing the
.member argument as "member.member". If a specified structure
member is an array, the output may be restricted to a single array
element by expressing the .member argument as "member[index]".
Furthermore, these embedded member specifications may extend beyond
one level deep, for example, by expressing the member argument as
"member.member.member", or "member[index].member".
(Alexandr_Terekhov(a)epam.com, anderson(a)redhat.com)
- Fix for any command that passes strings to gdb for evaluation,
where the string contains a parentheses-within-parentheses
expression along with a ">" or ">>" operator inside the outermost
set of parentheses. Without the patch, a command such as the
following fails like so:
crash> p ((1+1) >> 1)
p: gdb request failed: p ((1+1)
crash>
(anderson(a)redhat.com)
- Fix for the handling of ARM64 kernel module per-cpu symbols. Without
the patch, if the debuginfo data of an ARM64 kernel module that
contains a per-cpu section is loaded by "mod -s <module>" or
"mod -S", commands such as "bt" or "sym" may incorrectly translate
the module's virtual addresses to symbol names.
(Jan.Karlsson(a)sonymobile.com)
9 years, 7 months
Fix in bt for ARM64
by Karlsson, Jan
Hi Dave
I found an ARM64 problem for bt when a function belongs to a module.
Printout before fix given below:
#16 [ffffffc0be96f8d0] __this_module at ffffffbffc15a2f8 [wlan]
#17 [ffffffc0be96f9b0] __this_module at ffffffbffc161b18 [wlan]
#18 [ffffffc0be96f9c0] __this_module at ffffffbffc16033c [wlan]
#19 [ffffffc0be96fa10] __this_module at ffffffbffc1630f8 [wlan]
#20 [ffffffc0be96fab0] __this_module at ffffffbffc156ff8 [wlan]
#21 [ffffffc0be96faf0] __this_module at ffffffbffc15aa58 [wlan]
#22 [ffffffc0be96fb20] __this_module at ffffffbffc15bfc8 [wlan]
#23 [ffffffc0be96fb60] __this_module at ffffffbffc115fac [wlan]
#24 [ffffffc0be96fb90] tasklet_action at ffffffc000223738
#25 [ffffffc0be96fbb0] __do_softirq at ffffffc000222e94
Printout after fix:
#16 [ffffffc0be96f8d0] dhd_bus_rx_frame at ffffffbffc15a2f8 [wlan]
#17 [ffffffc0be96f9b0] dhd_update_flow_prio_map at ffffffbffc161b18 [wlan]
#18 [ffffffc0be96f9c0] dhd_update_flow_prio_map at ffffffbffc16033c [wlan]
#19 [ffffffc0be96fa10] dhd_prot_process_ctrlbuf at ffffffbffc1630f8 [wlan]
#20 [ffffffc0be96fab0] dhd_bus_ringbell at ffffffbffc156ff8 [wlan]
#21 [ffffffc0be96faf0] dhd_bus_console_in at ffffffbffc15aa58 [wlan]
#22 [ffffffc0be96fb20] dhd_bus_dpc at ffffffbffc15bfc8 [wlan]
#23 [ffffffc0be96fb60] dhd_sched_dpc at ffffffbffc115fac [wlan]
#24 [ffffffc0be96fb90] tasklet_action at ffffffc000223738
#25 [ffffffc0be96fbb0] __do_softirq at ffffffc000222e94
>From arm64.c:
static int
arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackframe *frame)
{
char *name, *name_plus_offset;
ulong symbol_offset;
struct syment *sp;
struct load_module *lm;
char buf[BUFSIZE];
name = closest_symbol(frame->pc);
name_plus_offset = NULL;
if (bt->flags & BT_SYMBOL_OFFSET) {
/*ADDED*/
if (module_symbol(frame->pc, NULL, &lm, NULL, 0))
sp = value_search_module(frame->pc, &symbol_offset);
else
/*END ADDED*/
sp = value_search(frame->pc, &symbol_offset);
You probably also want to prevent calling module_symbol a second time later in the function.
Jan
Jan Karlsson
Senior Software Engineer
System Assurance
Sony Mobile Communications
Tel: +46 703 062 174
jan.karlsson(a)sonymobile.com<mailto:Firstname.Lastname@sonymobile.com>
sonymobile.com<http://sonymobile.com/>
[cid:image001.gif@01D08BE8.D6EEC470]
9 years, 7 months
right shift of the subtraction result
by Derek Cheng
Hi Dave,
Does this sound like a bug, it need right shift of the subtraction result,
crash-git> pd (678324157984276 >> 32)$10 = 157934crash-git> pd ((681670518181331-678324157984276) >> 32)p: gdb request failed: p ((681670518181331-678324157984276)crash-git>
It might be lacking support of some advanced arithmetic, so what is a proper wayto do some arithmetic like this?
9 years, 7 months
[PATCH 1/1] Resend CLI list command, print deep structure members
by Alexandr Terekhov
Hello Dave,
here is the second reincarnation of the parser. I've updated
`task` and `struct` handlers along with the `list` handler:
crash> list task_struct.tasks -s task_struct.comm,pid,thread.cr2 -H 0xde83a1e0
de840aa0
comm = "ksoftirqd/0\000\000\000\000"
pid = 4
thread.cr2 = 0,
de840550
comm = "stopper/0\000\000\000\000\000\000"
pid = 5
thread.cr2 = 0,
..................
crash> task -R restart_block.fn,restart_block.futex,thread.tls_array[0].base1,cpu_timers[2].next
restart_block.fn = 0xc046fe10 <do_no_restart_syscall>,
restart_block.futex = {
uaddr = 0x0,
val = 0,
flags = 0,
bitset = 0,
time = 0,
uaddr2 = 0x0
},
thread.tls_array[0].base1 = 112,
cpu_timers[2].next = 0xdb9a7838,
crash> task_struct.comm,thread.tls_array[0].dpl 0xdb9a7550
comm = "bash\000\000\000\000\000\000\000\000\000\000\000"
thread.tls_array[0].dpl = 3,
I'm looking forward to your comments/suggestions.
Best regards,
Alexandr
--- crash-7.1.0.orig/symbols.c 2015-02-06 21:44:11.000000000 +0300
+++ crash-7.1.0/symbols.c 2015-05-11 16:11:56.587128595 +0300
@@ -93,6 +93,7 @@ static int dereference_pointer(ulong, st
#define PARSE_FOR_DATA (1)
#define PARSE_FOR_DECLARATION (2)
static void parse_for_member(struct datatype_member *, ulong);
+void parse_for_member_new(struct datatype_member *, ulong);
static int show_member_offset(FILE *, struct datatype_member *, char *);
@@ -5576,17 +5577,18 @@ dump_struct_member(char *s, ulong addr,
FREEBUF(buf);
error(FATAL, "invalid structure name: %s\n", dm->name);
}
- if (!MEMBER_EXISTS(dm->name, dm->member)) {
- FREEBUF(buf);
- error(FATAL, "invalid structure member name: %s\n",
- dm->member);
- }
set_temporary_radix(radix, &restore_radix);
open_tmpfile();
print_struct(dm->name, addr);
- parse_for_member(dm, PARSE_FOR_DATA);
+
+ if (MEMBER_EXISTS(dm->name, dm->member)) {
+ parse_for_member(dm, PARSE_FOR_DATA);
+ } else {
+ parse_for_member_new(dm, PARSE_FOR_DATA);
+ }
+
close_tmpfile();
restore_current_radix(restore_radix);
@@ -6026,8 +6028,7 @@ cmd_datatype_common(ulong flags)
if ((count_chars(args[optind], ',')+1) > MAXARGS)
error(FATAL, "too many members in comma-separated list!\n");
- if ((count_chars(args[optind], '.') > 1) ||
- (LASTCHAR(args[optind]) == ',') ||
+ if ((LASTCHAR(args[optind]) == ',') ||
(LASTCHAR(args[optind]) == '.'))
error(FATAL, "invalid format: %s\n", args[optind]);
@@ -6219,6 +6220,10 @@ do_datatype_addr(struct datatype_member
i = 0;
do {
if (argc_members) {
+ /* This call works fine with fields
+ * of the second, third, ... levels.
+ * There is no need to fix it
+ */
if (!member_to_datatype(memberlist[i], dm,
ANON_MEMBER_QUERY))
error(FATAL, "invalid data structure reference: %s.%s\n",
@@ -6250,7 +6255,12 @@ do_datatype_addr(struct datatype_member
if (dm->member) {
if (!((flags & DEREF_POINTERS) &&
dereference_pointer(addr, dm, flags)))
- parse_for_member(dm, PARSE_FOR_DATA);
+ {
+ if (count_chars(dm->member, '.'))
+ parse_for_member_new(dm, PARSE_FOR_DATA);
+ else
+ parse_for_member(dm, PARSE_FOR_DATA);
+ }
close_tmpfile();
}
@@ -6275,6 +6285,10 @@ do_datatype_declaration(struct datatype_
if (CRASHDEBUG(1))
dump_datatype_member(fp, dm);
+ if (dm->member && count_chars(dm->member, '.'))
+ error(FATAL, "invalid data structure reference: %s.%s\n",
+ dm->name, dm->member);
+
open_tmpfile();
whatis_datatype(dm->name, flags, pc->tmpfile);
rewind(pc->tmpfile);
@@ -7383,6 +7397,270 @@ next_item:
}
}
+struct struct_elem {
+ char field_name[BUFSIZE];
+ unsigned char field_len;
+ char value[BUFSIZE];
+ unsigned char is_array_root:1;
+
+ struct struct_elem *parent;
+ struct struct_elem *inner;
+ struct struct_elem *next;
+ struct struct_elem *prev;
+};
+
+#define ALLOC_XXX_ELEMENT(xxx, clone_parent) \
+{ \
+ if (NULL == current) { \
+ error(FATAL, "Internal error while parsing structure %s\n", dm->name); \
+ } \
+ current->xxx = calloc(1, sizeof(struct struct_elem)); \
+ if (clone_parent) current->xxx->parent = current->parent; \
+ else current->xxx->parent = current; \
+ current = current->xxx; \
+}
+
+#define ALLOC_INNER_ELEMENT { ALLOC_XXX_ELEMENT(inner, 0) }
+#define ALLOC_NEXT_ELEMENT { ALLOC_XXX_ELEMENT(next, 1) }
+
+void free_structure(struct struct_elem *p) {
+ if (p == NULL)
+ return;
+ free_structure(p->inner);
+ free_structure(p->next);
+ free(p);
+}
+
+unsigned char is_right_brace(const char *b) {
+ unsigned char r = 0;
+ for (; *b == ' '; b++);
+ if (*b == '}') {
+ b++;
+ r = 1;
+ if (*b == '}') {
+ r = 2;
+ b++;
+ }
+ }
+
+ if (*b == ',')
+ b++;
+
+ if (*b == '\0')
+ return r;
+ else
+ return 0;
+}
+
+struct struct_elem *find_node(struct struct_elem *s, char *n) {
+ char *p, *b, *e;
+ struct struct_elem *t = s;
+ unsigned i;
+
+ if (('\0' == *n) || (NULL == s))
+ return s;
+
+ /* [n .. p) - struct member with index*/
+ if (NULL == (p = strstr(n, ".")))
+ p = n + strlen(n);
+
+ /* [n .. b) - struct member without index*/
+ for (b = n; (b < p) && (*b != '['); b++);
+
+ /* s - is the current level of items [s, s->next, ..., s->...->next] */
+ for (; s; s = s->next) {
+ if (*s->field_name == '\0')
+ continue;
+
+ /* `field_name` doesn't match */
+ if (((b - n) != s->field_len) || memcmp(s->field_name, n, b - n))
+ continue;
+
+ if (*b == '[') { /* Array */
+ i = strtol(b + 1, &e, 10);
+ /* Check if the current node is array and
+ * we've parsed index more or less correctly
+ */
+ if (!(s->is_array_root && *e == ']'&& (e != b + 1)))
+ return NULL;
+
+ /* Look for the i-th element */
+ for (s = s->inner; s && i; s = s->next, i--);
+ if (i || (NULL == s))
+ return NULL;
+ }
+
+ /* Ok. We've found node, it's - the last member
+ * in our search string, let's return it.
+ */
+ if ('\0' == *p)
+ return s;
+ else
+ return find_node(s->inner, p + 1);
+ }
+
+ // We haven't found any field.
+ // Might happen, we've encountered anonymous structure
+ // of union. Lets try every record without `field_name`
+ s = t;
+ t = NULL;
+ for(; s; s = s->next) {
+ if (*s->field_name)
+ continue;
+ t = find_node(s->inner, n);
+ if (t)
+ break;
+ }
+
+ return t;
+}
+
+void dump_node(struct struct_elem *p, char *f, unsigned char level, unsigned char is_array) {
+ unsigned int i;
+ if (p == NULL)
+ return;
+ do {
+#define PUT_INDENTED_STRING(m, ...) { \
+ for (i = 0; i++ < 2 + 2 * (m * is_array + level); printf(" ")); \
+ printf(__VA_ARGS__); }
+
+ if (p->inner) {
+ if (*p->field_name) {
+ PUT_INDENTED_STRING(1, "%s = %s\n", f ? f : p->field_name, p->inner->is_array_root ? "{{" : "{");
+ } else {
+ if (f) /* For union */
+ PUT_INDENTED_STRING(1, "%s = ", f);
+ PUT_INDENTED_STRING(1, "%s\n", p->inner->is_array_root ? "{{" : "{");
+ }
+ dump_node(p->inner, NULL, is_array + level + 1, p->inner->is_array_root);
+ PUT_INDENTED_STRING(1, "%s%s\n", p->inner->is_array_root ? "}}" : "}", (p->next && !p->next->is_array_root) ? "," : "");
+ } else {
+ PUT_INDENTED_STRING(1, "%s = %s%s", f ? f : p->field_name, p->value, p->next ? ",\n" : "\n");
+ }
+ if (level) {
+ p = p->next;
+ if (p && p->is_array_root)
+ PUT_INDENTED_STRING(0, "}, {\n");
+ }
+ } while (p && level);
+}
+
+void parse_for_member_new(struct datatype_member *dm,
+ ulong __attribute__ ((unused)) flag)
+{
+ struct struct_elem *i, *current = NULL, *root = NULL;
+
+ char buf[BUFSIZE];
+ char *p, *p1;
+ char *s_e; // structure_element
+ unsigned int len;
+ unsigned char trailing_comma, braces, found = 0;
+
+ rewind(pc->tmpfile);
+
+ root = calloc(1, sizeof(struct struct_elem));
+ current = root;
+ ALLOC_INNER_ELEMENT;
+
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ len = strlen(buf) - 1;
+ for (; buf[len] <= ' '; buf[len--] = '\0');
+ if ((trailing_comma = (buf[len] == ',')))
+ buf[len--] = '\0';
+
+ if ((braces = is_right_brace(buf))) {
+ for (; braces && current; braces--)
+ current = current->parent;
+
+ if ((current->parent == root) || trailing_comma)
+ ALLOC_NEXT_ELEMENT;
+ continue;
+ }
+
+ for (p1 = buf; *p1 == ' '; p1++);
+
+ if (NULL != (p = strstr(buf, " = "))) {
+ s_e = p + 3;
+ } else {
+ s_e = p1;
+ }
+
+ /*
+ * After that we have pointers:
+ * foobar = bazzz
+ * -----^ ^ ^
+ * | ------| |
+ * | | |
+ * p1 p s_e
+ *
+ * OR
+ *
+ * {
+ * ^
+ * |
+ * ---------
+ * | |
+ * p1 s_e
+ *
+ * p == NULL
+ *
+ *
+ * p1 - the first non-whitespace symbol in line
+ * p - pointer to line ' = '. If not NULL, there is identifier
+ * s_e - element of structure (brace / double brace / array separator / scalar :))
+ *
+ */
+
+ if (current && p) strncpy(current->field_name, p1, p - p1);
+ current->field_len = p - p1;
+
+ if ( p && (*s_e != '{' || (*s_e == '{' && buf[len] == '}') )) {
+ /* Scalar or one-line array
+ * next = 0x0
+ * or
+ * files = {0x0, 0x0}
+ */
+ strcpy(current->value, s_e);
+ if (trailing_comma) ALLOC_NEXT_ELEMENT;
+ }
+ else
+ if ( *s_e == '{' ) {
+ ALLOC_INNER_ELEMENT;
+ if (*(s_e + 1) == '{') {
+ current->parent->is_array_root = 1;
+ ALLOC_INNER_ELEMENT;
+ }
+ }
+ else
+ if (strstr(s_e, "}, {")) {
+ /* Next array element */
+ current = current->parent;
+ ALLOC_NEXT_ELEMENT;
+ ALLOC_INNER_ELEMENT;
+ }
+ else
+ if (buf == (p = strstr(buf, "struct "))) {
+ p += 7; /* strlen "struct " */
+ p1 = strstr(buf, " {");
+ strncpy(current->field_name, p, p1 - p);
+ ALLOC_INNER_ELEMENT;
+ }
+ }
+
+ for (i = root->inner; i; i = i->next) {
+ if ((current = find_node(i->inner, dm->member))) {
+ dump_node(current, dm->member, 0, 0);
+ found = 1;
+ break;
+ }
+ }
+
+ free_structure(root);
+
+ if (!found)
+ error(WARNING, "invalid structure reference: %s\n", dm->member);
+}
+
/*
* Dig out a member name from a formatted gdb structure declaration dump,
* and print its offset from the named structure passed in.
--- crash-7.1.0.orig/task.c 2015-02-06 21:44:11.000000000 +0300
+++ crash-7.1.0/task.c 2015-05-11 15:52:57.387111513 +0300
@@ -107,6 +107,8 @@ static int sort_by_last_run(const void *
static void sort_context_array_by_last_run(void);
static void show_ps_summary(ulong);
static void irqstacks_init(void);
+static void parse_task_thread(int argcnt, char *arglist[], struct task_context *);
+void parse_for_member_new(struct datatype_member *, ulong);
/*
* Figure out how much space will be required to hold the task context
@@ -2746,13 +2748,9 @@ task_struct_member(struct task_context *
int argcnt;
char *arglist[MAXARGS];
char *refcopy;
- char buf[BUFSIZE];
- char lookfor1[BUFSIZE];
- char lookfor2[BUFSIZE];
- char lookfor3[BUFSIZE];
- int header_printed;
-
- header_printed = FALSE;
+ unsigned char call_new_parser = 0;
+ struct datatype_member dm;
+ char *member = GETBUF(BUFSIZE);
if ((count_chars(ref->str, ',')+1) > MAXARGS) {
error(INFO,
@@ -2767,14 +2765,39 @@ task_struct_member(struct task_context *
argcnt = parse_line(refcopy, arglist);
for (i = 0; i < argcnt; i++)
if (!MEMBER_EXISTS("task_struct", arglist[i]) &&
- !MEMBER_EXISTS("thread_info", arglist[i]))
- error(INFO, "%s: not a task_struct or thread_info member\n",
- arglist[i]);
-
+ !MEMBER_EXISTS("thread_info", arglist[i])) {
+ if (count_chars(arglist[i], '.') || count_chars(arglist[i], '['))
+ call_new_parser = 1;
+ else
+ error(INFO, "%s: not a task_struct or "
+ "thread_info member\n", arglist[i]);
+ }
open_tmpfile();
dump_struct("task_struct", tc->task, radix);
- if (tt->flags & THREAD_INFO)
- dump_struct("thread_info", tc->thread_info, radix);
+ if (tt->flags & THREAD_INFO)
+ dump_struct("thread_info", tc->thread_info, radix);
+ if (call_new_parser) {
+ for (i = 0; i < argcnt; i++) {
+ dm.member = arglist[i];
+ parse_for_member_new(&dm, 0);
+ }
+ } else {
+ parse_task_thread(argcnt, arglist, tc);
+ }
+ close_tmpfile();
+
+ FREEBUF(member);
+
+}
+
+static void parse_task_thread(int argcnt, char *arglist[], struct task_context *tc) {
+ char buf[BUFSIZE];
+ char lookfor1[BUFSIZE];
+ char lookfor2[BUFSIZE];
+ char lookfor3[BUFSIZE];
+ int header_printed = FALSE;
+ int i;
+
rewind(pc->tmpfile);
BZERO(lookfor1, BUFSIZE);
@@ -2825,7 +2848,6 @@ task_struct_member(struct task_context *
}
}
}
- close_tmpfile();
}
static char *ps_exclusive =
--- crash-7.1.0.orig/tools.c 2015-02-06 21:44:11.000000000 +0300
+++ crash-7.1.0/tools.c 2015-05-11 15:52:57.391111513 +0300
@@ -3526,13 +3526,9 @@ do_list(struct list_data *ld)
dump_struct(ld->structname[i],
next - ld->list_head_offset, radix);
break;
- case 1:
+ default:
dump_struct_members(ld, i, next);
break;
- default:
- error(FATAL,
- "invalid structure reference: %s\n",
- ld->structname[i]);
}
}
}
9 years, 7 months
New crash release for kernels >= 4.0?
by Michael Holzheu
Hello Dave,
At least on s390 the latest crash version 7.1 does not work with kernels >= 4.0:
WARNING: kernels compiled by different gcc versions:
/boot/vmlinux: (unknown)
vmcore kernel: 4.9.2
WARNING: kernel version inconsistency between vmlinux and dumpfile
crash: incompatible arguments: /boot/vmlinux is not SMP -- vmcore is SMP
The git master branch seems to have a patch that solves this problem.
IMO it would be good to have a new crash release with that fix.
What do you think?
Michael
9 years, 7 months
Re: [Crash-utility] [PATCH 1/1] Resend CLI list command, print deep structure members
by Dave Anderson
Alex,
Just send me a full patch against symbols.c, since that's the only file that you'll need to patch from this point on. I'm happy with the state of the other files.
Thanks,
Dave
Sent from my ASUS Pad
Alexandr Terekhov <Alexandr_Terekhov(a)epam.com> wrote:
>On Tue, May 19, 2015 at 12:14:49PM -0400, Dave Anderson wrote:
>> I've run into three problems dealing with embedded arrays.
>>
>> First, should array elements inside an embedded structure be
>> selectable? For example, the task_struct has an embedded
>> task_rss_stat structure:
>>
>.........
>> crash> task -R rss_stat.count[1]
>> PID: 11722 TASK: ffff8801073da5d0 CPU: 2 COMMAND: "crash"
>> task: invalid structure member reference: rss_stat.count[1]
>> crash>
>>
>> Is that expected behavior?
>
>Yes, the new logic consider structure
>
> count = {0, 0, 0}
>
>in the same way as scalar (you can find the corresponding comment within
>parser branches.
>+ if ( p && (*s_e != '{' || (*s_e == '{' && buf[len] == '}'))) {
>+ /* Scalar or one-line array
>+ * next = 0x0
>+ * or
>+ * files = {0x0, 0x0}
>+ */
>+ strcpy(current->value, s_e);
>+ if (trailing_comma) ALLOC_NEXT_ELEMENT;
>+ }
>
>Since this type of array is short, I wasn't sure whether it's necessary to
>access its elements or not.
>
>> But for some reason, it fails to accept the "pid_link.pid" member:
>>
>> crash> task -R pids[1].pid
>> PID: 11722 TASK: ffff8801073da5d0 CPU: 0 COMMAND: "crash"
>> task: invalid structure member reference: pids[1].pid
>
>This behavior is incorrent, I will check it.
>
>> And third, this behavior also doesn't seem correct. Here again I select
>> just the first element of the task_struct.pids[] array:
>>
>> crash> task -R pids[0].node
>> PID: 11722 TASK: ffff8801073da5d0 CPU: 2 COMMAND: "crash"
>> pids[0].node = {
>> next = 0x0,
>> pprev = 0xffff880105fc9888
>> },
>>
>> But it allows me to leave off the "pids[x]" reference, and if so, it defaults
>> to the first member of the array:
>>
>> crash> task -R pids.node
>> PID: 11722 TASK: ffff8801073da5d0 CPU: 0 COMMAND: "crash"
>> pids.node = {
>> next = 0x0,
>> pprev = 0xffff880105fc9888
>> },
>>
>> Should it reject that syntax?
>
>Yes, it should. I will fix it.
>
>And again, since you've started updating my patch, what is the best way
>to provide these fixes?
>
>Thanks,
>Alexandr
>
>--
>Crash-utility mailing list
>Crash-utility(a)redhat.com
>https://www.redhat.com/mailman/listinfo/crash-utility
>
9 years, 7 months
[PATCH] MIPS: support getting regs from kdump dumpfiles
by Rabin Vincent
Add support for using the notes in MIPS' kdump compressed format
dumpfiles.
---
diskdump.c | 19 +++++++++++++++----
mips.c | 4 ++++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/diskdump.c b/diskdump.c
index 585aaa9..90f3bff 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1285,14 +1285,11 @@ extern void get_netdump_regs_x86(struct bt_info *, ulong *, ulong *);
extern void get_netdump_regs_x86_64(struct bt_info *, ulong *, ulong *);
static void
-get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp)
+get_diskdump_regs_32(struct bt_info *bt, ulong *eip, ulong *esp)
{
Elf32_Nhdr *note;
int len;
- if (KDUMP_CMPRS_VALID())
- ppc_relocate_nt_prstatus_percpu(dd->nt_prstatus_percpu,
- &dd->num_prstatus_notes);
if (KDUMP_CMPRS_VALID() &&
(bt->task == tt->panic_task ||
(is_task_active(bt->task) && dd->num_prstatus_notes > 1))) {
@@ -1313,6 +1310,16 @@ get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp)
}
static void
+get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp)
+{
+ if (KDUMP_CMPRS_VALID())
+ ppc_relocate_nt_prstatus_percpu(dd->nt_prstatus_percpu,
+ &dd->num_prstatus_notes);
+
+ get_diskdump_regs_32(bt, eip, esp);
+}
+
+static void
get_diskdump_regs_ppc64(struct bt_info *bt, ulong *eip, ulong *esp)
{
if ((bt->task == tt->panic_task) && DISKDUMP_VALID())
@@ -1346,6 +1353,10 @@ get_diskdump_regs(struct bt_info *bt, ulong *eip, ulong *esp)
get_diskdump_regs_arm(bt, eip, esp);
break;
+ case EM_MIPS:
+ return get_diskdump_regs_32(bt, eip, esp);
+ break;
+
case EM_386:
return get_netdump_regs_x86(bt, eip, esp);
break;
diff --git a/mips.c b/mips.c
index 77077fb..4b62d1e 100644
--- a/mips.c
+++ b/mips.c
@@ -833,6 +833,10 @@ mips_init(int when)
#endif
switch (when) {
+ case SETUP_ENV:
+ machdep->process_elf_notes = process_elf32_notes;
+ break;
+
case PRE_SYMTAB:
machdep->verify_symbol = mips_verify_symbol;
machdep->machspec = &mips_machine_specific;
--
1.7.10.4
9 years, 7 months
[PATCH 1/6] MIPS: fix register numbers
by Rabin Vincent
The MIPS general purpose registers in the elf_gregset_t don't start at
index 0 but at index 6.
(Note that the example dump files I provided earlier use the wrong
offsets; I'll make new ones).
---
mips.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/mips.c b/mips.c
index c181074..e5567f0 100644
--- a/mips.c
+++ b/mips.c
@@ -47,6 +47,11 @@ typedef ulong pte_t;
#define MIPS_CPU_RIXI 0x00800000llu
+#define MIPS32_EF_R0 6
+#define MIPS32_EF_R29 35
+#define MIPS32_EF_R31 37
+#define MIPS32_EF_CPU0_EPC 40
+
static struct machine_specific mips_machine_specific = { 0 };
static void
@@ -520,7 +525,7 @@ mips_back_trace_cmd(struct bt_info *bt)
if (bt->machdep) {
struct mips_regset *regs = bt->machdep;
- previous.pc = current.ra = regs->regs[31];
+ previous.pc = current.ra = regs->regs[MIPS32_EF_R31];
}
while (INSTACK(current.sp, bt)) {
@@ -614,9 +619,9 @@ mips_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp)
}
if (nip)
- *nip = regs->regs[40];
+ *nip = regs->regs[MIPS32_EF_CPU0_EPC];
if (ksp)
- *ksp = regs->regs[29];
+ *ksp = regs->regs[MIPS32_EF_R29];
}
static int
--
1.7.10.4
9 years, 7 months
Re: [Crash-utility] [PATCH v2] kmem: Introduce -m option
by Dave Anderson
Aaron Tomlin and I have been collaborating offline/in-house with respect
to this patch, and we've finally come up with an implementation that is
queued for crash-7.1.1:
https://github.com/crash-utility/crash/commit/a8e7fc1e580122fac032c80f789...
- Implemented a new "kmem -m" option that is similar to "kmem -p",
but it allows the user to specify the page struct members to be
displayed. The option takes a comma-separated list of one or
more page struct members, which will be displayed following the
page structure address. The "flags" member will always be expressed
in hexadecimal format, and the "_count" and "_mapcount" members will
always be expressed in decimal format. Otherwise, all other members
will be displayed in hexadecimal format unless the current output
radix is 10 and the member is a signed/unsigned integer. Members
that are data structures may be specified by the data structure's
member name, or expanded to specify a member of that data structure.
For example, "-m lru" refers to a list_head data structure, in which
case both the list_head.next and list_head.prev pointer values will
be displayed; if "-m lru.next" is specified, just the list_head.next
value will be displayed.
(atomlin(a)redhat.com, anderson(a)redhat.com)
9 years, 7 months