mirror of
https://github.com/crash-utility/crash
synced 2025-03-03 12:57:40 +00:00
Currently, gdb passthroughs of 'bt', 'frame', 'up', 'down', 'info locals' don't work. This is due to gdb not knowing the register values to unwind the stack frames Every gdb passthrough goes through `gdb_interface`. And then, gdb expects `crash_target::fetch_registers` to give it the register values, which is dependent on `machdep->get_current_task_reg` to read the register values for specific architecture. ---------------------------- gdb passthrough (eg. "bt") | | crash -------------------------> | | | gdb_interface | | | | | | ---------------------- | fetch_registers | | | | crash_target<-------------------------+--| gdb | | --------------------------+->| | | Registers (SP,NIP, etc.)| | | | | | | | | ---------------------- | ---------------------------- Implement `machdep->get_current_task_reg` on PPC64, so that crash provides the register values to gdb to unwind stack frames properly With these changes, on powerpc, 'bt' command output in gdb mode, will look like this: gdb> bt #0 0xc0000000002a53e8 in crash_setup_regs (oldregs=<optimized out>, newregs=0xc00000000486f8d8) at ./arch/powerpc/include/asm/kexec.h:69 #1 __crash_kexec (regs=<optimized out>) at kernel/kexec_core.c:974 #2 0xc000000000168918 in panic (fmt=<optimized out>) at kernel/panic.c:358 #3 0xc000000000b735f8 in sysrq_handle_crash (key=<optimized out>) at drivers/tty/sysrq.c:155 #4 0xc000000000b742cc in __handle_sysrq (key=key@entry=99, check_mask=check_mask@entry=false) at drivers/tty/sysrq.c:602 #5 0xc000000000b7506c in write_sysrq_trigger (file=<optimized out>, buf=<optimized out>, count=2, ppos=<optimized out>) at drivers/tty/sysrq.c:1163 #6 0xc00000000069a7bc in pde_write (ppos=<optimized out>, count=<optimized out>, buf=<optimized out>, file=<optimized out>, pde=0xc000000009ed3a80) at fs/proc/inode.c:340 #7 proc_reg_write (file=<optimized out>, buf=<optimized out>, count=<optimized out>, ppos=<optimized out>) at fs/proc/inode.c:352 #8 0xc0000000005b3bbc in vfs_write (file=file@entry=0xc00000009dda7d00, buf=buf@entry=0xebcfc7c6040 <error: Cannot access memory at address 0xebcfc7c6040>, count=count@entry=2, pos=pos@entry=0xc00000000486fda0) at fs/read_write.c:582 instead of earlier output without this patch: gdb> bt #0 <unavailable> in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) Also, 'get_dumpfile_regs' has been introduced to get registers from multiple supported vmcore formats. Correspondingly a flag 'BT_NO_PRINT_REGS' has been introduced to tell helper functions to get registers, to not print registers with every call to backtrace in gdb. Note: This feature to support GDB unwinding doesn't support live debugging [lijiang: squash these five patches(see the Link) into one patch] Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01084.html Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01083.html Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01089.html Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01090.html Link: https://www.mail-archive.com/devel@lists.crash-utility.osci.io/msg01091.html Co-developed-by:: Tao Liu <ltao@redhat.com> Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
103 lines
3.0 KiB
C
103 lines
3.0 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#define CONFIG_64BIT 1
|
|
#define NULL ((void *)0)
|
|
|
|
typedef unsigned long size_t;
|
|
typedef unsigned char u8;
|
|
typedef signed short s16;
|
|
typedef unsigned short u16;
|
|
typedef signed int s32;
|
|
typedef unsigned int u32;
|
|
typedef unsigned long long u64;
|
|
|
|
struct pt_regs {
|
|
unsigned long r15;
|
|
unsigned long r14;
|
|
unsigned long r13;
|
|
unsigned long r12;
|
|
unsigned long rbp;
|
|
unsigned long rbx;
|
|
/* arguments: non interrupts/non tracing syscalls only save upto here*/
|
|
unsigned long r11;
|
|
unsigned long r10;
|
|
unsigned long r9;
|
|
unsigned long r8;
|
|
unsigned long rax;
|
|
unsigned long rcx;
|
|
unsigned long rdx;
|
|
unsigned long rsi;
|
|
unsigned long rdi;
|
|
unsigned long orig_rax;
|
|
/* end of arguments */
|
|
/* cpu exception frame or undefined */
|
|
unsigned long rip;
|
|
unsigned long cs;
|
|
unsigned long eflags;
|
|
unsigned long rsp;
|
|
unsigned long ss;
|
|
/* top of stack page */
|
|
};
|
|
|
|
struct unwind_frame_info
|
|
{
|
|
struct pt_regs regs;
|
|
};
|
|
|
|
extern int unwind(struct unwind_frame_info *, int);
|
|
extern void init_unwind_table(void);
|
|
extern void free_unwind_table(void);
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
|
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
|
#define get_unaligned(ptr) (*(ptr))
|
|
//#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
|
|
#define THREAD_ORDER 1
|
|
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
|
|
|
|
#define UNW_PC(frame) (frame)->regs.rip
|
|
#define UNW_SP(frame) (frame)->regs.rsp
|
|
#ifdef CONFIG_FRAME_POINTER
|
|
#define UNW_FP(frame) (frame)->regs.rbp
|
|
#define FRAME_RETADDR_OFFSET 8
|
|
#define FRAME_LINK_OFFSET 0
|
|
#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
|
|
#define STACK_TOP(tsk) ((tsk)->thread.rsp0)
|
|
#endif
|
|
|
|
|
|
#define EXTRA_INFO(f) { BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) % FIELD_SIZEOF(struct unwind_frame_info, f)) + offsetof(struct unwind_frame_info, f)/ FIELD_SIZEOF(struct unwind_frame_info, f), FIELD_SIZEOF(struct unwind_frame_info, f) }
|
|
|
|
#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
|
|
|
|
#define UNW_REGISTER_INFO \
|
|
PTREGS_INFO(rax),\
|
|
PTREGS_INFO(rdx),\
|
|
PTREGS_INFO(rcx),\
|
|
PTREGS_INFO(rbx), \
|
|
PTREGS_INFO(rsi), \
|
|
PTREGS_INFO(rdi), \
|
|
PTREGS_INFO(rbp), \
|
|
PTREGS_INFO(rsp), \
|
|
PTREGS_INFO(r8), \
|
|
PTREGS_INFO(r9), \
|
|
PTREGS_INFO(r10),\
|
|
PTREGS_INFO(r11), \
|
|
PTREGS_INFO(r12), \
|
|
PTREGS_INFO(r13), \
|
|
PTREGS_INFO(r14), \
|
|
PTREGS_INFO(r15), \
|
|
PTREGS_INFO(rip)
|
|
|