Message ID | 20190628042038.5862-1-npiggin@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | stack: unwinder fix endian heuristic at top of stack | expand |
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 |
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 --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);
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(-)