diff mbox series

stack: unwinder fix endian heuristic at top of stack

Message ID 20190628042038.5862-1-npiggin@gmail.com
State Accepted
Headers show
Series stack: unwinder fix endian heuristic at top of stack | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (742d66bbae8c6cc366e95e6ed663948ea028da3b)
snowpatch_ozlabs/build-multiarch success Test build-multiarch on branch master

Commit Message

Nicholas Piggin June 28, 2019, 4:20 a.m. UTC
When the stack is followed to the top and the next backpointer is
zero, the endian guess for the frame does not work properly. This
changes it to remember the previous endianness and use that.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
This stack unwinder is becoming a proper Rube Goldberg machine, it
can probably be rewritten sanely and more reliably, but here's one
last little fix I've been carrying around for a while that helps
things.

 src/thread.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Comments

Alistair Popple July 2, 2019, 2:13 a.m. UTC | #1
On Friday, 28 June 2019 2:20:38 PM AEST Nicholas Piggin wrote:
> When the stack is followed to the top and the next backpointer is
> zero, the endian guess for the frame does not work properly. This
> changes it to remember the previous endianness and use that.
> 
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> This stack unwinder is becoming a proper Rube Goldberg machine, it
> can probably be rewritten sanely and more reliably, but here's one
> last little fix I've been carrying around for a while that helps
> things.

Yeah, I convinced myself the original implementation worked but if these fixes 
make it more useful we can merge it and worry about sanity later :-)

Acked-by: Alistair Popple <alistair@popple.id.au>

>  src/thread.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/src/thread.c b/src/thread.c
> index 8f34233..ede797a 100644
> --- a/src/thread.c
> +++ b/src/thread.c
> @@ -57,6 +57,7 @@ static int dump_stack(struct thread_regs *regs, struct
> pdbg_target *adu) uint64_t next_sp = regs->gprs[1];
>  	uint64_t pc;
>  	bool finished = false;
> +	bool prev_flip = false;
> 
>  	printf("STACK:           SP                NIA\n");
>  	if (!(next_sp && is_real_address(regs, next_sp))) {
> @@ -82,13 +83,17 @@ static int dump_stack(struct thread_regs *regs, struct
> pdbg_target *adu) if (!load8(adu, sp + 16, &pc))
>  			return 1;
> 
> -		tmp2 = flip_endian(tmp);
> -
>  		if (!tmp) {
>  			finished = true;
> -			goto no_flip;
> +			flip = prev_flip;
> +			if (flip)
> +				be = !be;
> +			next_sp = 0;
> +			goto do_pc;
>  		}
> 
> +		tmp2 = flip_endian(tmp);
> +
>  		/*
>  		 * Basic endian detection.
>  		 * Stack grows down, so as we unwind it we expect to see
> @@ -130,11 +135,14 @@ no_flip:
>  			next_sp = tmp;
>  		}
> 
> +do_pc:
>  		if (flip)
>  			pc = flip_endian(pc);
> 
>  		printf(" 0x%016" PRIx64 " 0x%016" PRIx64 " (%s)\n",
>  			sp, pc, be ? "big-endian" : "little-endian");
> +
> +		prev_flip = flip;
>  	}
>  	printf(" 0x%016" PRIx64 "\n", next_sp);
diff mbox series

Patch

diff --git a/src/thread.c b/src/thread.c
index 8f34233..ede797a 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -57,6 +57,7 @@  static int dump_stack(struct thread_regs *regs, struct pdbg_target *adu)
 	uint64_t next_sp = regs->gprs[1];
 	uint64_t pc;
 	bool finished = false;
+	bool prev_flip = false;
 
 	printf("STACK:           SP                NIA\n");
 	if (!(next_sp && is_real_address(regs, next_sp))) {
@@ -82,13 +83,17 @@  static int dump_stack(struct thread_regs *regs, struct pdbg_target *adu)
 		if (!load8(adu, sp + 16, &pc))
 			return 1;
 
-		tmp2 = flip_endian(tmp);
-
 		if (!tmp) {
 			finished = true;
-			goto no_flip;
+			flip = prev_flip;
+			if (flip)
+				be = !be;
+			next_sp = 0;
+			goto do_pc;
 		}
 
+		tmp2 = flip_endian(tmp);
+
 		/*
 		 * Basic endian detection.
 		 * Stack grows down, so as we unwind it we expect to see
@@ -130,11 +135,14 @@  no_flip:
 			next_sp = tmp;
 		}
 
+do_pc:
 		if (flip)
 			pc = flip_endian(pc);
 
 		printf(" 0x%016" PRIx64 " 0x%016" PRIx64 " (%s)\n",
 			sp, pc, be ? "big-endian" : "little-endian");
+
+		prev_flip = flip;
 	}
 	printf(" 0x%016" PRIx64 "\n", next_sp);