[ANNOUNCE] crash version 5.1.1 is available
by Dave Anderson
- Fix for the potential to miss tasks when walking the pid_hash table
in 2.6.24 and later kernels. Without the patch, the task will simply
not be seen in the gathered task list.
(holzheu(a)linux.vnet.ibm.com)
- Enhancement for the ARM architecture's "bt" command to print out
the user space register set for tasks entering the kernel via the
syscall entry point.
(ext-mika.1.westerberg(a)nokia.com)
- Rework of the handling of "set" commands that are put in .crashrc
files so that only the following options are resolved prior to
session initialization: silent, console, core, edit, namelist, and
zero_excluded. All others are resolved immediately after session
initialization is complete. Accordingly, the use of "set -c <cpu>",
"set -p", "set -a [task|pid]" and set [pid|task]" are now acceptable
.crashrc commands.
(anderson(a)redhat.com)
- The entering of "set -v" in a .crashrc file would cause an immediate
segmentation violation. The "set" command rework above defers the
command until session initialization is complete.
(anderson(a)redhat.com)
- The entering of "set dumpfile <filename>" in a .crashrc file would
cause a fatal "seek" error during session initalization with most
most dumpfile types, so the "dumpfile" option has been removed from
the "set" command.
(anderson(a)redhat.com)
- The execution of "alias" commands from a .crashrc file used to be
performed immediately; that behavior has been changed so that they
are executed immediately after session initialization is complete.
(anderson(a)redhat.com)
- Enhancement of the "repeat" command to allow command aliases.
(anderson(a)redhat.com)
- Fix for running "kmem -s" on a live system if an offline cpu is
brought back online while the command is executing. Without the
patch, the online operation may cause a segmentation violation.
(anderson(a)redhat.com)
- Change the behavior of "bt -[tT]" to allow the command options
to be run on active tasks on live systems. Without the patch,
both command options would display the task data banner followed
by "(active)".
(anderson(a)redhat.com)
- Fix for the ARM architecuture's "irq" command when run on 2.6.36
and later kernels. Without the patch, the command fails with the
error message "irq: invalid kernel virtual address: 23 type:
irq_chip typename". The fix replaces the custom ARM IRQ dumping
function with the architecture-neutral version.
(ext-mika.1.westerberg(a)nokia.com)
- Introduced support for using /proc/kcore as an alternative source of
live memory to /dev/mem. Doing so allows vmalloc memory access on
32-bit architectures when the underlying mapped physical memory is in
highmem, which is not allowed by the /dev/mem driver. It would also
be usable on systems that are configured with CONFIG_STRICT_DEVMEM
but still configured with CONFIG_PROC_KCORE. To enforce the use of
/proc/kcore, it may be entered on the command line.
(anderson(a)redhat.com)
- If a live crash session attempts to use /dev/mem as a live memory
source, and it is determined that the system is configured with
CONFIG_STRICT_DEVMEM, /proc/kcore will automatically be tried as
an alternative.
(anderson(a)redhat.com)
- Fix to allow "/dev/crash" to be entered on the command line for live
sessions. Because it is used automatically if it exists, it is never
necessary to enter it on the command line. However, if it is used,
without the patch, the session fails during initializaion with the
error message "crash: /dev/crash: No such file or directory" if the
crash.ko driver is a module (RHEL4/RHEL5), or "crash: /dev/crash:
not a supported file format" if the driver is built into the kernel
(RHEL6).
(anderson(a)redhat.com)
- Fix for the ARM "bt" command to address the issue behind faulty
warning messages that indicate "WARNING: UNWIND: unsupported
personality routine".
(ext-mika.1.westerberg(a)nokia.com)
- Fix for the ARM "bt" command to address the issue behind faulty
warning messages that indicate "bt: WARNING: UNWIND: cannot find
index for <address>".
(ext-mika.1.westerberg(a)nokia.com)
Download from: http://people.redhat.com/anderson
13 years, 10 months
[PATCH 0/2] ARM unwinding fixes
by Mika Westerberg
Hi Dave,
Here's another set of bug fixes for the ARM port. This time related
to the unwinding code.
These apply on top of my previous patches. I'll appreciate if you could
consider queuing these for the next release :)
I've tested these on my ever increasing pile of crashdumps for ARM
and also on live system.
Thanks,
MW
Mika Westerberg (2):
ARM: unwind: fix unwinding when prel31 offset is used
ARM: unwind: limit unwinding to the kernel text
unwind_arm.c | 166 ++++++++++++++++++++++++++++++++++------------------------
1 files changed, 98 insertions(+), 68 deletions(-)
--
1.7.3.2
13 years, 10 months
[PATCH] ARM: use generic_dump_irq() instead of a custom one
by Mika Westerberg
There is no reason for having custom IRQ dumping function on ARM
and having such causes maintenance burden when the kernel IRQ
structures change.
So convert ARM to use generic_dump_irq() and remove all the now
unused ARM specific IRQ dumping code.
Signed-off-by: Mika Westerberg <ext-mika.1.westerberg(a)nokia.com>
Cc: jan.karlsson(a)sonyericsson.com
Cc: thomas.fange(a)sonyericsson.com
---
This patch applies on top of my 2 previous patches (the ones you
already queued).
arm.c | 326 +----------------------------------------------------------------
1 files changed, 3 insertions(+), 323 deletions(-)
diff --git a/arm.c b/arm.c
index 751fe00..4e6ab3d 100644
--- a/arm.c
+++ b/arm.c
@@ -52,8 +52,6 @@ static ulong arm_get_task_pgd(ulong);
static void arm_cmd_mach(void);
static void arm_display_machine_stats(void);
static int arm_get_smp_cpus(void);
-static void print_irq_member(char *, ulong, char *);
-static void arm_dump_irq(int);
static void arm_init_machspec(void);
static struct line_number_hook arm_line_number_hooks[];
@@ -237,22 +235,15 @@ arm_init(int when)
machdep->line_number_hooks = arm_line_number_hooks;
machdep->value_to_symbol = generic_machdep_value_to_symbol;
machdep->init_kernel_pgd = NULL;
-
- if (symbol_exists("irq_desc"))
- machdep->dump_irq = arm_dump_irq;
+ machdep->dump_irq = generic_dump_irq;
arm_init_machspec();
break;
case POST_GDB:
- if (symbol_exists("irq_desc")) {
+ if (symbol_exists("irq_desc"))
ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
"irq_desc", NULL, 0);
- if (MEMBER_EXISTS("irq_desc", "name"))
- MEMBER_OFFSET_INIT(irq_desc_t_name, "irq_desc",
- "name");
- }
-
/*
* Registers for idle threads are saved in
* thread_info.cpu_context.
@@ -343,10 +334,7 @@ arm_dump_machdep_table(ulong arg)
fprintf(fp, " uvtop: arm_uvtop()\n");
fprintf(fp, " kvtop: arm_kvtop()\n");
fprintf(fp, " get_task_pgd: arm_get_task_pgd()\n");
- if (symbol_exists("irq_desc"))
- fprintf(fp, " dump_irq: arm_dump_irq()\n");
- else
- fprintf(fp, " dump_irq: NULL\n");
+ fprintf(fp, " dump_irq: generic_dump_irq()\n");
fprintf(fp, " get_stack_frame: arm_get_stack_frame()\n");
fprintf(fp, " get_stackbase: generic_get_stackbase()\n");
fprintf(fp, " get_stacktop: generic_get_stacktop()\n");
@@ -1409,314 +1397,6 @@ arm_get_smp_cpus(void)
return get_cpus_online();
}
-static void
-print_irq_member(char *irq, ulong val, char *ind)
-{
- char buf[BUFSIZE];
- ulong val2;
-
- fprintf(fp, "%17s: %8lx ", irq, val);
- if (val) {
- if (is_kernel_text(val))
- fprintf(fp, "<%s>", value_to_symstr(val, buf, 0));
- else if (readmem(val, KVADDR, &val2,
- sizeof(ulong), ind, RETURN_ON_ERROR|QUIET) &&
- is_kernel_text(val2))
- fprintf(fp, "<%s>", value_to_symstr(val2, buf, 0));
- }
- fprintf(fp, "\n");
-}
-
-/*
- * Do the work for cmd_irq().
- */
-static void
-arm_dump_irq(int irq)
-{
- struct datatype_member datatype_member, *dm;
- ulong irq_desc_addr;
- ulong irq_desc_ptr;
- long len;
- char buf[BUFSIZE];
- int type, status, depth, others;
- ulong handler, action, value;
- ulong tmp1;
-
- dm = &datatype_member;
-
- if (!VALID_STRUCT(irq_desc_t))
- error(FATAL, "cannot determine size of irq_desc\n");
- len = SIZE(irq_desc_t);
-
- if (symbol_exists("irq_desc"))
- irq_desc_addr = symbol_value("irq_desc") + (len * irq);
- else if (symbol_exists("_irq_desc"))
- irq_desc_addr = symbol_value("_irq_desc") + (len * irq);
- else if (symbol_exists("irq_desc_ptrs")) {
- get_symbol_data("irq_desc_ptrs", sizeof(void *), &irq_desc_ptr);
- irq_desc_ptr += (irq * sizeof(void *));
- readmem(irq_desc_ptr, KVADDR, &irq_desc_addr,
- sizeof(void *), "irq_desc_ptrs entry",
- FAULT_ON_ERROR);
- if (!irq_desc_addr) {
- fprintf(fp, " IRQ: %d (unused)\n\n", irq);
- return;
- }
- } else {
- irq_desc_addr = 0;
- error(FATAL,
- "neither irq_desc, _irq_desc, nor irq_desc_ptrs "
- "symbols exist\n");
- }
-
- readmem(irq_desc_addr + OFFSET(irq_desc_t_status), KVADDR, &status,
- sizeof(int), "irq_desc entry", FAULT_ON_ERROR);
- if (VALID_MEMBER(irq_desc_t_handler))
- readmem(irq_desc_addr + OFFSET(irq_desc_t_handler), KVADDR,
- &handler, sizeof(long), "irq_desc entry",
- FAULT_ON_ERROR);
- else if (VALID_MEMBER(irq_desc_t_chip))
- readmem(irq_desc_addr + OFFSET(irq_desc_t_chip), KVADDR,
- &handler, sizeof(long), "irq_desc entry",
- FAULT_ON_ERROR);
- readmem(irq_desc_addr + OFFSET(irq_desc_t_action), KVADDR, &action,
- sizeof(long), "irq_desc entry", FAULT_ON_ERROR);
- readmem(irq_desc_addr + OFFSET(irq_desc_t_depth), KVADDR, &depth,
- sizeof(int), "irq_desc entry", FAULT_ON_ERROR);
-
- if (!action && (handler == (ulong)pc->curcmd_private))
- return;
-
- fprintf(fp, " IRQ: %d\n", irq);
- fprintf(fp, "ADDRESS: %08lx\n", irq_desc_addr);
-
- if (VALID_MEMBER(irq_desc_t_name)) {
- readmem(irq_desc_addr+OFFSET(irq_desc_t_name),
- KVADDR, &tmp1, sizeof(void *),
- "irq_desc name", FAULT_ON_ERROR);
- if (tmp1) {
- fprintf(fp, " NAME: %lx", tmp1);
- BZERO(buf, BUFSIZE);
- if (read_string(tmp1, buf, BUFSIZE-1))
- fprintf(fp, " \"%s\"", buf);
- fprintf(fp, "\n");
- }
- }
-
- type = status & IRQ_TYPE_SENSE_MASK;
- fprintf(fp, " TYPE: %x %s", type, type ? "(" : "");
- others = 0;
-
- if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- fprintf(fp, "%sEDGE_BOTH", others++ ? "|" : "");
- else {
- if (type & IRQ_TYPE_EDGE_RISING)
- fprintf(fp, "%sEDGE_RISING", others++ ? "|" : "");
- if (type & IRQ_TYPE_EDGE_FALLING)
- fprintf(fp, "%sEDGE_FALLING", others++ ? "|" : "");
- }
- if (type & IRQ_TYPE_LEVEL_HIGH)
- fprintf(fp, "%sLEVEL_HIGH", others++ ? "|" : "");
- if (type & IRQ_TYPE_LEVEL_LOW)
- fprintf(fp, "%sLEVEL_LOW", others++ ? "|" : "");
- fprintf(fp, "%s\n", type ? ")" : "");
-
- fprintf(fp, " PROBE: %s\n", status & IRQ_TYPE_PROBE ? "true" : "false");
-
- fprintf(fp, " STATUS: %x %s", status, status ? "(" : "");
- others = 0;
- if (status & IRQ_INPROGRESS) {
- fprintf(fp, "IRQ_INPROGRESS");
- others++;
- }
- if (status & IRQ_DISABLED)
- fprintf(fp, "%sIRQ_DISABLED", others++ ? "|" : "");
- if (status & IRQ_PENDING)
- fprintf(fp, "%sIRQ_PENDING", others++ ? "|" : "");
- if (status & IRQ_REPLAY)
- fprintf(fp, "%sIRQ_REPLAY", others++ ? "|" : "");
- if (status & IRQ_AUTODETECT)
- fprintf(fp, "%sIRQ_AUTODETECT", others++ ? "|" : "");
- if (status & IRQ_WAITING)
- fprintf(fp, "%sIRQ_WAITING", others++ ? "|" : "");
- if (status & IRQ_LEVEL)
- fprintf(fp, "%sIRQ_LEVEL", others++ ? "|" : "");
- if (status & IRQ_MASKED)
- fprintf(fp, "%sIRQ_MASKED", others++ ? "|" : "");
-
- if (status & IRQ_PER_CPU)
- fprintf(fp, "%sIRQ_PER_CPU", others++ ? "|" : "");
- if (status & IRQ_NOPROBE)
- fprintf(fp, "%sIRQ_NOPROBE", others++ ? "|" : "");
- if (status & IRQ_NOREQUEST)
- fprintf(fp, "%sIRQ_NOREQUEST", others++ ? "|" : "");
- if (status & IRQ_NOAUTOEN)
- fprintf(fp, "%sIRQ_NOAUTOEN", others++ ? "|" : "");
- if (status & IRQ_WAKEUP)
- fprintf(fp, "%sIRQ_WAKEUP", others++ ? "|" : "");
- if (status & IRQ_MOVE_PENDING)
- fprintf(fp, "%sIRQ_MOVE_PENDING", others++ ? "|" : "");
- if (status & IRQ_NO_BALANCING)
- fprintf(fp, "%sIRQ_NO_BALANCING", others++ ? "|" : "");
- if (status & IRQ_SPURIOUS_DISABLED)
- fprintf(fp, "%sIRQ_SPURIOUS_DISABLED", others++ ? "|" : "");
- if (status & IRQ_MOVE_PCNTXT)
- fprintf(fp, "%sIRQ_MOVE_PCNTXT", others++ ? "|" : "");
- if (status & IRQ_AFFINITY_SET)
- fprintf(fp, "%sIRQ_AFFINITY_SET", others++ ? "|" : "");
-
-
- fprintf(fp, "%s\n", status ? ")" : "");
-
- fprintf(fp, "HANDLER: %8lx ", handler);
- if (value_symbol(handler)) {
- pad_line(fp, VADDR_PRLEN == 8 ? VADDR_PRLEN+2 : VADDR_PRLEN-6, ' ');
- fprintf(fp, "<%s>", value_symbol(handler));
- }
- fprintf(fp, "\n");
-
-#define CHECK_HANDLER_OPT_MEMBER_PRT(x) \
- if (VALID_MEMBER(hw_interrupt_type_ ## x)) { \
- readmem(handler+OFFSET(hw_interrupt_type_ ## x), KVADDR, \
- &tmp1, sizeof(void *), "hw_interrupt_type " #x, \
- FAULT_ON_ERROR); \
- print_irq_member(#x, tmp1, #x " indirection"); \
- } else if (VALID_MEMBER(irq_chip_ ## x)) { \
- readmem(handler+OFFSET(irq_chip_ ## x),KVADDR, &tmp1, \
- sizeof(void *), "irq_chip " #x, FAULT_ON_ERROR); \
- print_irq_member(#x, tmp1, #x " indirection"); \
- }
-
-#define CHECK_HANDLER_OPT_MEMBER(x) \
- if (VALID_MEMBER(hw_interrupt_type_ ## x)) \
- readmem(handler+OFFSET(hw_interrupt_type_ ## x), KVADDR, \
- &tmp1, sizeof(void *), "hw_interrupt_type " #x, \
- FAULT_ON_ERROR); \
- else if (VALID_MEMBER(irq_chip_ ## x)) \
- readmem(handler+OFFSET(irq_chip_ ## x),KVADDR, &tmp1, \
- sizeof(void *), "irq_chip " #x, FAULT_ON_ERROR); \
-
-#define CHECK_HANDLER_MEMBER_PRT(x,s1,s2) \
- if (VALID_MEMBER(x)) { \
- readmem(handler+OFFSET(x), KVADDR, &tmp1, sizeof(void *),\
- s1, FAULT_ON_ERROR); \
- print_irq_member(s2, tmp1, s2 " indirection"); \
- }
-
- if (handler) {
- CHECK_HANDLER_OPT_MEMBER(typename);
-
- fprintf(fp, " typename: %lx ", tmp1);
- BZERO(buf, BUFSIZE);
- if (read_string(tmp1, buf, BUFSIZE-1))
- fprintf(fp, "\"%s\"", buf);
- fprintf(fp, "\n");
-
- CHECK_HANDLER_OPT_MEMBER(startup);
-
- print_irq_member("startup", tmp1, "startup indirection");
-
- CHECK_HANDLER_OPT_MEMBER(shutdown);
-
- print_irq_member("shutdown", tmp1, "shutdown indirection");
-
- CHECK_HANDLER_MEMBER_PRT(hw_interrupt_type_handle,
- "hw_interrupt_type handle",
- "handle");
-
- CHECK_HANDLER_OPT_MEMBER(enable);
-
- print_irq_member("enable", tmp1, "enable indirection");
-
- CHECK_HANDLER_OPT_MEMBER(disable);
-
- print_irq_member("disable", tmp1, "disable indirection");
-
- CHECK_HANDLER_OPT_MEMBER(ack);
-
- print_irq_member("ack", tmp1, "ack indirection");
-
- CHECK_HANDLER_MEMBER_PRT(irq_chip_mask, "irq_chip mask","mask");
-
- CHECK_HANDLER_MEMBER_PRT(irq_chip_mask_ack, "irq_chip mask_ack",
- "mask_ack");
-
- CHECK_HANDLER_MEMBER_PRT(irq_chip_unmask, "irq_chip unmask",
- "unmask");
-
- CHECK_HANDLER_MEMBER_PRT(irq_chip_eoi,"irq_chip eoi","eoi");
-
- CHECK_HANDLER_OPT_MEMBER_PRT(startup);
-
- CHECK_HANDLER_OPT_MEMBER_PRT(set_affinity);
-
- CHECK_HANDLER_MEMBER_PRT(irq_chip_retrigger,
- "irq_chip retrigger", "retrigger");
- CHECK_HANDLER_MEMBER_PRT(irq_chip_set_type,
- "irq_chip set_type", "set_type");
- CHECK_HANDLER_MEMBER_PRT(irq_chip_set_wake,
- "irq_chip set_wake", "set_wake");
- }
-
-do_linked_action:
-
- fprintf(fp, " ACTION: ");
- if (value_symbol(action)) {
- fprintf(fp, "%lx ", action);
- pad_line(fp, VADDR_PRLEN == 8 ?
- VADDR_PRLEN+2 : VADDR_PRLEN - 6, ' ');
- fprintf(fp, "<%s>\n", value_symbol(action));
- } else if (action) {
- fprintf(fp, "%8lx\n", action);
- } else {
- fprintf(fp, "(none)\n");
- }
-
- if (action) {
- readmem(action+OFFSET(irqaction_handler), KVADDR,
- &tmp1, sizeof(void *),
- "irqaction handler", FAULT_ON_ERROR);
-
- print_irq_member("handler", tmp1, "handler indirection");
-
- readmem(action+OFFSET(irqaction_flags), KVADDR,
- &value, sizeof(void *),
- "irqaction flags", FAULT_ON_ERROR);
- fprintf(fp, " flags: %8lx\n", value);
-
- if (VALID_MEMBER(irqaction_mask)) {
- readmem(action+OFFSET(irqaction_mask), KVADDR,
- &tmp1, sizeof(void *),
- "irqaction mask", FAULT_ON_ERROR);
- fprintf(fp, " mask: %8lx\n", tmp1);
- }
-
- readmem(action+OFFSET(irqaction_name), KVADDR,
- &tmp1, sizeof(void *),
- "irqaction name", FAULT_ON_ERROR);
- fprintf(fp, " name: %8lx ", tmp1);
- BZERO(buf, BUFSIZE);
- if (read_string(tmp1, buf, BUFSIZE-1))
- fprintf(fp, "\"%s\"", buf);
- fprintf(fp, "\n");
-
- readmem(action+OFFSET(irqaction_dev_id), KVADDR,
- &tmp1, sizeof(void *),
- "irqaction dev_id", FAULT_ON_ERROR);
- fprintf(fp, " dev_id: %8lx\n", tmp1);
-
- readmem(action+OFFSET(irqaction_next), KVADDR,
- &action, sizeof(void *),
- "irqaction dev_id", FAULT_ON_ERROR);
- fprintf(fp, " next: %8lx\n", action);
- }
-
- if (action)
- goto do_linked_action;
-
- fprintf(fp, " DEPTH: %d\n\n", depth);
-}
-
/*
* Initialize ARM specific stuff.
*/
--
1.7.3.2
13 years, 10 months
Re: [Crash-utility] [PATCH] ARM: dump also userspace registers when backtracing
by Dave Anderson
----- "Mika Westerberg" <ext-mika.1.westerberg(a)nokia.com> wrote:
> On Wed, Dec 01, 2010 at 11:27:32AM -0500, ext Dave Anderson wrote:
> >
> > ----- "Mika Westerberg" <ext-mika.1.westerberg(a)nokia.com> wrote:
> >
> > > Enhance backtracing code to print out userspace registers in case we
> > > are at syscall entry. Other architectures supported by crash are
> > > already doing this.
> > >
> > > Signed-off-by: Mika Westerberg <ext-mika.1.westerberg(a)nokia.com>
> > > ---
> > > I tested this with both unwind tables and framepointers enabled on
> > > my test vmcores, and also on live system.
> >
> > Works well on my sample dumpfiles -- queued for the next release.
>
> Dave,
>
> I just noticed that there's a bug in this patch - it handles slow
> syscall return path wrong.
>
> Below is a patch which applies on top of this and fixes the slow
> path also. If you prefer, I can also send you a single patch which
> combines both of the patches.
>
> Sorry about the mess.
No problem -- the patch applies fine to 5.1.0, and it's queued for
the next release.
Thanks,
Dave
> Regards,
> MW
>
> diff --git a/arm.c b/arm.c
> index a8a34b9..751fe00 100644
> --- a/arm.c
> +++ b/arm.c
> @@ -31,7 +31,7 @@ static int arm_verify_symbol(const char *, ulong,
> char);
> static int arm_is_module_addr(ulong);
> static int arm_is_kvaddr(ulong);
> static int arm_in_exception_text(ulong);
> -static int arm_in_ret_from_syscall(ulong);
> +static int arm_in_ret_from_syscall(ulong, int *);
> static void arm_back_trace(struct bt_info *);
> static void arm_back_trace_cmd(struct bt_info *);
> static ulong arm_processor_speed(void);
> @@ -669,13 +669,44 @@ arm_in_exception_text(ulong pc)
> }
>
> /*
> - * Returns TRUE if given pc points to a return from syscall
> entrypoint.
> + * Returns TRUE if given pc points to a return from syscall
> + * entrypoint. In case the function returns TRUE and if offset is
> given,
> + * it is filled with the offset that should be added to the SP to
> get
> + * address of the exception frame where the user registers are.
> */
> static int
> -arm_in_ret_from_syscall(ulong pc)
> +arm_in_ret_from_syscall(ulong pc, int *offset)
> {
> - return (pc == symbol_value("ret_fast_syscall") ||
> - pc == symbol_value("ret_slow_syscall"));
> + /*
> + * On fast syscall return path, the stack looks like:
> + *
> + * SP + 0 {r4, r5}
> + * SP + 8 user pt_regs
> + *
> + * The asm syscall handler pushes fifth and sixth registers
> + * onto the stack before calling the actual syscall handler.
> + *
> + * So in order to print out the user registers at the time
> + * the syscall was made, we need to adjust SP for 8.
> + */
> + if (pc == symbol_value("ret_fast_syscall")) {
> + if (offset)
> + *offset = 8;
> + return TRUE;
> + }
> +
> + /*
> + * In case we are on the slow syscall path, the SP already
> + * points to the start of the user registers hence no
> + * adjustments needs to be done.
> + */
> + if (pc == symbol_value("ret_slow_syscall")) {
> + if (offset)
> + *offset = 0;
> + return TRUE;
> + }
> +
> + return FALSE;
> }
>
> /*
> @@ -1178,6 +1209,7 @@ arm_dump_backtrace_entry(struct bt_info *bt, int
> level, ulong from, ulong sp)
> {
> struct load_module *lm;
> const char *name;
> + int offset = 0;
>
> name = closest_symbol(bt->instptr);
>
> @@ -1201,23 +1233,10 @@ arm_dump_backtrace_entry(struct bt_info *bt,
> int level, ulong from, ulong sp)
>
> if (arm_in_exception_text(bt->instptr)) {
> arm_dump_exception_stack(sp, sp + sizeof(struct arm_pt_regs));
> - } else if (arm_in_ret_from_syscall(from)) {
> - /*
> - * When we are returning from the syscall, here is
> - * what the stack frame looks like:
> - *
> - * SP + 0 {r4, r5}
> - * SP + 8 user pt_regs
> - *
> - * The asm syscall handler pushes fifth and sixth
> - * registers onto the stack before calling the
> - * actual syscall handler.
> - *
> - * So in order to print out the user registers when
> - * the syscall was made, we need to adjust sp for 8.
> - */
> - arm_dump_exception_stack(sp + 8,
> - sp + 8 + sizeof(struct arm_pt_regs));
> + } else if (arm_in_ret_from_syscall(from, &offset)) {
> + ulong nsp = sp + offset;
> +
> + arm_dump_exception_stack(nsp, nsp + sizeof(struct arm_pt_regs));
> }
>
> if (bt->flags & BT_FULL) {
13 years, 11 months
[PATCH] ARM: dump also userspace registers when backtracing
by Mika Westerberg
Enhance backtracing code to print out userspace registers in case we
are at syscall entry. Other architectures supported by crash are
already doing this.
Signed-off-by: Mika Westerberg <ext-mika.1.westerberg(a)nokia.com>
---
I tested this with both unwind tables and framepointers enabled on
my test vmcores, and also on live system.
arm.c | 31 ++++++++++++++++++++++++++++++-
1 files changed, 30 insertions(+), 1 deletions(-)
diff --git a/arm.c b/arm.c
index 985f78e..a8a34b9 100644
--- a/arm.c
+++ b/arm.c
@@ -31,6 +31,7 @@ static int arm_verify_symbol(const char *, ulong, char);
static int arm_is_module_addr(ulong);
static int arm_is_kvaddr(ulong);
static int arm_in_exception_text(ulong);
+static int arm_in_ret_from_syscall(ulong);
static void arm_back_trace(struct bt_info *);
static void arm_back_trace_cmd(struct bt_info *);
static ulong arm_processor_speed(void);
@@ -668,6 +669,16 @@ arm_in_exception_text(ulong pc)
}
/*
+ * Returns TRUE if given pc points to a return from syscall entrypoint.
+ */
+static int
+arm_in_ret_from_syscall(ulong pc)
+{
+ return (pc == symbol_value("ret_fast_syscall") ||
+ pc == symbol_value("ret_slow_syscall"));
+}
+
+/*
* Unroll the kernel stack using a minimal amount of gdb services.
*/
static void
@@ -1188,8 +1199,26 @@ arm_dump_backtrace_entry(struct bt_info *bt, int level, ulong from, ulong sp)
fprintf(fp, " %s\n", buf);
}
- if (arm_in_exception_text(bt->instptr))
+ if (arm_in_exception_text(bt->instptr)) {
arm_dump_exception_stack(sp, sp + sizeof(struct arm_pt_regs));
+ } else if (arm_in_ret_from_syscall(from)) {
+ /*
+ * When we are returning from the syscall, here is
+ * what the stack frame looks like:
+ *
+ * SP + 0 {r4, r5}
+ * SP + 8 user pt_regs
+ *
+ * The asm syscall handler pushes fifth and sixth
+ * registers onto the stack before calling the
+ * actual syscall handler.
+ *
+ * So in order to print out the user registers when
+ * the syscall was made, we need to adjust sp for 8.
+ */
+ arm_dump_exception_stack(sp + 8,
+ sp + 8 + sizeof(struct arm_pt_regs));
+ }
if (bt->flags & BT_FULL) {
if (kt->flags & DWARF_UNWIND) {
--
1.7.3.2
13 years, 11 months
Re: [Crash-utility] [PATCH] Show missing tasks in ps
by Dave Anderson
----- "Dave Anderson" <anderson(a)redhat.com> wrote:
> ----- "Michael Holzheu" <holzheu(a)linux.vnet.ibm.com> wrote:
>
> > Hi Dave,
> >
> > I got an s390x dump of a Linux 2.6.36 system, where a task (kmcheck, pid=44) is
> > missing in the ps output. I debugged the problem and I think that I found the
> > reason:
> >
> > It looks like that crash does not walk the linked list of the pid hash table
> > to the end, if it finds a NULL pointer in the pid.tasks[PIDTYPE_PID=0]
> > array. Unfortunately, for the struct pid that is before our lost task in the
> > linked list this condition is true. Therefore crash does not find our task.
>
> That sounds similar to the fix Bob Montgomery made in 5.0.7:
>
> - Fix for the potential to miss one or more tasks in 2.6.23 and earlier
> kernels, presumably due to catching an entry the kernel's pid_hash[]
> chain in transition. Without the patch, the task will simply not be
> seen in the gathered task list.
> (bob.montgomery(a)hp.com)
>
> where this was his patch posting -- which fixed refresh_hlist_task_table_v2():
>
> [Crash-utility] Missing PID 1 is crash problem with losing tasks
> https://www.redhat.com/archives/crash-utility/2010-August/msg00049.html
>
> and where your patch fixes refresh_hlist_task_table_v3().
>
> I'll give it a test run...
>
> Thanks,
> Dave
Hi Michael,
Works well -- it's a rare occurrance, but the patch uncovered a total of
seven missing tasks in a test run on a sample set of 50 "v3" dumpfiles.
Queued for next release.
Thanks,
Dave
>
> > The attached patch seems to fix this problem.
> >
> > Here my crash debug log with the 2.6.36 dump:
> > ---------------------------------------------
> > Task "kmcheck" is in hash slot 2941 in the linked list at position
> 2:
> >
> > crash> print pid_hash[2941]
> > $4 = {
> > first = 0x3f5fb7f8
> > }
> >
> > crash> upid
> > struct upid {
> > int nr;
> > struct pid_namespace *ns;
> > struct hlist_node pid_chain;
> > }
> > SIZE: 32
> >
> > crash> upid.pid_chain
> > struct upid {
> > [16] struct hlist_node pid_chain;
> > }
> >
> > crash> eval 0x3f5fb7f8 - 16
> > hexadecimal: 3f5fb7e8
> >
> > crash> upid 3f5fb7e8 <<<<---- the first upid in the list
> > struct upid {
> > nr = 565,
> > ns = 0x81d8f8,
> > pid_chain = {
> > next = 0x3edea2b0,
> > pprev = 0x96554e8
> > }
> > }
> >
> > crash> pid
> > struct pid {
> > atomic_t count;
> > unsigned int level;
> > struct hlist_head tasks[3];
> > struct rcu_head rcu;
> > struct upid numbers[1];
> > }
> > SIZE: 80
> >
> > crash> pid.numbers
> > struct pid {
> > [48] struct upid numbers[1];
> > }
> >
> > crash> eval 3f5fb7e8 - 48
> > hexadecimal: 3f5fb7b8
> >
> > crash> pid 3f5fb7b8
> > struct pid {
> > count = {
> > counter = 1
> > },
> > level = 0,
> > tasks = {{
> > first = 0x0 <<<----------- tasks[0] is NULL
> > }, {
> > first = 0x3d488620
> > }, {
> > first = 0x0
> > }},
> > rcu = {
> > next = 0x5a5a5a5a5a5a5a5a,
> > func = 0x5a5a5a5a5a5a5a5a
> > },
> > numbers = {{
> > nr = 565,
> > ns = 0x81d8f8,
> > pid_chain = {
> > next = 0x3edea2b0, <<<--------- Pointer to second element
> in
> > list
> > pprev = 0x96554e8
> > }
> > }}
> > }
> >
> > crash> eval 0x3edea2b0 - 16
> > hexadecimal: 3edea2a0 <<<-- The second upid in the list
> >
> > crash> upid 0x3edea2a0
> > struct upid {
> > nr = 44, <<<--- Our missing pid=44 (kmcheck)
> > ns = 0x81d8f8,
> > pid_chain = {
> > next = 0x0,
> > pprev = 0x3f5fb7f8
> > }
> > }
> >
> > crash> eval 0x3edea2a0 - 48
> > hexadecimal: 3edea270
> >
> > crash> pid 3edea270
> > struct pid {
> > count = {
> > counter = 5
> > },
> > level = 0,
> > tasks = {{
> > first = 0x3e799908 <<<--- Pointer to our task_struct.pids
> > }, {
> > first = 0x0
> > }, {
> > first = 0x0
> > }},
> > rcu = {
> > next = 0x5a5a5a5a5a5a5a5a,
> > func = 0x5a5a5a5a5a5a5a5a
> > },
> > numbers = {{
> > nr = 44,
> > ns = 0x81d8f8,
> > pid_chain = {
> > next = 0x0,
> > pprev = 0x3f5fb7f8
> > }
> > }}
> > }
> >
> > crash> task_struct.pids
> > struct task_struct {
> > [712] struct pid_link pids[3];
> > }
> >
> > crash> eval 0x3e799908 - 712
> > hexadecimal: 3e799640
> >
> > crash> task_struct 3e799640 | grep comm
> > comm = "kmcheck\000\000\000\000\000\000\000\000", <<<--- here it
> is
> > ---
> > task.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > --- a/task.c
> > +++ b/task.c
> > @@ -2006,7 +2006,7 @@ do_chained:
> > }
> >
> > if (pid_tasks_0 == 0)
> > - continue;
> > + goto chain_next;
> >
> > next = pid_tasks_0 - OFFSET(task_struct_pids);
> >
> > @@ -2042,7 +2042,7 @@ do_chained:
> > }
> >
> > cnt++;
> > -
> > +chain_next:
> > if (pnext) {
> > kpp = pnext;
> > upid = pnext - OFFSET(upid_pid_chain);
> >
> >
> > --
> > Crash-utility mailing list
> > Crash-utility(a)redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
13 years, 11 months