[Lldb-commits] [PATCH] D66250: [JIT][Unwinder] Add Trampoline ObjectFile and UnwindPlan support for FCB

Jason Molenda via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 15 14:51:29 PDT 2019

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.

  rG LLVM Github Monorepo



More information about the lldb-commits mailing list