[PATCH] D9259: [PowerPC]Adapt fast stack unwinding to work for Power.

Bill Schmidt wschmidt at linux.vnet.ibm.com
Mon Jul 27 19:56:24 PDT 2015


wschmidt added a comment.

In http://reviews.llvm.org/D9259#213181, @samsonov wrote:

> In http://reviews.llvm.org/D9259#213127, @wschmidt wrote:
>
> > OK, I've been looking at a small example.  I've taken the portion of Bill Seurer's patch that modifies the offset to the return address in the stack frame, but omitted the part that pops extra stack frames, so that I can get a look at why we get a bogus extra frame.
> >
> > In the example, we produce this:
> >
> > freed by thread T0 here:
> >
> >   #0 0x1010d988 in GetStackTraceWithPcBpAndContext /home/wschmidt/llvm/llvm-test2/projects/compiler-rt/lib/asan/asan_stack.h:50
> >   #1 0x1010d988 in operator delete(void*) /home/wschmidt/llvm/llvm-test2/projects/compiler-rt/lib/asan/asan_new_delete.cc:94
>
>
> ^^
>  Why do we output two identical (0x1010d988) addresses here, if you refer to them as 0x1010d98c and 0x1010d910 later?
>  We do call StackTrace::GetPreviousInstructionPC() when we symbolize addresses, but why isn't second address turned into 0x1010d99c?


I haven't looked into this yet, but the address that's printed is the value of the saved link register - 4 (the call address, not the return address).  That would be the same for both.  That's just an artifact, and not the root problem.  (see below)
<SNIP>

> I don't know why `pc1` and `pc` are compared, this code looks really weird to me. However, I'm pretty sure it's not intending to solve the problem you're facing (two top PCs coming from the same function). On x86_64 ABI two PCs from the same function will almost never be equal as well.


Agreed.  Since this code isn't documented and makes no sense, you might want to experiment with removing the check and see why somebody put it in there in the first place...

> I think there's some confusion here. You mention that we call `BufferedStackTrace::FastUnwindStack(pc = 0x1010d910, bp = 0x3fffffffeb20, ...)`, and `0x3fffffffeb20` is a frame of `operator delete`, `0x1010d910` is an instruction inside `operator delete` code. So far so good! But the value of `pc1` we fetch from a function frame is supposed to be a *return address of operator delete*, not a return address of StackTrace::Unwind() called from operator delete. Probably, we're just reading incorrect value from the function frame? (that's weird, though, docs I found suggest that "link register" used to store return address is callee-saved, as on x86: https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/110-64-bit_PowerPC_Function_Calling_Conventions/64bitPowerPC.html#//apple_ref/doc/uid/TP40002471-SW14)


Aha!  This is where the problem comes from.  The link register is indeed callee-saved, but it is saved by the callee at offset 16 from the base of the *caller's* stack frame prior to pushing the callee's frame.  To find the correct return address on Power from the callee's stack frame, you must load the back chain pointer (located at the base of the callee's stack frame) and add 16 to that.  See Figure 2-18 of the ELFv2 ABI at https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?id=B81AEC1A37F5DAF185257C3E004E8845.  (Requires free registration.  Let me know if you have trouble accessing this and I'll send you a copy.)

In prolog code on Power, you will see:

  mflr r0
  std r0,16(r1)

prior to decrementing r1 to establish the callee stack frame.


http://reviews.llvm.org/D9259







More information about the llvm-commits mailing list