The value of EXCP_FRAME_MARKER is outdated for kernel>=6.1.0 by kernel
commit bbd71709087a9 ("powerpc: Make stack frame marker upper case") and
commit 19c95df1277c4 ("powerpc: Reverse stack frame marker on little endian").
Also its offset is changed since kernel>=6.2.0 by kernel commit
cd52414d5a6c ("powerpc/64: ELFv2 use minimal stack frames in int and switch
frame sizes"). This patch will fix the issue by updating its values.
Before:
crash> bt
...
#8 [c00000000a327b80] system_call_exception at c000000000031a30
#9 [c00000000a327e50] system_call_vectored_common at c00000000000d05c
After:
crash> bt
...
#8 [c00000000a327b80] system_call_exception at c000000000031a30
#9 [c00000000a327e50] system_call_vectored_common at c00000000000d05c
System Call Vectored [3000] exception frame:
R0: 0000000000000004 R1: 00007fffc3345f40 R2: 0000000000100000
R3: 0000000000000001 R4: 000000012572c620 R5: 0000000000000002
R6: 0000000000000001 R7: 0000000000000004 R8: 0000000000000001
...
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
defs.h | 6 +++++-
ppc64.c | 37 +++++++++++++++++++++++++++----------
2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/defs.h b/defs.h
index abde47c..6b9b8db 100644
--- a/defs.h
+++ b/defs.h
@@ -4652,7 +4652,11 @@ struct efi_memory_desc_t {
#define STACK_SWITCH_FRAME_REGS 48
#define STACK_FRAME_OVERHEAD 112
-#define EXCP_FRAME_MARKER 0x7265677368657265
+#define EXCP_FRAME_MARKER \
+ (THIS_KERNEL_VERSION >= LINUX(6,1,0) ? \
+ (__BYTE_ORDER == __BIG_ENDIAN ? 0x52454753 : 0x53474552) : \
+ 0x7265677368657265) /* See arch/powerpc/include/asm/ptrace.h: */
+ /* STACK_FRAME_REGS_MARKER */
#define _SECTION_SIZE_BITS 24
#define _MAX_PHYSMEM_BITS 44
diff --git a/ppc64.c b/ppc64.c
index 87f9c4c..f607060 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -2204,19 +2204,34 @@ ppc64_back_trace(struct gnu_request *req, struct bt_info *bt)
eframe_found = TRUE;
else if (STREQ(req->name, ".ret_from_except"))
eframe_found = TRUE;
- } else if ((newsp - req->sp - STACK_FRAME_OVERHEAD) >=
- sizeof(struct ppc64_pt_regs)) {
- readmem(req->sp+0x60, KVADDR, &marker,
- sizeof(ulong), "stack frame", FAULT_ON_ERROR);
- if (marker == EXCP_FRAME_MARKER)
- eframe_found = TRUE;
+ } else if (THIS_KERNEL_VERSION >= LINUX(6,2,0) && is_ppc64_elf_abi_v2()) {
+ if ((newsp - req->sp - STACK_SWITCH_FRAME_REGS) >=
+ sizeof(struct ppc64_pt_regs)) {
+ readmem(req->sp+0x20, KVADDR, &marker,
+ sizeof(ulong), "stack frame",
+ FAULT_ON_ERROR);
+ }
+ } else {
+ if ((newsp - req->sp - STACK_FRAME_OVERHEAD) >=
+ sizeof(struct ppc64_pt_regs)) {
+ readmem(req->sp+0x60, KVADDR, &marker,
+ sizeof(ulong), "stack frame",
+ FAULT_ON_ERROR);
+ }
}
- if (eframe_found) {
+
+ if (eframe_found || marker == EXCP_FRAME_MARKER) {
char *efrm_str = NULL;
struct ppc64_pt_regs regs;
- readmem(req->sp+STACK_FRAME_OVERHEAD, KVADDR, ®s,
- sizeof(struct ppc64_pt_regs),
- "exception frame", FAULT_ON_ERROR);
+ if (THIS_KERNEL_VERSION >= LINUX(6,2,0) && is_ppc64_elf_abi_v2()) {
+ readmem(req->sp+STACK_SWITCH_FRAME_REGS, KVADDR, ®s,
+ sizeof(struct ppc64_pt_regs),
+ "exception frame", FAULT_ON_ERROR);
+ } else {
+ readmem(req->sp+STACK_FRAME_OVERHEAD, KVADDR, ®s,
+ sizeof(struct ppc64_pt_regs),
+ "exception frame", FAULT_ON_ERROR);
+ }
efrm_str = ppc64_check_eframe(®s);
if (efrm_str) {
@@ -2427,6 +2442,8 @@ ppc64_check_eframe(struct ppc64_pt_regs *regs)
return("Denormalisation");
case 0x1700:
return("Altivec Assist");
+ case 0x3000:
+ return("System Call Vectored");
}
/* No exception frame exists */
--
2.46.2