jasonmolenda added a comment.

In D66250#1631200 <https://reviews.llvm.org/D66250#1631200>, @labath wrote:

> I have one high-level question. Who is generating the code inside the 
> "trampoline" object file? Couldn't we have him generate proper unwind 
> information so that the regular unwind machinery "just works"? I imagine all 
> it would take is a couple of well-placed `.cfi` assembler directives...


The ABI plugin creates the trampoline by writing bytes directly IIRC.  The 
trampoline has to save the entire register context to the stack before it calls 
the jitted function that does the comparison and possibly breaks.  Then the 
trampoline restores all the register context, executes any replaced functions, 
and then jumps directly back into the original function.

The trampoline has to be expressed in terms of assembly (or hardcoded bytes) 
because we're not using the normal calling conventions - we have to spill all 
registers so the jitted function doesn't overwrite a caller-spilled register 
and corrupt the original user function that we're patching in to.  Also, it is 
not CALLed from the original user function, it is JMPed to, so there's no way 
for the unwinder to get from the trampoline function back to the original user 
function by looking at the stack.

The question is then, why do we have to JMP to the trampoline?  This simplifies 
running the replaced instructions in the trampoline, because the stack pointer 
and frame pointer have the original user function's values when the replaced 
instructions are executed at the end of the trampoline.  Using a CALL to get 
from the original function to the trampoline solves the unwinder problem, but 
we're still going to need to express the trampoline in assembly terms to save & 
restore all the registers, and have the replaced instructions execute.

On non-x86 architectures, like Aarch64, doing a function call to the trampoline 
would mean we need to spill the $lr value to the stack in the original user 
function before calling the trampoline so we don't overwrite the value; that's 
a larger number of instructions that need to be shifted into the trampoline to 
execute.

Of course the only reason we have this ObjectFile plugin is for the unwinder's 
benefit.  If we used a CALL instruction to get to the trampoline, and we sent 
the assembly through the clang FE as a series of asm()s to jit it, instead of 
writing the bytes down, the unwinder would get the unwind information as we do 
a normal jitted function -- you're right, cfi directives to point to the saved 
register context would be sufficient.

But because we're jumping directly to the trampoline, and jumping back from the 
trampoline, we need to have a hand-written unwind plan that has the return 
address hard coded in it for the unwinder to work.

Is having a small ObjectFile plugin for this purpose a bad idea?  It seems like 
the right approach, but maybe I'm not seeing the issue.  The CreateInstance 
method returns false always, so when we iterate looking for an ObjectFile 
plugin, we will call this method but it will return false right away.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66250/new/

https://reviews.llvm.org/D66250



_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to