[Pdbg] [PATCH] stack: guess endian for stack frame walking

Nicholas Piggin npiggin at gmail.com
Fri Sep 21 13:38:55 AEST 2018


The stack unwinder currently does not do any endian conversion, which
means it won't work correctly if the stack does not match pdbg endian.

This patch attempts an endian flip if the stack looks wrong, and goes
with that if it's an improvement. This was nice for debugging skiboot.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 src/thread.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 57 insertions(+), 5 deletions(-)

diff --git a/src/thread.c b/src/thread.c
index d282307..6d568b9 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -105,6 +105,15 @@ static int load8(struct pdbg_target *target, uint64_t addr, uint64_t *value)
 	return 1;
 }
 
+uint64_t flip_endian(uint64_t v)
+{
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	return be64toh(v);
+#else
+	return le64toh(v);
+#endif
+}
+
 static int dump_stack(struct thread_regs *regs)
 {
 	struct pdbg_target *target;
@@ -117,24 +126,67 @@ static int dump_stack(struct thread_regs *regs)
 		break;
 	}
 
-	printf("STACK:\n");
+	printf("STACK:           SP                NIA\n");
 	if (!target)
 		pdbg_log(PDBG_ERROR, "Unable to read memory (no ADU found)\n");
 
 	if (sp && is_real_address(regs, sp)) {
-		if (!load8(target, sp, &sp))
+		uint64_t tmp;
+		bool flip = false;
+		bool be;
+
+		if (!load8(target, sp, &tmp))
 			return 1;
-		while (sp && is_real_address(regs, sp)) {
+
+		if (!tmp) {
+badstack:
+			printf("SP:0x%016" PRIx64 " points to 0x%016" PRIx64 ", not decoding\n", sp, tmp);
+			return 0;
+		}
+
+		/* Haphazard endian detection */
+		if (tmp < sp || (tmp - sp > (1024*1024*1024))) {
+			uint64_t tmp2;
+			tmp2 = flip_endian(tmp);
+			if (tmp2 < sp || (tmp2 - sp > (1024*1024*1024)))
+				goto badstack;
+			sp = tmp2;
+			flip = true;
+		} else {
+			sp = tmp;
+		}
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+		be = false;
+#else
+		be = true;
+#endif
+		if (flip)
+			be = !be;
+		if (be)
+			printf("Looks like big-endian\n");
+		else
+			printf("Looks like little-endian\n");
+
+		while (sp) {
+			if (!is_real_address(regs, sp))
+				break;
+
 			if (!load8(target, sp + 16, &pc))
 				return 1;
+			if (flip)
+				pc = flip_endian(pc);
 
-			printf(" 0x%016" PRIx64 " 0x%16" PRIx64 "\n", sp, pc);
+			printf(" 0x%016" PRIx64 " 0x%016" PRIx64 "\n", sp, pc);
 
 			if (!load8(target, sp, &sp))
 				return 1;
+			if (flip)
+				sp = flip_endian(sp);
 		}
+	} else {
+		printf("SP:0x%016" PRIx64 " does not appear to be a stack\n", sp);
 	}
-
 	return 0;
 }
 
-- 
2.18.0



More information about the Pdbg mailing list