> My question is about this "initial frame". In our testcase we don't have
> this case since the backtrace starts in a function that has some CFI.
> But I assume you have some tests that rely on this behavior.

Actually the test I provided does exercise this code. The initial 
__libc_do_syscall() frame does not have CFI. Only raise() has. You can check 
that by dropping the code for pc & 0x1.

> The first question is how/why the (pc & 0x1) == 0 check works?
> Why is that the correct check?
> 
> Secondly, if it really is the initial (or signal frame) we are after,
> should we pass in into bool *signal_framep argument. Currently we don't

We have this piece of code in __libdwfl_frame_unwind, in frame_unwind.c:

  if (! state->initial_frame && ! state->signal_frame)
      pc--;

AArch64 has a fixed instruction width of 32bit. So, normally the pc is aligned 
to 4 bytes. Except if we decrement it, then we are guaranteed to have an odd 
number, which we can then test to see if the frame in question is the initial 
or a signal frame. Of course it would be nicer to pass this information 
directly, but the signal_frame parameter is supposed to be an output parameter. 
After all we do the following after calling ebl_unwind():

  state->unwound->signal_frame = signal_frame;

> Lastly could you instead of returning the frame itself with just the pc
> adjusted do that directly?
> 
>   if ((pc & 0x1) == 0)
>     lr = lr & (~0x1);

If I dig up the first frame after the initial one from the stack, then we drop 
whatever we initially had in LR. Apparently, on aarch64 PC is always one frame 
"ahead" of the other registers. To establish that, we have to set PC to the 
value of LR on the initial frame, without actually unwinding.

br,
Ulf

Reply via email to